diff --git a/README.md b/README.md index b9d378fc3..f0b1a9f4b 100644 --- a/README.md +++ b/README.md @@ -24,18 +24,18 @@ New users may wish to do the following setup to access the server via a GUI and Terminal on Mac, cmd on Windows, xterm on Linux See A.1 about ssh -Y login from a terminal -Then clone the repo, source setup, make the tests and run regression +Then fork and clone the repo, source setup, make the tests and run regression If you don't already have a Github account, create one In a web browser, visit https://github.com/openhwgroup/cvw In the upper right part of the screen, click on Fork - Create a fork, choosing the owner as your github account and the repository as cvw. + Create a fork, choosing the owner as your github account + and the repository as cvw. On the Linux computer where you will be working, log in Clone your fork of the repo and run the setup script. Change to your github id. - $ cd $ git clone --recurse-submodules https://github.com//cvw $ cd cvw $ git remote add upstream https://github.com/openhwgroup/cvw diff --git a/bin/derivgen.pl b/bin/derivgen.pl index 096918400..630962ca8 100755 --- a/bin/derivgen.pl +++ b/bin/derivgen.pl @@ -33,13 +33,14 @@ use strict; use warnings; -import os; +import os; use Data::Dumper; my $curderiv = ""; my @derivlist = (); my %derivs; my %basederiv; +my @derivnames = (); if ($#ARGV != -1) { die("Usage: $0") @@ -69,13 +70,20 @@ foreach my $line (<$fh>) { } &terminateDeriv(); close($fh); -foreach my $key (keys %derivs) { +#foreach my $key (keys %derivs) { +foreach my $key (@derivnames) { my $dir = "$ENV{WALLY}/config/deriv/$key"; system("rm -rf $dir"); system("mkdir -p $dir"); my $configunmod = "$dir/config_unmod.vh"; my $config = "$dir/config.vh"; my $base = "$ENV{WALLY}/config/$basederiv{$key}/config.vh"; + if (! -e $base) { + $base = "$ENV{WALLY}/config/deriv/$basederiv{$key}/config.vh"; + #if (! -e $base) { + # die("Unable to find base config $base for $key\n"); + #} + } system("cp $base $configunmod"); open(my $unmod, $configunmod) or die "Could not open file '$configunmod' $!"; open(my $fh, '>>', $config) or die "Could not open file '$config' $!"; @@ -111,6 +119,7 @@ sub terminateDeriv { if ($curderiv ne "") { # close out the previous derivative my @dl = @derivlist; $derivs{$curderiv} = \@dl; + push(@derivnames, $curderiv); } }; diff --git a/config/buildroot/config.vh b/config/buildroot/config.vh deleted file mode 100644 index 6629af297..000000000 --- a/config/buildroot/config.vh +++ /dev/null @@ -1,184 +0,0 @@ -////////////////////////////////////////// -// config.vh -// -// Written: David_Harris@hmc.edu 4 January 2021 -// Modified: -// -// Purpose: Specify which features are configured -// Macros to determine which modes are supported based on MISA -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -// include shared configuration -`include "BranchPredictorType.vh" - -// RV32 or RV64: XLEN = 32 or 64 -localparam XLEN = 32'd64; - -// IEEE 754 compliance -localparam IEEE754 = 0; - -localparam MISA = (32'h0014112D); -localparam ZICSR_SUPPORTED = 1; -localparam ZIFENCEI_SUPPORTED = 1; -localparam ZICNTR_SUPPORTED = 1; -localparam ZIHPM_SUPPORTED = 1; -localparam COUNTERS = 12'd32; -localparam ZFH_SUPPORTED = 1; -localparam ZFA_SUPPORTED = 0; -localparam SSTC_SUPPORTED = 1; -localparam ZICBOM_SUPPORTED = 1; -localparam ZICBOZ_SUPPORTED = 1; -localparam ZICBOP_SUPPORTED = 1; -localparam ZICCLSM_SUPPORTED = 1; -localparam ZICOND_SUPPORTED = 1; -localparam SVPBMT_SUPPORTED = 1; -localparam SVNAPOT_SUPPORTED = 1; -localparam SVINVAL_SUPPORTED = 1; - -// LSU microarchitectural Features -localparam BUS_SUPPORTED = 1; -localparam DCACHE_SUPPORTED = 1; -localparam ICACHE_SUPPORTED = 1; -localparam VIRTMEM_SUPPORTED = 1; -localparam VECTORED_INTERRUPTS_SUPPORTED = 1; -localparam BIGENDIAN_SUPPORTED = 1; - -// TLB configuration. Entries should be a power of 2 -localparam ITLB_ENTRIES = 32'd32; -localparam DTLB_ENTRIES = 32'd32; - -// Cache configuration. Sizes should be a power of two -// typical configuration 4 ways, 4096 bytes per way, 256 bit or more lines -localparam DCACHE_NUMWAYS = 32'd4; -localparam DCACHE_WAYSIZEINBYTES = 32'd4096; -localparam DCACHE_LINELENINBITS = 32'd512; -localparam ICACHE_NUMWAYS = 32'd4; -localparam ICACHE_WAYSIZEINBYTES = 32'd4096; -localparam ICACHE_LINELENINBITS = 32'd512; -localparam CACHE_SRAMLEN = 32'd128; - -// Integer Divider Configuration -// IDIV_BITSPERCYCLE must be 1, 2, or 4 -localparam IDIV_BITSPERCYCLE = 32'd4; -localparam IDIV_ON_FPU = 1; - -// Legal number of PMP entries are 0, 16, or 64 -localparam PMP_ENTRIES = 32'd16; - -// Address space -localparam logic [63:0] RESET_VECTOR = 64'h0000000000001000; - -// WFI Timeout Wait -localparam WFI_TIMEOUT_BIT = 32'd16; - -// Peripheral Addresses -// Peripheral memory space extends from BASE to BASE+RANGE -// Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits -localparam DTIM_SUPPORTED = 1'b0; -localparam logic [63:0] DTIM_BASE = 64'h80000000; -localparam logic [63:0] DTIM_RANGE = 64'h00001FFF; -localparam IROM_SUPPORTED = 1'b0; -localparam logic [63:0] IROM_BASE = 64'h80000000; -localparam logic [63:0] IROM_RANGE = 64'h00001FFF; -localparam BOOTROM_SUPPORTED = 1'b1; -localparam logic [63:0] BOOTROM_BASE = 64'h00001000 ; -localparam logic [63:0] BOOTROM_RANGE = 64'h00000FFF; -localparam BOOTROM_PRELOAD = 1'b1; -localparam UNCORE_RAM_SUPPORTED = 1'b1; -localparam logic [63:0] UNCORE_RAM_BASE = 64'h80000000; -localparam logic [63:0] UNCORE_RAM_RANGE = 64'h0FFFFFFF; -localparam UNCORE_RAM_PRELOAD = 1'b1; -localparam EXT_MEM_SUPPORTED = 1'b0; -localparam logic [63:0] EXT_MEM_BASE = 64'h80000000; -localparam logic [63:0] EXT_MEM_RANGE = 64'h07FFFFFF; -localparam CLINT_SUPPORTED = 1'b1; -localparam logic [63:0] CLINT_BASE = 64'h02000000; -localparam logic [63:0] CLINT_RANGE = 64'h0000FFFF; -localparam GPIO_SUPPORTED = 1'b1; -localparam logic [63:0] GPIO_BASE = 64'h10060000; -localparam logic [63:0] GPIO_RANGE = 64'h000000FF; -localparam UART_SUPPORTED = 1'b1; -localparam logic [63:0] UART_BASE = 64'h10000000; -localparam logic [63:0] UART_RANGE = 64'h00000007; -localparam PLIC_SUPPORTED = 1'b1; -localparam logic [63:0] PLIC_BASE = 64'h0C000000; -localparam logic [63:0] PLIC_RANGE = 64'h03FFFFFF; -localparam SDC_SUPPORTED = 1'b0; -localparam logic [63:0] SDC_BASE = 64'h00013000; -localparam logic [63:0] SDC_RANGE = 64'h0000007F; -localparam SPI_SUPPORTED = 1'b1; -localparam logic [63:0] SPI_BASE = 64'h10040000; -localparam logic [63:0] SPI_RANGE = 64'h00000FFF; - -// Bus Interface width -localparam AHBW = 32'd64; - -// AHB -localparam RAM_LATENCY = 32'b0; -localparam BURST_EN = 1; - -// Test modes - -// Tie GPIO outputs back to inputs -localparam GPIO_LOOPBACK_TEST = 0; -localparam SPI_LOOPBACK_TEST = 0; - -// Hardware configuration -localparam UART_PRESCALE = 32'd0; - -// Interrupt configuration -localparam PLIC_NUM_SRC = 32'd53; -localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32); -localparam PLIC_UART_ID = 32'd10; -localparam PLIC_GPIO_ID = 32'd3; -localparam PLIC_SPI_ID = 32'd6; -localparam PLIC_SDC_ID = 32'd20; - -localparam BPRED_SUPPORTED = 1; -localparam BPRED_TYPE = `BP_GSHARE; // BP_GSHARE_BASIC, BP_GLOBAL, BP_GLOBAL_BASIC, BP_TWOBIT -localparam BPRED_SIZE = 32'd10; -localparam BPRED_NUM_LHR = 32'd6; -localparam BTB_SIZE = 32'd10; -localparam RAS_SIZE = 32'd16; -localparam INSTR_CLASS_PRED = 1; - -localparam SVADU_SUPPORTED = 1; -localparam ZMMUL_SUPPORTED = 0; - -// FPU division architecture -localparam RADIX = 32'h4; -localparam DIVCOPIES = 32'h4; - -// bit manipulation -localparam ZBA_SUPPORTED = 1; -localparam ZBB_SUPPORTED = 1; -localparam ZBC_SUPPORTED = 1; -localparam ZBS_SUPPORTED = 1; - -// New compressed instructions -localparam ZCB_SUPPORTED = 1; -localparam ZCA_SUPPORTED = 0; -localparam ZCF_SUPPORTED = 0; -localparam ZCD_SUPPORTED = 0; - -// Memory synthesis configuration -localparam USE_SRAM = 0; - -`include "config-shared.vh" diff --git a/config/derivlist.txt b/config/derivlist.txt index 581922b9c..c0cae3bd3 100644 --- a/config/derivlist.txt +++ b/config/derivlist.txt @@ -41,12 +41,12 @@ RESET_VECTOR 64'h1000 UNCORE_RAM_RANGE 64'h0FFFFFFF UNCORE_RAM_PRELOAD 1 GPIO_LOOPBACK_TEST 0 -SPI_LOOPBACK_TEST 0 -UART_PRESCALE 0 +SPI_LOOPBACK_TEST 0 +UART_PRESCALE 32'd0 PLIC_NUM_SRC 32'd53 # fpga is used for FPGA hardware. It adds the SDC and DDR (EXT_MEM) -deriv fpga rv64gc buildroot +deriv fpga buildroot BOOTROM_PRELOAD 1 UNCORE_RAM_BASE 64'h2000 UNCORE_RAM_RANGE 64'hFFF @@ -71,7 +71,7 @@ BTB_SIZE 32'd5 # The other syn configurations have the same trimming deriv syn_rv32i rv32i syn_rv32e deriv syn_rv32imc rv32imc syn_rv32e -deriv syn_rv32gc rv32gc syn_rv32e +deriv syn_rv32gc syn_rv32e deriv syn_rv64i rv64i syn_rv32e deriv syn_rv64gc rv64gc syn_rv32e @@ -84,34 +84,34 @@ USE_SRAM 1 # The other syn configurations have the same trimming deriv syn_sram_rv32i rv32i syn_sram_rv32e deriv syn_sram_rv32imc rv32imc syn_sram_rv32e -deriv syn_sram_rv32gc rv32gc syn_sram_rv32e +deriv syn_sram_rv32gc syn_sram_rv32e deriv syn_sram_rv64i rv64i syn_sram_rv32e deriv syn_sram_rv64gc rv64gc syn_sram_rv32e # The following syn configurations gradually turn off features -deriv syn_pmp0_rv64gc rv64gc syn_rv64gc +deriv syn_pmp0_rv64gc syn_rv64gc PMP_ENTRIES 32'd0 -deriv syn_sram_pmp0_rv64gc rv64gc syn_sram_rv64gc +deriv syn_sram_pmp0_rv64gc syn_sram_rv64gc PMP_ENTRIES 32'd0 -deriv syn_noPriv_rv64gc rv64gc syn_pmp0_rv64gc +deriv syn_noPriv_rv64gc syn_pmp0_rv64gc ZICSR_SUPPORTED 0 -deriv syn_sram_noPriv_rv64gc rv64gc syn_sram_pmp0_rv64gc +deriv syn_sram_noPriv_rv64gc syn_sram_pmp0_rv64gc ZICSR_SUPPORTED 0 -deriv syn_noFPU_rv64gc rv64gc syn_noPriv_rv64gc +deriv syn_noFPU_rv64gc syn_noPriv_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0) -deriv syn_sram_noFPU_rv64gc rv64gc syn_sram_noPriv_rv64gc +deriv syn_sram_noFPU_rv64gc syn_sram_noPriv_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0) -deriv syn_noMulDiv_rv64gc rv64gc syn_noFPU_rv64gc +deriv syn_noMulDiv_rv64gc syn_noFPU_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20 | 1 << 0) -deriv syn_sram_noMulDiv_rv64gc rv64gc syn_sram_noFPU_rv64gc +deriv syn_sram_noMulDiv_rv64gc syn_sram_noFPU_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20 | 1 << 0) -deriv syn_noAtomic_rv64gc rv64gc syn_noMulDiv_rv64gc +deriv syn_noAtomic_rv64gc syn_noMulDiv_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20) -deriv syn_sram_noAtomic_rv64gc rv64gc syn_sram_noMulDiv_rv64gc +deriv syn_sram_noAtomic_rv64gc syn_sram_noMulDiv_rv64gc MISA (32'h00000104 | 1 << 18 | 1 << 20) # Divider variants to check logical correctness @@ -119,85 +119,98 @@ MISA (32'h00000104 | 1 << 18 | 1 << 20) deriv div_2_1_rv32gc rv32gc RADIX 32'd2 DIVCOPIES 32'd1 +IDIV_ON_FPU 0 deriv div_2_2_rv32gc rv32gc RADIX 32'd2 DIVCOPIES 32'd2 +IDIV_ON_FPU 0 deriv div_2_4_rv32gc rv32gc RADIX 32'd2 DIVCOPIES 32'd4 +IDIV_ON_FPU 0 deriv div_4_1_rv32gc rv32gc RADIX 32'd4 DIVCOPIES 32'd1 +IDIV_ON_FPU 0 deriv div_4_2_rv32gc rv32gc RADIX 32'd4 +IDIV_ON_FPU 0 DIVCOPIES 32'd2 +IDIV_ON_FPU 0 deriv div_4_4_rv32gc rv32gc RADIX 32'd4 DIVCOPIES 32'd4 +IDIV_ON_FPU 0 -deriv div_2_1i_rv32gc rv32gc div_2_1_rv32gc +deriv div_2_1i_rv32gc div_2_1_rv32gc IDIV_ON_FPU 1 -deriv div_2_2i_rv32gc rv32gc div_2_2_rv32gc +deriv div_2_2i_rv32gc div_2_2_rv32gc IDIV_ON_FPU 1 -deriv div_2_4i_rv32gc rv32gc div_2_4_rv32gc +deriv div_2_4i_rv32gc div_2_4_rv32gc IDIV_ON_FPU 1 -deriv div_4_1i_rv32gc rv32gc div_4_1_rv32gc +deriv div_4_1i_rv32gc div_4_1_rv32gc IDIV_ON_FPU 1 -deriv div_4_2i_rv32gc rv32gc div_4_2_rv32gc +deriv div_4_2i_rv32gc div_4_2_rv32gc IDIV_ON_FPU 1 -deriv div_4_4i_rv32gc rv32gc div_4_4_rv32gc +deriv div_4_4i_rv32gc div_4_4_rv32gc IDIV_ON_FPU 1 deriv div_2_1_rv64gc rv64gc RADIX 32'd2 DIVCOPIES 32'd1 +IDIV_ON_FPU 0 deriv div_2_2_rv64gc rv64gc RADIX 32'd2 DIVCOPIES 32'd2 +IDIV_ON_FPU 0 deriv div_2_4_rv64gc rv64gc RADIX 32'd2 DIVCOPIES 32'd4 +IDIV_ON_FPU 0 deriv div_4_1_rv64gc rv64gc RADIX 32'd4 DIVCOPIES 32'd1 +IDIV_ON_FPU 0 deriv div_4_2_rv64gc rv64gc RADIX 32'd4 DIVCOPIES 32'd2 +IDIV_ON_FPU 0 deriv div_4_4_rv64gc rv64gc RADIX 32'd4 DIVCOPIES 32'd4 +IDIV_ON_FPU 0 -deriv div_2_1i_rv64gc rv64gc div_2_1_rv64gc +deriv div_2_1i_rv64gc div_2_1_rv64gc IDIV_ON_FPU 1 -deriv div_2_2i_rv64gc rv64gc div_2_2_rv64gc +deriv div_2_2i_rv64gc div_2_2_rv64gc IDIV_ON_FPU 1 -deriv div_2_4i_rv64gc rv64gc div_2_4_rv64gc +deriv div_2_4i_rv64gc div_2_4_rv64gc IDIV_ON_FPU 1 -deriv div_4_1i_rv64gc rv64gc div_4_1_rv64gc +deriv div_4_1i_rv64gc div_4_1_rv64gc IDIV_ON_FPU 1 -deriv div_4_2i_rv64gc rv64gc div_4_2_rv64gc +deriv div_4_2i_rv64gc div_4_2_rv64gc IDIV_ON_FPU 1 -deriv div_4_4i_rv64gc rv64gc div_4_4_rv64gc +deriv div_4_4i_rv64gc div_4_4_rv64gc IDIV_ON_FPU 1 # RAM latency and Burst mode for bus stress testing @@ -242,22 +255,22 @@ BPRED_SIZE 32'd14 deriv bpred_GSHARE_16_16_10_1_rv32gc rv32gc BPRED_SIZE 32'd16 -deriv bpred_TWOBIT_6_16_10_1_rv32gc rv32gc bpred_GSHARE_6_16_10_1_rv32gc +deriv bpred_TWOBIT_6_16_10_1_rv32gc bpred_GSHARE_6_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT -deriv bpred_TWOBIT_8_16_10_1_rv32gc rv32gc bpred_GSHARE_8_16_10_1_rv32gc +deriv bpred_TWOBIT_8_16_10_1_rv32gc bpred_GSHARE_8_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT -deriv bpred_TWOBIT_10_16_10_1_rv32gc rv32gc bpred_GSHARE_10_16_10_1_rv32gc +deriv bpred_TWOBIT_10_16_10_1_rv32gc bpred_GSHARE_10_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT -deriv bpred_TWOBIT_12_16_10_1_rv32gc rv32gc bpred_GSHARE_12_16_10_1_rv32gc +deriv bpred_TWOBIT_12_16_10_1_rv32gc bpred_GSHARE_12_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT -deriv bpred_TWOBIT_14_16_10_1_rv32gc rv32gc bpred_GSHARE_14_16_10_1_rv32gc +deriv bpred_TWOBIT_14_16_10_1_rv32gc bpred_GSHARE_14_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT -deriv bpred_TWOBIT_16_16_10_1_rv32gc rv32gc bpred_GSHARE_16_16_10_1_rv32gc +deriv bpred_TWOBIT_16_16_10_1_rv32gc bpred_GSHARE_16_16_10_1_rv32gc BPRED_TYPE `BP_TWOBIT deriv bpred_GSHARE_10_2_10_1_rv32gc rv32gc @@ -272,100 +285,104 @@ RAS_SIZE 32'd4 deriv bpred_GSHARE_10_6_10_1_rv32gc rv32gc RAS_SIZE 32'd6 -deriv bpred_GSHARE_10_2_10_1_rv32gc rv32gc +deriv bpred_GSHARE_10_10_10_1_rv32gc rv32gc RAS_SIZE 32'd10 deriv bpred_GSHARE_10_16_10_1_rv32gc rv32gc RAS_SIZE 32'd16 -deriv bpred_GSHARE_10_2_6_1_rv32gc rv32gc +deriv bpred_GSHARE_10_16_6_1_rv32gc rv32gc BTB_SIZE 32'd6 -deriv bpred_GSHARE_10_2_8_1_rv32gc rv32gc +deriv bpred_GSHARE_10_16_8_1_rv32gc rv32gc BTB_SIZE 32'd8 -deriv bpred_GSHARE_10_2_12_1_rv32gc rv32gc +deriv bpred_GSHARE_10_16_12_1_rv32gc rv32gc BTB_SIZE 32'd12 -deriv bpred_GSHARE_10_2_14_1_rv32gc rv32gc +deriv bpred_GSHARE_10_16_14_1_rv32gc rv32gc BTB_SIZE 32'd14 -deriv bpred_GSHARE_10_2_16_1_rv32gc rv32gc +deriv bpred_GSHARE_10_16_16_1_rv32gc rv32gc BTB_SIZE 32'd16 -deriv bpred_GSHARE_6_16_10_0_rv32gc rv32gc bpred_GSHARE_6_16_10_1_rv32gc + + + +deriv bpred_GSHARE_6_16_10_0_rv32gc bpred_GSHARE_6_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_8_16_10_0_rv32gc rv32gc bpred_GSHARE_8_16_10_1_rv32gc +deriv bpred_GSHARE_8_16_10_0_rv32gc bpred_GSHARE_8_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_16_10_0_rv32gc rv32gc bpred_GSHARE_10_16_10_1_rv32gc +deriv bpred_GSHARE_10_16_10_0_rv32gc bpred_GSHARE_10_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_12_16_10_0_rv32gc rv32gc bpred_GSHARE_12_16_10_1_rv32gc +deriv bpred_GSHARE_12_16_10_0_rv32gc bpred_GSHARE_12_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_14_16_10_0_rv32gc rv32gc bpred_GSHARE_14_16_10_1_rv32gc +deriv bpred_GSHARE_14_16_10_0_rv32gc bpred_GSHARE_14_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_16_16_10_0_rv32gc rv32gc bpred_GSHARE_16_16_10_1_rv32gc +deriv bpred_GSHARE_16_16_10_0_rv32gc bpred_GSHARE_16_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_6_16_10_0_rv32gc rv32gc bpred_GSHARE_6_16_10_0_rv32gc +deriv bpred_TWOBIT_6_16_10_0_rv32gc bpred_TWOBIT_6_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_8_16_10_0_rv32gc rv32gc bpred_GSHARE_8_16_10_0_rv32gc +deriv bpred_TWOBIT_8_16_10_0_rv32gc bpred_TWOBIT_8_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_10_16_10_0_rv32gc rv32gc bpred_GSHARE_10_16_10_0_rv32gc +deriv bpred_TWOBIT_10_16_10_0_rv32gc bpred_TWOBIT_10_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_12_16_10_0_rv32gc rv32gc bpred_GSHARE_12_16_10_0_rv32gc +deriv bpred_TWOBIT_12_16_10_0_rv32gc bpred_TWOBIT_12_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_14_16_10_0_rv32gc rv32gc bpred_GSHARE_14_16_10_0_rv32gc +deriv bpred_TWOBIT_14_16_10_0_rv32gc bpred_TWOBIT_14_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_TWOBIT_16_16_10_0_rv32gc rv32gc bpred_GSHARE_16_16_10_0_rv32gc +deriv bpred_TWOBIT_16_16_10_0_rv32gc bpred_TWOBIT_16_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_10_0_rv32gc rv32gc bpred_GSHARE_10_2_10_1_rv32gc +deriv bpred_GSHARE_10_2_10_0_rv32gc bpred_GSHARE_10_2_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_3_10_0_rv32gc rv32gc bpred_GSHARE_10_3_10_1_rv32gc +deriv bpred_GSHARE_10_3_10_0_rv32gc bpred_GSHARE_10_3_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_4_10_0_rv32gc rv32gc bpred_GSHARE_10_4_10_1_rv32gc +deriv bpred_GSHARE_10_4_10_0_rv32gc bpred_GSHARE_10_4_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_6_10_0_rv32gc rv32gc bpred_GSHARE_10_6_10_1_rv32gc +deriv bpred_GSHARE_10_6_10_0_rv32gc bpred_GSHARE_10_6_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_10_0_rv32gc rv32gc bpred_GSHARE_10_2_10_1_rv32gc +deriv bpred_GSHARE_10_10_10_0_rv32gc bpred_GSHARE_10_10_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_16_10_0_rv32gc rv32gc bpred_GSHARE_10_16_10_1_rv32gc +deriv bpred_GSHARE_10_16_10_0_rv32gc bpred_GSHARE_10_16_10_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_6_0_rv32gc rv32gc bpred_GSHARE_10_2_6_1_rv32gc +deriv bpred_GSHARE_10_16_6_0_rv32gc bpred_GSHARE_10_16_6_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_8_0_rv32gc rv32gc bpred_GSHARE_10_2_8_1_rv32gc +deriv bpred_GSHARE_10_16_8_0_rv32gc bpred_GSHARE_10_16_8_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_12_0_rv32gc rv32gc bpred_GSHARE_10_2_12_1_rv32gc +deriv bpred_GSHARE_10_16_12_0_rv32gc bpred_GSHARE_10_16_12_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_14_0_rv32gc rv32gc bpred_GSHARE_10_2_14_1_rv32gc +deriv bpred_GSHARE_10_16_14_0_rv32gc bpred_GSHARE_10_16_14_1_rv32gc INSTR_CLASS_PRED 0 -deriv bpred_GSHARE_10_2_16_0_rv32gc rv32gc bpred_GSHARE_10_2_16_1_rv32gc +deriv bpred_GSHARE_10_16_16_0_rv32gc bpred_GSHARE_10_16_16_1_rv32gc INSTR_CLASS_PRED 0 # Cache configurations deriv noicache_rv32gc rv32gc ICACHE_SUPPORTED 0 +VIRTMEM_SUPPORTED 0 deriv nodcache_rv32gc rv32gc DCACHE_SUPPORTED 0 @@ -374,6 +391,31 @@ deriv nocache_rv32gc rv32gc ICACHE_SUPPORTED 0 DCACHE_SUPPORTED 0 +deriv noicache_rv64gc rv64gc +ICACHE_SUPPORTED 0 +VIRTMEM_SUPPORTED 0 +SVPBMT_SUPPORTED 0 +SVNAPOT_SUPPORTED 0 + +deriv nodcache_rv64gc rv64gc +DCACHE_SUPPORTED 0 +VIRTMEM_SUPPORTED 0 +ZICBOM_SUPPORTED 0 +ZICBOZ_SUPPORTED 0 +SVPBMT_SUPPORTED 0 +SVNAPOT_SUPPORTED 0 +MISA (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12) + +deriv nocache_rv64gc rv64gc +ICACHE_SUPPORTED 0 +DCACHE_SUPPORTED 0 +VIRTMEM_SUPPORTED 0 +ZICBOM_SUPPORTED 0 +ZICBOZ_SUPPORTED 0 +SVPBMT_SUPPORTED 0 +SVNAPOT_SUPPORTED 0 +MISA (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12) + deriv way_1_4096_512_rv32gc rv32gc DCACHE_NUMWAYS 32'd1 DCACHE_WAYSIZEINBYTES 32'd4096 @@ -382,40 +424,26 @@ ICACHE_NUMWAYS 32'd1 ICACHE_WAYSIZEINBYTES 32'd4096 ICACHE_LINELENINBITS 32'd512 -deriv way_2_4096_512_rv32gc rv32gc way_1_4096_512_rv32gc +deriv way_2_4096_512_rv32gc way_1_4096_512_rv32gc DCACHE_NUMWAYS 32'd1 ICACHE_NUMWAYS 32'd1 -deriv way_4_4096_512_rv32gc rv32gc way_1_4096_512_rv32gc +deriv way_4_4096_512_rv32gc way_1_4096_512_rv32gc DCACHE_NUMWAYS 32'd4 ICACHE_NUMWAYS 32'd4 -deriv way_8_4096_512_rv32gc rv32gc way_1_4096_512_rv32gc +deriv way_8_4096_512_rv32gc way_1_4096_512_rv32gc DCACHE_NUMWAYS 32'd8 ICACHE_NUMWAYS 32'd8 -deriv way_4_2048_512_rv32gc rv32gc way_4_4096_512_rv32gc +deriv way_4_2048_512_rv32gc way_4_4096_512_rv32gc DCACHE_WAYSIZEINBYTES 32'd2048 ICACHE_WAYSIZEINBYTES 32'd2048 -deriv way_4_4096_256_rv32gc rv32gc way_4_4096_512_rv32gc +deriv way_4_4096_256_rv32gc way_4_4096_512_rv32gc DCACHE_LINELENINBITS 32'd256 ICACHE_LINELENINBITS 32'd256 -deriv way_4_4096_1024_rv32gc rv32gc way_4_4096_512_rv32gc -DCACHE_LINELENINBITS 32'd1024 -ICACHE_LINELENINBITS 32'd1024 - -deriv noicache_rv64gc rv64gc -ICACHE_SUPPORTED 0 - -deriv nodcache_rv64gc rv64gc -DCACHE_SUPPORTED 0 - -deriv nocache_rv64gc rv64gc -ICACHE_SUPPORTED 0 -DCACHE_SUPPORTED 0 - deriv way_1_4096_512_rv64gc rv64gc DCACHE_NUMWAYS 32'd1 DCACHE_WAYSIZEINBYTES 32'd4096 @@ -424,27 +452,27 @@ ICACHE_NUMWAYS 32'd1 ICACHE_WAYSIZEINBYTES 32'd4096 ICACHE_LINELENINBITS 32'd512 -deriv way_2_4096_512_rv64gc rv64gc way_1_4096_512_rv64gc +deriv way_2_4096_512_rv64gc way_1_4096_512_rv64gc DCACHE_NUMWAYS 32'd1 ICACHE_NUMWAYS 32'd1 -deriv way_4_4096_512_rv64gc rv64gc way_1_4096_512_rv64gc +deriv way_4_4096_512_rv64gc way_1_4096_512_rv64gc DCACHE_NUMWAYS 32'd4 ICACHE_NUMWAYS 32'd4 -deriv way_8_4096_512_rv64gc rv64gc way_1_4096_512_rv64gc +deriv way_8_4096_512_rv64gc way_1_4096_512_rv64gc DCACHE_NUMWAYS 32'd8 ICACHE_NUMWAYS 32'd8 -deriv way_4_2048_512_rv64gc rv64gc way_4_4096_512_rv64gc +deriv way_4_2048_512_rv64gc way_4_4096_512_rv64gc DCACHE_WAYSIZEINBYTES 32'd2048 ICACHE_WAYSIZEINBYTES 32'd2048 -deriv way_4_4096_256_rv64gc rv64gc way_4_4096_512_rv64gc +deriv way_4_4096_256_rv64gc way_4_4096_512_rv64gc DCACHE_LINELENINBITS 32'd256 ICACHE_LINELENINBITS 32'd256 -deriv way_4_4096_1024_rv64gc rv64gc way_4_4096_512_rv64gc +deriv way_4_4096_1024_rv64gc way_4_4096_512_rv64gc DCACHE_LINELENINBITS 32'd1024 ICACHE_LINELENINBITS 32'd1024 @@ -490,6 +518,10 @@ deriv fh_rv32gc rv32gc MISA (32'h00000104 | 1 << 5 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0) ZFH_SUPPORTED 1 +deriv fd_rv32gc rv32gc +MISA (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0) +ZFH_SUPPORTED 0 + deriv fdh_rv32gc rv32gc MISA (32'h00000104 | 1 << 5 | 1 << 3 | 1 << 18 | 1 << 20 | 1 << 12 | 1 << 0) ZFH_SUPPORTED 1 @@ -524,32 +556,35 @@ ZFH_SUPPORTED 1 # IEEE compatible variants for TestFloat -deriv f_ieee_rv32gc rv32gc f_rv32gc +deriv f_ieee_rv32gc f_rv32gc IEEE754 1 -deriv fh_ieee_v32gc rv32gc fh_rv32gc +deriv fh_ieee_rv32gc fh_rv32gc IEEE754 1 -deriv fdh_ieee_rv32gc rv32gc fdh_rv32gc +deriv fd_ieee_rv32gc fd_rv32gc IEEE754 1 -deriv fdq_ieee_rv32gc rv32gc fdq_rv32gc +deriv fdh_ieee_rv32gc fdh_rv32gc IEEE754 1 -deriv fdqh_ieee_rv32gc rv32gc fdqh_rv32gc +deriv fdq_ieee_rv32gc fdq_rv32gc IEEE754 1 -deriv f_ieee_rv64gc rv64gc f_rv64gc +deriv fdqh_ieee_rv32gc fdqh_rv32gc IEEE754 1 -deriv fh_ieee_rv64gc rv64gc fh_rv64gc +deriv f_ieee_rv64gc f_rv64gc IEEE754 1 -deriv fd_ieee_rv64gc rv64gc fd_rv64gc +deriv fh_ieee_rv64gc fh_rv64gc IEEE754 1 -deriv fdq_ieee_rv64gc rv64gc fdq_rv64gc +deriv fd_ieee_rv64gc fd_rv64gc IEEE754 1 -deriv fdqh_ieee_rv64gc rv64gc fdqh_rv64gc +deriv fdq_ieee_rv64gc fdq_rv64gc +IEEE754 1 + +deriv fdqh_ieee_rv64gc fdqh_rv64gc IEEE754 1 diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index 8b4b78a4f..843f55530 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -154,22 +154,11 @@ localparam PLIC_SPI_ID = 32'd6; localparam PLIC_SDC_ID = 32'd9; localparam BPRED_SUPPORTED = 1; -// this is an annoying hack for the branch predictor parameterization override. -`ifdef BPRED_OVERRIDE -localparam BPRED_TYPE = `BPRED_TYPE; -localparam BPRED_SIZE = `BPRED_SIZE; -`else localparam BPRED_TYPE = `BP_GSHARE; // BP_GSHARE_BASIC, BP_GLOBAL, BP_GLOBAL_BASIC, BP_TWOBIT localparam BPRED_SIZE = 32'd10; -`endif localparam BPRED_NUM_LHR = 32'd6; -`ifdef BTB_OVERRIDE -localparam BTB_SIZE = `BTB_SIZE; -localparam RAS_SIZE = `RAS_SIZE; -`else localparam BTB_SIZE = 32'd10; localparam RAS_SIZE = 32'd16; -`endif localparam INSTR_CLASS_PRED = 1; localparam SVADU_SUPPORTED = 1; diff --git a/config/shared/config-shared.vh b/config/shared/config-shared.vh index ba215785c..be5543967 100644 --- a/config/shared/config-shared.vh +++ b/config/shared/config-shared.vh @@ -103,15 +103,15 @@ localparam RESBITS = DIVMINb + LOGR; // number of bits in a result: r intege localparam FPDUR = (RESBITS-1)/RK + 1 ; // ceiling((r+b)/rk) localparam DIVb = FPDUR*RK - LOGR; // divsqrt fractional bits, so total number of bits is a multiple of rk after r integer bits localparam DURLEN = $clog2(FPDUR); // enough bits to count the duration -localparam DIVBLEN = $clog2(DIVb); // enough bits to count number of fractional bits +localparam DIVBLEN = $clog2(DIVb+1); // enough bits to count number of fractional bits + 1 integer bit // largest length in IEU/FPU localparam CVTLEN = ((NF(DIVb + 1 +NF+1) & (CVTLEN+NF+1)>(3*NF+6)) ? (CVTLEN+NF+1) : ((DIVb + 1 +NF+1) > (3*NF+6) ? (DIVb + 1 +NF+1) : (3*NF+6))); +localparam NORMSHIFTSZ = (((CVTLEN+NF+1)>(DIVb + 1 +NF+1) & (CVTLEN+NF+1)>(3*NF+6)) ? (CVTLEN+NF+1) : ((DIVb + 1 +NF+1) > (3*NF+6) ? (DIVb + 1 +NF+1) : (3*NF+6))); // max(CVTLEN+NF+1, DIVb + 1 + NF + 1, 3*NF+6) localparam LOGNORMSHIFTSZ = ($clog2(NORMSHIFTSZ)); -localparam CORRSHIFTSZ = (((DIVMINb+1+NF) > (3*NF+4) ? (DIVMINb+1+NF) : (3*NF+4))); // max(DIVMINb+NF+1, 3*NF+4) +localparam CORRSHIFTSZ = (NORMSHIFTSZ-2 > (DIVMINb + 1 + NF)) ? NORMSHIFTSZ-2 : (DIVMINb+1+NF); // max(NORMSHIFTSZ-2, DIVMINb + 1 + NF) // Disable spurious Verilator warnings diff --git a/fpga/generator/Makefile b/fpga/generator/Makefile index 179926218..e6807a6a6 100644 --- a/fpga/generator/Makefile +++ b/fpga/generator/Makefile @@ -48,29 +48,14 @@ IP_Arty: $(dst)/xlnx_proc_sys_reset.log \ PreProcessFiles: + $(MAKE) -C ../../sim deriv rm -rf ../src/CopiedFiles_do_not_add_to_repo/ cp -r ../../src/ ../src/CopiedFiles_do_not_add_to_repo/ mkdir ../src/CopiedFiles_do_not_add_to_repo/config/ - cp ../../config/rv64gc/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/ + cp ../../config/deriv/fpga/config.vh ../src/CopiedFiles_do_not_add_to_repo/config/ ./insert_debug_comment.sh # modify config *** RT: eventually setup for variably defined sized memory - sed -i "s/ZICCLSM_SUPPORTED.*/ZICCLSM_SUPPORTED = 1;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/RESET_VECTOR.*/RESET_VECTOR = 64'h0000000000001000;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/BOOTROM_PRELOAD.*/BOOTROM_PRELOAD = 1'b1;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/UNCORE_RAM_BASE.*/UNCORE_RAM_BASE = 64'h00002000;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE = 64'h00000FFF;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/UNCORE_RAM_PRELOAD.*/UNCORE_RAM_PRELOAD = 1'b1;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/EXT_MEM_SUPPORTED.*/EXT_MEM_SUPPORTED = 1'b1;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/EXT_MEM_RANGE.*/EXT_MEM_RANGE = 64'h0FFFFFFF;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/SDC_SUPPORTED.*/SDC_SUPPORTED = 1'b1;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/SPI_SUPPORTED.*/SPI_SUPPORTED = 1'b0;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh # *** RT: Add SPI when ready - sed -i "s/GPIO_LOOPBACK_TEST.*/GPIO_LOOPBACK_TEST = 0;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/SPI_LOOPBACK_TEST.*/SPI_LOOPBACK_TEST = 0;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/UART_PRESCALE.*/UART_PRESCALE = 32'd0;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/PLIC_NUM_SRC = .*/PLIC_NUM_SRC = 32'd53;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/PLIC_SDC_ID.*/PLIC_SDC_ID = 32'd20;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/BPRED_SIZE.*/BPRED_SIZE = 32'd12;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh - sed -i "s/$\$readmemh.*/$\$readmemh(\"..\/..\/..\/fpga\/src\/boot.mem\", ROM, 0);/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv + #sed -i "s/EXT_MEM_RANGE.*/EXT_MEM_RANGE = 64'h0FFFFFFF;/g" ../src/CopiedFiles_do_not_add_to_repo/config/config.vh # This line allows the Bootloader to be loaded in a Block RAM on the FPGA sed -i "s/logic \[DATA_WIDTH-1:0\].*ROM.*/(\* rom_style=\"block\" \*) &/g" ../src/CopiedFiles_do_not_add_to_repo/generic/mem/rom1p1r.sv diff --git a/linux/sdcard/flash-sd.sh b/linux/sdcard/flash-sd.sh index 73c9e1b9e..a636f3d60 100755 --- a/linux/sdcard/flash-sd.sh +++ b/linux/sdcard/flash-sd.sh @@ -72,6 +72,13 @@ if [ ! -e "$SDCARD" ] ; then exit 1 fi +# Prefix partition with "p" for non-SCSI disks (mmcblk, nvme) +if [[ $SDCARD == "/dev/sd"* ]]; then + $PART_PREFIX="" +else + $PART_PREFIX="p" +fi + # If no images directory, images have not been built if [ ! -d $IMAGES ] ; then echo -e "$ERRORTEXT Buildroot images directory does not exist" @@ -155,18 +162,18 @@ if [[ $REPLY =~ ^[Yy]$ ]] ; then DD_FLAGS="bs=4k iflag=fullblock oflag=direct conv=fsync status=progress" echo -e "$NAME Copying device tree" - sudo dd if=$DEVICE_TREE of="$SDCARD"1 $DD_FLAGS + sudo dd if=$DEVICE_TREE of="$SDCARD""$PART_PREFIX"1 $DD_FLAGS echo -e "$NAME Copying OpenSBI" - sudo dd if=$FW_JUMP of="$SDCARD"2 $DD_FLAGS + sudo dd if=$FW_JUMP of="$SDCARD""$PART_PREFIX"2 $DD_FLAGS echo -e "$NAME Copying Kernel" - sudo dd if=$LINUX_KERNEL of="$SDCARD"3 $DD_FLAGS + sudo dd if=$LINUX_KERNEL of="$SDCARD""$PART_PREFIX"3 $DD_FLAGS - sudo mkfs.ext4 "$SDCARD"4 + sudo mkfs.ext4 "$SDCARD""$PART_PREFIX"4 sudo mkdir /mnt/$MNT_DIR - sudo mount -v "$SDCARD"4 /mnt/$MNT_DIR + sudo mount -v "$SDCARD""$PART_PREFIX"4 /mnt/$MNT_DIR sudo umount -v /mnt/$MNT_DIR diff --git a/sim/Makefile b/sim/Makefile index d7d259632..b23d1cb47 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -1,5 +1,5 @@ -all: riscoftests memfiles coveragetests deriv +all: riscoftests memfiles coveragetests deriv benchmarks # *** Build old tests/imperas-riscv-tests for now; # Delete this part when the privileged tests transition over to tests/wally-riscv-arch-test # DH: 2/27/22 temporarily commented out imperas-riscv-tests because license expired @@ -54,7 +54,7 @@ riscoftests: wallyriscoftests: # Builds riscv-arch-test 64 and 32-bit versions and builds wally-riscv-arch-test 64 and 32-bit versions make -C ../tests/riscof/ wally-riscv-arch-test - + memfiles: make -f makefile-memfile wally-sim-files --jobs @@ -63,4 +63,10 @@ coveragetests: deriv: derivgen.pl - \ No newline at end of file + +benchmarks: + $(MAKE) -C ../benchmarks/embench build + $(MAKE) -C ../benchmarks/embench size + $(MAKE) -C ../benchmarks/embench modelsim_build_memfile + $(MAKE) -C ../benchmarks/coremark + diff --git a/sim/bp-results/branch-list.txt b/sim/bp-results/branch-list.txt index 956fc9847..10827b3b9 100644 --- a/sim/bp-results/branch-list.txt +++ b/sim/bp-results/branch-list.txt @@ -1,12 +1,12 @@ -../logs/rv32gc_gshare6.log gshare 6 -../logs/rv32gc_gshare8.log gshare 8 -../logs/rv32gc_gshare10.log gshare 10 -../logs/rv32gc_gshare12.log gshare 12 -../logs/rv32gc_gshare14.log gshare 14 -../logs/rv32gc_gshare16.log gshare 16 -../logs/rv32gc_twobit6.log twobit 6 -../logs/rv32gc_twobit8.log twobit 8 -../logs/rv32gc_twobit10.log twobit 10 -../logs/rv32gc_twobit12.log twobit 12 -../logs/rv32gc_twobit14.log twobit 14 -../logs/rv32gc_twobit16.log twobit 16 +../logs/bpred_GSHARE_6_16_10_0_rv32gc_embench.log gshare 6 +../logs/bpred_GSHARE_8_16_10_0_rv32gc_embench.log gshare 8 +../logs/bpred_GSHARE_10_16_10_0_rv32gc_embench.log gshare 10 +../logs/bpred_GSHARE_12_16_10_0_rv32gc_embench.log gshare 12 +../logs/bpred_GSHARE_14_16_10_0_rv32gc_embench.log gshare 14 +../logs/bpred_GSHARE_16_16_10_0_rv32gc_embench.log gshare 16 +../logs/bpred_TWOBIT_6_16_10_0_rv32gc_embench.log twobit 6 +../logs/bpred_TWOBIT_8_16_10_0_rv32gc_embench.log twobit 8 +../logs/bpred_TWOBIT_10_16_10_0_rv32gc_embench.log twobit 10 +../logs/bpred_TWOBIT_12_16_10_0_rv32gc_embench.log twobit 12 +../logs/bpred_TWOBIT_14_16_10_0_rv32gc_embench.log twobit 14 +../logs/bpred_TWOBIT_16_16_10_0_rv32gc_embench.log twobit 16 diff --git a/sim/bp-results/btb-list.txt b/sim/bp-results/btb-list.txt index 30811459e..a4671ba9f 100644 --- a/sim/bp-results/btb-list.txt +++ b/sim/bp-results/btb-list.txt @@ -1,6 +1,6 @@ -../logs/rv32gc_BTB6.log btb 6 -../logs/rv32gc_BTB8.log btb 8 -../logs/rv32gc_BTB10.log btb 10 -../logs/rv32gc_BTB12.log btb 12 -../logs/rv32gc_BTB14.log btb 14 -../logs/rv32gc_BTB16.log btb 16 +../logs/bpred_GSHARE_16_16_6_0_rv32gc_embench.log btb 6 +../logs/bpred_GSHARE_16_16_8_0_rv32gc_embench.log btb 8 +../logs/bpred_GSHARE_16_16_10_0_rv32gc_embench.log btb 10 +../logs/bpred_GSHARE_16_16_12_0_rv32gc_embench.log btb 12 +../logs/bpred_GSHARE_16_16_14_0_rv32gc_embench.log btb 14 +../logs/bpred_GSHARE_16_16_16_0_rv32gc_embench.log btb 16 diff --git a/sim/bp-results/class-list.txt b/sim/bp-results/class-list.txt index 3926af969..0be63e91a 100644 --- a/sim/bp-results/class-list.txt +++ b/sim/bp-results/class-list.txt @@ -1,6 +1,6 @@ -../logs/rv32gc_class6.log class 6 -../logs/rv32gc_class8.log class 8 -../logs/rv32gc_class10.log class 10 -../logs/rv32gc_class12.log class 12 -../logs/rv32gc_class14.log class 14 -../logs/rv32gc_class16.log class 16 +../logs/bpred_GSHARE_16_16_6_1_rv32gc_embench.log btb 6 +../logs/bpred_GSHARE_16_16_8_1_rv32gc_embench.log btb 8 +../logs/bpred_GSHARE_16_16_10_1_rv32gc_embench.log btb 10 +../logs/bpred_GSHARE_16_16_12_1_rv32gc_embench.log btb 12 +../logs/bpred_GSHARE_16_16_14_1_rv32gc_embench.log btb 14 +../logs/bpred_GSHARE_16_16_16_1_rv32gc_embench.log btb 16 diff --git a/sim/bp-results/ras-list.txt b/sim/bp-results/ras-list.txt index c7628ffaa..c9246b14d 100644 --- a/sim/bp-results/ras-list.txt +++ b/sim/bp-results/ras-list.txt @@ -1,5 +1,5 @@ -../logs/rv32gc_RAS3.log ras 3 -../logs/rv32gc_RAS4.log ras 4 -../logs/rv32gc_RAS6.log ras 6 -../logs/rv32gc_RAS10.log ras 10 -../logs/rv32gc_RAS16.log ras 16 +../logs/bpred_GSHARE_10_3_10_0_rv32gc_embench.log ras 3 +../logs/bpred_GSHARE_10_4_10_0_rv32gc_embench.log ras 4 +../logs/bpred_GSHARE_10_6_10_0_rv32gc_embench.log ras 6 +../logs/bpred_GSHARE_10_10_10_0_rv32gc_embench.log ras 10 +../logs/bpred_GSHARE_10_16_10_0_rv32gc_embench.log ras 16 diff --git a/sim/coverage-exclusions-rv64gc.do b/sim/coverage-exclusions-rv64gc.do index b6eb0214f..1880d870f 100644 --- a/sim/coverage-exclusions-rv64gc.do +++ b/sim/coverage-exclusions-rv64gc.do @@ -58,11 +58,12 @@ coverage exclude -scope /dut/core/fpu/fpu/postprocess/flags -linerange [GetLineN # This is cleaner than trying to set an I$-specific pragma in cachefsm.sv (which would exclude it for the D$ instance too) # Also exclude the write line to ready transition for the I$ since we can't get a flush during this operation. coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -fstate CurrState STATE_FLUSH STATE_FLUSH_WRITEBACK STATE_FLUSH_WRITEBACK STATE_WRITEBACK -coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -ftrans CurrState STATE_WRITE_LINE->STATE_READY STATE_FETCH->STATE_READY # exclude unused transitions from case statement. Unfortunately the whole branch needs to be excluded I think. Expression coverage should still work. coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache state-case"] -item b 1 # exclude branch/condition coverage: LineDirty if statement coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache FETCHStatement"] -item bc 1 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache FLUSHStatement"] -item bs 1 # exclude the unreachable logic set start [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-start: icache case"] set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache case"] @@ -81,7 +82,9 @@ set end [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag-end: icache flushdir coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange $start-$end coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusW"] coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache SelAdrCauses"] -item e 1 -fecexprrow 4 10 +coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache SelAdrTag"] -item e 1 -fecexprrow 8 coverage exclude -scope /dut/core/ifu/bus/icache/icache/cachefsm -linerange [GetLineNum ../src/cache/cachefsm.sv "exclusion-tag: icache CacheBusRCauses"] -item e 1 -fecexprrow 1-2 12 + # cache.sv AdrSelMuxData and AdrSelMuxTag and CacheBusAdrMux, excluding unhit Flush branch coverage exclude -scope /dut/core/ifu/bus/icache/icache/AdrSelMuxData -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 coverage exclude -scope /dut/core/ifu/bus/icache/icache/AdrSelMuxTag -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 @@ -100,6 +103,26 @@ for {set i 0} {$i < $numcacheways} {incr i} { # No dirty ways in read-only I$ coverage exclude -scope /dut/core/ifu/bus/icache/icache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "// exclusion-tag: icache DirtyWay"] -item e 1 } +# I$ buscachefsm does not perform atomics or write/writeback; HREADY is always 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicReadData"] +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicElse"] -item s 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicPhase"] +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicWait"] -item bs 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm FetchWriteback"] -item b 2 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm FetchWriteback"] -item s 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm WritebackWriteback"] +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm WritebackWriteback2"] -item bs 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY4"] -item bs 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY6"] -item bs 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADYread"] -item c 1 -feccondrow 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm FetchWriteback"] -item c 1 -feccondrow 1,2,3,4,6 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY4"] -item c 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY6"] -item c 1 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign HTRANS"] -item c 1 -feccondrow 5 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign BeatCntEn"] -item e 1 -fecexprrow 4 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign CacheAccess"] -item e 1 -fecexprrow 4 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign BusStall"] -item e 1 -fecexprrow 10,12,18 +coverage exclude -scope /dut/core/ifu/bus/icache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign CacheBusAck"] -item e 1 -fecexprrow 3 ## D$ Exclusions. # InvalidateCache is I$ only: @@ -117,10 +140,10 @@ for {set i 0} {$i < $numcacheways} {incr i} { # going into the WRITE_LINE state (and asserting SetValidWay). No TrapM can fire and since StallW is high, a stallM caused by WFIStallM would not cause a flushW. coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache SetValidEN"] -item e 1 -fecexprrow 4 coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache ClearValidEN"] -item e 1 -fecexprrow 4 -# Not right; other ways can get flushed and dirtied simultaneously coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache UpdateDirty"] -item c 1 -fecexprrow 6 +# Not right; other ways can get flushed and dirtied simultaneously coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/CacheWays[$i] -linerange [GetLineNum ../src/cache/cacheway.sv "exclusion-tag: cache UpdateDirty"] -item c 1 -feccondrow 6 } # D$ writeback, flush, write_line, or flush_writeback states can't be cancelled by a flush -coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/cachefsm -ftrans CurrState STATE_WRITEBACK->STATE_READY STATE_FLUSH->STATE_READY STATE_WRITE_LINE->STATE_READY STATE_FLUSH_WRITEBACK->STATE_READY +coverage exclude -scope /dut/core/lsu/bus/dcache/dcache/cachefsm -ftrans CurrState STATE_WRITEBACK->STATE_READY STATE_FLUSH->STATE_READY STATE_WRITE_LINE->STATE_READY STATE_FLUSH_WRITEBACK->STATE_READY #################### # Unused / illegal peripheral accesses @@ -136,7 +159,13 @@ coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/iromdec coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/ddr4dec coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/sdcdec -# PMA Regions 8, 9, and 10 (dtim, irom, ddr4) are never used in the rv64gc configuration, so exclude coverage +# PMA Regions 1, 2, and 3 (dtim, irom, ddr4) are never used in the rv64gc configuration, so exclude coverage +set line [GetLineNum ../src/mmu/pmachecker.sv "exclusion-tag: unused-atomic"] +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2,4 +coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2,4 +set line [GetLineNum ../src/mmu/pmachecker.sv "exclusion-tag: unused-tim"] +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2,4 +coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2,4 set line [GetLineNum ../src/mmu/pmachecker.sv "exclusion-tag: unused-cachable"] coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2 coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2 @@ -145,11 +174,17 @@ coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker -linerange $line-$lin coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker -linerange $line-$line -item e 1 -fecexprrow 2,4,6,8 # Excluding so far un-used instruction sources for the ifu -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/bootromdec -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/uncoreramdec +coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/bootromdec +coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/uncoreramdec +coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/spidec -#Excluding the bootrom, uncoreran, and clint as sources for the lsu -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/bootromdec +# The following peripherals are always supported +set line [GetLineNum ../src/mmu/adrdec.sv "exclusion-tag: adrdecSel"] +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/bootromdec -linerange $line-$line -item e 1 -fecexprrow 3,7 +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/gpiodec -linerange $line-$line -item e 1 -fecexprrow 3 +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/uartdec -linerange $line-$line -item e 1 -fecexprrow 3 +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/plicdec -linerange $line-$line -item e 1 -fecexprrow 3 +coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/spidec -linerange $line-$line -item e 1 -fecexprrow 3 #Excluding signals in lsu: clintdec and uncoreram accept all sizes so 'SizeValid' will never be 0 set line [GetLineNum ../src/mmu/adrdec.sv "& SizeValid"] @@ -158,22 +193,15 @@ set line [GetLineNum ../src/mmu/adrdec.sv "& SizeValid"] coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/uncoreramdec -linerange $line-$line -item e 1 -fecexprrow 5 # set line [GetLineNum ../src/mmu/adrdec.sv "& Supported"] -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/dtimdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/iromdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/ddr4dec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/gpiodec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/uartdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/plicdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/sdcdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/dtimdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/iromdec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/ddr4dec -linerange $line-$line -item e 1 -fecexprrow 3 -# coverage exclude -scope /dut/core/ifu/immu/immu/pmachecker/adrdecs/sdcdec -linerange $line-$line -item e 1 -fecexprrow 3 coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/dtimdec coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/iromdec coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/ddr4dec coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmachecker/adrdecs/sdcdec +# No DTIM or IROM +coverage exclude -scope /dut/core/ifu/bus/icache/UnCachedDataMux -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 +coverage exclude -scope /dut/core/lsu/bus/dcache/UnCachedDataMux -linerange [GetLineNum ../src/generic/mux.sv "exclusion-tag: mux3"] -item b 1 + #################### # Unused access types due to sharing IFU and LSU logic #################### @@ -216,6 +244,10 @@ set line [GetLineNum ../src/mmu/mmu.sv "ExecuteAccessF \\| ReadAccessM"] coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line -item e 1 -fecexprrow 1,3,4 set line [GetLineNum ../src/mmu/mmu.sv "ReadAccessM & ~WriteAccessM"] coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line -item e 1 -fecexprrow 2-4 +set line [GetLineNum ../src/mmu/mmu.sv "assign AmoAccessM"] +coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line -item e 1 +set line [GetLineNum ../src/mmu/mmu.sv "assign AmoMisalignedCausesAccessFaultM"] +coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line -item e 1 set line [GetLineNum ../src/mmu/mmu.sv "DataMisalignedM & WriteAccessM"] coverage exclude -scope /dut/core/ifu/immu/immu -linerange $line-$line -item e 1 -fecexprrow 1,2,4 set line [GetLineNum ../src/mmu/mmu.sv "TLBPageFault & ExecuteAccessF"] @@ -308,6 +340,56 @@ coverage exclude -scope /dut/core/ebu/ebu/ebufsmarb -linerange $line-$line -item set line [GetLineNum ../src/ebu/ebufsmarb.sv "FinalBeatReg\\("] coverage exclude -scope /dut/core/ebu/ebu/ebufsmarb -linerange $line-$line -item e 1 -fecexprrow 1 +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicElse"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item bc 1 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicWait"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item bc 1 + +# The WritebackWriteback and FetchWriteback support back to back pipelined cache writebacks and fetch then +# writebacks. The cache never issues these type of requests. +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm WritebackWriteback"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item bc 2 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm FetchWriteback"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item bc 2 + +# FetchWait never occurs because HREADY is never 0. +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm FetchWait"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item bc 1 + +# all of these HREADY exclusions occur because HREADY is always 1. The ram_ahb module never stalls. +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY0"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 + +#set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY1"] +#coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 + +#set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY2"] +#coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY3"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 4 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY4"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 3 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY5"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 + +set line [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm HREADY6"] +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 1 +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange $line-$line -item c 1 -feccondrow 5 + +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "assign CacheBusAck"] -item e 1 -fecexprrow 5 + +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicElse"] -item s 1 +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -linerange [GetLineNum ../src/ebu/buscachefsm.sv "exclusion-tag: buscachefsm AtomicWait"] -item s 1 + +# these transitions will not happen +coverage exclude -scope /dut/core/lsu/bus/dcache/ahbcacheinterface/AHBBuscachefsm -ftrans CurrState DATA_PHASE->ADR_PHASE ATOMIC_READ_DATA_PHASE->ADR_PHASE ATOMIC_PHASE->ADR_PHASE + # TLB not recently used never has all RU bits = 1 because it will then clear all to 0 # This is a blunt instrument; perhaps there is a more graceful exclusion coverage exclude -srcfile priorityonehot.sv @@ -316,6 +398,13 @@ coverage exclude -srcfile priorityonehot.sv coverage exclude -scope /dut/core/ifu/immu/immu/pmp/pmpchecker/pmp/pmpadrdecs[0] -linerange [GetLineNum ../src/mmu/pmpadrdec.sv "exclusion-tag: PAgePMPAdrIn"] -item e 1 -fecexprrow 1 coverage exclude -scope /dut/core/lsu/dmmu/dmmu/pmp/pmpchecker/pmp/pmpadrdecs[0] -linerange [GetLineNum ../src/mmu/pmpadrdec.sv "exclusion-tag: PAgePMPAdrIn"] -item e 1 -fecexprrow 1 +#################### +# Privileged +#################### + +# Instruction Misaligned never asserted because compresssed instructions are accepted +coverage exclude -scope /dut/core/priv/priv/trap -linerange [GetLineNum ../src/privileged/trap.sv "assign ExceptionM"] -item e 1 -fecexprrow 2 + #################### # EBU #################### diff --git a/sim/lint-wally b/sim/lint-wally index 3d28a62ec..5964d20ed 100755 --- a/sim/lint-wally +++ b/sim/lint-wally @@ -6,26 +6,43 @@ export PATH=$PATH:/usr/local/bin/ verilator=`which verilator` basepath=$(dirname $0)/.. +RED='\033[0;31m' +GREEN='\033[0;32m' +NC='\033[0m' # No Color +fails=0 if [ "$1" == "-nightly" ]; then configs=(rv32e rv64gc rv32gc rv32imc rv32i rv64i) # fdqh_rv64gc derivconfigs=`ls $WALLY/config/deriv` for entry in $derivconfigs do - configs[${#configs[@]}]=$entry + if [[ $entry != *"syn_sram"* ]]; then # ignore syn_sram* configs that contain undefined module + configs[${#configs[@]}]=$entry + fi done else - configs=(rv32e rv64gc rv32gc rv32imc rv32i rv64i fdqh_rv64gc) + configs=(rv32e rv64gc rv32gc rv32imc rv32i rv64i div_2_1i_rv64gc ) # add fdqh_rv64gc when working fi for config in ${configs[@]}; do - echo "$config linting..." +# echo "$config linting..." if !($verilator --no-timing --lint-only --top-module wallywrapper "-I$basepath/config/shared" "-I$basepath/config/$config" "-I$basepath/config/deriv/$config" $basepath/src/cvw.sv $basepath/testbench/wallywrapper.sv $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes ); then - echo "Exiting after $config lint due to errors or warnings" - exit 1 + if [ "$1" == "-nightly" ]; then + echo -e "${RED}$config failed lint${NC}" + fails=$((fails+1)) + else + echo -e "${RED}$config fails with lint errors or warnings" + exit 1 + fi + else + echo -e "${GREEN}$config passed lint${NC}" fi done -echo "All lints run with no errors or warnings" +if [ $fails -gt 0 ]; then + echo -e "${RED}Linting failed for $fails of ${#configs[@]} configurations" + exit 1 +fi +echo -e "${GREEN}All ${#configs[@]} lints run with no errors or warnings" # --lint-only just runs lint rather than trying to compile and simulate # -I points to the include directory where files such as `include config.vh are found diff --git a/sim/regression-wally b/sim/regression-wally index 07c3774ed..d06ac0b28 100755 --- a/sim/regression-wally +++ b/sim/regression-wally @@ -11,6 +11,9 @@ # ################################## import sys,os,shutil +import multiprocessing + + class bcolors: HEADER = '\033[95m' @@ -51,7 +54,7 @@ else: name="lints", variant="all", cmd="./lint-wally " + nightMode + " | tee {}", - grepstr="All lints run with no errors or warnings" + grepstr="lints run with no errors or warnings" ) ] @@ -69,7 +72,7 @@ def getBuildrootTC(boot): BRcmd="vsim > {} -c < {} -c < {} -c < {} -c < XLEN +# ["nodcache_rv32gc", ["ahb32"]], +# ["nocache_rv32gc", ["ahb32"]], + ["noicache_rv64gc", ["ahb64"]], + ["nodcache_rv64gc", ["ahb64"]], + ["nocache_rv64gc", ["ahb64"]], + + ### add misaligned tests + ["div_2_1_rv32gc", ["arch32f_divsqrt", "arch32d_divsqrt", "arch32m"]], ["div_2_1i_rv32gc", ["arch32f_divsqrt", "arch32d_divsqrt", "arch32m"]], ["div_2_2_rv32gc", ["arch32f_divsqrt", "arch32d_divsqrt", "arch32m"]], @@ -215,15 +219,83 @@ if (nightly): ["div_4_4_rv64gc", ["arch64f_divsqrt", "arch64d_divsqrt", "arch64m"]], ["div_4_4i_rv64gc", ["arch64f_divsqrt", "arch64d_divsqrt", "arch64m"]], + ### branch predictor simulation + + ["bpred_TWOBIT_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_TWOBIT_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + + ["bpred_GSHARE_6_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_6_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_8_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_8_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_12_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_12_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_14_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_14_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_16_16_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_16_16_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + + # btb + ["bpred_GSHARE_10_16_6_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_6_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_8_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_8_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_12_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_16_12_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + + # ras + ["bpred_GSHARE_10_2_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_2_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_3_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_3_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_4_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_4_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_6_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_6_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_10_10_0_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + ["bpred_GSHARE_10_10_10_1_rv32gc", ["embench"], "configOptions", "-GPrintHPMCounters=1"], + + +# enable floating-point tests when lint is fixed +# ["f_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma"]], +# ["fh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32zfh", "arch32zfh_divsqrt"]], +# ["fdh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]], +# ["fdq_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]], +# ["fdqh_rv32gc", ["arch32f", "arch32f_divsqrt", "arch32f_fma", "arch32d", "arch32d_divsqrt", "arch32d_fma", "arch32zfh", "arch32zfh_divsqrt"]], +# ["f_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma"]], +# ["fh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64zfh", "arch64zfh_divsqrt"]], # hanging 1/31/24 dh; try again when lint is fixed +# ["fdh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]], +# ["fdq_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]], +# ["fdqh_rv64gc", ["arch64f", "arch64f_divsqrt", "arch64f_fma", "arch64d", "arch64d_divsqrt", "arch64d_fma", "arch64zfh", "arch64zfh_divsqrt"]], + + ] for test in derivconfigtests: config = test[0]; tests = test[1]; + if(len(test) >= 4 and test[2] == "configOptions"): + configOptions = test[3] + cmdPrefix = "vsim > {} -c < {} -c < {} -c < $argc} break + set arg [expr "$$x"] + lappend lst $arg +} + if {$argc >= 3} { if {$3 eq "-coverage" || ($argc >= 7 && $7 eq "-coverage")} { set coverage 1 + set CoverageVoptArg "+cover=sbecf" + set CoverageVsimArg "-coverage" + } elseif {$3 eq "configOptions"} { + set configOptions $lst + puts $configOptions } } @@ -58,91 +65,20 @@ if {$argc >= 3} { # default to config/rv64ic, but allow this to be overridden at the command line. For example: # do wally-pipelined-batch.do ../config/rv32imc rv32imc -if {$2 eq "buildroot"} { - vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation - if { $coverage } { - echo "wally-batch buildroot coverage" - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -o testbenchopt +cover=sbecf - vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 -cover - } else { - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -o testbenchopt - vsim -lib wkdir/work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3691,13286 -fatal 7 - } - run -all - run -all - exec ./slack-notifier/slack-notifier.py -} elseif {$2 eq "buildroot-no-trace"} { - vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation - vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G NO_SPOOFING=1 -o testbenchopt - vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 +vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 - #-- Run the Simulation - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - echo "Don't forget to change DEBUG_LEVEL = 0." - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" - run -all - run -all - exec ./slack-notifier/slack-notifier.py +# start and run simulation +# remove +acc flag for faster sim during regressions if there is no need to access internal signals +vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 ${configOptions} -o testbenchopt ${CoverageVoptArg} +vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 ${CoverageVsimArg} -} elseif {$2 eq "ahb"} { - vlog -lint -work wkdir/work_${1}_${2}_${3}_${4} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 +define+RAM_LATENCY=$3 +define+BURST_EN=$4 - # start and run simulation - # remove +acc flag for faster sim during regressions if there is no need to access internal signals - vopt wkdir/work_${1}_${2}_${3}_${4}.testbench -work wkdir/work_${1}_${2}_${3}_${4} -G TEST=$2 -o testbenchopt - vsim -lib wkdir/work_${1}_${2}_${3}_${4} testbenchopt -fatal 7 - # Adding coverage increases runtime from 2:00 to 4:29. Can't run it all the time - #vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf - #vsim -coverage -lib work_$2 workopt_$2 - - # power add generates the logging necessary for said generation. - # power add -r /dut/core/* - run -all - # power off -r /dut/core/* - -} elseif {$2 eq "configOptions"} { - # set arguments " " - # for {set i 5} {$i <= $argc} {incr i} { - # append arguments "\$$i " - # } - # puts $arguments - # set options eval $arguments - # **** fix this so we can pass any number of +defines. - # only allows 3 right now - - vlog -lint -work wkdir/work_${1}_${3}_${4} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 $5 $6 $7 - # start and run simulation - # remove +acc flag for faster sim during regressions if there is no need to access internal signals - vopt wkdir/work_${1}_${3}_${4}.testbench -work wkdir/work_${1}_${3}_${4} -G TEST=$4 -o testbenchopt - vsim -lib wkdir/work_${1}_${3}_${4} testbenchopt -fatal 7 -suppress 3829 - # Adding coverage increases runtime from 2:00 to 4:29. Can't run it all the time - #vopt work_$2.testbench -work work_$2 -o workopt_$2 +cover=sbectf - #vsim -coverage -lib work_$2 workopt_$2 - # power add generates the logging necessary for said generation. - # power add -r /dut/core/* - run -all - # power off -r /dut/core/* - -} else { - vlog -lint -work wkdir/work_${1}_${2} +incdir+../config/$1 +incdir+../config/deriv/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 -suppress 7063,2596,13286 - # start and run simulation - # remove +acc flag for faster sim during regressions if there is no need to access internal signals - if {$coverage} { -# vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt +cover=sbectf - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt +cover=sbecf - vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 -coverage - } else { - vopt wkdir/work_${1}_${2}.testbench -work wkdir/work_${1}_${2} -G TEST=$2 -o testbenchopt - vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 - } # vsim -lib wkdir/work_${1}_${2} testbenchopt -fatal 7 -suppress 3829 - # power add generates the logging necessary for said generation. - # power add -r /dut/core/* - run -all - # power off -r /dut/core/* -} +# power add generates the logging necessary for said generation. +# power add -r /dut/core/* +run -all +# power off -r /dut/core/* + if {$coverage} { echo "Saving coverage to ${1}_${2}.ucdb" diff --git a/sim/wally-linux-imperas.do b/sim/wally-linux-imperas.do index e9bad30d5..1165676a0 100644 --- a/sim/wally-linux-imperas.do +++ b/sim/wally-linux-imperas.do @@ -32,25 +32,10 @@ vlib work # start and run simulation # remove +acc flag for faster sim during regressions if there is no need to access internal signals -if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { - vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation - vopt work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=$4 -G INSTR_WAVEON=$5 -G CHECKPOINT=$6 -G NO_SPOOFING=0 -o testbenchopt - vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 - - #-- Run the Simulation - #run -all - run 7000 ms - add log -recursive /* - do linux-wave.do - run -all - - exec ./slack-notifier/slack-notifier.py - -} elseif {$2 eq "buildroot-no-trace"} { +if {$2 eq "buildroot"} { vlog -lint -work work_${1}_${2} \ +define+USE_IMPERAS_DV \ - +incdir+../config/$1 \ + +incdir+../config/deriv/$1 \ +incdir+../config/shared \ +incdir+$env(IMPERAS_HOME)/ImpPublic/include/host \ +incdir+$env(IMPERAS_HOME)/ImpProprietary/include/host \ @@ -64,7 +49,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2cov.sv \ $env(IMPERAS_HOME)/ImpProprietary/source/host/idv/trace2bin.sv \ ../src/cvw.sv \ - ../testbench/testbench-linux-imperas.sv \ + ../testbench/testbench.sv \ ../testbench/common/*.sv ../src/*/*.sv \ ../src/*/*/*.sv -suppress 2583 @@ -76,7 +61,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { # visualizer -fprofile+perf+dir=fprofile # eval vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 \ - -G INSTR_LIMIT=0 -G INSTR_WAVEON=0 -G CHECKPOINT=0 -G NO_SPOOFING=1 -o testbenchopt + -G TEST=$2 -o testbenchopt eval vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829,13286 -fatal 7 \ -sv_lib $env(IMPERAS_HOME)/lib/Linux64/ImperasLib/imperas.com/verification/riscv/1.0/model \ $env(OTHERFLAGS) @@ -96,60 +81,4 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { exec ./slack-notifier/slack-notifier.py -} elseif {$2 eq "fpga"} { - echo "hello" - vlog -work work +incdir+../config/fpga +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/sdc/*.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv ../../fpga/sim/*.sv -suppress 8852,12070,3084,3829,2583,7063,13286 - vopt +acc work.testbench -G TEST=$2 -G DEBUG=0 -o workopt - vsim workopt +nowarn3829 -fatal 7 - - do fpga-wave.do - add log -r /* - run 20 ms - -} else { - if {$2 eq "ahb"} { - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 +define+RAM_LATENCY=$3 +define+BURST_EN=$4 - } else { - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 - } - vopt +acc work.testbench -G TEST=$2 -G DEBUG=1 -o workopt - - vsim workopt +nowarn3829 -fatal 7 - - view wave - #-- display input and output signals as hexidecimal values - #do ./wave-dos/peripheral-waves.do - add log -recursive /* - do wave.do - #do wave-bus.do - - # power add generates the logging necessary for saif generation. - #power add -r /dut/core/* - #-- Run the Simulation - - run -all - #power off -r /dut/core/* - #power report -all -bsaif power.saif - noview ../testbench/testbench.sv - view wave } - - - -#elseif {$2 eq "buildroot-no-trace""} { -# vlog -lint -work work_${1}_${2} +incdir+../config/$1 +incdir+../config/shared ../testbench/testbench-linux.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583 - # start and run simulation -# vopt +acc work_${1}_${2}.testbench -work work_${1}_${2} -G RISCV_DIR=$3 -G INSTR_LIMIT=470350800 -G INSTR_WAVEON=470350800 -G CHECKPOINT=470350800 -G DEBUG_TRACE=0 -o testbenchopt -# vsim -lib work_${1}_${2} testbenchopt -suppress 8852,12070,3084,3829 - - #-- Run the Simulation -# run 100 ns -# force -deposit testbench/dut/core/priv/priv/csr/csri/IE_REGW 16'h2aa -# force -deposit testbench/dut/uncore/uncore/clint/clint/MTIMECMP 64'h1000 -# add log -recursive /* -# do linux-wave.do -# run -all - -# exec ./slack-notifier/slack-notifier.py -#} diff --git a/sim/wally.do b/sim/wally.do index bc987e3d3..4c1a22074 100644 --- a/sim/wally.do +++ b/sim/wally.do @@ -77,12 +77,7 @@ if {$2 eq "buildroot" || $2 eq "buildroot-checkpoint"} { run 20 ms } else { - if {$2 eq "ahb"} { - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 +define+RAM_LATENCY=$3 +define+BURST_EN=$4 - } else { - # *** modelsim won't take `PA_BITS, but will take other defines for the lengths of DTIM_RANGE and IROM_LEN. For now just live with the warnings. - vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 - } + vlog +incdir+../config/$1 +incdir+../config/shared ../src/cvw.sv ../testbench/testbench.sv ../testbench/common/*.sv ../src/*/*.sv ../src/*/*/*.sv -suppress 2583,13286 -suppress 7063 vopt +acc work.testbench -G TEST=$2 -G DEBUG=1 -o workopt vsim workopt +nowarn3829 -fatal 7 diff --git a/src/cache/cacheLRU.sv b/src/cache/cacheLRU.sv index 870633405..e795dd765 100644 --- a/src/cache/cacheLRU.sv +++ b/src/cache/cacheLRU.sv @@ -143,7 +143,7 @@ module cacheLRU // This is a two port memory. // Every cycle must read from CacheSetData and each load/store must write the new LRU. always_ff @(posedge clk) begin - if (reset | (InvalidateCache & ~FlushStage)) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = '0; + if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] = '0; // exclusion-tag: initialize if(CacheEn) begin if(ClearValid & ~FlushStage) LRUMemory[PAdr] <= '0; diff --git a/src/cache/cachefsm.sv b/src/cache/cachefsm.sv index 0d3b2c0e0..8692511ed 100644 --- a/src/cache/cachefsm.sv +++ b/src/cache/cachefsm.sv @@ -117,12 +117,11 @@ module cachefsm import cvw::*; #(parameter cvw_t P, NextState = STATE_READY; case (CurrState) // exclusion-tag: icache state-case STATE_READY: if(InvalidateCache) NextState = STATE_READY; // exclusion-tag: dcache InvalidateCheck - else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; + else if(FlushCache & ~READ_ONLY_CACHE) NextState = STATE_FLUSH; // exclusion-tag: icache FLUSHStatement else if(AnyMiss & (READ_ONLY_CACHE | ~LineDirty)) NextState = STATE_FETCH; // exclusion-tag: icache FETCHStatement - else if(AnyMiss | CMOWriteback) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement + else if((AnyMiss | CMOWriteback) & ~READ_ONLY_CACHE) NextState = STATE_WRITEBACK; // exclusion-tag: icache WRITEBACKStatement else NextState = STATE_READY; STATE_FETCH: if(CacheBusAck) NextState = STATE_WRITE_LINE; - else if(CacheBusAck) NextState = STATE_READY; else NextState = STATE_FETCH; STATE_WRITE_LINE: NextState = STATE_READ_HOLD; STATE_READ_HOLD: if(Stall) NextState = STATE_READ_HOLD; @@ -158,7 +157,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P, (CurrState == STATE_WRITEBACK & CacheBusAck & CMOpM[3]); assign ClearValid = (CurrState == STATE_READY & CMOpM[0]) | (CurrState == STATE_WRITEBACK & CMOpM[2] & CacheBusAck); - // coverage off -item e 1 -fecexprrow 8 assign LRUWriteEn = (((CurrState == STATE_READY & (AnyHit | CMOZeroNoEviction)) | (CurrState == STATE_WRITE_LINE)) & ~FlushStage) | (CurrState == STATE_WRITEBACK & CMOpM[3] & CacheBusAck); @@ -190,8 +188,6 @@ module cachefsm import cvw::*; #(parameter cvw_t P, (CurrState == STATE_WRITEBACK & CacheBusAck & ~(|CMOpM)); logic LoadMiss; - - //assign StoreMiss = (CacheRW[0]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss assign LoadMiss = (CacheRW[1]) & ~CacheHit & ~InvalidateCache; // exclusion-tag: cache AnyMiss assign CacheBusRW[0] = (CurrState == STATE_READY & LoadMiss & LineDirty) | // exclusion-tag: icache CacheBusW @@ -204,7 +200,7 @@ module cachefsm import cvw::*; #(parameter cvw_t P, (CurrState == STATE_WRITEBACK) | (CurrState == STATE_WRITE_LINE) | resetDelay; - assign SelAdrTag = (CurrState == STATE_READY & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrCauses // changes if store delay hazard removed + assign SelAdrTag = (CurrState == STATE_READY & (AnyMiss | (|CMOpM))) | // exclusion-tag: icache SelAdrTag // changes if store delay hazard removed (CurrState == STATE_FETCH) | (CurrState == STATE_WRITEBACK) | (CurrState == STATE_WRITE_LINE) | diff --git a/src/cache/cacheway.sv b/src/cache/cacheway.sv index b2be76838..678f7acac 100644 --- a/src/cache/cacheway.sv +++ b/src/cache/cacheway.sv @@ -53,7 +53,7 @@ module cacheway import cvw::*; #(parameter cvw_t P, output logic [LINELEN-1:0] ReadDataLineWay,// This way's read data if valid output logic HitWay, // This way hits output logic ValidWay, // This way is valid - output logic HitDirtyWay, // The hit way is dirty + output logic HitDirtyWay, // The hit way is dirty output logic DirtyWay , // The selected way is dirty output logic [TAGLEN-1:0] TagWay); // This way's tag if valid diff --git a/src/ebu/buscachefsm.sv b/src/ebu/buscachefsm.sv index 75f444e4b..e1fded607 100644 --- a/src/ebu/buscachefsm.sv +++ b/src/ebu/buscachefsm.sv @@ -79,7 +79,7 @@ module buscachefsm #( logic CacheAccess; logic BusWrite; - assign BusWrite = CacheBusRW[0] | BusCMOZero; + assign BusWrite = (CacheBusRW[0] | BusCMOZero) & ~READ_ONLY_CACHE; always_ff @(posedge HCLK) if (~HRESETn | Flush) CurrState <= #1 ADR_PHASE; @@ -87,28 +87,28 @@ module buscachefsm #( always_comb begin case(CurrState) - ADR_PHASE: if (HREADY & |BusRW) NextState = DATA_PHASE; - else if (HREADY & BusWrite) NextState = CACHE_WRITEBACK; - else if (HREADY & CacheBusRW[1]) NextState = CACHE_FETCH; + ADR_PHASE: if (HREADY & |BusRW) NextState = DATA_PHASE; // exclusion-tag: buscachefsm HREADY0 + else if (HREADY & BusWrite & ~READ_ONLY_CACHE) NextState = CACHE_WRITEBACK; // exclusion-tag: buscachefsm HREADY1 + else if (HREADY & CacheBusRW[1]) NextState = CACHE_FETCH; // exclusion-tag: buscachefsm HREADYread else NextState = ADR_PHASE; - DATA_PHASE: if(HREADY & BusAtomic) NextState = ATOMIC_READ_DATA_PHASE; - else if(HREADY & ~BusAtomic) NextState = MEM3; + DATA_PHASE: if(HREADY & BusAtomic & ~READ_ONLY_CACHE) NextState = ATOMIC_READ_DATA_PHASE; // exclusion-tag: buscachefsm HREADY2 + else if(HREADY & ~BusAtomic) NextState = MEM3; // exclusion-tag: buscachefsm HREADY3 else NextState = DATA_PHASE; - ATOMIC_READ_DATA_PHASE: if(HREADY) NextState = ATOMIC_PHASE; - else NextState = ATOMIC_READ_DATA_PHASE; - ATOMIC_PHASE: if(HREADY) NextState = MEM3; - else NextState = ATOMIC_PHASE; + ATOMIC_READ_DATA_PHASE: if(HREADY) NextState = ATOMIC_PHASE; // exclusion-tag: buscachefsm AtomicReadData + else NextState = ATOMIC_READ_DATA_PHASE; // exclusion-tag: buscachefsm AtomicElse + ATOMIC_PHASE: if(HREADY) NextState = MEM3; // exclusion-tag: buscachefsm AtomicPhase + else NextState = ATOMIC_PHASE; // exclusion-tag: buscachefsm AtomicWait MEM3: if(Stall) NextState = MEM3; else NextState = ADR_PHASE; - CACHE_FETCH: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK; - else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; + CACHE_FETCH: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK; // exclusion-tag: buscachefsm FetchWriteback + else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; // exclusion-tag: buscachefsm FetchWait else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE; else NextState = CACHE_FETCH; - CACHE_WRITEBACK: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK; - else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; - else if(HREADY & FinalBeatCount & BusCMOZero) NextState = MEM3; - else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE; - else NextState = CACHE_WRITEBACK; + CACHE_WRITEBACK: if(HREADY & FinalBeatCount & CacheBusRW[0]) NextState = CACHE_WRITEBACK; // exclusion-tag: buscachefsm WritebackWriteback + else if(HREADY & FinalBeatCount & CacheBusRW[1]) NextState = CACHE_FETCH; // exclusion-tag: buscachefsm HREADY4 + else if(HREADY & FinalBeatCount & BusCMOZero) NextState = MEM3; // exclusion-tag: buscachefsm HREADY5 + else if(HREADY & FinalBeatCount & ~|CacheBusRW) NextState = ADR_PHASE; // exclusion-tag: buscachefsm HREADY6 + else NextState = CACHE_WRITEBACK; // exclusion-tag: buscachefsm WritebackWriteback2 default: NextState = ADR_PHASE; endcase end @@ -139,12 +139,12 @@ module buscachefsm #( // AHB bus interface assign HTRANS = (CurrState == ADR_PHASE & HREADY & ((|BusRW) | (|CacheBusRW) | BusCMOZero) & ~Flush) | - (CurrState == ATOMIC_READ_DATA_PHASE & BusAtomic) | + (CurrState == ATOMIC_READ_DATA_PHASE) | (CacheAccess & FinalBeatCount & |CacheBusRW & HREADY & ~Flush) ? AHB_NONSEQ : // if we have a pipelined request (CacheAccess & |BeatCount) ? (BURST_EN ? AHB_SEQ : AHB_NONSEQ) : AHB_IDLE; - assign HWRITE = ((BusRW[0] & ~BusAtomic) | BusWrite & ~Flush) | (CurrState == ATOMIC_READ_DATA_PHASE & BusAtomic) | - (CurrState == CACHE_WRITEBACK & |BeatCount); + assign HWRITE = (((BusRW[0] & ~BusAtomic) | BusWrite & ~Flush) | (CurrState == ATOMIC_READ_DATA_PHASE & BusAtomic) | + (CurrState == CACHE_WRITEBACK & |BeatCount)) & ~READ_ONLY_CACHE; assign HBURST = BURST_EN & ((|CacheBusRW & ~Flush) | (CacheAccess & |BeatCount)) ? LocalBurstType : 3'b0; always_comb begin diff --git a/src/fpu/fctrl.sv b/src/fpu/fctrl.sv index 60edbfd8a..788ac2e27 100755 --- a/src/fpu/fctrl.sv +++ b/src/fpu/fctrl.sv @@ -237,11 +237,10 @@ module fctrl import cvw::*; #(parameter cvw_t P) ( 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1_0; // fcvt.l.q q->l 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1_0; // fcvt.lu.q q->lu endcase - // coverage on + // coverage off + // Not covered in testing because rv64gc is not RV64Q or RV32D 7'b1011001: if (P.ZFA_SUPPORTED & P.XLEN == 32 & P.D_SUPPORTED & Funct3D == 3'b000) ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fmvp.d.x (Zfa) *** untested, controls could be wrong - // Not covered in testing because rv64gc does not support quad precision - // coverage off 7'b1011011: if (P.ZFA_SUPPORTED & P.XLEN == 64 & P.Q_SUPPORTED & Funct3D == 3'b000) ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0_0; // fmvp.q.x (Zfa) // coverage on diff --git a/src/fpu/fpu.sv b/src/fpu/fpu.sv index 85021d269..54957d530 100755 --- a/src/fpu/fpu.sv +++ b/src/fpu/fpu.sv @@ -278,9 +278,14 @@ module fpu import cvw::*; #(parameter cvw_t P) ( end else assign FliResE = '0; // fmv.*.x: NaN Box SrcA to extend integer to requested FP size - if(P.FPSIZES == 1) assign PreIntSrcE = {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE}; + if(P.FPSIZES == 1) + if (P.FLEN >= P.XLEN) assign PreIntSrcE = {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE}; + else assign PreIntSrcE = ForwardedSrcAE[P.FLEN-1:0]; else if(P.FPSIZES == 2) - mux2 #(P.FLEN) SrcAMux ({{P.FLEN-P.LEN1{1'b1}}, ForwardedSrcAE[P.LEN1-1:0]}, {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE}, FmtE, PreIntSrcE); + if (P.FLEN >= P.XLEN) + mux2 #(P.FLEN) SrcAMux ({{P.FLEN-P.LEN1{1'b1}}, ForwardedSrcAE[P.LEN1-1:0]}, {{P.FLEN-P.XLEN{1'b1}}, ForwardedSrcAE}, FmtE, PreIntSrcE); + else + mux2 #(P.FLEN) SrcAMux ({{P.FLEN-P.LEN1{1'b1}}, ForwardedSrcAE[P.LEN1-1:0]}, ForwardedSrcAE[P.FLEN-1:0], FmtE, PreIntSrcE); else if(P.FPSIZES == 3 | P.FPSIZES == 4) begin localparam XD_LEN = P.D_LEN < P.XLEN ? P.D_LEN : P.XLEN; // shorter of D_LEN and XLEN mux3 #(P.FLEN) SrcAMux ({{P.FLEN-P.S_LEN{1'b1}}, ForwardedSrcAE[P.S_LEN-1:0]}, diff --git a/src/fpu/postproc/shiftcorrection.sv b/src/fpu/postproc/shiftcorrection.sv index 275ee4cff..5f6e46da1 100644 --- a/src/fpu/postproc/shiftcorrection.sv +++ b/src/fpu/postproc/shiftcorrection.sv @@ -45,7 +45,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) ( output logic [P.NE+1:0] Ue // corrected exponent for divider ); - logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction + logic [P.CORRSHIFTSZ-1:0] CorrSumShifted; // the shifted sum after LZA correction logic [P.CORRSHIFTSZ-1:0] CorrQm0, CorrQm1; // portions of Shifted to select for CorrQmShifted logic [P.CORRSHIFTSZ-1:0] CorrQmShifted; // the shifted divsqrt result after one bit shift logic ResSubnorm; // is the result Subnormal @@ -69,7 +69,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) ( // if the result of the divider was calculated to be subnormal, then the result was correctly normalized, so select the top shifted bits always_comb - if(FmaOp) Mf = {CorrSumShifted, {P.CORRSHIFTSZ-(3*P.NF+4){1'b0}}}; + if(FmaOp) Mf = {CorrSumShifted}; else if (DivOp&~DivResSubnorm) Mf = CorrQmShifted; else Mf = Shifted[P.NORMSHIFTSZ-1:P.NORMSHIFTSZ-P.CORRSHIFTSZ]; diff --git a/src/fpu/unpackinput.sv b/src/fpu/unpackinput.sv index ca58c9d9f..e5c5f3deb 100644 --- a/src/fpu/unpackinput.sv +++ b/src/fpu/unpackinput.sv @@ -140,15 +140,12 @@ module unpackinput import cvw::*; #(parameter cvw_t P) ( endcase always_comb - if (BadNaNBox) begin - case (Fmt) - P.FMT: PostBox = In; - P.FMT1: PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, {(P.LEN1-P.NE1-2){1'b0}}}; - P.FMT2: PostBox = {{(P.FLEN-P.LEN2){1'b1}}, 1'b1, {(P.NE2+1){1'b1}}, {(P.LEN2-P.NE2-2){1'b0}}}; - default: PostBox = 'x; - endcase - end else - PostBox = In; + if (BadNaNBox & Fmt == P.FMT1) + PostBox = {{(P.FLEN-P.LEN1){1'b1}}, 1'b1, {(P.NE1+1){1'b1}}, {(P.LEN1-P.NE1-2){1'b0}}}; + else if (BadNaNBox) // Fmt == P.FMT2 + PostBox = {{(P.FLEN-P.LEN2){1'b1}}, 1'b1, {(P.NE2+1){1'b1}}, {(P.LEN2-P.NE2-2){1'b0}}}; + else + PostBox = In; // extract the sign bit always_comb diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index b18df36ec..d9c076dbd 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -42,6 +42,7 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic BranchD, // Branch instruction output logic StructuralStallD, // Structural stalls detected by controller output logic LoadStallD, // Structural stalls for load, sent to performance counters + output logic StoreStallD, // load after store hazard output logic [4:0] Rs1D, Rs2D, // Register sources to read in Decode or Execute stage // Execute stage control signals input logic StallE, FlushE, // Stall, flush Execute stage @@ -159,7 +160,6 @@ module controller import cvw::*; #(parameter cvw_t P) ( logic CMOStallD; // Structural hazards from cache management ops logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read - logic StoreStallD; // load after store hazard logic FunctCZeroD; // Funct7 and Funct3 indicate czero.* (not including Op check) // Extract fields diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index 5a2b8d6dc..438ca7534 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -76,6 +76,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( input logic FlushD, FlushE, FlushM, FlushW, // Flush signals output logic StructuralStallD, // IEU detects structural hazard in Decode stage output logic LoadStallD, // Structural stalls for load, sent to performance counters + output logic StoreStallD, // load after store hazard output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions ); @@ -107,7 +108,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( controller #(P) c( .clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD, .IllegalIEUFPUInstrD, .IllegalBaseInstrD, - .StructuralStallD, .LoadStallD, .Rs1D, .Rs2D, + .StructuralStallD, .LoadStallD, .StoreStallD, .Rs1D, .Rs2D, .StallE, .FlushE, .FlagsE, .FWriteIntE, .PCSrcE, .ALUSrcAE, .ALUSrcBE, .ALUResultSrcE, .ALUSelectE, .MemReadE, .CSRReadE, .Funct3E, .IntDivE, .MDUE, .W64E, .SubArithE, .BranchD, .BranchE, .JumpD, .JumpE, .SCE, diff --git a/src/ifu/bpred/bpred.sv b/src/ifu/bpred/bpred.sv index faf537d91..006a60b1d 100644 --- a/src/ifu/bpred/bpred.sv +++ b/src/ifu/bpred/bpred.sv @@ -88,15 +88,17 @@ module bpred import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] BPBTAD; - logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF; - logic BPBranchF, BPJumpF, BPReturnF, BPCallF; - logic BPBranchD, BPJumpD, BPReturnD, BPCallD; - logic ReturnD, CallD; - logic ReturnE, CallE; - logic BranchM, JumpM, ReturnM, CallM; - logic BranchW, JumpW, ReturnW, CallW; - logic BPReturnWrongD; + logic BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF; + logic BPBranchF, BPJumpF, BPReturnF, BPCallF; + logic BPBranchD, BPJumpD, BPReturnD, BPCallD; + logic ReturnD, CallD; + logic ReturnE, CallE; + logic BranchM, JumpM, ReturnM, CallM; + logic BranchW, JumpW, ReturnW, CallW; + logic BPReturnWrongD; logic [P.XLEN-1:0] BPBTAE; + logic BPBTAWrongM; + logic PCSrcM; // Part 1 branch direction prediction if (P.BPRED_TYPE == `BP_TWOBIT) begin:Predictor @@ -144,6 +146,8 @@ module bpred import cvw::*; #(parameter cvw_t P) ( .BranchD, .BranchE, .BranchM, .PCSrcE); end + flopenrc #(1) PCSrcMReg(clk, reset, FlushM, ~StallM, PCSrcE, PCSrcM); + // Part 2 Branch target address prediction // BTB contains target address for all CFI @@ -152,6 +156,7 @@ module bpred import cvw::*; #(parameter cvw_t P) ( .PCNextF, .PCF, .PCD, .PCE, .PCM, .BPBTAF, .BPBTAD, .BPBTAE, .BTBIClassF({BTBCallF, BTBReturnF, BTBJumpF, BTBBranchF}), + .BPBTAWrongM, .IClassWrongM, .IClassWrongE, .IEUAdrE, .IEUAdrM, .InstrClassD({CallD, ReturnD, JumpD, BranchD}), @@ -196,7 +201,7 @@ module bpred import cvw::*; #(parameter cvw_t P) ( if(P.ZIHPM_SUPPORTED) begin logic [P.XLEN-1:0] RASPCD, RASPCE; - logic BTAWrongE, RASPredPCWrongE; + logic RASPredPCWrongE; // performance counters // 1. class (class wrong / minstret) (IClassWrongM / csr) // Correct now // 2. target btb (btb target wrong / class[0,1,3]) (btb target wrong / (br + j + jal) @@ -208,14 +213,15 @@ module bpred import cvw::*; #(parameter cvw_t P) ( // By pipeline the BTB's PC and RAS address through the pipeline we can measure the accuracy of // both without the above inaccuracies. // **** use BPBTAWrongM from BTB. - assign BTAWrongE = (BPBTAE != IEUAdrE) & (BranchE | JumpE & ~ReturnE) & PCSrcE; assign RASPredPCWrongE = (RASPCE != IEUAdrE) & ReturnE & PCSrcE; flopenrc #(P.XLEN) RASTargetDReg(clk, reset, FlushD, ~StallD, RASPCF, RASPCD); flopenrc #(P.XLEN) RASTargetEReg(clk, reset, FlushE, ~StallE, RASPCD, RASPCE); - flopenrc #(3) BPPredWrongRegM(clk, reset, FlushM, ~StallM, - {BPDirPredWrongE, BTAWrongE, RASPredPCWrongE}, - {BPDirPredWrongM, BTAWrongM, RASPredPCWrongM}); + flopenrc #(2) BPPredWrongRegM(clk, reset, FlushM, ~StallM, + {BPDirPredWrongE, RASPredPCWrongE}, + {BPDirPredWrongM, RASPredPCWrongM}); + + assign BTAWrongM = BPBTAWrongM & PCSrcM; end else begin assign {BTAWrongM, RASPredPCWrongM} = '0; diff --git a/src/ifu/bpred/btb.sv b/src/ifu/bpred/btb.sv index 2d0d30727..448be38d0 100644 --- a/src/ifu/bpred/btb.sv +++ b/src/ifu/bpred/btb.sv @@ -39,6 +39,7 @@ module btb import cvw::*; #(parameter cvw_t P, output logic [P.XLEN-1:0] BPBTAD, output logic [P.XLEN-1:0] BPBTAE, output logic [3:0] BTBIClassF, // BTB's guess at instruction class + output logic BPBTAWrongM, // update input logic IClassWrongM, // BTB's instruction class guess was wrong input logic IClassWrongE, @@ -57,7 +58,7 @@ module btb import cvw::*; #(parameter cvw_t P, logic [P.XLEN-1:0] IEUAdrW; logic [P.XLEN-1:0] PCW; logic BTBWrongE, BPBTAWrongE; - logic BTBWrongM, BPBTAWrongM; + logic BTBWrongM; // hashing function for indexing the PC diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index c997d58ff..f53bb9296 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -374,12 +374,12 @@ module lsu import cvw::*; #(parameter cvw_t P) ( ahbinterface #(P.XLEN, 1'b1) ahbinterface(.HCLK(clk), .HRESETn(~reset), .Flush(FlushW), .HREADY(LSUHREADY), .HRDATA(HRDATA), .HTRANS(LSUHTRANS), .HWRITE(LSUHWRITE), .HWDATA(LSUHWDATA), - .HWSTRB(LSUHWSTRB), .BusRW, .BusAtomic(AtomicM[1]), .ByteMask(ByteMaskM), .WriteData(LSUWriteDataM[P.XLEN-1:0]), + .HWSTRB(LSUHWSTRB), .BusRW, .BusAtomic(AtomicM[1]), .ByteMask(ByteMaskM[P.XLEN/8-1:0]), .WriteData(LSUWriteDataM[P.XLEN-1:0]), .Stall(GatedStallW), .BusStall, .BusCommitted(BusCommittedM), .FetchBuffer(FetchBuffer)); // Mux between the 2 sources of read data, 0: Bus, 1: DTIM if(P.DTIM_SUPPORTED) mux2 #(P.XLEN) ReadDataMux2(FetchBuffer, DTIMReadDataWordM[P.XLEN-1:0], SelDTIM, ReadDataWordMuxM[P.XLEN-1:0]); - else assign ReadDataWordMuxM = FetchBuffer[P.XLEN-1:0]; + else assign ReadDataWordMuxM[P.XLEN-1:0] = FetchBuffer[P.XLEN-1:0]; // *** bus only does not support double wide floats. assign LSUHBURST = 3'b0; assign {DCacheStallM, DCacheCommittedM, DCacheMiss, DCacheAccess} = '0; end @@ -406,7 +406,11 @@ module lsu import cvw::*; #(parameter cvw_t P) ( end if (P.F_SUPPORTED) - mux2 #(P.LLEN) datamux({{{P.LLEN-P.XLEN}{1'b0}}, IMAWriteDataM}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM); + if (P.FLEN >= P.XLEN) + mux2 #(P.LLEN) datamux({{{P.LLEN-P.XLEN}{1'b0}}, IMAWriteDataM}, FWriteDataM, FpLoadStoreM, IMAFWriteDataM); + else + mux2 #(P.LLEN) datamux(IMAWriteDataM, {{{P.XLEN-P.FLEN}{1'b0}}, FWriteDataM}, FpLoadStoreM, IMAFWriteDataM); + else assign IMAFWriteDataM = IMAWriteDataM; ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/mmu/adrdec.sv b/src/mmu/adrdec.sv index 05ac45bd0..bf092dbc6 100644 --- a/src/mmu/adrdec.sv +++ b/src/mmu/adrdec.sv @@ -49,5 +49,5 @@ module adrdec #(parameter PA_BITS) ( assign SizeValid = SizeMask[Size]; // Select this peripheral if the address matches, the peripheral is supported, and the type and size of access is ok - assign Sel = Match & Supported & AccessValid & SizeValid; + assign Sel = Match & Supported & AccessValid & SizeValid; // exclusion-tag: adrdecSel endmodule diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index e4dda5121..4be12e383 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -54,7 +54,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( input logic [3:0] CauseM, // Trap cause input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode // inputs for performance counters - input logic LoadStallD, + input logic LoadStallD, StoreStallD, input logic ICacheStallF, input logic DCacheStallM, input logic BPDirPredWrongM, @@ -275,7 +275,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( if (P.ZICNTR_SUPPORTED) begin:counters csrc #(P) counters(.clk, .reset, .StallE, .StallM, .FlushM, - .InstrValidNotFlushedM, .LoadStallD, .CSRWriteM, .CSRMWriteM, + .InstrValidNotFlushedM, .LoadStallD, .StoreStallD, .CSRWriteM, .CSRMWriteM, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .IClassWrongM, .BPWrongM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .sfencevmaM, .InterruptM, .ExceptionM, .InvalidateICacheM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE, diff --git a/src/privileged/csrc.sv b/src/privileged/csrc.sv index 348ba1596..722449284 100644 --- a/src/privileged/csrc.sv +++ b/src/privileged/csrc.sv @@ -33,7 +33,7 @@ module csrc import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, input logic StallE, StallM, input logic FlushM, - input logic InstrValidNotFlushedM, LoadStallD, + input logic InstrValidNotFlushedM, LoadStallD, StoreStallD, input logic CSRMWriteM, CSRWriteM, input logic BPDirPredWrongM, input logic BTAWrongM, @@ -76,6 +76,7 @@ module csrc import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] HPMCOUNTER_REGW[P.COUNTERS-1:0]; logic [P.XLEN-1:0] HPMCOUNTERH_REGW[P.COUNTERS-1:0]; logic LoadStallE, LoadStallM; + logic StoreStallE, StoreStallM; logic [P.COUNTERS-1:0] WriteHPMCOUNTERM; logic [P.COUNTERS-1:0] CounterEvent; logic [63:0] HPMCOUNTERPlusM[P.COUNTERS-1:0]; @@ -85,6 +86,9 @@ module csrc import cvw::*; #(parameter cvw_t P) ( // Interface signals flopenrc #(1) LoadStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(LoadStallD), .q(LoadStallE)); // don't flush the load stall during a load stall. flopenrc #(1) LoadStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(LoadStallE), .q(LoadStallM)); + + flopenrc #(1) StoreStallEReg(.clk, .reset, .clear(1'b0), .en(~StallE), .d(StoreStallD), .q(StoreStallE)); // don't flush the load stall during a load stall. + flopenrc #(1) StoreStallMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(StoreStallE), .q(StoreStallM)); // Determine when to increment each counter assign CounterEvent[0] = 1'b1; // MCYCLE always increments @@ -100,7 +104,7 @@ module csrc import cvw::*; #(parameter cvw_t P) ( assign CounterEvent[9] = RASPredPCWrongM & InstrValidNotFlushedM; // return address stack wrong address assign CounterEvent[10] = IClassWrongM & InstrValidNotFlushedM; // instruction class predictor wrong assign CounterEvent[11] = LoadStallM; // Load Stalls. don't want to suppress on flush as this only happens if flushed. - assign CounterEvent[12] = 0; // depricated Store Stall + assign CounterEvent[12] = StoreStallM; // depricated Store Stall assign CounterEvent[13] = DCacheAccess; // data cache access assign CounterEvent[14] = DCacheMiss; // data cache miss. Miss asserted 1 cycle at start of cache miss assign CounterEvent[15] = DCacheStallM; // d cache miss cycles diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index d6ef8d9d1..09a56259f 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -46,6 +46,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( // processor events for performance counter logging input logic FRegWriteM, // instruction will write floating-point registers input logic LoadStallD, // load instruction is stalling + input logic StoreStallD, // store instruction is stalling input logic ICacheStallF, // I cache stalled input logic DCacheStallM, // D cache stalled input logic BPDirPredWrongM, // branch predictor guessed wrong direction @@ -135,7 +136,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .InterruptM, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, - .MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, + .MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD, .BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .BPWrongM, .sfencevmaM, .ExceptionM, .InvalidateICacheM, .ICacheStallF, .DCacheStallM, .DivBusyE, .FDivBusyE, .IClassWrongM, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index ec0679f13..440307806 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -78,6 +78,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic DivBusyE; logic StructuralStallD; logic LoadStallD; + logic StoreStallD; logic SquashSCW; logic MDUActiveE; // Mul/Div instruction being executed logic ENVCFG_ADUE; // HPTW A/D Update enable @@ -212,7 +213,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .InstrValidM, .InstrValidE, .InstrValidD, .FCvtIntResW, .FCvtIntW, // hazards .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, - .StructuralStallD, .LoadStallD, .PCSrcE, + .StructuralStallD, .LoadStallD, .StoreStallD, .PCSrcE, .CSRReadM, .CSRWriteM, .PrivilegedM, .CSRWriteFenceM, .InvalidateICacheM); lsu #(P) lsu( @@ -286,7 +287,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .InstrM, .InstrOrigM, .CSRReadValW, .EPCM, .TrapVectorM, .RetM, .TrapM, .sfencevmaM, .InvalidateICacheM, .DCacheStallM, .ICacheStallF, .InstrValidM, .CommittedM, .CommittedF, - .FRegWriteM, .LoadStallD, + .FRegWriteM, .LoadStallD, .StoreStallD, .BPDirPredWrongM, .BTAWrongM, .BPWrongM, .RASPredPCWrongM, .IClassWrongM, .DivBusyE, .FDivBusyE, .InstrClassM, .DCacheMiss, .DCacheAccess, .ICacheMiss, .ICacheAccess, .PrivilegedM, diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index dcbe7e32a..b439b3d75 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -21,53 +21,51 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); initial begin - assert (P.PMP_ENTRIES == 0 || P.PMP_ENTRIES==16 || P.PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64"); - assert (P.S_SUPPORTED || P.VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support"); - assert (P.IDIV_BITSPERCYCLE == 1 || P.IDIV_BITSPERCYCLE==2 || P.IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4"); - assert (P.F_SUPPORTED || ~P.D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)"); - assert (P.D_SUPPORTED || ~P.Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)"); - assert (P.F_SUPPORTED || ~P.ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)"); - assert (P.DCACHE_SUPPORTED || ~P.F_SUPPORTED || P.FLEN <= P.XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN"); - assert (P.I_SUPPORTED ^ P.E_SUPPORTED) else $error("Exactly one of I and E must be supported"); - assert (P.FLEN<=P.XLEN || P.DCACHE_SUPPORTED || P.DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported"); - assert (P.DCACHE_WAYSIZEINBYTES <= 4096 || (!P.DCACHE_SUPPORTED) || P.VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); - assert (P.DCACHE_LINELENINBITS >= 128 || (!P.DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); - assert (P.DCACHE_LINELENINBITS < P.DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size"); - assert (P.ICACHE_WAYSIZEINBYTES <= 4096 || (!P.ICACHE_SUPPORTED) || P.VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); - assert (P.ICACHE_LINELENINBITS >= 32 || (!P.ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); - assert (P.ICACHE_LINELENINBITS < P.ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size"); - assert (2**$clog2(P.DCACHE_LINELENINBITS) == P.DCACHE_LINELENINBITS || (!P.DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2"); - assert (2**$clog2(P.DCACHE_WAYSIZEINBYTES) == P.DCACHE_WAYSIZEINBYTES || (!P.DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); - assert (2**$clog2(P.ICACHE_LINELENINBITS) == P.ICACHE_LINELENINBITS || (!P.ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2"); - assert (2**$clog2(P.ICACHE_WAYSIZEINBYTES) == P.ICACHE_WAYSIZEINBYTES || (!P.ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); - assert (2**$clog2(P.ITLB_ENTRIES) == P.ITLB_ENTRIES || P.VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2"); - assert (2**$clog2(P.DTLB_ENTRIES) == P.DTLB_ENTRIES || P.VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2"); + assert (P.PMP_ENTRIES == 0 || P.PMP_ENTRIES==16 || P.PMP_ENTRIES==64) else $fatal(1, "Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64"); + assert (P.S_SUPPORTED || P.VIRTMEM_SUPPORTED == 0) else $fatal(1, "Virtual memory requires S mode support"); + assert (P.IDIV_BITSPERCYCLE == 1 || P.IDIV_BITSPERCYCLE==2 || P.IDIV_BITSPERCYCLE==4) else $fatal(1, "Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4"); + assert (P.F_SUPPORTED || ~P.D_SUPPORTED) else $fatal(1, "Can't support double fp (D) without supporting float (F)"); + assert (P.D_SUPPORTED || ~P.Q_SUPPORTED) else $fatal(1, "Can't support quad fp (Q) without supporting double (D)"); + assert (P.F_SUPPORTED || ~P.ZFH_SUPPORTED) else $fatal(1, "Can't support half-precision fp (ZFH) without supporting float (F)"); + assert (P.DCACHE_SUPPORTED || ~P.F_SUPPORTED || P.FLEN <= P.XLEN) else $fatal(1, "Data cache required to support FLEN > XLEN because AHB/DTIM bus width is XLEN"); + assert (P.I_SUPPORTED ^ P.E_SUPPORTED) else $fatal(1, "Exactly one of I and E must be supported"); + assert (P.DCACHE_WAYSIZEINBYTES <= 4096 || (!P.DCACHE_SUPPORTED) || P.VIRTMEM_SUPPORTED == 0) else $fatal(1, "DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); + assert (P.DCACHE_LINELENINBITS >= 128 || (!P.DCACHE_SUPPORTED)) else $fatal(1, "DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); + assert (P.DCACHE_LINELENINBITS < P.DCACHE_WAYSIZEINBYTES*8) else $fatal(1, "DCACHE_LINELENINBITS must be smaller than way size"); + assert (P.ICACHE_WAYSIZEINBYTES <= 4096 || (!P.ICACHE_SUPPORTED) || P.VIRTMEM_SUPPORTED == 0) else $fatal(1, "ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); + assert (P.ICACHE_LINELENINBITS >= 32 || (!P.ICACHE_SUPPORTED)) else $fatal(1, "ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); + assert (P.ICACHE_LINELENINBITS < P.ICACHE_WAYSIZEINBYTES*8) else $fatal(1, "ICACHE_LINELENINBITS must be smaller than way size"); + assert (2**$clog2(P.DCACHE_LINELENINBITS) == P.DCACHE_LINELENINBITS || (!P.DCACHE_SUPPORTED)) else $fatal(1, "DCACHE_LINELENINBITS must be a power of 2"); + assert (2**$clog2(P.DCACHE_WAYSIZEINBYTES) == P.DCACHE_WAYSIZEINBYTES || (!P.DCACHE_SUPPORTED)) else $fatal(1, "DCACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(P.ICACHE_LINELENINBITS) == P.ICACHE_LINELENINBITS || (!P.ICACHE_SUPPORTED)) else $fatal(1, "ICACHE_LINELENINBITS must be a power of 2"); + assert (2**$clog2(P.ICACHE_WAYSIZEINBYTES) == P.ICACHE_WAYSIZEINBYTES || (!P.ICACHE_SUPPORTED)) else $fatal(1, "ICACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(P.ITLB_ENTRIES) == P.ITLB_ENTRIES || P.VIRTMEM_SUPPORTED==0) else $fatal(1, "ITLB_ENTRIES must be a power of 2"); + assert (2**$clog2(P.DTLB_ENTRIES) == P.DTLB_ENTRIES || P.VIRTMEM_SUPPORTED==0) else $fatal(1, "DTLB_ENTRIES must be a power of 2"); assert (P.UNCORE_RAM_RANGE >= 64'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 64'h07FFFFFF"); - assert (P.ZICSR_SUPPORTED == 1 || (P.PMP_ENTRIES == 0 && P.VIRTMEM_SUPPORTED == 0)) else $error("PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported."); - assert (P.ZICSR_SUPPORTED == 1 || (P.S_SUPPORTED == 0 && P.U_SUPPORTED == 0)) else $error("S and U modes not supported if ZICSR not supported"); + assert (P.ZICSR_SUPPORTED == 1 || (P.PMP_ENTRIES == 0 && P.VIRTMEM_SUPPORTED == 0)) else $fatal(1, "PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported."); + assert (P.ZICSR_SUPPORTED == 1 || (P.S_SUPPORTED == 0 && P.U_SUPPORTED == 0)) else $fatal(1, "S and U modes not supported if ZICSR not supported"); assert (P.U_SUPPORTED || (P.S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported"); - assert (P.VIRTMEM_SUPPORTED == 0 || (P.DTIM_SUPPORTED == 0 && P.IROM_SUPPORTED == 0)) else $error("Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses"); - assert (P.DCACHE_SUPPORTED || P.VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache"); - assert (P.ICACHE_SUPPORTED || P.VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache"); - assert ((P.DCACHE_SUPPORTED == 0 && P.ICACHE_SUPPORTED == 0) || P.BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS_SUPPORTED."); - assert (P.DCACHE_LINELENINBITS <= P.XLEN*16 || (!P.DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1"); - assert (P.DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); - assert (P.DCACHE_SUPPORTED || (P.A_SUPPORTED == 0)) else $error("Atomic extension (A) requires cache on Wally."); - assert (P.IDIV_ON_FPU == 0 || P.F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED"); - assert (P.SSTC_SUPPORTED == 0 || (P.S_SUPPORTED)) else $error("SSTC requires S_SUPPORTED"); - assert ((P.ZMMUL_SUPPORTED == 0) || (P.M_SUPPORTED ==0)) else $error("At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled"); - assert ((P.ZICNTR_SUPPORTED == 0) || (P.ZICSR_SUPPORTED == 1)) else $error("ZICNTR_SUPPORTED requires ZICSR_SUPPORTED"); - assert ((P.ZIHPM_SUPPORTED == 0) || (P.ZICNTR_SUPPORTED == 1)) else $error("ZIPHM_SUPPORTED requires ZICNTR_SUPPORTED"); - assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOM requires DCACHE_SUPPORTED"); - assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOZ requires DCACHE_SUPPORTED"); - assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP requires DCACHE_SUPPORTED"); - assert ((P.SVPBMT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVPBMT requires VIRTMEM_SUPPORTED and RV64"); - assert ((P.SVNAPOT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVNAPOT requires VIRTMEM_SUPPORTED and RV64"); - assert ((P.ZCB_SUPPORTED == 0) || (P.M_SUPPORTED == 1 && (P.ZBA_SUPPORTED == 1 || P.XLEN == 32) && P.ZBB_SUPPORTED == 1)) else $error("ZCB requires M and ZBB (and also ZBA for RV64)"); - assert ((P.C_SUPPORTED == 0) || (P.ZCA_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0 && P.ZCD_SUPPORTED == 0)) else $error("C and ZCA/ZCD/ZCF cannot simultaneously be supported"); - assert ((P.ZCA_SUPPORTED == 1) || (P.ZCD_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0)) else $error("ZCF or ZCD requires ZCA"); - assert ((P.ZCF_SUPPORTED == 0) || (P.F_SUPPORTED == 1)) else $error("ZCF requires F"); - assert ((P.ZCD_SUPPORTED == 0) || (P.D_SUPPORTED == 1)) else $error("ZCD requires D"); + assert (P.VIRTMEM_SUPPORTED == 0 || (P.DTIM_SUPPORTED == 0 && P.IROM_SUPPORTED == 0)) else $fatal(1, "Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses"); + assert (P.DCACHE_SUPPORTED || P.VIRTMEM_SUPPORTED ==0) else $fatal(1, "Virtual memory needs dcache"); + assert (P.ICACHE_SUPPORTED || P.VIRTMEM_SUPPORTED ==0) else $fatal(1, "Virtual memory needs icache"); + assert ((P.DCACHE_SUPPORTED == 0 && P.ICACHE_SUPPORTED == 0) || P.BUS_SUPPORTED) else $fatal(1, "Dcache and Icache requires DBUS_SUPPORTED."); + assert (P.DCACHE_LINELENINBITS <= P.XLEN*16 || (!P.DCACHE_SUPPORTED)) else $fatal(1, "DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 16"); + assert (P.DCACHE_LINELENINBITS % 4 == 0) else $fatal(1, "DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); + assert (P.DCACHE_SUPPORTED || (P.A_SUPPORTED == 0)) else $fatal(1, "Atomic extension (A) requires cache on Wally."); + assert (P.IDIV_ON_FPU == 0 || P.F_SUPPORTED) else $fatal(1, "IDIV on FPU needs F_SUPPORTED"); + assert (P.SSTC_SUPPORTED == 0 || (P.S_SUPPORTED)) else $fatal(1, "SSTC requires S_SUPPORTED"); + assert ((P.ZMMUL_SUPPORTED == 0) || (P.M_SUPPORTED ==0)) else $fatal(1, "At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled"); + assert ((P.ZICNTR_SUPPORTED == 0) || (P.ZICSR_SUPPORTED == 1)) else $fatal(1, "ZICNTR_SUPPORTED requires ZICSR_SUPPORTED"); + assert ((P.ZIHPM_SUPPORTED == 0) || (P.ZICNTR_SUPPORTED == 1)) else $fatal(1, "ZIPHM_SUPPORTED requires ZICNTR_SUPPORTED"); + assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICBOM requires DCACHE_SUPPORTED"); + assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $fatal(1, "ZICBOZ requires DCACHE_SUPPORTED"); + assert ((P.SVPBMT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $fatal(1, "SVPBMT requires VIRTMEM_SUPPORTED and RV64"); + assert ((P.SVNAPOT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $fatal(1, "SVNAPOT requires VIRTMEM_SUPPORTED and RV64"); + assert ((P.ZCB_SUPPORTED == 0) || (P.M_SUPPORTED == 1 && (P.ZBA_SUPPORTED == 1 || P.XLEN == 32) && P.ZBB_SUPPORTED == 1)) else $fatal(1, "ZCB requires M and ZBB (and also ZBA for RV64)"); + assert ((P.C_SUPPORTED == 0) || (P.ZCA_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0 && P.ZCD_SUPPORTED == 0)) else $fatal(1, "C and ZCA/ZCD/ZCF cannot simultaneously be supported"); + assert ((P.ZCA_SUPPORTED == 1) || (P.ZCD_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0)) else $fatal(1, "ZCF or ZCD requires ZCA"); + assert ((P.ZCF_SUPPORTED == 0) || (P.F_SUPPORTED == 1)) else $fatal(1, "ZCF requires F"); + assert ((P.ZCD_SUPPORTED == 0) || (P.D_SUPPORTED == 1)) else $fatal(1, "ZCD requires D"); end endmodule diff --git a/testbench/testbench-linux-imperas.sv b/testbench/testbench-linux-imperas.sv deleted file mode 100644 index 8f22b82a7..000000000 --- a/testbench/testbench-linux-imperas.sv +++ /dev/null @@ -1,1050 +0,0 @@ -/////////////////////////////////////////// -// testbench-linux.sv -// -// Written: nboorstin@g.hmc.edu 2021 -// Modified: -// -// Purpose: Testbench for Buildroot Linux -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -`include "config.vh" -`include "BranchPredictorType.vh" - -// This is set from the command line script -// `define USE_IMPERAS_DV - -`ifdef USE_IMPERAS_DV - `include "idv/idv.svh" -`endif - -import cvw::*; - -`define DEBUG_TRACE 0 -// Debug Levels -// 0: don't check against QEMU -// 1: print disagreements with QEMU, but only halt on PCW disagreements -// 2: halt on any disagreement with QEMU except CSRs -// 3: halt on all disagreements with QEMU -// 4: print memory accesses whenever they happen -// 5: print everything - -module testbench; - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////// CONFIG //////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Recommend setting all of these in 'do' script using -G option - parameter INSTR_LIMIT = 0; // # of instructions at which to stop - parameter INSTR_WAVEON = 0; // # of instructions at which to turn on waves in graphical sim - parameter CHECKPOINT = 0; - parameter RISCV_DIR = "/opt/riscv"; - parameter NO_SPOOFING = 0; - - - `ifdef USE_IMPERAS_DV - import idvPkg::*; - import rvviApiPkg::*; - import idvApiPkg::*; - `endif - - - `include "parameter-defs.vh" - - - - //////////////////////////////////////////////////////////////////////////////////// - //////////////////////// SIGNAL / VAR / MACRO DECLARATIONS ///////////////////////// - //////////////////////////////////////////////////////////////////////////////////// - // ========== Testbench Core ========== - integer warningCount = 0; - integer errorCount = 0; - integer fault; - string ProgramAddrMapFile, ProgramLabelMapFile; - // ========== Initialization ========== - string testvectorDir; - string linuxImageDir; - integer memFile; - integer readResult; - // ========== Checkpointing ========== - string checkpointDir; - logic [1:0] initPriv; - // ========== Trace parsing & checking ========== - integer garbageInt; - string garbageString; - `define DECLARE_TRACE_SCANNER_SIGNALS(STAGE) \ - integer traceFile``STAGE; \ - integer matchCount``STAGE; \ - string line``STAGE; \ - string token``STAGE; \ - string ExpectedTokens``STAGE [31:0]; \ - integer index``STAGE; \ - integer StartIndex``STAGE, EndIndex``STAGE; \ - integer TokenIndex``STAGE; \ - integer MarkerIndex``STAGE; \ - integer NumCSR``STAGE; \ - logic [P.XLEN-1:0] ExpectedPC``STAGE; \ - logic [31:0] ExpectedInstr``STAGE; \ - string text``STAGE; \ - string MemOp``STAGE; \ - string RegWrite``STAGE; \ - integer ExpectedRegAdr``STAGE; \ - logic [P.XLEN-1:0] ExpectedRegValue``STAGE; \ - logic [P.XLEN-1:0] ExpectedIEUAdr``STAGE, ExpectedMemReadData``STAGE, ExpectedMemWriteData``STAGE; \ - string ExpectedCSRArray``STAGE[10:0]; \ - logic [P.XLEN-1:0] ExpectedCSRArrayValue``STAGE[10:0]; // *** might be redundant? - `DECLARE_TRACE_SCANNER_SIGNALS(E) - `DECLARE_TRACE_SCANNER_SIGNALS(M) - // M-stage expected values - logic checkInstrM; - integer MIPexpected, SIPexpected; - string name; - logic [P.AHBW-1:0] readDataExpected; - // W-stage expected values - logic checkInstrW; - logic [P.XLEN-1:0] ExpectedPCW; - logic [31:0] ExpectedInstrW; - string textW; - string RegWriteW; - integer ExpectedRegAdrW; - logic [P.XLEN-1:0] ExpectedRegValueW; - string MemOpW; - logic [P.XLEN-1:0] ExpectedIEUAdrW, ExpectedMemReadDataW, ExpectedMemWriteDataW; - integer NumCSRW; - string ExpectedCSRArrayW[10:0]; - logic [P.XLEN-1:0] ExpectedCSRArrayValueW[10:0]; - logic [P.XLEN-1:0] ExpectedIntType; - integer NumCSRWIndex; - integer NumCSRPostWIndex; - logic [P.XLEN-1:0] InstrCountW; - // ========== Interrupt parsing & spoofing ========== - string interrupt; - string interruptLine; - integer interruptFile; - integer interruptInstrCount; - integer interruptHartVal; - integer interruptAsyncVal; - longint interruptCauseVal; - longint interruptEpcVal; - longint interruptTVal; - string interruptDesc; - integer NextMIPexpected, NextSIPexpected; - integer NextMepcExpected; - logic [P.XLEN-1:0] AttemptedInstructionCount; - // ========== Misc Aliases ========== - `define RF dut.core.ieu.dp.regf.rf - `define PC dut.core.ifu.pcreg.q - `define PRIV_BASE dut.core.priv.priv - `define PRIV `PRIV_BASE.privmode.privmode.privmodereg.q - `define CSR_BASE `PRIV_BASE.csr - `define MEIP `PRIV_BASE.MExtInt - `define SEIP `PRIV_BASE.SExtInt - `define MTIP `PRIV_BASE.MTimerInt - `define HPMCOUNTER `CSR_BASE.counters.counters.HPMCOUNTER_REGW - `define MEDELEG `CSR_BASE.csrm.deleg.MEDELEGreg.q - `define MIDELEG `CSR_BASE.csrm.deleg.MIDELEGreg.q - `define MIE `CSR_BASE.csri.MIE_REGW - `define MIP `CSR_BASE.csri.MIP_REGW_writeable - `define MCAUSE `CSR_BASE.csrm.MCAUSEreg.q - `define SCAUSE `CSR_BASE.csrs.csrs.SCAUSEreg.q - `define MEPC `CSR_BASE.csrm.MEPCreg.q - `define SEPC `CSR_BASE.csrs.csrs.SEPCreg.q - `define MCOUNTEREN `CSR_BASE.csrm.mcounteren.MCOUNTERENreg.q - `define SCOUNTEREN `CSR_BASE.csrs.csrs.SCOUNTERENreg.q - `define MSCRATCH `CSR_BASE.csrm.MSCRATCHreg.q - `define SSCRATCH `CSR_BASE.csrs.csrs.SSCRATCHreg.q - `define MTVEC `CSR_BASE.csrm.MTVECreg.q - `define STVEC `CSR_BASE.csrs.csrs.STVECreg.q - `define SATP `CSR_BASE.csrs.csrs.genblk2.SATPreg.q - `define INSTRET `CSR_BASE.counters.counters.HPMCOUNTER_REGW[2] - `define MSTATUS `CSR_BASE.csrsr.MSTATUS_REGW - `define SSTATUS `CSR_BASE.csrsr.SSTATUS_REGW - `define STATUS_TSR `CSR_BASE.csrsr.STATUS_TSR_INT - `define STATUS_TW `CSR_BASE.csrsr.STATUS_TW_INT - `define STATUS_TVM `CSR_BASE.csrsr.STATUS_TVM_INT - `define STATUS_MXR `CSR_BASE.csrsr.STATUS_MXR_INT - `define STATUS_SUM `CSR_BASE.csrsr.STATUS_SUM_INT - `define STATUS_MPRV `CSR_BASE.csrsr.STATUS_MPRV_INT - `define STATUS_FS `CSR_BASE.csrsr.STATUS_FS_INT - `define STATUS_MPP `CSR_BASE.csrsr.STATUS_MPP - `define STATUS_SPP `CSR_BASE.csrsr.STATUS_SPP - `define STATUS_MPIE `CSR_BASE.csrsr.STATUS_MPIE - `define STATUS_SPIE `CSR_BASE.csrsr.STATUS_SPIE - `define STATUS_MIE `CSR_BASE.csrsr.STATUS_MIE - `define STATUS_SIE `CSR_BASE.csrsr.STATUS_SIE - `define UART dut.uncore.uncore.uart.uart.u - `define UART_IER `UART.IER - `define UART_LCR `UART.LCR - `define UART_MCR `UART.MCR - `define UART_SCR `UART.SCR - `define UART_IP `UART.INTR - `define PLIC dut.uncore.uncore.plic.plic - `define PLIC_INT_PRIORITY `PLIC.intPriority - `define PLIC_INT_ENABLE `PLIC.intEn - `define PLIC_THRESHOLD `PLIC.intThreshold - `define PCM dut.core.ifu.PCM - // ========== COMMON MACROS ========== - // Needed for initialization and core - `define SCAN_NEW_INTERRUPT \ - begin \ - $fgets(interruptLine, interruptFile); \ - //$display("Time %t, interruptLine %x", $time, interruptLine); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptInstrCount); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptHartVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptAsyncVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptCauseVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptEpcVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptTVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%s", interruptDesc); \ - end - - - - - - - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////// HARDWARE /////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Clock and Reset - logic clk, reset_ext; - logic reset; - initial begin reset_ext <= 1; # 22; reset_ext <= 0; end - always begin clk <= 1; # 5; clk <= 0; # 5; end - // Wally Interface - logic [P.AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; - logic HCLK, HRESETn; - logic HREADY; - logic HSELEXT; - logic HSELEXTSDC; - logic [P.PA_BITS-1:0] HADDR; - logic [P.AHBW-1:0] HWDATA; - logic [P.XLEN/8-1:0] HWSTRB; - logic HWRITE; - logic [2:0] HSIZE; - logic [2:0] HBURST; - logic [3:0] HPROT; - logic [1:0] HTRANS; - logic HMASTLOCK; - logic [31:0] GPIOIN; - logic [31:0] GPIOOUT, GPIOEN; - logic UARTSin, UARTSout; - - // FPGA-specific Stuff - logic SDCCLK; - logic SDCCmdIn; - logic SDCCmdOut; - logic SDCCmdOE; - logic [3:0] SDCDatIn; - logic SDCIntr; - logic SPIIn, SPIOut; - logic [3:0] SPICS; - - - // Hardwire UART, GPIO pins - assign GPIOIN = 0; - assign UARTSin = 1; - assign SDCIntr = 0; - - - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////// Cache Issue /////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - - // Duplicate copy of pipeline registers that are optimized out of some configurations - logic [31:0] NextInstrE, InstrM; - mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); - flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); - - logic probe; - if (NO_SPOOFING) - assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c - & InstrM != 32'h14021273 - & testbench.dut.core.InstrValidM; - - - `ifdef USE_IMPERAS_DV - - logic DCacheFlushDone, DCacheFlushStart; - - rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); - wallyTracer #(P) wallyTracer(rvvi); - - trace2log idv_trace2log(rvvi); -// trace2cov idv_trace2cov(rvvi); - - // enabling of comparison types - trace2api #(.CMP_PC (1), - .CMP_INS (1), - .CMP_GPR (1), - .CMP_FPR (1), - .CMP_VR (0), - .CMP_CSR (1) - ) idv_trace2api(rvvi); - - initial begin - int iter; - #1; - IDV_MAX_ERRORS = 3; - - // Initialize REF (do this before initializing the DUT) - if (!rvviVersionCheck(RVVI_API_VERSION)) begin - $display($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION)); - $fatal; - end - - void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); - void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); - void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC")); - void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56)); - void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); - - if (!rvviRefInit("")) begin - $display($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); - $fatal; - end - - // Volatile CSRs - void'(rvviRefCsrSetVolatile(0, 32'hC00)); // CYCLE - void'(rvviRefCsrSetVolatile(0, 32'hB00)); // MCYCLE - void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET - void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET - void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME - - // User HPMCOUNTER3 - HPMCOUNTER31 - for (iter='hC03; iter<='hC1F; iter++) begin - void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx - end - - // Machine MHPMCOUNTER3 - MHPMCOUNTER31 - for (iter='hB03; iter<='hB1F; iter++) begin - void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx - end - - // cannot predict this register due to latency between - // pending and taken - void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP - void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP - - // Privileges for PMA are set in the imperas.ic - // volatile (IO) regions are defined here - // only real ROM/RAM areas are BOOTROM and UNCORE_RAM - if (P.CLINT_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.CLINT_BASE, (P.CLINT_BASE + P.CLINT_RANGE))); - end - if (P.GPIO_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.GPIO_BASE, (P.GPIO_BASE + P.GPIO_RANGE))); - end - if (P.UART_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.UART_BASE, (P.UART_BASE + P.UART_RANGE))); - end - if (P.PLIC_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.PLIC_BASE, (P.PLIC_BASE + P.PLIC_RANGE))); - end - if (P.SDC_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.SDC_BASE, (P.SDC_BASE + P.SDC_RANGE))); - end - if (P.SPI_SUPPORTED) begin - void'(rvviRefMemorySetVolatile(P.SPI_BASE, (P.SPI_BASE + P.SPI_RANGE))); - end - - if(P.XLEN==32) begin - void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH - void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH - void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH - void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH - end - - void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!! - - // Load memory - begin - longint x64; - int x32[2]; - longint index; - - $sformat(testvectorDir,"%s/linux-testvectors/",RISCV_DIR); - - $display("RVVI Loading bootmem.bin"); - memFile = $fopen({testvectorDir,"bootmem.bin"}, "rb"); - index = 'h1000 - 8; - while(!$feof(memFile)) begin - index+=8; - readResult = $fread(x64, memFile); - if (x64 == 0) continue; - x32[0] = x64 & 'hffffffff; - x32[1] = x64 >> 32; - rvviRefMemoryWrite(0, index+0, x32[0], 4); - rvviRefMemoryWrite(0, index+4, x32[1], 4); - //$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); - end - $fclose(memFile); - - $display("RVVI Loading ram.bin"); - memFile = $fopen({testvectorDir,"ram.bin"}, "rb"); - index = 'h80000000 - 8; - while(!$feof(memFile)) begin - index+=8; - readResult = $fread(x64, memFile); - if (x64 == 0) continue; - x32[0] = x64 & 'hffffffff; - x32[1] = x64 >> 32; - rvviRefMemoryWrite(0, index+0, x32[0], 4); - rvviRefMemoryWrite(0, index+4, x32[1], 4); - //$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); - end - $fclose(memFile); - - $display("RVVI Loading Complete"); - - void'(rvviRefPcSet(0, 'h1000)); // set BOOTROM address - end - end - - always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7])); - always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11])); - always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9])); - always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3])); - always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1])); - always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5])); - - final begin - void'(rvviRefShutdown()); - end - - `endif - - - // Wally - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, - .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, - .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr, .SPIIn, .SPIOut, .SPICS); - - // W-stage hardware not needed by Wally itself - parameter nop = 'h13; - logic [P.XLEN-1:0] PCW; - logic [31:0] InstrW; - logic InstrValidW; - logic [P.XLEN-1:0] IEUAdrW, WriteDataW; - logic TrapW; - `define FLUSHW dut.core.FlushW - `define STALLW dut.core.StallW - flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW); - flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); - flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); - flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); - flopenr #(1) TrapWReg(clk, reset, ~`STALLW, dut.core.hzu.TrapM, TrapW); - - - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////// INITIALIZATION //////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // ========== CHECKPOINTING ========== - `define MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - logic DIM init``SIGNAL[ARRAY_MAX:ARRAY_MIN]; \ - initial begin \ - #1; \ - if (CHECKPOINT!=0) $readmemh({checkpointDir,"checkpoint-",`"SIGNAL`"}, init``SIGNAL); \ - end - - `define INIT_CHECKPOINT_SIMPLE_ARRAY(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - `MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - initial begin \ - if (CHECKPOINT!=0) begin \ - force `SIGNAL = init``SIGNAL[ARRAY_MAX:ARRAY_MIN]; \ - while (reset!==1) #1; \ - while (reset!==0) #1; \ - #1; \ - release `SIGNAL; \ - end \ - end - - `define INIT_CHECKPOINT_PACKED_ARRAY(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - `MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - for (i=ARRAY_MIN; i= 2)) fault = 1; \ - end - - `define checkCSR(CSR) \ - begin \ - if (CSR != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin \ - $display("%tns, %d instrs: CSR %s = %016x, does not equal expected value %016x", $time, AttemptedInstructionCount, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \ - if(`DEBUG_TRACE >= 3) fault = 1; \ - end \ - end - - // =========== CORE =========== - assign checkInstrM = dut.core.ieu.InstrValidM & ~dut.core.priv.priv.trap.InstrPageFaultM & ~dut.core.priv.priv.trap.InterruptM & ~dut.core.StallM; - always @(negedge clk) begin - `SCAN_NEW_INSTR_FROM_TRACE(E) - `SCAN_NEW_INSTR_FROM_TRACE(M) - end - - // step 1: register expected state into the write back stage. - always @(posedge clk) begin - if (reset) begin - ExpectedPCW <= '0; - ExpectedInstrW <= '0; - textW <= ""; - RegWriteW <= ""; - ExpectedRegAdrW <= '0; - ExpectedRegValueW <= '0; - ExpectedIEUAdrW <= '0; - MemOpW <= ""; - ExpectedMemWriteDataW <= '0; - ExpectedMemReadDataW <= '0; - NumCSRW <= '0; - end else if(~dut.core.StallW) begin - if(dut.core.FlushW) begin - ExpectedPCW <= '0; - ExpectedInstrW <= '0; - textW <= ""; - RegWriteW <= ""; - ExpectedRegAdrW <= '0; - ExpectedRegValueW <= '0; - ExpectedIEUAdrW <= '0; - MemOpW <= ""; - ExpectedMemWriteDataW <= '0; - ExpectedMemReadDataW <= '0; - NumCSRW <= '0; - end else if (dut.core.ieu.c.InstrValidM) begin - ExpectedPCW <= ExpectedPCM; - ExpectedInstrW <= ExpectedInstrM; - textW <= textM; - RegWriteW <= RegWriteM; - ExpectedRegAdrW <= ExpectedRegAdrM; - ExpectedRegValueW <= ExpectedRegValueM; - ExpectedIEUAdrW <= ExpectedIEUAdrM; - MemOpW <= MemOpM; - ExpectedMemWriteDataW <= ExpectedMemWriteDataM; - ExpectedMemReadDataW <= ExpectedMemReadDataM; - NumCSRW <= NumCSRM; - for(NumCSRWIndex = 0; NumCSRWIndex < NumCSRM; NumCSRWIndex++) begin - ExpectedCSRArrayW[NumCSRWIndex] = ExpectedCSRArrayM[NumCSRWIndex]; - ExpectedCSRArrayValueW[NumCSRWIndex] = ExpectedCSRArrayValueM[NumCSRWIndex]; - end - end - #1; - // override on special conditions - if(~dut.core.StallW) begin - if(textW.substr(0,5) == "rdtime") begin - //$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, AttemptedInstructionCount); - if(!NO_SPOOFING) - release dut.uncore.uncore.clint.clint.MTIME; - end - //if (ExpectedIEUAdrM == 'h10000005) begin - //$display("%tns, %d instrs: releasing force of ReadDataM.", $time, AttemptedInstructionCount); - //release dut.core.ieu.dp.ReadDataM; - //end - end - end - end - - // step2: make all checks in the write back stage. - assign checkInstrW = InstrValidW & ~dut.core.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction. - always @(negedge clk) begin - #1; // small delay allows interrupt spoofing to happen first - // always check PC, instruction bits - if (checkInstrW) begin - InstrCountW += 1; - // print progress message - if (AttemptedInstructionCount % 'd100000 == 0) $display("Reached %d instructions", AttemptedInstructionCount); - // turn on waves - if (AttemptedInstructionCount == INSTR_WAVEON) $stop; - // end sim - if ((AttemptedInstructionCount == INSTR_LIMIT) & (INSTR_LIMIT!=0)) begin $stop; $stop; end - fault = 0; - if (`DEBUG_TRACE >= 1) begin - `checkEQ("PCW",PCW,ExpectedPCW) - //`checkEQ("InstrW",InstrW,ExpectedInstrW) <-- not viable because of - // compressed to uncompressed conversion - `checkEQ("Instr Count",dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2],InstrCountW) - #2; // delay 2 ns. - if(`DEBUG_TRACE >= 5) begin - $display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, AttemptedInstructionCount, dut.core.ieu.dp.regf.a3, ExpectedRegAdrW); - $display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, AttemptedInstructionCount, ExpectedRegAdrW, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW); - end - if (RegWriteW == "GPR") begin - `checkEQ("Reg Write Address",dut.core.ieu.dp.regf.a3,ExpectedRegAdrW) - $sformat(name,"RF[%02d]",ExpectedRegAdrW); - `checkEQ(name, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW) - end - if (MemOpW.substr(0,2) == "Mem") begin - if(`DEBUG_TRACE >= 4) $display("\tIEUAdrW: %016x ? expected: %016x", IEUAdrW, ExpectedIEUAdrW); - `checkEQ("IEUAdrW",IEUAdrW,ExpectedIEUAdrW) - if(MemOpW == "MemR" | MemOpW == "MemRW") begin - if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.core.ieu.dp.ReadDataW, ExpectedMemReadDataW); - `checkEQ("ReadDataW",dut.core.ieu.dp.ReadDataW,ExpectedMemReadDataW) - end else if(MemOpW == "MemW" | MemOpW == "MemRW") begin - if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW); - `checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW) - end - end - // check csr - for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin - case(ExpectedCSRArrayW[NumCSRPostWIndex]) - "mhartid": `checkCSR(`CSR_BASE.csrm.MHARTID_REGW) - "mstatus": `checkCSR(`CSR_BASE.csrm.MSTATUS_REGW) - "sstatus": `checkCSR(`CSR_BASE.csrs.csrs.SSTATUS_REGW) - "mtvec": `checkCSR(`CSR_BASE.csrm.MTVEC_REGW) - "mie": `checkCSR(`CSR_BASE.csrm.MIE_REGW) - "mideleg": `checkCSR(`CSR_BASE.csrm.MIDELEG_REGW) - "medeleg": `checkCSR(`CSR_BASE.csrm.MEDELEG_REGW) - "mepc": `checkCSR(`CSR_BASE.csrm.MEPC_REGW) - "mtval": `checkCSR(`CSR_BASE.csrm.MTVAL_REGW) - "menvcfg": `checkCSR(`CSR_BASE.csrm.MENVCFG_REGW) - "sepc": `checkCSR(`CSR_BASE.csrs.csrs.SEPC_REGW) - "scause": `checkCSR(`CSR_BASE.csrs.csrs.SCAUSE_REGW) - "stvec": `checkCSR(`CSR_BASE.csrs.csrs.STVEC_REGW) - "stval": `checkCSR(`CSR_BASE.csrs.csrs.STVAL_REGW) - // "senvcfg": `checkCSR(`CSR_BASE.csrs.SENVCFG_REGW) // *** fix me - "mip": begin - `checkCSR(`CSR_BASE.csrm.MIP_REGW) - if(!NO_SPOOFING) begin - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<11) == 0) - force `MEIP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<09) == 0) - force `SEIP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & ((1<<11) | (1<<09))) == 0) - force `UART_IP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<07) == 0) - force `MTIP = 0; - end - end - endcase - end - if (fault == 1) begin - errorCount +=1; - $display("processed %0d instructions with %0d warnings", AttemptedInstructionCount, warningCount); - $stop; $stop; - end - end // if (`DEBUG_TRACE >= 1) - end // if (checkInstrW) - end // always @ (negedge clk) - - - // New IP spoofing - logic globalIntsBecomeEnabled; - assign globalIntsBecomeEnabled = (`CSR_BASE.csrm.WriteMSTATUSM || `CSR_BASE.csrs.csrs.WriteSSTATUSM) && (|(`CSR_BASE.CSRWriteValM & (~`CSR_BASE.csrm.MSTATUS_REGW) & 32'h22)); - logic checkInterruptM; - assign checkInterruptM = dut.core.ieu.InstrValidM & ~dut.core.priv.priv.trap.InstrPageFaultM & ~dut.core.priv.priv.trap.InterruptM; - - always @(negedge clk) begin - if(checkInterruptM) begin - if((interruptInstrCount+1) == AttemptedInstructionCount) begin - if(!NO_SPOOFING) begin - case (interruptCauseVal) - 11: begin - force `MEIP = 1; - force `UART_IP = 1; - end - 09: begin - force `SEIP = 1; - force `UART_IP = 1; - end - 07: force `MTIP = 1; - default: $display("Unsupported interrupt in interrupts.txt. cause = %0d",interruptCauseVal); - endcase - $display("Forcing interrupt."); - end - `SCAN_NEW_INTERRUPT - if (globalIntsBecomeEnabled) begin - $display("Enabled global interrupts"); - // The idea here is if a CSR instruction causes an interrupt by - // enabling interrupts, that CSR instruction will commit. - end else begin - // Other instructions, however, will get interrupted and not - // commit, so we don't want our W-stage checker to look for them - // and get confused when it doesn't find them. - garbageInt = $fgets(garbageString,traceFileE); - garbageInt = $fgets(garbageString,traceFileM); - AttemptedInstructionCount += 1; - end - end - end - end - - - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// Extra Features /////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Function Tracking - FunctionName #(P) FunctionName(.reset(reset), - .clk(clk), - .ProgramAddrMapFile(ProgramAddrMapFile), - .ProgramLabelMapFile(ProgramLabelMapFile)); - - // Instr Opcode Tracking - // For waveview convenience - string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; - instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, - dut.core.ifu.InstrRawF[31:0], - dut.core.ifu.InstrD, dut.core.ifu.InstrE, - InstrM, InstrW, - InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); - - // ------------------ - // Address Translator - // ------------------ - /** - * Walk the page table stored in ram according to sv39 logic and translate a - * virtual address to a physical address. - * - * See section 4.3.2 of the RISC-V Privileged specification for a full - * explanation of the below algorithm. - */ - logic SvMode, PTE_R, PTE_X; - logic [P.XLEN-1:0] SATP, PTE; - logic [55:0] BaseAdr, PAdr; - logic [8:0] VPN [2:0]; - logic [11:0] Offset; - function logic [P.XLEN-1:0] adrTranslator( - input logic [P.XLEN-1:0] adrIn); - begin - int i; - // Grab the SATP register from privileged unit - SATP = dut.core.priv.priv.csr.SATP_REGW; - // Split the virtual address into page number segments and offset - VPN[2] = adrIn[38:30]; - VPN[1] = adrIn[29:21]; - VPN[0] = adrIn[20:12]; - Offset = adrIn[11:0]; - // We do not support sv48; only sv39 - SvMode = SATP[63]; - // Only perform translation if translation is on and the processor is not - // in machine mode - if (SvMode & (dut.core.priv.priv.PrivilegeModeW != P.M_MODE)) begin - BaseAdr = SATP[43:0] << 12; - for (i = 2; i >= 0; i--) begin - PAdr = BaseAdr + (VPN[i] << 3); - // ram.memory.RAM is 64-bit addressed. PAdr specifies a byte. We right shift - // by 3 (the PTE size) to get the requested 64-bit PTE. - PTE = dut.uncore.uncore.ram.ram.memory.RAM[PAdr >> 3]; - PTE_R = PTE[1]; - PTE_X = PTE[3]; - if (PTE_R | PTE_X) begin - // Leaf page found - break; - end else begin - // Go to next level of table - BaseAdr = PTE[53:10] << 12; - end - end - // Determine which parts of the PTE page number to use based on the - // level of the page table we reached. - if (i == 2) begin - // Gigapage - assign adrTranslator = {8'b0, PTE[53:28], VPN[1], VPN[0], Offset}; - end else if (i == 1) begin - // Megapage - assign adrTranslator = {8'b0, PTE[53:19], VPN[0], Offset}; - end else begin - // Kilopage - assign adrTranslator = {8'b0, PTE[53:10], Offset}; - end - end else begin - // Direct translation if address translation is not on - assign adrTranslator = adrIn; - end - end - endfunction -endmodule diff --git a/testbench/testbench-linux.sv b/testbench/testbench-linux.sv deleted file mode 100644 index 011c4d148..000000000 --- a/testbench/testbench-linux.sv +++ /dev/null @@ -1,870 +0,0 @@ -/////////////////////////////////////////// -// testbench-linux.sv -// -// Written: nboorstin@g.hmc.edu 2021 -// Modified: -// -// Purpose: Testbench for Buildroot Linux -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 -// -// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file -// except in compliance with the License, or, at your option, the Apache License version 2.0. You -// may obtain a copy of the License at -// -// https://solderpad.org/licenses/SHL-2.1/ -// -// Unless required by applicable law or agreed to in writing, any work distributed under the -// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions -// and limitations under the License. -//////////////////////////////////////////////////////////////////////////////////////////////// - -`include "config.vh" -import cvw::*; - -`define DEBUG_TRACE 0 -// Debug Levels -// 0: don't check against QEMU -// 1: print disagreements with QEMU, but only halt on PCW disagreements -// 2: halt on any disagreement with QEMU except CSRs -// 3: halt on all disagreements with QEMU -// 4: print memory accesses whenever they happen -// 5: print everything - -module testbench; - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////// CONFIG //////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Recommend setting all of these in 'do' script using -G option - parameter INSTR_LIMIT = 0; // # of instructions at which to stop - parameter INSTR_WAVEON = 0; // # of instructions at which to turn on waves in graphical sim - parameter CHECKPOINT = 0; - parameter RISCV_DIR = "/opt/riscv"; - parameter NO_SPOOFING = 0; - - -`include "parameter-defs.vh" - - - //////////////////////////////////////////////////////////////////////////////////// - //////////////////////// SIGNAL / VAR / MACRO DECLARATIONS ///////////////////////// - //////////////////////////////////////////////////////////////////////////////////// - // ========== Testbench Core ========== - integer warningCount = 0; - integer errorCount = 0; - integer fault; - string ProgramAddrMapFile, ProgramLabelMapFile; - // ========== Initialization ========== - string testvectorDir; - string linuxImageDir; - integer memFile; - integer readResult; - // ========== Checkpointing ========== - string checkpointDir; - logic [1:0] initPriv; - // ========== Trace parsing & checking ========== - integer garbageInt; - string garbageString; - `define DECLARE_TRACE_SCANNER_SIGNALS(STAGE) \ - integer traceFile``STAGE; \ - integer matchCount``STAGE; \ - string line``STAGE; \ - string token``STAGE; \ - string ExpectedTokens``STAGE [31:0]; \ - integer index``STAGE; \ - integer StartIndex``STAGE, EndIndex``STAGE; \ - integer TokenIndex``STAGE; \ - integer MarkerIndex``STAGE; \ - integer NumCSR``STAGE; \ - logic [P.XLEN-1:0] ExpectedPC``STAGE; \ - logic [31:0] ExpectedInstr``STAGE; \ - string text``STAGE; \ - string MemOp``STAGE; \ - string RegWrite``STAGE; \ - integer ExpectedRegAdr``STAGE; \ - logic [P.XLEN-1:0] ExpectedRegValue``STAGE; \ - logic [P.XLEN-1:0] ExpectedIEUAdr``STAGE, ExpectedMemReadData``STAGE, ExpectedMemWriteData``STAGE; \ - string ExpectedCSRArray``STAGE[10:0]; \ - logic [P.XLEN-1:0] ExpectedCSRArrayValue``STAGE[10:0]; // *** might be redundant? - `DECLARE_TRACE_SCANNER_SIGNALS(E) - `DECLARE_TRACE_SCANNER_SIGNALS(M) - // M-stage expected values - logic checkInstrM; - integer MIPexpected, SIPexpected; - string name; - logic [P.AHBW-1:0] readDataExpected; - // W-stage expected values - logic checkInstrW; - logic [P.XLEN-1:0] ExpectedPCW; - logic [31:0] ExpectedInstrW; - string textW; - string RegWriteW; - integer ExpectedRegAdrW; - logic [P.XLEN-1:0] ExpectedRegValueW; - string MemOpW; - logic [P.XLEN-1:0] ExpectedIEUAdrW, ExpectedMemReadDataW, ExpectedMemWriteDataW; - integer NumCSRW; - string ExpectedCSRArrayW[10:0]; - logic [P.XLEN-1:0] ExpectedCSRArrayValueW[10:0]; - logic [P.XLEN-1:0] ExpectedIntType; - integer NumCSRWIndex; - integer NumCSRPostWIndex; - logic [P.XLEN-1:0] InstrCountW; - // ========== Interrupt parsing & spoofing ========== - string interrupt; - string interruptLine; - integer interruptFile; - integer interruptInstrCount; - integer interruptHartVal; - integer interruptAsyncVal; - longint interruptCauseVal; - longint interruptEpcVal; - longint interruptTVal; - string interruptDesc; - integer NextMIPexpected, NextSIPexpected; - integer NextMepcExpected; - logic [P.XLEN-1:0] AttemptedInstructionCount; - // ========== Misc Aliases ========== - `define RF dut.core.ieu.dp.regf.rf - `define PC dut.core.ifu.pcreg.q - `define PRIV_BASE dut.core.priv.priv - `define PRIV `PRIV_BASE.privmode.privmode.privmodereg.q - `define CSR_BASE `PRIV_BASE.csr - `define MEIP `PRIV_BASE.MExtInt - `define SEIP `PRIV_BASE.SExtInt - `define MTIP `PRIV_BASE.MTimerInt - `define HPMCOUNTER `CSR_BASE.counters.counters.HPMCOUNTER_REGW - `define MEDELEG `CSR_BASE.csrm.deleg.MEDELEGreg.q - `define MIDELEG `CSR_BASE.csrm.deleg.MIDELEGreg.q - `define MIE `CSR_BASE.csri.MIE_REGW - `define MIP `CSR_BASE.csri.MIP_REGW_writeable - `define MCAUSE `CSR_BASE.csrm.MCAUSEreg.q - `define SCAUSE `CSR_BASE.csrs.csrs.SCAUSEreg.q - `define MEPC `CSR_BASE.csrm.MEPCreg.q - `define SEPC `CSR_BASE.csrs.csrs.SEPCreg.q - `define MCOUNTEREN `CSR_BASE.csrm.mcounteren.MCOUNTERENreg.q - `define SCOUNTEREN `CSR_BASE.csrs.csrs.SCOUNTERENreg.q - `define MSCRATCH `CSR_BASE.csrm.MSCRATCHreg.q - `define SSCRATCH `CSR_BASE.csrs.csrs.SSCRATCHreg.q - `define MTVEC `CSR_BASE.csrm.MTVECreg.q - `define STVEC `CSR_BASE.csrs.csrs.STVECreg.q - `define SATP `CSR_BASE.csrs.csrs.genblk2.SATPreg.q - `define INSTRET `CSR_BASE.counters.counters.HPMCOUNTER_REGW[2] - `define MSTATUS `CSR_BASE.csrsr.MSTATUS_REGW - `define SSTATUS `CSR_BASE.csrsr.SSTATUS_REGW - `define STATUS_TSR `CSR_BASE.csrsr.STATUS_TSR_INT - `define STATUS_TW `CSR_BASE.csrsr.STATUS_TW_INT - `define STATUS_TVM `CSR_BASE.csrsr.STATUS_TVM_INT - `define STATUS_MXR `CSR_BASE.csrsr.STATUS_MXR_INT - `define STATUS_SUM `CSR_BASE.csrsr.STATUS_SUM_INT - `define STATUS_MPRV `CSR_BASE.csrsr.STATUS_MPRV_INT - `define STATUS_FS `CSR_BASE.csrsr.STATUS_FS_INT - `define STATUS_MPP `CSR_BASE.csrsr.STATUS_MPP - `define STATUS_SPP `CSR_BASE.csrsr.STATUS_SPP - `define STATUS_MPIE `CSR_BASE.csrsr.STATUS_MPIE - `define STATUS_SPIE `CSR_BASE.csrsr.STATUS_SPIE - `define STATUS_MIE `CSR_BASE.csrsr.STATUS_MIE - `define STATUS_SIE `CSR_BASE.csrsr.STATUS_SIE - `define UART dut.uncore.uncore.uart.uart.u - `define UART_IER `UART.IER - `define UART_LCR `UART.LCR - `define UART_MCR `UART.MCR - `define UART_SCR `UART.SCR - `define UART_IP `UART.INTR - `define PLIC dut.uncore.uncore.plic.plic - `define PLIC_INT_PRIORITY `PLIC.intPriority - `define PLIC_INT_ENABLE `PLIC.intEn - `define PLIC_THRESHOLD `PLIC.intThreshold - `define PCM dut.core.ifu.PCM - // ========== COMMON MACROS ========== - // Needed for initialization and core - `define SCAN_NEW_INTERRUPT \ - begin \ - $fgets(interruptLine, interruptFile); \ - //$display("Time %t, interruptLine %x", $time, interruptLine); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptInstrCount); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptHartVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%d", interruptAsyncVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptCauseVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptEpcVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%x", interruptTVal); \ - $fgets(interruptLine, interruptFile); \ - $sscanf(interruptLine, "%s", interruptDesc); \ - end - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////// Cache Issue /////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - - // Duplicate copy of pipeline registers that are optimized out of some configurations - logic [31:0] NextInstrE, InstrM; - mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); - flopenr #(32) InstrMReg(dut.core.clk, dut.core.reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); - - logic probe; - if (NO_SPOOFING) - assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c - & InstrM != 32'h14021273 - & testbench.dut.core.InstrValidM; - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////// HARDWARE /////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Clock and Reset - logic clk, reset_ext; - logic reset; - initial begin reset_ext <= 1; # 22; reset_ext <= 0; end - always begin clk <= 1; # 5; clk <= 0; # 5; end - // Wally Interface - logic [P.AHBW-1:0] HRDATAEXT; - logic HREADYEXT, HRESPEXT; - logic HCLK, HRESETn; - logic HREADY; - logic HSELEXT; - logic HSELEXTSDC; - logic [P.PA_BITS-1:0] HADDR; - logic [P.AHBW-1:0] HWDATA; - logic [P.XLEN/8-1:0] HWSTRB; - logic HWRITE; - logic [2:0] HSIZE; - logic [2:0] HBURST; - logic [3:0] HPROT; - logic [1:0] HTRANS; - logic HMASTLOCK; - logic [31:0] GPIOIN; - logic [31:0] GPIOOUT, GPIOEN; - logic UARTSin, UARTSout; - logic SPIIn, SPIOut; - logic [3:0] SPICS; - - // FPGA-specific Stuff - logic SDCIntr; - - // Hardwire UART, GPIO pins - assign GPIOIN = 0; - assign UARTSin = 1; - assign SDCIntr = 0; - - // Wally - wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, - .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, - .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr, .SPICS, .SPIOut, .SPIIn); - - // W-stage hardware not needed by Wally itself - parameter nop = 'h13; - logic [P.XLEN-1:0] PCW; - logic [31:0] InstrW; - logic InstrValidW; - logic [P.XLEN-1:0] IEUAdrW, WriteDataW; - logic TrapW; - `define FLUSHW dut.core.FlushW - `define STALLW dut.core.StallW - flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW); - flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); - flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); - flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); - flopenr #(1) TrapWReg(clk, reset, ~`STALLW, dut.core.hzu.TrapM, TrapW); - - - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////// INITIALIZATION //////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // ========== CHECKPOINTING ========== - `define MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - logic DIM init``SIGNAL[ARRAY_MAX:ARRAY_MIN]; \ - initial begin \ - #1; \ - if (CHECKPOINT!=0) $readmemh({checkpointDir,"checkpoint-",`"SIGNAL`"}, init``SIGNAL); \ - end - - `define INIT_CHECKPOINT_SIMPLE_ARRAY(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - `MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - initial begin \ - if (CHECKPOINT!=0) begin \ - force `SIGNAL = init``SIGNAL[ARRAY_MAX:ARRAY_MIN]; \ - while (reset!==1) #1; \ - while (reset!==0) #1; \ - #1; \ - release `SIGNAL; \ - end \ - end - - `define INIT_CHECKPOINT_PACKED_ARRAY(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - `MAKE_CHECKPOINT_INIT_SIGNAL(SIGNAL,DIM,ARRAY_MAX,ARRAY_MIN) \ - for (i=ARRAY_MIN; i= 2)) fault = 1; \ - end - - `define checkCSR(CSR) \ - begin \ - if (CSR != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin \ - $display("%tns, %d instrs: CSR %s = %016x, does not equal expected value %016x", $time, AttemptedInstructionCount, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \ - if(`DEBUG_TRACE >= 3) fault = 1; \ - end \ - end - - // =========== CORE =========== - assign checkInstrM = dut.core.ieu.InstrValidM & ~dut.core.priv.priv.trap.InstrPageFaultM & ~dut.core.priv.priv.trap.InterruptM & ~dut.core.StallM; - always @(negedge clk) begin - `SCAN_NEW_INSTR_FROM_TRACE(E) - `SCAN_NEW_INSTR_FROM_TRACE(M) - end - - // step 1: register expected state into the write back stage. - always @(posedge clk) begin - if (reset) begin - ExpectedPCW <= '0; - ExpectedInstrW <= '0; - textW <= ""; - RegWriteW <= ""; - ExpectedRegAdrW <= '0; - ExpectedRegValueW <= '0; - ExpectedIEUAdrW <= '0; - MemOpW <= ""; - ExpectedMemWriteDataW <= '0; - ExpectedMemReadDataW <= '0; - NumCSRW <= '0; - end else if(~dut.core.StallW) begin - if(dut.core.FlushW) begin - ExpectedPCW <= '0; - ExpectedInstrW <= '0; - textW <= ""; - RegWriteW <= ""; - ExpectedRegAdrW <= '0; - ExpectedRegValueW <= '0; - ExpectedIEUAdrW <= '0; - MemOpW <= ""; - ExpectedMemWriteDataW <= '0; - ExpectedMemReadDataW <= '0; - NumCSRW <= '0; - end else if (dut.core.ieu.c.InstrValidM) begin - ExpectedPCW <= ExpectedPCM; - ExpectedInstrW <= ExpectedInstrM; - textW <= textM; - RegWriteW <= RegWriteM; - ExpectedRegAdrW <= ExpectedRegAdrM; - ExpectedRegValueW <= ExpectedRegValueM; - ExpectedIEUAdrW <= ExpectedIEUAdrM; - MemOpW <= MemOpM; - ExpectedMemWriteDataW <= ExpectedMemWriteDataM; - ExpectedMemReadDataW <= ExpectedMemReadDataM; - NumCSRW <= NumCSRM; - for(NumCSRWIndex = 0; NumCSRWIndex < NumCSRM; NumCSRWIndex++) begin - ExpectedCSRArrayW[NumCSRWIndex] = ExpectedCSRArrayM[NumCSRWIndex]; - ExpectedCSRArrayValueW[NumCSRWIndex] = ExpectedCSRArrayValueM[NumCSRWIndex]; - end - end - #1; - // override on special conditions - if(~dut.core.StallW) begin - if(textW.substr(0,5) == "rdtime") begin - //$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, AttemptedInstructionCount); - if(!NO_SPOOFING) - release dut.uncore.uncore.clint.clint.MTIME; - end - //if (ExpectedIEUAdrM == 'h10000005) begin - //$display("%tns, %d instrs: releasing force of ReadDataM.", $time, AttemptedInstructionCount); - //release dut.core.ieu.dp.ReadDataM; - //end - end - end - end - - // step2: make all checks in the write back stage. - assign checkInstrW = InstrValidW & ~dut.core.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction. - always @(negedge clk) begin - #1; // small delay allows interrupt spoofing to happen first - // always check PC, instruction bits - if (checkInstrW) begin - InstrCountW += 1; - // print progress message - if (AttemptedInstructionCount % 'd100000 == 0) $display("Reached %d instructions", AttemptedInstructionCount); - // turn on waves - if (AttemptedInstructionCount == INSTR_WAVEON) $stop; - // end sim - if ((AttemptedInstructionCount == INSTR_LIMIT) & (INSTR_LIMIT!=0)) begin $stop; $stop; end - fault = 0; - if (`DEBUG_TRACE >= 1) begin - `checkEQ("PCW",PCW,ExpectedPCW) - //`checkEQ("InstrW",InstrW,ExpectedInstrW) <-- not viable because of - // compressed to uncompressed conversion - `checkEQ("Instr Count",dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2],InstrCountW) - #2; // delay 2 ns. - if(`DEBUG_TRACE >= 5) begin - $display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, AttemptedInstructionCount, dut.core.ieu.dp.regf.a3, ExpectedRegAdrW); - $display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, AttemptedInstructionCount, ExpectedRegAdrW, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW); - end - if (RegWriteW == "GPR") begin - `checkEQ("Reg Write Address",dut.core.ieu.dp.regf.a3,ExpectedRegAdrW) - $sformat(name,"RF[%02d]",ExpectedRegAdrW); - `checkEQ(name, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW) - end - if (MemOpW.substr(0,2) == "Mem") begin - if(`DEBUG_TRACE >= 4) $display("\tIEUAdrW: %016x ? expected: %016x", IEUAdrW, ExpectedIEUAdrW); - `checkEQ("IEUAdrW",IEUAdrW,ExpectedIEUAdrW) - if(MemOpW == "MemR" | MemOpW == "MemRW") begin - if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.core.ieu.dp.ReadDataW, ExpectedMemReadDataW); - `checkEQ("ReadDataW",dut.core.ieu.dp.ReadDataW,ExpectedMemReadDataW) - end else if(MemOpW == "MemW" | MemOpW == "MemRW") begin - if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW); - `checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW) - end - end - // check csr - for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin - case(ExpectedCSRArrayW[NumCSRPostWIndex]) - "mhartid": `checkCSR(`CSR_BASE.csrm.MHARTID_REGW) - "mstatus": `checkCSR(`CSR_BASE.csrm.MSTATUS_REGW) - "sstatus": `checkCSR(`CSR_BASE.csrs.csrs.SSTATUS_REGW) - "mtvec": `checkCSR(`CSR_BASE.csrm.MTVEC_REGW) - "mie": `checkCSR(`CSR_BASE.csrm.MIE_REGW) - "mideleg": `checkCSR(`CSR_BASE.csrm.MIDELEG_REGW) - "medeleg": `checkCSR(`CSR_BASE.csrm.MEDELEG_REGW) - "mepc": `checkCSR(`CSR_BASE.csrm.MEPC_REGW) - "mtval": `checkCSR(`CSR_BASE.csrm.MTVAL_REGW) - "sepc": `checkCSR(`CSR_BASE.csrs.csrs.SEPC_REGW) - "scause": `checkCSR(`CSR_BASE.csrs.csrs.SCAUSE_REGW) - "stvec": `checkCSR(`CSR_BASE.csrs.csrs.STVEC_REGW) - "stval": `checkCSR(`CSR_BASE.csrs.csrs.STVAL_REGW) - "mip": begin - `checkCSR(`CSR_BASE.csrm.MIP_REGW) - if(!NO_SPOOFING) begin - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<11) == 0) - force `MEIP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<09) == 0) - force `SEIP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & ((1<<11) | (1<<09))) == 0) - force `UART_IP = 0; - if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<07) == 0) - force `MTIP = 0; - end - end - endcase - end - if (fault == 1) begin - errorCount +=1; - $display("processed %0d instructions with %0d warnings", AttemptedInstructionCount, warningCount); - $stop; $stop; - end - end // if (`DEBUG_TRACE >= 1) - end // if (checkInstrW) - end // always @ (negedge clk) - - - // New IP spoofing - logic globalIntsBecomeEnabled; - assign globalIntsBecomeEnabled = (`CSR_BASE.csrm.WriteMSTATUSM || `CSR_BASE.csrs.csrs.WriteSSTATUSM) && (|(`CSR_BASE.CSRWriteValM & (~`CSR_BASE.csrm.MSTATUS_REGW) & 32'h22)); - logic checkInterruptM; - assign checkInterruptM = dut.core.ieu.InstrValidM & ~dut.core.priv.priv.trap.InstrPageFaultM & ~dut.core.priv.priv.trap.InterruptM; - - always @(negedge clk) begin - if(checkInterruptM) begin - if((interruptInstrCount+1) == AttemptedInstructionCount) begin - if(!NO_SPOOFING) begin - case (interruptCauseVal) - 11: begin - force `MEIP = 1; - force `UART_IP = 1; - end - 09: begin - force `SEIP = 1; - force `UART_IP = 1; - end - 07: force `MTIP = 1; - default: $display("Unsupported interrupt in interrupts.txt. cause = %0d",interruptCauseVal); - endcase - $display("Forcing interrupt."); - end - `SCAN_NEW_INTERRUPT - if (globalIntsBecomeEnabled) begin - $display("Enabled global interrupts"); - // The idea here is if a CSR instruction causes an interrupt by - // enabling interrupts, that CSR instruction will commit. - end else begin - // Other instructions, however, will get interrupted and not - // commit, so we don't want our W-stage checker to look for them - // and get confused when it doesn't find them. - garbageInt = $fgets(garbageString,traceFileE); - garbageInt = $fgets(garbageString,traceFileM); - AttemptedInstructionCount += 1; - end - end - end - end - - - - - - - - - - - /////////////////////////////////////////////////////////////////////////////// - //////////////////////////////// Extra Features /////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - // Function Tracking - FunctionName #(P) FunctionName(.reset(reset), - .clk(clk), - .ProgramAddrMapFile(ProgramAddrMapFile), - .ProgramLabelMapFile(ProgramLabelMapFile)); - - // Instr Opcode Tracking - // For waveview convenience - string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; - instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, - dut.core.ifu.InstrRawF[31:0], - dut.core.ifu.InstrD, dut.core.ifu.InstrE, - InstrM, InstrW, - InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); - - // ------------------ - // Address Translator - // ------------------ - /** - * Walk the page table stored in ram according to sv39 logic and translate a - * virtual address to a physical address. - * - * See section 4.3.2 of the RISC-V Privileged specification for a full - * explanation of the below algorithm. - */ - logic SvMode, PTE_R, PTE_X; - logic [P.XLEN-1:0] SATP, PTE; - logic [55:0] BaseAdr, PAdr; - logic [8:0] VPN [2:0]; - logic [11:0] Offset; - function logic [P.XLEN-1:0] adrTranslator( - input logic [P.XLEN-1:0] adrIn); - begin - int i; - // Grab the SATP register from privileged unit - SATP = dut.core.priv.priv.csr.SATP_REGW; - // Split the virtual address into page number segments and offset - VPN[2] = adrIn[38:30]; - VPN[1] = adrIn[29:21]; - VPN[0] = adrIn[20:12]; - Offset = adrIn[11:0]; - // We do not support sv48; only sv39 - SvMode = SATP[63]; - // Only perform translation if translation is on and the processor is not - // in machine mode - if (SvMode & (dut.core.priv.priv.PrivilegeModeW != P.M_MODE)) begin - BaseAdr = SATP[43:0] << 12; - for (i = 2; i >= 0; i--) begin - PAdr = BaseAdr + (VPN[i] << 3); - // ram.memory.RAM is 64-bit addressed. PAdr specifies a byte. We right shift - // by 3 (the PTE size) to get the requested 64-bit PTE. - PTE = dut.uncore.uncore.ram.ram.memory.RAM[PAdr >> 3]; - PTE_R = PTE[1]; - PTE_X = PTE[3]; - if (PTE_R | PTE_X) begin - // Leaf page found - break; - end else begin - // Go to next level of table - BaseAdr = PTE[53:10] << 12; - end - end - // Determine which parts of the PTE page number to use based on the - // level of the page table we reached. - if (i == 2) begin - // Gigapage - assign adrTranslator = {8'b0, PTE[53:28], VPN[1], VPN[0], Offset}; - end else if (i == 1) begin - // Megapage - assign adrTranslator = {8'b0, PTE[53:19], VPN[0], Offset}; - end else begin - // Kilopage - assign adrTranslator = {8'b0, PTE[53:10], Offset}; - end - end else begin - // Direct translation if address translation is not on - assign adrTranslator = adrIn; - end - end - endfunction -endmodule diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 893eb678b..0f8194e62 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -29,6 +29,10 @@ `include "tests.vh" `include "BranchPredictorType.vh" +`ifdef USE_IMPERAS_DV + `include "idv/idv.svh" +`endif + import cvw::*; module testbench; @@ -40,7 +44,15 @@ module testbench; parameter BPRED_LOGGER=0; parameter I_CACHE_ADDR_LOGGER=0; parameter D_CACHE_ADDR_LOGGER=0; - + parameter RISCV_DIR = "/opt/riscv"; + parameter INSTR_LIMIT = 0; + + `ifdef USE_IMPERAS_DV + import idvPkg::*; + import rvviApiPkg::*; + import idvApiPkg::*; + `endif + `include "parameter-defs.vh" logic clk; @@ -121,7 +133,7 @@ module testbench; "wally64periph": tests = wally64periph; "coremark": tests = coremark; "fpga": tests = fpga; - "ahb" : tests = ahb; + "ahb64" : tests = ahb64; "coverage64gc" : tests = coverage64gc; "arch64zba": if (P.ZBA_SUPPORTED) tests = arch64zba; "arch64zbb": if (P.ZBB_SUPPORTED) tests = arch64zbb; @@ -130,10 +142,11 @@ module testbench; "arch64zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch64zicboz; "arch64zcb": if (P.ZCB_SUPPORTED) tests = arch64zcb; "arch64zfh": if (P.ZFH_SUPPORTED) tests = arch64zfh; -// "arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma; *** not yet in riscv-arch-tst PR367 + "arch64zfh_fma": if (P.ZFH_SUPPORTED) tests = arch64zfh_fma; "arch64zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch64zfh_divsqrt; "arch64zfaf": if (P.ZFA_SUPPORTED) tests = arch64zfaf; "arch64zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch64zfad; + "buildroot": tests = buildroot; endcase end else begin // RV32 case (TEST) @@ -162,6 +175,7 @@ module testbench; "wally32i": tests = wally32i; "wally32priv": tests = wally32priv; "wally32periph": tests = wally32periph; + "ahb32" : tests = ahb32; "embench": tests = embench; "coremark": tests = coremark; "arch32zba": if (P.ZBA_SUPPORTED) tests = arch32zba; @@ -171,7 +185,7 @@ module testbench; "arch32zicboz": if (P.ZICBOZ_SUPPORTED) tests = arch32zicboz; "arch32zcb": if (P.ZCB_SUPPORTED) tests = arch32zcb; "arch32zfh": if (P.ZFH_SUPPORTED) tests = arch32zfh; - // "arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma; *** not yet in riscv-arch-tst PR367 + "arch32zfh_fma": if (P.ZFH_SUPPORTED) tests = arch32zfh_fma; "arch32zfh_divsqrt": if (P.ZFH_SUPPORTED) tests = arch32zfh_divsqrt; "arch32zfaf": if (P.ZFA_SUPPORTED) tests = arch32zfaf; "arch32zfad": if (P.ZFA_SUPPORTED & P.D_SUPPORTED) tests = arch32zfad; @@ -179,7 +193,7 @@ module testbench; end if (tests.size() == 0) begin $display("TEST %s not supported in this configuration", TEST); - $stop; + $finish; end end // initial begin @@ -209,7 +223,7 @@ module testbench; logic ResetCntRst; logic CopyRAM; - string signame, memfilename, pathname; + string signame, memfilename, bootmemfilename, pathname; integer begin_signature_addr, end_signature_addr, signature_size; assign ResetThreshold = 3'd5; @@ -278,10 +292,17 @@ module testbench; always @(posedge clk) begin if(SelectTest) begin if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; + else if(TEST == "buildroot") begin + memfilename = {RISCV_DIR, "/linux-testvectors/ram.bin"}; + bootmemfilename = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; + end else memfilename = {pathname, tests[test], ".elf.memfile"}; if (riscofTest) begin ProgramAddrMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.addr"}; ProgramLabelMapFile = {pathname, tests[test], "/ref/ref.elf.objdump.lab"}; + end else if (TEST == "buildroot") begin + ProgramAddrMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.addr"}; + ProgramLabelMapFile = {RISCV_DIR, "/buildroot/output/images/disassembly/vmlinux.objdump.lab"}; end else begin ProgramAddrMapFile = {pathname, tests[test], ".elf.objdump.addr"}; ProgramLabelMapFile = {pathname, tests[test], ".elf.objdump.lab"}; @@ -325,19 +346,18 @@ module testbench; end else begin // for tests with no self checking mechanism, read .signature.output file and compare to check for errors // clear signature to prevent contamination from previous tests + if (!begin_signature_addr) + $display("begin_signature addr not found in %s", ProgramLabelMapFile); + else if (TEST != "embench") begin // *** quick hack for embench. need a better long term solution + CheckSignature(pathname, tests[test], riscofTest, begin_signature_addr, errors); + if(errors > 0) totalerrors = totalerrors + 1; + end end - - if (!begin_signature_addr) - $display("begin_signature addr not found in %s", ProgramLabelMapFile); - else if (TEST != "embench") begin // *** quick hack for embench. need a better long term solution - CheckSignature(pathname, tests[test], riscofTest, begin_signature_addr, errors); - end - if(errors > 0) totalerrors = totalerrors + 1; test = test + 1; // *** this probably needs to be moved. if (test == tests.size()) begin if (totalerrors == 0) $display("SUCCESS! All tests ran without failures."); else $display("FAIL: %d test programs had errors", totalerrors); - $stop; + $stop; // if this is changed to $finish, wally-batch.do does not go to the next step to run coverage end end end @@ -352,6 +372,8 @@ module testbench; integer StartIndex; integer EndIndex; integer BaseIndex; + integer memFile; + integer readResult; if (P.SDC_SUPPORTED) begin always @(posedge clk) begin if (LoadMem) begin @@ -373,7 +395,16 @@ module testbench; end else if (P.BUS_SUPPORTED) begin : bus_supported always @(posedge clk) begin if (LoadMem) begin - $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); + if (TEST == "buildroot") begin + memFile = $fopen(bootmemfilename, "rb"); + readResult = $fread(dut.uncore.uncore.bootrom.bootrom.memory.ROM, memFile); + $fclose(memFile); + memFile = $fopen(memfilename, "rb"); + readResult = $fread(dut.uncore.uncore.ram.ram.memory.RAM, memFile); + $fclose(memFile); + end else + $readmemh(memfilename, dut.uncore.uncore.ram.ram.memory.RAM); + if (TEST == "embench") $display("Read memfile %s", memfilename); end if (CopyRAM) begin LogXLEN = (1 + P.XLEN/32); // 2 for rv32 and 3 for rv64 @@ -519,6 +550,175 @@ module testbench; DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone)); + if(P.ZICSR_SUPPORTED & INSTR_LIMIT != 0) begin + logic [P.XLEN-1:0] Minstret; + assign Minstret = testbench.dut.core.priv.priv.csr.counters.counters.HPMCOUNTER_REGW[2]; + always @(negedge clk) begin + if((Minstret != 0) && (Minstret % 'd100000 == 0)) $display("Reached %d instructions", Minstret); + if((Minstret == INSTR_LIMIT) & (INSTR_LIMIT!=0)) begin $stop; $stop; end + end +end + + //////////////////////////////////////////////////////////////////////////////// + // ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// +`ifdef USE_IMPERAS_DV + + rvviTrace #(.XLEN(P.XLEN), .FLEN(P.FLEN)) rvvi(); + wallyTracer #(P) wallyTracer(rvvi); + + trace2log idv_trace2log(rvvi); + // trace2cov idv_trace2cov(rvvi); + + // enabling of comparison types + trace2api #(.CMP_PC (1), + .CMP_INS (1), + .CMP_GPR (1), + .CMP_FPR (1), + .CMP_VR (0), + .CMP_CSR (1) + ) idv_trace2api(rvvi); + + initial begin + int iter; + #1; + IDV_MAX_ERRORS = 3; + + // Initialize REF (do this before initializing the DUT) + if (!rvviVersionCheck(RVVI_API_VERSION)) begin + $display($sformatf("%m @ t=%0t: Expecting RVVI API version %0d.", $time, RVVI_API_VERSION)); + $fatal; + end + + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VENDOR, "riscv.ovpworld.org")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_NAME, "riscv")); + void'(rvviRefConfigSetString(IDV_CONFIG_MODEL_VARIANT, "RV64GC")); + void'(rvviRefConfigSetInt(IDV_CONFIG_MODEL_ADDRESS_BUS_WIDTH, 56)); + void'(rvviRefConfigSetInt(IDV_CONFIG_MAX_NET_LATENCY_RETIREMENTS, 6)); + + if (!rvviRefInit("")) begin + $display($sformatf("%m @ t=%0t: rvviRefInit failed", $time)); + $fatal; + end + + // Volatile CSRs + void'(rvviRefCsrSetVolatile(0, 32'hC00)); // CYCLE + void'(rvviRefCsrSetVolatile(0, 32'hB00)); // MCYCLE + void'(rvviRefCsrSetVolatile(0, 32'hC02)); // INSTRET + void'(rvviRefCsrSetVolatile(0, 32'hB02)); // MINSTRET + void'(rvviRefCsrSetVolatile(0, 32'hC01)); // TIME + + // User HPMCOUNTER3 - HPMCOUNTER31 + for (iter='hC03; iter<='hC1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // HPMCOUNTERx + end + + // Machine MHPMCOUNTER3 - MHPMCOUNTER31 + for (iter='hB03; iter<='hB1F; iter++) begin + void'(rvviRefCsrSetVolatile(0, iter)); // MHPMCOUNTERx + end + + // cannot predict this register due to latency between + // pending and taken + void'(rvviRefCsrSetVolatile(0, 32'h344)); // MIP + void'(rvviRefCsrSetVolatile(0, 32'h144)); // SIP + + // Privileges for PMA are set in the imperas.ic + // volatile (IO) regions are defined here + // only real ROM/RAM areas are BOOTROM and UNCORE_RAM + if (P.CLINT_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.CLINT_BASE, (P.CLINT_BASE + P.CLINT_RANGE))); + end + if (P.GPIO_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.GPIO_BASE, (P.GPIO_BASE + P.GPIO_RANGE))); + end + if (P.UART_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.UART_BASE, (P.UART_BASE + P.UART_RANGE))); + end + if (P.PLIC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.PLIC_BASE, (P.PLIC_BASE + P.PLIC_RANGE))); + end + if (P.SDC_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SDC_BASE, (P.SDC_BASE + P.SDC_RANGE))); + end + if (P.SPI_SUPPORTED) begin + void'(rvviRefMemorySetVolatile(P.SPI_BASE, (P.SPI_BASE + P.SPI_RANGE))); + end + + if(P.XLEN==32) begin + void'(rvviRefCsrSetVolatile(0, 32'hC80)); // CYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hB80)); // MCYCLEH + void'(rvviRefCsrSetVolatile(0, 32'hC82)); // INSTRETH + void'(rvviRefCsrSetVolatile(0, 32'hB82)); // MINSTRETH + end + + void'(rvviRefCsrSetVolatile(0, 32'h104)); // SIE - Temporary!!!! + + // Load memory + // *** RT: This section can probably be moved into the same chunk of code which + // loads the memories. However I'm not sure that ImperasDV supports reloading + // the memories without relaunching the simulator. + begin + longint x64; + int x32[2]; + longint index; + string memfilenameImperasDV, bootmemfilenameImperasDV; + + memfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/ram.bin"}; + bootmemfilenameImperasDV = {RISCV_DIR, "/linux-testvectors/bootmem.bin"}; + + $display("RVVI Loading bootmem.bin"); + memFile = $fopen(bootmemfilenameImperasDV, "rb"); + index = 'h1000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("boot %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading ram.bin"); + memFile = $fopen(memfilenameImperasDV, "rb"); + index = 'h80000000 - 8; + while(!$feof(memFile)) begin + index+=8; + readResult = $fread(x64, memFile); + if (x64 == 0) continue; + x32[0] = x64 & 'hffffffff; + x32[1] = x64 >> 32; + rvviRefMemoryWrite(0, index+0, x32[0], 4); + rvviRefMemoryWrite(0, index+4, x32[1], 4); + //$display("ram %08X x32[0]=%08X x32[1]=%08X", index, x32[0], x32[1]); + end + $fclose(memFile); + + $display("RVVI Loading Complete"); + + void'(rvviRefPcSet(0, P.RESET_VECTOR)); // set BOOTROM address + end + end + + always @(dut.core.priv.priv.csr.csri.MIP_REGW[7]) void'(rvvi.net_push("MTimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[7])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[11]) void'(rvvi.net_push("MExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[11])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[9]) void'(rvvi.net_push("SExternalInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[9])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[3]) void'(rvvi.net_push("MSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[3])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[1]) void'(rvvi.net_push("SSWInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[1])); + always @(dut.core.priv.priv.csr.csri.MIP_REGW[5]) void'(rvvi.net_push("STimerInterrupt", dut.core.priv.priv.csr.csri.MIP_REGW[5])); + + final begin + void'(rvviRefShutdown()); + end + +`endif + //////////////////////////////////////////////////////////////////////////////// + // END of ImperasDV Co-simulator hooks + //////////////////////////////////////////////////////////////////////////////// + task automatic CheckSignature; // This task must be declared inside this module as it needs access to parameter P. There is // no way to pass P to the task unless we convert it to a module. @@ -601,7 +801,7 @@ module testbench; errors = errors+1; $display(" Error on test %s result %d: adr = %h sim (D$) %h sim (DTIM_SUPPORTED) = %h, signature = %h", TestName, i, (testadr+i)*(P.XLEN/8), testbench.DCacheFlushFSM.ShadowRAM[testadr+i], sig, signature[i]); - $stop; + $stop; // if this is changed to $finish, wally-batch.do does not get to the next step to run coverage end end if (errors) $display("%s failed with %d errors. :(", TestName, errors); diff --git a/testbench/tests.vh b/testbench/tests.vh index f5c9cc0ac..11afd2224 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -31,6 +31,7 @@ `define EMBENCH "4" `define CUSTOM "5" `define COVERAGE "6" +`define BUILDROOT "7" string tvpaths[] = '{ "$RISCV/imperas-riscv-tests/work/", @@ -71,6 +72,11 @@ string tvpaths[] = '{ "pmpadrdecs" }; + string buildroot[] = '{ + `BUILDROOT, + "buildroot" + }; + string coremark[] = '{ `COREMARK, "coremark.bare.riscv" @@ -1126,6 +1132,14 @@ string imperas32f[] = '{ // "rv64i_m/F/src/fnmsub_b15-01.S" }; + string arch64zfh_fma[] = '{ + `RISCVARCHTEST, + "rv64i_m/Zfh/src/fmadd_b15-01.S", + "rv64i_m/Zfh/src/fmsub_b15-01.S", + "rv64i_m/Zfh/src/fnmadd_b15-01.S", + "rv64i_m/Zfh/src/fnmsub_b15-01.S" + }; + string arch64f_divsqrt[] = '{ `RISCVARCHTEST, "rv64i_m/F/src/fdiv_b20-01.S", @@ -1393,7 +1407,55 @@ string imperas32f[] = '{ "rv64i_m/Zfh/src/fsub_b5-01.S", "rv64i_m/Zfh/src/fsub_b7-01.S", "rv64i_m/Zfh/src/fsub_b8-01.S", - "rv64i_m/Zfh/src/fsh-align-01.S" + "rv64i_m/Zfh/src/fsh-align-01.S", + "rv64i_m/Zfh/src/fmadd_b1-01.S", + "rv64i_m/Zfh/src/fmadd_b14-01.S", + "rv64i_m/Zfh/src/fmadd_b16-01.S", + "rv64i_m/Zfh/src/fmadd_b17-01.S", + "rv64i_m/Zfh/src/fmadd_b18-01.S", + "rv64i_m/Zfh/src/fmadd_b2-01.S", + "rv64i_m/Zfh/src/fmadd_b3-01.S", + "rv64i_m/Zfh/src/fmadd_b4-01.S", + "rv64i_m/Zfh/src/fmadd_b5-01.S", + "rv64i_m/Zfh/src/fmadd_b6-01.S", + "rv64i_m/Zfh/src/fmadd_b7-01.S", + "rv64i_m/Zfh/src/fmadd_b8-01.S", + "rv64i_m/Zfh/src/fmsub_b1-01.S", + "rv64i_m/Zfh/src/fmsub_b14-01.S", + "rv64i_m/Zfh/src/fmsub_b16-01.S", + "rv64i_m/Zfh/src/fmsub_b17-01.S", + "rv64i_m/Zfh/src/fmsub_b18-01.S", + "rv64i_m/Zfh/src/fmsub_b2-01.S", + "rv64i_m/Zfh/src/fmsub_b3-01.S", + "rv64i_m/Zfh/src/fmsub_b4-01.S", + "rv64i_m/Zfh/src/fmsub_b5-01.S", + "rv64i_m/Zfh/src/fmsub_b6-01.S", + "rv64i_m/Zfh/src/fmsub_b7-01.S", + "rv64i_m/Zfh/src/fmsub_b8-01.S", + "rv64i_m/Zfh/src/fnmadd_b1-01.S", + "rv64i_m/Zfh/src/fnmadd_b14-01.S", + "rv64i_m/Zfh/src/fnmadd_b16-01.S", + "rv64i_m/Zfh/src/fnmadd_b17-01.S", + "rv64i_m/Zfh/src/fnmadd_b18-01.S", + "rv64i_m/Zfh/src/fnmadd_b2-01.S", + "rv64i_m/Zfh/src/fnmadd_b3-01.S", + "rv64i_m/Zfh/src/fnmadd_b4-01.S", + "rv64i_m/Zfh/src/fnmadd_b5-01.S", + "rv64i_m/Zfh/src/fnmadd_b6-01.S", + "rv64i_m/Zfh/src/fnmadd_b7-01.S", + "rv64i_m/Zfh/src/fnmadd_b8-01.S", + "rv64i_m/Zfh/src/fnmsub_b1-01.S", + "rv64i_m/Zfh/src/fnmsub_b14-01.S", + "rv64i_m/Zfh/src/fnmsub_b16-01.S", + "rv64i_m/Zfh/src/fnmsub_b17-01.S", + "rv64i_m/Zfh/src/fnmsub_b18-01.S", + "rv64i_m/Zfh/src/fnmsub_b2-01.S", + "rv64i_m/Zfh/src/fnmsub_b3-01.S", + "rv64i_m/Zfh/src/fnmsub_b4-01.S", + "rv64i_m/Zfh/src/fnmsub_b5-01.S", + "rv64i_m/Zfh/src/fnmsub_b6-01.S", + "rv64i_m/Zfh/src/fnmsub_b7-01.S", + "rv64i_m/Zfh/src/fnmsub_b8-01.S" }; @@ -1975,7 +2037,55 @@ string arch64zbs[] = '{ "rv32i_m/Zfh/src/fsub_b5-01.S", "rv32i_m/Zfh/src/fsub_b7-01.S", "rv32i_m/Zfh/src/fsub_b8-01.S", - "rv32i_m/Zfh/src/fsh-align-01.S" + "rv32i_m/Zfh/src/fsh-align-01.S", + "rv32i_m/Zfh/src/fmadd_b1-01.S", + "rv32i_m/Zfh/src/fmadd_b14-01.S", + "rv32i_m/Zfh/src/fmadd_b16-01.S", + "rv32i_m/Zfh/src/fmadd_b17-01.S", + "rv32i_m/Zfh/src/fmadd_b18-01.S", + "rv32i_m/Zfh/src/fmadd_b2-01.S", + "rv32i_m/Zfh/src/fmadd_b3-01.S", + "rv32i_m/Zfh/src/fmadd_b4-01.S", + "rv32i_m/Zfh/src/fmadd_b5-01.S", + "rv32i_m/Zfh/src/fmadd_b6-01.S", + "rv32i_m/Zfh/src/fmadd_b7-01.S", + "rv32i_m/Zfh/src/fmadd_b8-01.S", + "rv32i_m/Zfh/src/fmsub_b1-01.S", + "rv32i_m/Zfh/src/fmsub_b14-01.S", + "rv32i_m/Zfh/src/fmsub_b16-01.S", + "rv32i_m/Zfh/src/fmsub_b17-01.S", + "rv32i_m/Zfh/src/fmsub_b18-01.S", + "rv32i_m/Zfh/src/fmsub_b2-01.S", + "rv32i_m/Zfh/src/fmsub_b3-01.S", + "rv32i_m/Zfh/src/fmsub_b4-01.S", + "rv32i_m/Zfh/src/fmsub_b5-01.S", + "rv32i_m/Zfh/src/fmsub_b6-01.S", + "rv32i_m/Zfh/src/fmsub_b7-01.S", + "rv32i_m/Zfh/src/fmsub_b8-01.S", + "rv32i_m/Zfh/src/fnmadd_b1-01.S", + "rv32i_m/Zfh/src/fnmadd_b14-01.S", + "rv32i_m/Zfh/src/fnmadd_b16-01.S", + "rv32i_m/Zfh/src/fnmadd_b17-01.S", + "rv32i_m/Zfh/src/fnmadd_b18-01.S", + "rv32i_m/Zfh/src/fnmadd_b2-01.S", + "rv32i_m/Zfh/src/fnmadd_b3-01.S", + "rv32i_m/Zfh/src/fnmadd_b4-01.S", + "rv32i_m/Zfh/src/fnmadd_b5-01.S", + "rv32i_m/Zfh/src/fnmadd_b6-01.S", + "rv32i_m/Zfh/src/fnmadd_b7-01.S", + "rv32i_m/Zfh/src/fnmadd_b8-01.S", + "rv32i_m/Zfh/src/fnmsub_b1-01.S", + "rv32i_m/Zfh/src/fnmsub_b14-01.S", + "rv32i_m/Zfh/src/fnmsub_b16-01.S", + "rv32i_m/Zfh/src/fnmsub_b17-01.S", + "rv32i_m/Zfh/src/fnmsub_b18-01.S", + "rv32i_m/Zfh/src/fnmsub_b2-01.S", + "rv32i_m/Zfh/src/fnmsub_b3-01.S", + "rv32i_m/Zfh/src/fnmsub_b4-01.S", + "rv32i_m/Zfh/src/fnmsub_b5-01.S", + "rv32i_m/Zfh/src/fnmsub_b6-01.S", + "rv32i_m/Zfh/src/fnmsub_b7-01.S", + "rv32i_m/Zfh/src/fnmsub_b8-01.S" }; string arch32zfaf[] = '{ @@ -2066,6 +2176,14 @@ string arch64zbs[] = '{ "rv32i_m/D/src/fnmsub.d_b15-01.S" }; +string arch32zfh_fma[] = '{ + `RISCVARCHTEST, + "rv32i_m/Zfh/src/fmadd_b15-01.S", + "rv32i_m/Zfh/src/fmsub_b15-01.S", + "rv32i_m/Zfh/src/fnmadd_b15-01.S", + "rv32i_m/Zfh/src/fnmsub_b15-01.S" + }; + string arch32d_divsqrt[] = '{ `RISCVARCHTEST, "rv32i_m/D/src/fdiv.d_b1-01.S", @@ -2472,7 +2590,12 @@ string arch64zbs[] = '{ }; - string ahb[] = '{ + string ahb64[] = '{ `RISCVARCHTEST, "rv64i_m/F/src/fadd_b11-01.S" }; + + string ahb32[] = '{ + `RISCVARCHTEST, + "rv32i_m/F/src/fadd_b11-01.S" + }; diff --git a/tests/coverage/Makefile b/tests/coverage/Makefile index 676e77855..6e13dc000 100644 --- a/tests/coverage/Makefile +++ b/tests/coverage/Makefile @@ -19,7 +19,7 @@ all: $(OBJECTS) %.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zfa_zba_zbb_zbc_zbs_zfh_zicboz_zicbop_zicbom -mabi=lp64 -mcmodel=medany \ -nostartfiles -T../../examples/link/link.ld $< - riscv64-unknown-elf-objdump -S $@ > $@.objdump + riscv64-unknown-elf-objdump -S -D $@ > $@.objdump riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile extractFunctionRadix.sh $@.objdump diff --git a/tests/coverage/fpu.S b/tests/coverage/fpu.S index ca68e7275..a88ed8a51 100644 --- a/tests/coverage/fpu.S +++ b/tests/coverage/fpu.S @@ -37,6 +37,26 @@ main: flw ft0, 0(t0) fclass.s t1, ft0 + # zfa instructions (because Zfa tests aren't running yet) + fli.d fs0, 16 + fcvtmod.w.d t0, fs0, rtz +# fminm.d fs1, fs0, fs0 +# fmaxm.d fs1, fs0, fs0 +# fltq.d t0, fs1, ft0 +# fleq.d t0, fs1, ft0 + fcvt.d.q fs1, fs0 + fcvt.h.q fs1, fs0 + fcvt.s.q fs1, fs0 + # round for now because these tests are excluded from Zfa until rounding is implemented + fround.s fs1, fs0 + froundnx.s fs1, fs0 + fround.d fs1, fs0 + froundnx.d fs1, fs0 + fround.h fs1, fs0 + froundnx.h fs1, fs0 + fround.s fs1, fs0 + froundnx.s fs1, fs0 + #Result Sign Test Coverage la t0, TestData2 flw ft0, 0(t0) @@ -109,6 +129,12 @@ main: # fcvt.w.q a0, ft0 # fcvt.q.d ft3, ft0 + # half-precision NaN boxing + la t0, TestData3 + fld ft2, 0(t0) // bad NaN-boxed number + fmadd.h ft1, ft2, ft2, ft2 // Test NaN boxing + fmadd.s ft1, ft2, ft2, ft2 // Test NaN boxing + // fdivsqrt: test busy->idle transition caused by a FlushE while divider is busy (when interrupt arrives) // This code doesn't actually trigger a busy->idle transition because the pending timer interrupt doesn't occur until the division finishes. li t0, 0x3F812345 # random value slightly bigger than 1 @@ -159,6 +185,10 @@ main: .word 0xD5F00053 // illegal fcvt.h.* (bad Rs2D) .word 0xC5F00053 // illegal fcvt.*.h (bad Rs2D) .word 0x04000043 // illegal fmadd.h (h not supported) + .word 0xC2800053 // illegal fcvtmod.w.d with rm rne + .word 0xF0101053 // illegal fli with Funct3D not 0 + .word 0xF0400053 // illegal fli with Rs2D not 1 + .word 0x44200053 // illegal instruction for f.cvt.h.h // Test divide by zero with rounding mode toward zero li t0, 1 @@ -206,4 +236,6 @@ TestData2: .int 0xbf800000 #FP -1.0 .int 0x7fa00000 #SNaN .int 0x3fffffff #OverFlow Test +TestData3: +.dword 0xABCD543212345678 # NaN box test DivTestData: diff --git a/tests/coverage/tlbASID.S b/tests/coverage/tlbASID.S index ecf66feed..25cf650ca 100644 --- a/tests/coverage/tlbASID.S +++ b/tests/coverage/tlbASID.S @@ -4,7 +4,8 @@ // Written: mmendozamanriquez@hmc.edu 4 April 2023 // nlimpert@hmc.edu // -// Purpose: Test coverage for LSU +// Purpose: Test coverage for IFU TLB camlines with mismatched ASID values. This file tests odd +// numbered camlines. tlbASID2.S covers even numbered tlb camlines. These two files are identical. // // A component of the CORE-V-WALLY configurable RISC-V project. // https://github.com/openhwgroup/cvw @@ -25,6 +26,8 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// + + // load code to initalize stack, handle interrupts, terminate #include "WALLY-init-lib.h" @@ -43,11 +46,12 @@ main: li t0, 0xC0000000 - li t2, 0 # i = 0 + li t2, 0 # i = 0 li t5, 0 # j = 0 // now use as a counter for new asid loop - li t3, 32 # Max amount of Loops = 32 + li t3, 32 # Max amount of Loops = 32 loop: bge t2, t3, finished # exit loop if i >= loops + sfence.vma li t1, 0x00008067 #load in jalr sw t1, 0(t0) fence.I @@ -55,7 +59,7 @@ loop: bge t2, t3, finished # exit loop if i >= loops li t5, 0x9001000000080080 // try making asid = 1 csrw satp, t5 jalr t0 - li t5, 0x9000000000080080 // try making asid = 0 + li t5, 0x9000000000080080 // try making asid = 0 csrw satp, t5 li t4, 0x1000 add t0, t0, t4 @@ -71,7 +75,7 @@ finished: pagetable: .8byte 0x200204C1 -.align 12 // level 2 page table, contains direction to a gigapageg +.align 12 // level 2 page table, contains direction to a gigapage .8byte 0x0 .8byte 0x0 .8byte 0x200000CF // gigapage that starts at 8000 0000 goes to C000 0000 diff --git a/tests/coverage/tlbNAPOT.S b/tests/coverage/tlbNAPOT.S index 56d2943f4..508eb057c 100644 --- a/tests/coverage/tlbNAPOT.S +++ b/tests/coverage/tlbNAPOT.S @@ -55,14 +55,24 @@ main: li t4, 0x1000 # address step size li a2, 0x80216000 # Test NAPOT pages jal a1, looptest + + sfence.vma + li t4, 0x200000 # address step size + li a2, 0x80215240 # Test NAPOT pages + jal a1, looptest + li a2, 0xC0215240 # Test ill-formed NAPOT pages + jal a1, looptest + li a2, 0x40215240 # Test properly formed pages with 1 in PPN[3] that are not NAPOT + jal a1, looptest + li a0, 3 # switch back to machine mode because code at 0x80000000 may not have clean page table entry ecall j done looptest: mv t0, a2 # base address - li t2, 0 # i = 0 - li t3, 35 # Max amount of Loops = 34 + li t2, 0 # i = 0 + li t3, 32 # Max amount of Loops = 32 li t5, 0x8082 # return instruction opcode loop: bge t2, t3, finished # exit loop if i >= loops diff --git a/tests/coverage/tlbmisc.S b/tests/coverage/tlbmisc.S index 4bbb4958a..f64645689 100644 --- a/tests/coverage/tlbmisc.S +++ b/tests/coverage/tlbmisc.S @@ -96,6 +96,49 @@ main: sw t1, 0(t0) # write to page jalr ra, t0 # jump to page + # AMO at page has PBMT = 2 or 1 (uncached) + li t0, 0x80401000 + li t1, 10 + amoadd.w t1, t1, (t0) + + la t2, SpecialPage + li t0, 0x200000000 # an address to a specific 1 GiB page + j ConcurrentICacheMissDTLBMiss + +.align 6 +ConcurrentICacheMissDTLBMiss: + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + lw t1, 0(t0) + + # write a cacheline length (512 bits) to memory in uncached region + li t0, 0x80401000 + cbo.zero (t0) + # Nonleaf PTE has PBMT != 0 causes a page fault during page walking. H li t0, 0x80600000 lw t1, 0(t0) # read from page @@ -163,6 +206,10 @@ main: # change back to default trap handler after checking everything that might cause an instruction page fault jal changetodefaulthandler + # uncachable AMO access + li t0, 0x80401000 # PBMT sets as uncachable + amoadd.w t0, t0, 0(t0) + # exercise CBOM instructions with various permissions li t0, 0x80800000 cbo.zero (t0) @@ -294,6 +341,12 @@ pagetable: .8byte 0x00000000200058C1 # PTE for pages at 0x40000000 pointing to 0x80150000 .8byte 0x00000000200048C1 # gigapage at 0x80000000 pointing to 0x80120000 .8byte 0x00000000000000C1 # gigapage at VA 0xC0000000 causes access fault + .8byte 0x0 + .8byte 0x0 + .8byte 0x0 + .8byte 0x0 +SpecialPage: + .8byte 0x00000000200000CF # 0x2_0000_0000 1GiB page1 # Next page table at 0x80012000 for gigapage at 0x80000000 @@ -408,7 +461,8 @@ pagetable: # Leaf page table at 0x80014000 with PBMT pages .align 12 #80400000 - .8byte 0x60000000200020CF # reserved entry + .8byte 0x60000000200020CF # reserved entry VA 80400000 + .8byte 0x40000000201000CF # non-cache non-idempotent VA 80401000 # Leaf page table at 0x80015000 with various permissions for testing CBOM and CBOZ .align 12