From 98aaa970dd11123248aa44c88415f3dd1f4931cc Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 30 Dec 2021 00:53:39 +0000 Subject: [PATCH] rv32i regression and linting --- wally-pipelined/config/rv32ic/wally-config.vh | 14 ++--- wally-pipelined/regression/lint-wally | 2 +- .../regression/regression-wally.py | 30 +++++++---- wally-pipelined/regression/sim-wally-batch | 2 +- wally-pipelined/src/lsu/lsu.sv | 2 +- wally-pipelined/src/mmu/pmpchecker.sv | 51 +++++++++---------- wally-pipelined/src/sdc/SDC.sv | 2 +- wally-pipelined/testbench/testbench.sv | 24 ++++++--- 8 files changed, 73 insertions(+), 54 deletions(-) diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 36146e655..b93d77bdc 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -40,10 +40,10 @@ `define IEEE754 0 `define MISA (32'h00000104) -`define ZICSR_SUPPORTED 1 -`define ZIFENCEI_SUPPORTED 1 +`define ZICSR_SUPPORTED 0 +`define ZIFENCEI_SUPPORTED 0 `define COUNTERS 32 -`define ZICOUNTERS_SUPPORTED 1 +`define ZICOUNTERS_SUPPORTED 0 // Microarchitectural Features `define UARCH_PIPELINED 1 @@ -53,12 +53,12 @@ `define MEM_DCACHE 1 `define MEM_IROM 1 `define MEM_ICACHE 1 -`define MEM_VIRTMEM 1 +`define MEM_VIRTMEM 0 `define VECTORED_INTERRUPTS_SUPPORTED 1 // TLB configuration. Entries should be a power of 2 -`define ITLB_ENTRIES 32 -`define DTLB_ENTRIES 32 +`define ITLB_ENTRIES 0 +`define DTLB_ENTRIES 0 // Cache configuration. Sizes should be a power of two // typical configuration 4 ways, 4096 bytes per way, 256 bit or more blocks @@ -75,7 +75,7 @@ `define DIV_BITSPERCYCLE 4 // Legal number of PMP entries are 0, 16, or 64 -`define PMP_ENTRIES 16 +`define PMP_ENTRIES 0 // Address space `define RESET_VECTOR 32'h80000000 diff --git a/wally-pipelined/regression/lint-wally b/wally-pipelined/regression/lint-wally index 23f239c1a..5968cb4df 100755 --- a/wally-pipelined/regression/lint-wally +++ b/wally-pipelined/regression/lint-wally @@ -5,7 +5,7 @@ export PATH=$PATH:/usr/local/bin/ verilator=`which verilator` basepath=$(dirname $0)/.. -for config in rv64gc rv32gc; do +for config in rv64gc rv32gc rv32ic; do echo "$config linting..." if !($verilator --lint-only "$@" --top-module wallypipelinedsoc "-I$basepath/config/shared" "-I$basepath/config/$config" $basepath/src/*/*.sv $basepath/src/*/*/*.sv --relative-includes); then echo "Exiting after $config lint due to errors or warnings" diff --git a/wally-pipelined/regression/regression-wally.py b/wally-pipelined/regression/regression-wally.py index 508dd3716..2c6850b62 100755 --- a/wally-pipelined/regression/regression-wally.py +++ b/wally-pipelined/regression/regression-wally.py @@ -15,7 +15,7 @@ import sys,os from collections import namedtuple regressionDir = os.path.dirname(os.path.abspath(__file__)) os.chdir(regressionDir) -TestCase = namedtuple("TestCase", ['name', 'cmd', 'grepstr']) +TestCase = namedtuple("TestCase", ['name', 'variant', 'cmd', 'grepstr']) # name: the name of this test configuration (used in printing human-readable # output and picking logfile names) # cmd: the command to run to test (should include the logfile as '{}', and @@ -28,6 +28,7 @@ TestCase = namedtuple("TestCase", ['name', 'cmd', 'grepstr']) configs = [ TestCase( name="lints", + variant="all", cmd="./lint-wally &> {}", grepstr="All lints run with no errors or warnings" ) @@ -41,29 +42,40 @@ def getBuildrootTC(short): else: BRcmd="vsim > {} -c < {} -c < {} -c < {} -c < {} -c < 0) begin: pmpchecker + // Bit i is high when the address falls in PMP region i + logic EnforcePMP; + logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges + logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. + logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null + logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set + logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] + + pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( + .PhysicalAddress, + .PMPCfg(PMPCFG_ARRAY_REGW), + .PMPAdr(PMPADDR_ARRAY_REGW), + .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), + .PAgePMPAdrOut(PAgePMPAdr), + .FirstMatch, .Match, .Active, .L, .X, .W, .R); - // Bit i is high when the address falls in PMP region i - logic EnforcePMP; -// logic [7:0] PMPCfg[`PMP_ENTRIES-1:0]; - logic [`PMP_ENTRIES-1:0] Match; // physical address matches one of the pmp ranges - logic [`PMP_ENTRIES-1:0] FirstMatch; // onehot encoding for the first pmpaddr to match the current address. - logic [`PMP_ENTRIES-1:0] Active; // PMP register i is non-null - logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set - logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] - genvar i,j; + priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. - pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( - .PhysicalAddress, - .PMPCfg(PMPCFG_ARRAY_REGW), - .PMPAdr(PMPADDR_ARRAY_REGW), - .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), - .PAgePMPAdrOut(PAgePMPAdr), - .FirstMatch, .Match, .Active, .L, .X, .W, .R); - - priorityonehot #(`PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches. - - // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region - assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; - - assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X; - assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W; - assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R; + // Only enforce PMP checking for S and U modes when at least one PMP is active or in Machine mode when L bit is set in selected region + assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; + assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X; + assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W; + assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R; + end + endgenerate //assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM; - endmodule diff --git a/wally-pipelined/src/sdc/SDC.sv b/wally-pipelined/src/sdc/SDC.sv index 424d45771..732141152 100644 --- a/wally-pipelined/src/sdc/SDC.sv +++ b/wally-pipelined/src/sdc/SDC.sv @@ -79,7 +79,7 @@ module SDC logic SDCDataValid; logic [`XLEN-1:0] SDCReadData; - logic [`XLEN-1:0] SDCReadDataPreNibbleSwap; + logic [`XLEN-1:0] SDCReadDataPreNibbleSwap; logic [`XLEN-1:0] SDCWriteData; logic FatalError; diff --git a/wally-pipelined/testbench/testbench.sv b/wally-pipelined/testbench/testbench.sv index 417bf7811..16e0b3f77 100644 --- a/wally-pipelined/testbench/testbench.sv +++ b/wally-pipelined/testbench/testbench.sv @@ -76,7 +76,7 @@ logic [3:0] dummy; // pick tests based on modes supported initial begin $display("TEST is %s", TEST); - tests = '{}; + //tests = '{}; if (`XLEN == 64) begin // RV64 case (TEST) "arch64i": tests = arch64i; @@ -291,7 +291,15 @@ logic [3:0] dummy; // or sw gp,-56(t0) for new Imperas tests // or sw gp, -56(t0) // or on a jump to self infinite loop (6f) for RISC-V Arch tests - assign DCacheFlushStart = dut.hart.priv.priv.EcallFaultM && + logic ecf; // remove this once we don't rely on old Imperas tests with Ecalls + generate + if (`ZICSR_SUPPORTED) begin + assign ecf = dut.hart.priv.priv.EcallFaultM; + end else begin + assign ecf = 0; + end + endgenerate + assign DCacheFlushStart = ecf && (dut.hart.ieu.dp.regf.rf[3] == 1 || (dut.hart.ieu.dp.regf.we3 && dut.hart.ieu.dp.regf.a3 == 3 && @@ -330,12 +338,12 @@ module riscvassertions; assert (`ICACHE_WAYSIZEINBYTES <= 4096 || `MEM_ICACHE == 0 || `MEM_VIRTMEM == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); assert (`ICACHE_BLOCKLENINBITS >= 32 || `MEM_ICACHE == 0) else $error("ICACHE_BLOCKLENINBITS must be at least 32 when caches are enabled"); assert (`ICACHE_BLOCKLENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_BLOCKLENINBITS must be smaller than way size"); - assert (2**$clog2(`DCACHE_BLOCKLENINBITS) == `DCACHE_BLOCKLENINBITS) else $error("DCACHE_BLOCKLENINBITS must be a power of 2"); - assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); - assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS) else $error("ICACHE_BLOCKLENINBITS must be a power of 2"); - assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); - assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES) else $error("ITLB_ENTRIES must be a power of 2"); - assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES) else $error("DTLB_ENTRIES must be a power of 2"); + assert (2**$clog2(`DCACHE_BLOCKLENINBITS) == `DCACHE_BLOCKLENINBITS || `MEM_DCACHE==0) else $error("DCACHE_BLOCKLENINBITS must be a power of 2"); + assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES || `MEM_DCACHE==0) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(`ICACHE_BLOCKLENINBITS) == `ICACHE_BLOCKLENINBITS || `MEM_ICACHE==0) else $error("ICACHE_BLOCKLENINBITS must be a power of 2"); + assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES || `MEM_ICACHE==0) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); + assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES || `MEM_VIRTMEM==0) else $error("ITLB_ENTRIES must be a power of 2"); + assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES || `MEM_VIRTMEM==0) else $error("DTLB_ENTRIES must be a power of 2"); assert (`RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if RAM_RANGE is less than 56'h07FFFFFF"); assert (`ZICSR_SUPPORTED == 1 || (`PMP_ENTRIES == 0 && `MEM_VIRTMEM == 0)) else $error("PMP_ENTRIES and MEM_VIRTMEM must be zero if ZICSR not supported."); end