From 0bd18ff662d67995f3f416a06a9569bfa8a8fbfb Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 2 Jul 2021 17:08:13 -0400 Subject: [PATCH 01/21] Fixed PMPCFG read faults --- wally-pipelined/src/privileged/csrm.sv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index f30ebb4f..8c74b951 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -187,9 +187,9 @@ module csrm #(parameter (CSRAdrM == MEDELEG || CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode if (CSRAdrM >= PMPADDR0 && CSRAdrM < PMPADDR0 + `PMP_ENTRIES) // reading a PMP entry CSRMReadValM = PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]; - else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/8) begin - if (~CSRAdrM[0]) CSRMReadValM = PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][`XLEN-1:0]; - else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[CSRAdrM - PMPCFG0][63:32]}; + else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/4) begin + if (~CSRAdrM[0]) CSRMReadValM = PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0)/2][`XLEN-1:0]; + else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0-1)/2][63:32]}; end else case (CSRAdrM) MISA_ADR: CSRMReadValM = MISA_REGW; From 59b177beac982097afd36de8c6a5f1a67f157cd5 Mon Sep 17 00:00:00 2001 From: Ben Bracker Date: Fri, 2 Jul 2021 17:22:09 -0500 Subject: [PATCH 02/21] stop busybear from hanging --- wally-pipelined/regression/wally-busybear-batch.do | 1 + wally-pipelined/regression/wally-busybear.do | 3 ++- wally-pipelined/testbench/testbench-linux.sv | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/wally-pipelined/regression/wally-busybear-batch.do b/wally-pipelined/regression/wally-busybear-batch.do index a4a80eb7..e2817dfa 100644 --- a/wally-pipelined/regression/wally-busybear-batch.do +++ b/wally-pipelined/regression/wally-busybear-batch.do @@ -35,5 +35,6 @@ vopt work_busybear.testbench -o workopt_busybear vsim workopt_busybear -suppress 8852,12070 +run -all run -all quit diff --git a/wally-pipelined/regression/wally-busybear.do b/wally-pipelined/regression/wally-busybear.do index 11876dde..204d1c4e 100644 --- a/wally-pipelined/regression/wally-busybear.do +++ b/wally-pipelined/regression/wally-busybear.do @@ -35,9 +35,10 @@ vopt +acc work.testbench -o workopt vsim workopt -suppress 8852,12070 -do ./wave-dos/linux-waves.do #-- Run the Simulation run -all +do ./wave-dos/linux-waves.do +run -all ##quit diff --git a/wally-pipelined/testbench/testbench-linux.sv b/wally-pipelined/testbench/testbench-linux.sv index 6676d1a7..8f8a5d44 100644 --- a/wally-pipelined/testbench/testbench-linux.sv +++ b/wally-pipelined/testbench/testbench-linux.sv @@ -27,8 +27,8 @@ module testbench(); - parameter waveOnICount = 2657000; // # of instructions at which to turn on waves in graphical sim - + parameter waveOnICount = `BUSYBEAR*140000 + `BUILDROOT*2400000; // # of instructions at which to turn on waves in graphical sim + parameter stopICount = `BUSYBEAR*143898 + `BUILDROOT*0000000; // # instructions at which to halt sim completely (set to 0 to let it run as far as it can) /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////// DUT ///////////////////////////////////// @@ -248,6 +248,9 @@ module testbench(); if (instrs == waveOnICount) begin $display("turning on waves at %0d instructions", instrs); $stop; + end else if (instrs == stopICount && stopICount != 0) begin + $display("Ending sim at %0d instructions (set stopICount to 0 to let the sim go on)", instrs); + $stop; end // Check if PCD is going to be flushed due to a branch or jump From d44916dacf691c33b8e171b34a1d5bfe362ba273 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sat, 3 Jul 2021 02:25:31 -0400 Subject: [PATCH 03/21] Cleaned up PMA/PMP checker unused code --- wally-pipelined/src/mmu/pmachecker.sv | 4 -- wally-pipelined/src/mmu/pmpadrdec.sv | 64 ++------------------------- wally-pipelined/src/mmu/pmpchecker.sv | 45 +------------------ 3 files changed, 5 insertions(+), 108 deletions(-) diff --git a/wally-pipelined/src/mmu/pmachecker.sv b/wally-pipelined/src/mmu/pmachecker.sv index 8d31f3ae..26d8ac87 100644 --- a/wally-pipelined/src/mmu/pmachecker.sv +++ b/wally-pipelined/src/mmu/pmachecker.sv @@ -32,9 +32,6 @@ module pmachecker ( input logic [`PA_BITS-1:0] PhysicalAddress, input logic [1:0] Size, -// input logic [31:0] HADDR, -// input logic [2:0] HSIZE, -// input logic [2:0] HBURST, // *** in AHBlite, HBURST is hardwired to zero for single bursts only allowed. consider removing from this module if unused. input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, // *** atomicaccessM is unused but might want to stay in for future use. @@ -46,7 +43,6 @@ module pmachecker ( output logic PMAStoreAccessFaultM ); - // logic BootTim, Tim, CLINT, GPIO, UART, PLIC; logic PMAAccessFault; logic AccessRW, AccessRWX, AccessRX; logic [5:0] SelRegions; diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index 3286368f..bdd46bef 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -31,7 +31,6 @@ module pmpadrdec ( input logic [`PA_BITS-1:0] PhysicalAddress, -// input logic [31:0] HADDR, // *** replace with PAdr input logic [1:0] AdrMode, input logic [`XLEN-1:0] CurrentPMPAdr, input logic AdrAtLeastPreviousPMP, @@ -46,20 +45,19 @@ module pmpadrdec ( logic TORMatch, NAMatch; logic AdrBelowCurrentPMP; logic [`PA_BITS-1:0] CurrentAdrFull; -// logic [`PA_BITS-1:0] FakePhysAdr; - // ***replace this when the true physical address from MMU is available -// assign FakePhysAdr = {{(`PA_BITS-32){1'b0}}, HADDR}; + // The two lsb of the physical address don't matter for this checking. + // The following code includes them, but hardwires the PMP checker lsbs to 00 + // and masks them later. Logic synthesis should optimize away these bottom bits. // Top-of-range (TOR) // Append two implicit trailing 0's to PMPAdr value assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00}; - assign AdrBelowCurrentPMP = PhysicalAddress < CurrentAdrFull; // *** make sure unsigned comparison works correctly + assign AdrBelowCurrentPMP = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP; assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; // Naturally aligned regions - // *** should be able to optimize away bottom 2 bits // verilator lint_off UNOPTFLAT logic [`PA_BITS-1:0] Mask; @@ -76,60 +74,6 @@ module pmpadrdec ( assign NAMatch = &((PhysicalAddress ~^ CurrentAdrFull) | Mask); - /* generate - if (`XLEN == 32 || `XLEN == 64) begin // ***redo for various sizes - // priority encoder to translate address to range - // *** We'd like to replace this with a better priority encoder - // *** We should not be truncating 64 bit physical addresses to 32 bits... - // *** there is an easy combinatinoal way to do this with a cascade of AND gates O(32) rather than O(32^2) dh - always_comb - if (AdrMode == NA4) Range = (2**2) - 1; - else casez (CurrentPMPAdr[31:0]) // NAPOT regions - 32'b???????????????????????????????0: Range = (2**3) - 1; - 32'b??????????????????????????????01: Range = (2**4) - 1; - 32'b?????????????????????????????011: Range = (2**5) - 1; - 32'b????????????????????????????0111: Range = (2**6) - 1; - 32'b???????????????????????????01111: Range = (2**7) - 1; - 32'b??????????????????????????011111: Range = (2**8) - 1; - 32'b?????????????????????????0111111: Range = (2**9) - 1; - 32'b????????????????????????01111111: Range = (2**10) - 1; - 32'b???????????????????????011111111: Range = (2**11) - 1; - 32'b??????????????????????0111111111: Range = (2**12) - 1; - 32'b?????????????????????01111111111: Range = (2**13) - 1; - 32'b????????????????????011111111111: Range = (2**14) - 1; - 32'b???????????????????0111111111111: Range = (2**15) - 1; - 32'b??????????????????01111111111111: Range = (2**16) - 1; - 32'b?????????????????011111111111111: Range = (2**17) - 1; - 32'b????????????????0111111111111111: Range = (2**18) - 1; - 32'b???????????????01111111111111111: Range = (2**19) - 1; - 32'b??????????????011111111111111111: Range = (2**20) - 1; - 32'b?????????????0111111111111111111: Range = (2**21) - 1; - 32'b????????????01111111111111111111: Range = (2**22) - 1; - 32'b???????????011111111111111111111: Range = (2**23) - 1; - 32'b??????????0111111111111111111111: Range = (2**24) - 1; - 32'b?????????01111111111111111111111: Range = (2**25) - 1; - 32'b????????011111111111111111111111: Range = (2**26) - 1; - 32'b???????0111111111111111111111111: Range = (2**27) - 1; - 32'b??????01111111111111111111111111: Range = (2**28) - 1; - 32'b?????011111111111111111111111111: Range = (2**29) - 1; - 32'b????0111111111111111111111111111: Range = (2**30) - 1; - 32'b???01111111111111111111111111111: Range = (2**31) - 1; - 32'b??011111111111111111111111111111: Range = (2**32) - 1; - 32'b?0111111111111111111111111111111: Range = (2**33) - 1; - 32'b01111111111111111111111111111111: Range = (2**34) - 1; - 32'b11111111111111111111111111111111: Range = (2**35) - 1; - default: Range = '0; - endcase - end else begin - assign Range = '0; - end - endgenerate - - // *** Range should not be truncated... but our physical address space is - // currently only 32 bits wide. - // with a bit of combining of range selection, this could be shared with NA4Match *** - assign NAMatch = &((HADDR ~^ CurrentAdrFull) | Range[31:0]);*/ - assign Match = (AdrMode == TOR) ? TORMatch : (AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch : 0; diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 409e2ccb..0d45229a 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -29,12 +29,8 @@ `include "wally-config.vh" module pmpchecker ( -// input logic clk, reset, //*** it seems like clk, reset is also not needed here? input logic [`PA_BITS-1:0] PhysicalAddress, -// input logic [31:0] HADDR, - - input logic [1:0] PrivilegeModeW, - + input logic [1:0] PrivilegeModeW, // *** ModelSim has a switch -svinputport which controls whether input ports // are nets (wires) or vars by default. The default setting of this switch is @@ -43,10 +39,6 @@ module pmpchecker ( // this will be understood as a var. However, if we don't supply the `var` // keyword, the compiler warns us that it's interpreting the signal as a var, // which we might not intend. - // However, it's still bad form to pass 512 or 1024 signals across a module - // boundary. It would be better to store the PMP address registers in a module - // somewhere in the CSR hierarchy and do PMP checking _within_ that module, so - // we don't have to pass around 16 whole registers. input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], @@ -61,7 +53,6 @@ module pmpchecker ( // Bit i is high when the address falls in PMP region i logic [`PMP_ENTRIES-1:0] Regions, FirstMatch; - //logic [3:0] MatchedRegion; logic EnforcePMP; logic [7:0] PMPCFG [`PMP_ENTRIES-1:0]; @@ -74,7 +65,6 @@ module pmpchecker ( logic [`PMP_ENTRIES-1:0] ActiveRegion; logic [`PMP_ENTRIES-1:0] L_Bits, X_Bits, W_Bits, R_Bits; - //logic InvalidExecute, InvalidWrite, InvalidRead; genvar i,j; @@ -100,11 +90,8 @@ module pmpchecker ( end endgenerate - //assign Match = |Regions; - // verilator lint_off UNOPTFLAT logic [`PMP_ENTRIES-1:0] NoLowerMatch; -// assign NoLowerMatch[0] = 1; generate // verilator lint_off WIDTH for (j=0; j<`PMP_ENTRIES; j = j+8) begin @@ -127,36 +114,6 @@ module pmpchecker ( end // verilator lint_on UNOPTFLAT endgenerate -/* // *** extend to up to 64, fold bit extraction to avoid need for binary encoding of region - always_comb - casez (Regions) - 16'b???????????????1: MatchedRegion = 0; - 16'b??????????????10: MatchedRegion = 1; - 16'b?????????????100: MatchedRegion = 2; - 16'b????????????1000: MatchedRegion = 3; - 16'b???????????10000: MatchedRegion = 4; - 16'b??????????100000: MatchedRegion = 5; - 16'b?????????1000000: MatchedRegion = 6; - 16'b????????10000000: MatchedRegion = 7; - 16'b???????100000000: MatchedRegion = 8; - 16'b??????1000000000: MatchedRegion = 9; - 16'b?????10000000000: MatchedRegion = 10; - 16'b????100000000000: MatchedRegion = 11; - 16'b???1000000000000: MatchedRegion = 12; - 16'b??10000000000000: MatchedRegion = 13; - 16'b?100000000000000: MatchedRegion = 14; - 16'b1000000000000000: MatchedRegion = 15; - default: MatchedRegion = 0; // Should only occur if there is no match - endcase - - assign L_Bit = PMPCFG[MatchedRegion][7] && Match; - assign X_Bit = PMPCFG[MatchedRegion][2] && Match; - assign W_Bit = PMPCFG[MatchedRegion][1] && Match; - assign R_Bit = PMPCFG[MatchedRegion][0] && Match; - - assign InvalidExecute = ExecuteAccessF && ~X_Bit; - assign InvalidWrite = WriteAccessM && ~W_Bit; - assign InvalidRead = ReadAccessM && ~R_Bit;*/ // 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_Bits : |ActiveRegion; From 1fa4abf7b6c8ac60c7c491d042deba0b91890a66 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sat, 3 Jul 2021 03:29:33 -0400 Subject: [PATCH 04/21] Changed IMMU ExecuteAccessF to 1 rather than InstrReadF to fix buildroot; simplified PMP checker --- wally-pipelined/src/ebu/ahblite.sv | 1 + wally-pipelined/src/ifu/ifu.sv | 2 +- wally-pipelined/src/mmu/pmpadrdec.sv | 40 ++++++++---- wally-pipelined/src/mmu/pmpchecker.sv | 87 +++++++++------------------ wally-pipelined/src/uncore/uncore.sv | 1 + 5 files changed, 61 insertions(+), 70 deletions(-) diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 70f32bf7..84e8f3b6 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -146,6 +146,7 @@ module ahblite ( // (ProposedNextBusState == MMUTRANSLATE); // The PMA and PMP checkers can decide to squash the access + // *** this probably needs to be controlled by the caches rather than EBU dh 7/2/11 assign NextBusState = (DSquashBusAccessM || ISquashBusAccessF) ? IDLE : ProposedNextBusState; // stall signals diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 04110d9a..ddfd88cc 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -127,7 +127,7 @@ module ifu ( .TLBMiss(ITLBMissF), .TLBHit(ITLBHitF), .TLBPageFault(ITLBInstrPageFaultF), - .ExecuteAccessF(InstrReadF), /// *** Ross Thompson this is definitely wrong. InstrReadF changed to icache read to memory. + .ExecuteAccessF(1'b1), // ***dh -- this should eventually change to only true if an instruction fetch is occurring .AtomicAccessM(1'b0), .ReadAccessM(1'b0), .WriteAccessM(1'b0), diff --git a/wally-pipelined/src/mmu/pmpadrdec.sv b/wally-pipelined/src/mmu/pmpadrdec.sv index bdd46bef..50d399ae 100644 --- a/wally-pipelined/src/mmu/pmpadrdec.sv +++ b/wally-pipelined/src/mmu/pmpadrdec.sv @@ -31,20 +31,29 @@ module pmpadrdec ( input logic [`PA_BITS-1:0] PhysicalAddress, - input logic [1:0] AdrMode, - input logic [`XLEN-1:0] CurrentPMPAdr, - input logic AdrAtLeastPreviousPMP, - output logic AdrAtLeastCurrentPMP, - output logic Match + input logic [7:0] PMPCfg, + input logic [`XLEN-1:0] PMPAdr, + input logic PAgePMPAdrIn, + input logic NoLowerMatchIn, + output logic PAgePMPAdrOut, + output logic NoLowerMatchOut, + output logic Match, Active, + output logic L, X, W, R ); + localparam TOR = 2'b01; localparam NA4 = 2'b10; localparam NAPOT = 2'b11; logic TORMatch, NAMatch; - logic AdrBelowCurrentPMP; + logic PAltPMPAdr; + logic FirstMatch; logic [`PA_BITS-1:0] CurrentAdrFull; + logic [1:0] AdrMode; + + + assign AdrMode = PMPCfg[4:3]; // The two lsb of the physical address don't matter for this checking. // The following code includes them, but hardwires the PMP checker lsbs to 00 @@ -52,10 +61,10 @@ module pmpadrdec ( // Top-of-range (TOR) // Append two implicit trailing 0's to PMPAdr value - assign CurrentAdrFull = {CurrentPMPAdr[`PA_BITS-3:0], 2'b00}; - assign AdrBelowCurrentPMP = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison - assign AdrAtLeastCurrentPMP = ~AdrBelowCurrentPMP; - assign TORMatch = AdrAtLeastPreviousPMP && AdrBelowCurrentPMP; + assign CurrentAdrFull = {PMPAdr[`PA_BITS-3:0], 2'b00}; + assign PAltPMPAdr = {1'b0, PhysicalAddress} < {1'b0, CurrentAdrFull}; // unsigned comparison + assign PAgePMPAdrOut = ~PAltPMPAdr; + assign TORMatch = PAgePMPAdrIn && PAltPMPAdr; // Naturally aligned regions @@ -68,7 +77,7 @@ module pmpadrdec ( assign Mask[1:0] = 2'b11; assign Mask[2] = (AdrMode == NAPOT); // mask has 0s in upper bis for NA4 region for (i=3; i < `PA_BITS; i=i+1) - assign Mask[i] = Mask[i-1] & CurrentPMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore + assign Mask[i] = Mask[i-1] & PMPAdr[i-3]; // NAPOT mask: 1's indicate bits to ignore endgenerate // verilator lint_on UNOPTFLAT @@ -78,5 +87,12 @@ module pmpadrdec ( (AdrMode == NA4 || AdrMode == NAPOT) ? NAMatch : 0; -endmodule + assign FirstMatch = NoLowerMatchIn & Match; + assign NoLowerMatchOut = NoLowerMatchIn & ~Match; + assign L = PMPCfg[7] & FirstMatch; + assign X = PMPCfg[2] & FirstMatch; + assign W = PMPCfg[1] & FirstMatch; + assign R = PMPCfg[0] & FirstMatch; + assign Active = |PMPCfg[4:3]; + endmodule diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 0d45229a..27c7e508 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -51,76 +51,49 @@ module pmpchecker ( output logic PMPStoreAccessFaultM ); + // verilator lint_off UNOPTFLAT + // Bit i is high when the address falls in PMP region i - logic [`PMP_ENTRIES-1:0] Regions, FirstMatch; - logic EnforcePMP; - - logic [7:0] PMPCFG [`PMP_ENTRIES-1:0]; - - // Bit i is high when the address is greater than or equal to PMPADR[i] - // Used for determining whether TOR PMP regions match - logic [`PMP_ENTRIES-1:0] AboveRegion; - - // Bit i is high if PMP register i is non-null - logic [`PMP_ENTRIES-1:0] ActiveRegion; - - logic [`PMP_ENTRIES-1:0] L_Bits, X_Bits, W_Bits, R_Bits; - + logic EnforcePMP; + logic [7:0] PMPCFG [`PMP_ENTRIES-1:0]; + logic [`PMP_ENTRIES-1:0] Match; // PMP Entry matches + 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:0] NoLowerMatch; // None of the lower PMP entries match + logic [`PMP_ENTRIES:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] genvar i,j; - pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress), - .AdrMode(PMPCFG[0][4:3]), - .CurrentPMPAdr(PMPADDR_ARRAY_REGW[0]), - .AdrAtLeastPreviousPMP(1'b1), - .AdrAtLeastCurrentPMP(AboveRegion[0]), - .Match(Regions[0])); - - assign ActiveRegion[0] = |PMPCFG[0][4:3]; - - generate // *** only for PMP_ENTRIES > 0 - for (i = 1; i < `PMP_ENTRIES; i++) begin - pmpadrdec pmpadrdec(.PhysicalAddress(PhysicalAddress), - .AdrMode(PMPCFG[i][4:3]), - .CurrentPMPAdr(PMPADDR_ARRAY_REGW[i]), - .AdrAtLeastPreviousPMP(AboveRegion[i-1]), - .AdrAtLeastCurrentPMP(AboveRegion[i]), - .Match(Regions[i])); - - assign ActiveRegion[i] = |PMPCFG[i][4:3]; - end - endgenerate - - // verilator lint_off UNOPTFLAT - logic [`PMP_ENTRIES-1:0] NoLowerMatch; + assign PAgePMPAdr[0] = 1'b1; + assign NoLowerMatch[0] = 1'b1; + generate // verilator lint_off WIDTH - for (j=0; j<`PMP_ENTRIES; j = j+8) begin + for (j=0; j<`PMP_ENTRIES; j = j+8) assign {PMPCFG[j+7], PMPCFG[j+6], PMPCFG[j+5], PMPCFG[j+4], PMPCFG[j+3], PMPCFG[j+2], PMPCFG[j+1], PMPCFG[j]} = PMPCFG_ARRAY_REGW[j/8]; - end // verilator lint_on WIDTH - for (i=0; i<`PMP_ENTRIES; i++) begin - if (i==0) begin - assign FirstMatch[i] = Regions[i]; - assign NoLowerMatch[i] = ~Regions[i]; - end else begin - assign FirstMatch[i] = Regions[i] & NoLowerMatch[i]; - assign NoLowerMatch[i] = NoLowerMatch[i-1] & ~Regions[i]; - end - assign L_Bits[i] = PMPCFG[i][7] & FirstMatch[i]; - assign X_Bits[i] = PMPCFG[i][2] & FirstMatch[i]; - assign W_Bits[i] = PMPCFG[i][1] & FirstMatch[i]; - assign R_Bits[i] = PMPCFG[i][0] & FirstMatch[i]; - end + for (i=0; i<`PMP_ENTRIES; i++) + pmpadrdec pmpadrdec(.PhysicalAddress, + .PMPCfg(PMPCFG[i]), + .PMPAdr(PMPADDR_ARRAY_REGW[i]), + .PAgePMPAdrIn(PAgePMPAdr[i]), + .PAgePMPAdrOut(PAgePMPAdr[i+1]), + .NoLowerMatchIn(NoLowerMatch[i]), + .NoLowerMatchOut(NoLowerMatch[i+1]), + .Match(Match[i]), + .Active(Active[i]), + .L(L[i]), .X(X[i]), .W(W[i]), .R(R[i]) + ); + // verilator lint_on UNOPTFLAT endgenerate // 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_Bits : |ActiveRegion; + assign EnforcePMP = (PrivilegeModeW == `M_MODE) ? |L : |Active; - assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X_Bits; - assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W_Bits; - assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R_Bits; + assign PMPInstrAccessFaultF = EnforcePMP && ExecuteAccessF && ~|X; + assign PMPStoreAccessFaultM = EnforcePMP && WriteAccessM && ~|W; + assign PMPLoadAccessFaultM = EnforcePMP && ReadAccessM && ~|R; assign PMPSquashBusAccess = PMPInstrAccessFaultF | PMPLoadAccessFaultM | PMPStoreAccessFaultM; diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index 91aee66b..79f7a0e8 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -74,6 +74,7 @@ module uncore ( // Determine which region of physical memory (if any) is being accessed // Use a trimmed down portion of the PMA checker - only the address decoders + // Set access types to all 1 as don't cares because the MMU has already done access checking adrdecs adrdecs({{(`PA_BITS-32){1'b0}}, HADDR}, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals From eff5a1b90f0ce153b48278ced705de3110e0d67a Mon Sep 17 00:00:00 2001 From: Ben Bracker Date: Sat, 3 Jul 2021 11:11:07 -0500 Subject: [PATCH 05/21] fix ICache indenting --- .../regression/wave-dos/linux-waves.do | 10 +- wally-pipelined/src/cache/ICacheCntrl.sv | 240 +++++++++--------- 2 files changed, 123 insertions(+), 127 deletions(-) diff --git a/wally-pipelined/regression/wave-dos/linux-waves.do b/wally-pipelined/regression/wave-dos/linux-waves.do index 63623891..a891c206 100644 --- a/wally-pipelined/regression/wave-dos/linux-waves.do +++ b/wally-pipelined/regression/wave-dos/linux-waves.do @@ -122,11 +122,11 @@ add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UEPC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UTVEC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIP_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIE_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG01_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG23_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPADDR_ARRAY_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/MISA_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csru/FRM_REGW +#add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG01_REGW +#add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG23_REGW +#add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPADDR_ARRAY_REGW +#add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/MISA_REGW +#add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csru/FRM_REGW add wave -divider add wave -hex -r /testbench/* diff --git a/wally-pipelined/src/cache/ICacheCntrl.sv b/wally-pipelined/src/cache/ICacheCntrl.sv index ea52130c..b969437e 100644 --- a/wally-pipelined/src/cache/ICacheCntrl.sv +++ b/wally-pipelined/src/cache/ICacheCntrl.sv @@ -213,179 +213,175 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) ICacheStallF = 1'b1; case (CurrState) - STATE_READY: begin - PCMux = 2'b00; - ICacheReadEn = 1'b1; - if (ITLBMissF) begin - NextState = STATE_TLB_MISS; - end else if (hit & ~spill) begin - SavePC = 1'b1; - ICacheStallF = 1'b0; - NextState = STATE_READY; - end else if (hit & spill) begin - spillSave = 1'b1; - PCMux = 2'b10; - NextState = STATE_HIT_SPILL; - end else if (~hit & ~spill) begin - CntReset = 1'b1; - NextState = STATE_MISS_FETCH_WDV; - end else if (~hit & spill) begin - CntReset = 1'b1; - PCMux = 2'b01; - NextState = STATE_MISS_SPILL_FETCH_WDV; - end else begin + PCMux = 2'b00; + ICacheReadEn = 1'b1; + if (ITLBMissF) begin + NextState = STATE_TLB_MISS; + end else if (hit & ~spill) begin + SavePC = 1'b1; + ICacheStallF = 1'b0; NextState = STATE_READY; - end + end else if (hit & spill) begin + spillSave = 1'b1; + PCMux = 2'b10; + NextState = STATE_HIT_SPILL; + end else if (~hit & ~spill) begin + CntReset = 1'b1; + NextState = STATE_MISS_FETCH_WDV; + end else if (~hit & spill) begin + CntReset = 1'b1; + PCMux = 2'b01; + NextState = STATE_MISS_SPILL_FETCH_WDV; + end else begin + NextState = STATE_READY; + end end - // branch 1, hit spill and 2, miss spill hit STATE_HIT_SPILL: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; - if (hit) begin + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; + if (hit) begin NextState = STATE_HIT_SPILL_FINAL; - end else begin - CntReset = 1'b1; + end else begin + CntReset = 1'b1; NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; - end + end end STATE_HIT_SPILL_MISS_FETCH_WDV: begin - PCMux = 2'b10; - //InstrReadF = 1'b1; - PreCntEn = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; - end else begin - NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; - end + PCMux = 2'b10; + //InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_HIT_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_HIT_SPILL_MISS_FETCH_WDV; + end end STATE_HIT_SPILL_MISS_FETCH_DONE: begin - PCMux = 2'b10; - ICacheMemWriteEnable = 1'b1; + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; NextState = STATE_HIT_SPILL_MERGE; end STATE_HIT_SPILL_MERGE: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_HIT_SPILL_FINAL; end STATE_HIT_SPILL_FINAL: begin - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - NextState = STATE_READY; - ICacheStallF = 1'b0; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + NextState = STATE_READY; + ICacheStallF = 1'b0; end - // branch 3 miss no spill STATE_MISS_FETCH_WDV: begin - PCMux = 2'b01; - //InstrReadF = 1'b1; - PreCntEn = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_FETCH_DONE; - end else begin - NextState = STATE_MISS_FETCH_WDV; - end + PCMux = 2'b01; + //InstrReadF = 1'b1; + PreCntEn = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_FETCH_WDV; + end end STATE_MISS_FETCH_DONE: begin - PCMux = 2'b01; - ICacheMemWriteEnable = 1'b1; + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; NextState = STATE_MISS_READ; end STATE_MISS_READ: begin - PCMux = 2'b01; - ICacheReadEn = 1'b1; - NextState = STATE_READY; + PCMux = 2'b01; + ICacheReadEn = 1'b1; + NextState = STATE_READY; end - // branch 4 miss spill hit, and 5 miss spill miss STATE_MISS_SPILL_FETCH_WDV: begin - PCMux = 2'b01; - PreCntEn = 1'b1; - //InstrReadF = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_SPILL_FETCH_DONE; - end else begin - NextState = STATE_MISS_SPILL_FETCH_WDV; - end + PCMux = 2'b01; + PreCntEn = 1'b1; + //InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_FETCH_WDV; + end end STATE_MISS_SPILL_FETCH_DONE: begin - PCMux = 2'b01; - ICacheMemWriteEnable = 1'b1; - NextState = STATE_MISS_SPILL_READ1; + PCMux = 2'b01; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_READ1; end STATE_MISS_SPILL_READ1: begin // always be a hit as we just wrote that cache block. - PCMux = 2'b01; // there is a 1 cycle delay after setting the address before the date arrives. - ICacheReadEn = 1'b1; - NextState = STATE_MISS_SPILL_2; + PCMux = 2'b01; // there is a 1 cycle delay after setting the address before the date arrives. + ICacheReadEn = 1'b1; + NextState = STATE_MISS_SPILL_2; end STATE_MISS_SPILL_2: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. - ICacheReadEn = 1'b1; - NextState = STATE_MISS_SPILL_2_START; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + spillSave = 1'b1; /// *** Could pipeline these to make it clearer in the fsm. + ICacheReadEn = 1'b1; + NextState = STATE_MISS_SPILL_2_START; end STATE_MISS_SPILL_2_START: begin - if (~hit) begin - CntReset = 1'b1; - NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; - end else begin - NextState = STATE_READY; - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - ICacheStallF = 1'b0; - end + if (~hit) begin + CntReset = 1'b1; + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end else begin + NextState = STATE_READY; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + ICacheStallF = 1'b0; + end end STATE_MISS_SPILL_MISS_FETCH_WDV: begin - PCMux = 2'b10; - PreCntEn = 1'b1; - //InstrReadF = 1'b1; - if (FetchCountFlag & InstrAckF) begin - NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; - end else begin - NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; - end + PCMux = 2'b10; + PreCntEn = 1'b1; + //InstrReadF = 1'b1; + if (FetchCountFlag & InstrAckF) begin + NextState = STATE_MISS_SPILL_MISS_FETCH_DONE; + end else begin + NextState = STATE_MISS_SPILL_MISS_FETCH_WDV; + end end STATE_MISS_SPILL_MISS_FETCH_DONE: begin - PCMux = 2'b10; - ICacheMemWriteEnable = 1'b1; - NextState = STATE_MISS_SPILL_MERGE; + PCMux = 2'b10; + ICacheMemWriteEnable = 1'b1; + NextState = STATE_MISS_SPILL_MERGE; end STATE_MISS_SPILL_MERGE: begin - PCMux = 2'b10; - UnalignedSelect = 1'b1; - ICacheReadEn = 1'b1; + PCMux = 2'b10; + UnalignedSelect = 1'b1; + ICacheReadEn = 1'b1; NextState = STATE_MISS_SPILL_FINAL; end STATE_MISS_SPILL_FINAL: begin - ICacheReadEn = 1'b1; - PCMux = 2'b00; - UnalignedSelect = 1'b1; - SavePC = 1'b1; - ICacheStallF = 1'b0; - NextState = STATE_READY; + ICacheReadEn = 1'b1; + PCMux = 2'b00; + UnalignedSelect = 1'b1; + SavePC = 1'b1; + ICacheStallF = 1'b0; + NextState = STATE_READY; end STATE_TLB_MISS: begin - if (ITLBWriteF | WalkerInstrPageFaultF) begin - NextState = STATE_TLB_MISS_DONE; - end else begin - NextState = STATE_TLB_MISS; - end + if (ITLBWriteF | WalkerInstrPageFaultF) begin + NextState = STATE_TLB_MISS_DONE; + end else begin + NextState = STATE_TLB_MISS; + end end STATE_TLB_MISS_DONE : begin - NextState = STATE_READY; + NextState = STATE_READY; end default: begin - PCMux = 2'b01; - NextState = STATE_READY; + PCMux = 2'b01; + NextState = STATE_READY; end // *** add in error handling and invalidate/evict endcase From d8facacef65568268dd26c4756f97b1fb734ea35 Mon Sep 17 00:00:00 2001 From: Ben Bracker Date: Sat, 3 Jul 2021 11:24:41 -0500 Subject: [PATCH 06/21] src/cache/ICacheCntrl.sv --- wally-pipelined/src/cache/ICacheCntrl.sv | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/wally-pipelined/src/cache/ICacheCntrl.sv b/wally-pipelined/src/cache/ICacheCntrl.sv index b969437e..748b3f5e 100644 --- a/wally-pipelined/src/cache/ICacheCntrl.sv +++ b/wally-pipelined/src/cache/ICacheCntrl.sv @@ -71,11 +71,11 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) ); // FSM states - localparam STATE_READY = 0; - localparam STATE_HIT_SPILL = 1; // spill, block 0 hit - localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 2; // block 1 miss, issue read to AHB and wait data. - localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 3; // write data into SRAM/LUT - localparam STATE_HIT_SPILL_MERGE = 4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. + localparam STATE_READY = 'h0; + localparam STATE_HIT_SPILL = 'h1; // spill, block 0 hit + localparam STATE_HIT_SPILL_MISS_FETCH_WDV = 'h2; // block 1 miss, issue read to AHB and wait data. + localparam STATE_HIT_SPILL_MISS_FETCH_DONE = 'h3; // write data into SRAM/LUT + localparam STATE_HIT_SPILL_MERGE = 'h4; // Read block 0 of CPU access, should be able to optimize into STATE_HIT_SPILL. // a challenge is the spill signal gets us out of the ready state and moves us to // 1 of the 2 spill branches. However the original fsm design had us return to @@ -91,30 +91,30 @@ module ICacheCntrl #(parameter BLOCKLEN = 256) // between CPU stalling and that register. // Picking option 1. - localparam STATE_HIT_SPILL_FINAL = 5; // this state replicates STATE_READY's replay of the + localparam STATE_HIT_SPILL_FINAL = 'h5; // this state replicates STATE_READY's replay of the // spill access but does nto consider spill. It also does not do another operation. - localparam STATE_MISS_FETCH_WDV = 6; // aligned miss, issue read to AHB and wait for data. - localparam STATE_MISS_FETCH_DONE = 7; // write data into SRAM/LUT - localparam STATE_MISS_READ = 8; // read block 1 from SRAM/LUT + localparam STATE_MISS_FETCH_WDV = 'h6; // aligned miss, issue read to AHB and wait for data. + localparam STATE_MISS_FETCH_DONE = 'h7; // write data into SRAM/LUT + localparam STATE_MISS_READ = 'h8; // read block 1 from SRAM/LUT - localparam STATE_MISS_SPILL_FETCH_WDV = 9; // spill, miss on block 0, issue read to AHB and wait - localparam STATE_MISS_SPILL_FETCH_DONE = 10; // write data into SRAM/LUT - localparam STATE_MISS_SPILL_READ1 = 11; // read block 0 from SRAM/LUT - localparam STATE_MISS_SPILL_2 = 12; // return to ready if hit or do second block update. - localparam STATE_MISS_SPILL_2_START = 13; // return to ready if hit or do second block update. - localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 14; // miss on block 1, issue read to AHB and wait - localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 15; // write data to SRAM/LUT - localparam STATE_MISS_SPILL_MERGE = 16; // read block 0 of CPU access, + localparam STATE_MISS_SPILL_FETCH_WDV = 'h9; // spill, miss on block 0, issue read to AHB and wait + localparam STATE_MISS_SPILL_FETCH_DONE = 'ha; // write data into SRAM/LUT + localparam STATE_MISS_SPILL_READ1 = 'hb; // read block 0 from SRAM/LUT + localparam STATE_MISS_SPILL_2 = 'hc; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_2_START = 'hd; // return to ready if hit or do second block update. + localparam STATE_MISS_SPILL_MISS_FETCH_WDV = 'he; // miss on block 1, issue read to AHB and wait + localparam STATE_MISS_SPILL_MISS_FETCH_DONE = 'hf; // write data to SRAM/LUT + localparam STATE_MISS_SPILL_MERGE = 'h10; // read block 0 of CPU access, - localparam STATE_MISS_SPILL_FINAL = 17; // this state replicates STATE_READY's replay of the + localparam STATE_MISS_SPILL_FINAL = 'h11; // this state replicates STATE_READY's replay of the // spill access but does nto consider spill. It also does not do another operation. - localparam STATE_INVALIDATE = 18; // *** not sure if invalidate or evict? invalidate by cache block or address? - localparam STATE_TLB_MISS = 19; - localparam STATE_TLB_MISS_DONE = 20; + localparam STATE_INVALIDATE = 'h12; // *** not sure if invalidate or evict? invalidate by cache block or address? + localparam STATE_TLB_MISS = 'h13; + localparam STATE_TLB_MISS_DONE = 'h14; From d68791a6d96550c3e52287f92c0f22deff56c4b1 Mon Sep 17 00:00:00 2001 From: bbracker Date: Sat, 3 Jul 2021 17:25:19 -0400 Subject: [PATCH 07/21] optionally output GDB-formatted instruction list to main buildroot folder --- wally-pipelined/linux-testgen/logAllBuildroot.sh | 7 ++++--- wally-pipelined/linux-testgen/parse_qemu.py | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/wally-pipelined/linux-testgen/logAllBuildroot.sh b/wally-pipelined/linux-testgen/logAllBuildroot.sh index 740fa8c4..86bba6af 100755 --- a/wally-pipelined/linux-testgen/logAllBuildroot.sh +++ b/wally-pipelined/linux-testgen/logAllBuildroot.sh @@ -21,11 +21,12 @@ # - Logs parse_qemu.py's simulated gdb output to qemu_in_gdb_format.txt #cat qemu_output.txt | ./parse_qemu.py >qemu_in_gdb_format.txt #cat qemu_output.txt | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot/" + # Uncomment this version in case you just want to have qemu_in_gdb_format.txt around # It is often helpful for general debugging -#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | ./parse_qemu.py >qemu_in_gdb_format.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog - +(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | ./parse_qemu.py >/courses/e190ax/buildroot_boot/qemu_in_gdb_format.txt) & riscv64-unknown-elf-gdb -x gdbinit_qemulog # Split qemu_in_gdb_format.txt into chunks of 100,000 instructions for easier inspection +#cd /courses/e190ax/buildroot_boot #split -d -l 5600000 qemu_in_gdb_format.txt --verbose # Uncomment this version for parse_gdb_output.py debugging @@ -36,4 +37,4 @@ # =========== Just Do the Thing ========== # Uncomment this version for the whole thing # - Logs info needed by buildroot testbench -(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot_new/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog +#(qemu-system-riscv64 -M virt -nographic -bios /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/fw_jump.elf -kernel /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/Image -append "root=/dev/vda ro" -initrd /courses/e190ax/qemu_sim/rv64_initrd/buildroot_experimental/output/images/rootfs.cpio -d nochain,cpu,in_asm -serial /dev/null -singlestep -s -S 2>&1 >/dev/null | ./parse_qemu.py | ./parse_gdb_output.py "/courses/e190ax/buildroot_boot_new/") & riscv64-unknown-elf-gdb -x gdbinit_qemulog diff --git a/wally-pipelined/linux-testgen/parse_qemu.py b/wally-pipelined/linux-testgen/parse_qemu.py index ac5d95f0..4da168ab 100755 --- a/wally-pipelined/linux-testgen/parse_qemu.py +++ b/wally-pipelined/linux-testgen/parse_qemu.py @@ -9,9 +9,10 @@ pageFaultCSRs = {} regs = {} pageFaultRegs = {} instrs = {} +instrCount = 0 def printPC(l): - global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount if not inPageFault: inst = l.split() if len(inst) > 3: @@ -19,6 +20,9 @@ def printPC(l): else: print(f'=> {inst[1]}:\t{inst[2]}') print(f'{inst[0]} 0x{inst[1]}') + instrCount += 1 + if ((instrCount % 100000) == 0): + sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n") def printCSRs(): global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs From 9645b023c95164c5c10854e871a6762cd3e5beb8 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 01:19:38 -0400 Subject: [PATCH 08/21] Moved BOOTTIM to 0x1000-0x1FFF. Added logic to detect an access to undefined memory and assert HREADY so bus doesn't hang. --- .../config/buildroot/wally-config.vh | 8 +++--- .../config/busybear/wally-config.vh | 8 +++--- .../config/coremark-64i/wally-config.vh | 27 +++++++++---------- .../config/coremark/wally-config.vh | 26 +++++++++--------- .../config/coremark_bare/wally-config.vh | 26 +++++++++--------- wally-pipelined/config/rv32ic/wally-config.vh | 6 ++--- wally-pipelined/config/rv64BP/wally-config.vh | 26 +++++++++--------- wally-pipelined/config/rv64ic/wally-config.vh | 8 +++--- .../config/rv64icfd/wally-config.vh | 26 +++++++++--------- .../config/rv64imc/wally-config.vh | 26 +++++++++--------- .../regression/wave-dos/linux-waves.do | 3 +-- wally-pipelined/src/generic/flop.sv | 2 +- wally-pipelined/src/mmu/adrdecs.sv | 6 ++++- wally-pipelined/src/mmu/pmachecker.sv | 2 +- wally-pipelined/src/mmu/pmpchecker.sv | 2 +- wally-pipelined/src/uncore/uncore.sv | 20 +++++--------- .../testbench/testbench-imperas.sv | 12 +++++++++ wally-pipelined/testbench/testbench-linux.sv | 12 +++++++++ 18 files changed, 125 insertions(+), 121 deletions(-) diff --git a/wally-pipelined/config/buildroot/wally-config.vh b/wally-pipelined/config/buildroot/wally-config.vh index e1e4f300..ace7366d 100644 --- a/wally-pipelined/config/buildroot/wally-config.vh +++ b/wally-pipelined/config/buildroot/wally-config.vh @@ -62,10 +62,10 @@ // 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 `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 56'h00003FFF -//`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 56'h00000FFF +//`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +//`define BOOTTIM_RANGE 56'h00003FFF +`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/busybear/wally-config.vh b/wally-pipelined/config/busybear/wally-config.vh index 58c1c8a0..44729449 100644 --- a/wally-pipelined/config/busybear/wally-config.vh +++ b/wally-pipelined/config/busybear/wally-config.vh @@ -64,10 +64,10 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 56'h00003FFF -//`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 56'h00000FFF +//`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +//`define BOOTTIM_RANGE 56'h00003FFF +`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/coremark-64i/wally-config.vh b/wally-pipelined/config/coremark-64i/wally-config.vh index f72b4f61..17d48344 100644 --- a/wally-pipelined/config/coremark-64i/wally-config.vh +++ b/wally-pipelined/config/coremark-64i/wally-config.vh @@ -55,26 +55,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF - +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes // Tie GPIO outputs back to inputs diff --git a/wally-pipelined/config/coremark/wally-config.vh b/wally-pipelined/config/coremark/wally-config.vh index ccf0a64b..7bfdc882 100644 --- a/wally-pipelined/config/coremark/wally-config.vh +++ b/wally-pipelined/config/coremark/wally-config.vh @@ -63,25 +63,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 34'h80000000 +`define TIM_RANGE 34'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 34'h02000000 +`define CLINT_RANGE 34'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 34'h10012000 +`define GPIO_RANGE 34'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 34'h10000000 +`define UART_RANGE 34'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 34'h0C000000 +`define PLIC_RANGE 34'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/coremark_bare/wally-config.vh b/wally-pipelined/config/coremark_bare/wally-config.vh index d55200b4..fb4bee34 100644 --- a/wally-pipelined/config/coremark_bare/wally-config.vh +++ b/wally-pipelined/config/coremark_bare/wally-config.vh @@ -66,25 +66,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 34'h80000000 +`define TIM_RANGE 34'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 34'h02000000 +`define CLINT_RANGE 34'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 34'h10012000 +`define GPIO_RANGE 34'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 34'h10000000 +`define UART_RANGE 34'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 34'h0C000000 +`define PLIC_RANGE 34'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index 29cd973a..1933a2e7 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -63,10 +63,8 @@ // *** each of these is `PA_BITS wide. is this paramaterizable INSIDE the config file? `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 34'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 34'h00003FFF -//`define BOOTTIM_BASE 34'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 34'h00000FFF +`define BOOTTIM_BASE 34'h00001000 +`define BOOTTIM_RANGE 34'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 34'h80000000 `define TIM_RANGE 34'h07FFFFFF diff --git a/wally-pipelined/config/rv64BP/wally-config.vh b/wally-pipelined/config/rv64BP/wally-config.vh index 2e5eaf37..335f2d87 100644 --- a/wally-pipelined/config/rv64BP/wally-config.vh +++ b/wally-pipelined/config/rv64BP/wally-config.vh @@ -64,25 +64,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index a15ef18b..ad97d446 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -67,10 +67,10 @@ // *** each of these is `PA_BITS wide. is this paramaterizable INSIDE the config file? `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_RANGE 56'h00003FFF -`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 56'h00000FFF +//`define BOOTTIM_RANGE 56'h00003FFF +//`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 `define TIM_RANGE 56'h07FFFFFF diff --git a/wally-pipelined/config/rv64icfd/wally-config.vh b/wally-pipelined/config/rv64icfd/wally-config.vh index 29322210..e645f014 100644 --- a/wally-pipelined/config/rv64icfd/wally-config.vh +++ b/wally-pipelined/config/rv64icfd/wally-config.vh @@ -66,25 +66,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/config/rv64imc/wally-config.vh b/wally-pipelined/config/rv64imc/wally-config.vh index 5ecb9bef..885a519d 100644 --- a/wally-pipelined/config/rv64imc/wally-config.vh +++ b/wally-pipelined/config/rv64imc/wally-config.vh @@ -62,25 +62,23 @@ // Range should be a thermometer code with 0's in the upper bits and 1s in the lower bits `define BOOTTIM_SUPPORTED 1'b1 -`define BOOTTIM_BASE 32'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -`define BOOTTIM_RANGE 32'h00003FFF -//`define BOOTTIM_BASE 32'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 32'h00000FFF +`define BOOTTIM_BASE 56'h00001000 +`define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 -`define TIM_BASE 32'h80000000 -`define TIM_RANGE 32'h07FFFFFF +`define TIM_BASE 56'h80000000 +`define TIM_RANGE 56'h07FFFFFF `define CLINT_SUPPORTED 1'b1 -`define CLINT_BASE 32'h02000000 -`define CLINT_RANGE 32'h0000FFFF +`define CLINT_BASE 56'h02000000 +`define CLINT_RANGE 56'h0000FFFF `define GPIO_SUPPORTED 1'b1 -`define GPIO_BASE 32'h10012000 -`define GPIO_RANGE 32'h000000FF +`define GPIO_BASE 56'h10012000 +`define GPIO_RANGE 56'h000000FF `define UART_SUPPORTED 1'b1 -`define UART_BASE 32'h10000000 -`define UART_RANGE 32'h00000007 +`define UART_BASE 56'h10000000 +`define UART_RANGE 56'h00000007 `define PLIC_SUPPORTED 1'b1 -`define PLIC_BASE 32'h0C000000 -`define PLIC_RANGE 32'h03FFFFFF +`define PLIC_BASE 56'h0C000000 +`define PLIC_RANGE 56'h03FFFFFF // Test modes diff --git a/wally-pipelined/regression/wave-dos/linux-waves.do b/wally-pipelined/regression/wave-dos/linux-waves.do index 63623891..843ed274 100644 --- a/wally-pipelined/regression/wave-dos/linux-waves.do +++ b/wally-pipelined/regression/wave-dos/linux-waves.do @@ -122,8 +122,7 @@ add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UEPC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UTVEC_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIP_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrn/UIE_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG01_REGW -add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG23_REGW +add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPCFG_ARRAY_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/PMPADDR_ARRAY_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csrm/MISA_REGW add wave -hex sim:/testbench/dut/hart/priv/csr/genblk1/csru/FRM_REGW diff --git a/wally-pipelined/src/generic/flop.sv b/wally-pipelined/src/generic/flop.sv index a5636c6f..cb583de2 100644 --- a/wally-pipelined/src/generic/flop.sv +++ b/wally-pipelined/src/generic/flop.sv @@ -77,7 +77,7 @@ module flopenr #(parameter WIDTH = 8) ( output logic [WIDTH-1:0] q); always_ff @(posedge clk, posedge reset) - if (reset) q <= #1 0; + if (reset) q <= #1 0; else if (en) q <= #1 d; endmodule diff --git a/wally-pipelined/src/mmu/adrdecs.sv b/wally-pipelined/src/mmu/adrdecs.sv index 8585a4ee..94951aad 100644 --- a/wally-pipelined/src/mmu/adrdecs.sv +++ b/wally-pipelined/src/mmu/adrdecs.sv @@ -24,12 +24,13 @@ /////////////////////////////////////////// `include "wally-config.vh" + // verilator lint_off UNOPTFLAT module adrdecs ( input logic [`PA_BITS-1:0] PhysicalAddress, input logic AccessRW, AccessRX, AccessRWX, input logic [1:0] Size, - output logic [5:0] SelRegions + output logic [6:0] SelRegions ); // Determine which region of physical memory (if any) is being accessed @@ -41,5 +42,8 @@ module adrdecs ( adrdec uartdec(PhysicalAddress, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[1]); adrdec plicdec(PhysicalAddress, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[0]); + assign SelRegions[6] = ~|(SelRegions[5:0]); + endmodule + // verilator lint_on UNOPTFLAT diff --git a/wally-pipelined/src/mmu/pmachecker.sv b/wally-pipelined/src/mmu/pmachecker.sv index 26d8ac87..86abcb3f 100644 --- a/wally-pipelined/src/mmu/pmachecker.sv +++ b/wally-pipelined/src/mmu/pmachecker.sv @@ -45,7 +45,7 @@ module pmachecker ( logic PMAAccessFault; logic AccessRW, AccessRWX, AccessRX; - logic [5:0] SelRegions; + logic [6:0] SelRegions; // Determine what type of access is being made assign AccessRW = ReadAccessM | WriteAccessM; diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 27c7e508..96018231 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -72,7 +72,7 @@ module pmpchecker ( assign {PMPCFG[j+7], PMPCFG[j+6], PMPCFG[j+5], PMPCFG[j+4], PMPCFG[j+3], PMPCFG[j+2], PMPCFG[j+1], PMPCFG[j]} = PMPCFG_ARRAY_REGW[j/8]; // verilator lint_on WIDTH - for (i=0; i<`PMP_ENTRIES; i++) + for (i=0; i<`PMP_ENTRIES; i++) // *** can this be done with array notation? pmpadrdec pmpadrdec(.PhysicalAddress, .PMPCfg(PMPCFG[i]), .PMPAdr(PMPADDR_ARRAY_REGW[i]), diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index 79f7a0e8..e5f5fdd7 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -62,13 +62,14 @@ module uncore ( logic [`XLEN-1:0] HWDATA; logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART; - logic [5:0] HSELRegions; + logic [6:0] HSELRegions; logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART; logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD; logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART; logic HREADYTim, HREADYCLINT, HREADYPLIC, HREADYGPIO, HREADYUART; logic [`XLEN-1:0] HREADBootTim; logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim; + logic HSELNoneD; logic [1:0] MemRWboottim; logic UARTIntr,GPIOIntr; @@ -78,7 +79,7 @@ module uncore ( adrdecs adrdecs({{(`PA_BITS-32){1'b0}}, HADDR}, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions; + assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions[5:0]; // subword accesses: converts HWDATAIN to HWDATA subwordwrite sww(.*); @@ -134,19 +135,10 @@ module uncore ( HSELPLICD & HREADYPLIC | HSELGPIOD & HREADYGPIO | HSELBootTimD & HREADYBootTim | - HSELUARTD & HREADYUART; - - /* PMA checker now handles access faults. *** This can be deleted - // Faults - assign DataAccessFaultM = ~(HSELTimD | HSELCLINTD | HSELPLICD | HSELGPIOD | HSELBootTimD | HSELUARTD); - */ + HSELUARTD & HREADYUART | + HSELNoneD; // don't lock up the bus if no region is being accessed // Address Decoder Delay (figure 4-2 in spec) - flopr #(1) hseltimreg(HCLK, ~HRESETn, HSELTim, HSELTimD); - flopr #(1) hselclintreg(HCLK, ~HRESETn, HSELCLINT, HSELCLINTD); - flopr #(1) hselplicreg(HCLK, ~HRESETn, HSELPLIC, HSELPLICD); - flopr #(1) hselgpioreg(HCLK, ~HRESETn, HSELGPIO, HSELGPIOD); - flopr #(1) hseluartreg(HCLK, ~HRESETn, HSELUART, HSELUARTD); - flopr #(1) hselboottimreg(HCLK, ~HRESETn, HSELBootTim, HSELBootTimD); + flopr #(7) hseldelayreg(HCLK, ~HRESETn, HSELRegions, {HSELNoneD, HSELBootTimD, HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD}); endmodule diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 11b8e562..8c3e28c3 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -520,6 +520,7 @@ string tests32f[] = '{ // check assertions for a legal configuration riscvassertions riscvassertions(); + logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS); // pick tests based on modes supported initial begin @@ -722,6 +723,7 @@ module riscvassertions(); // Legal number of PMP entries are 0, 16, or 64 initial begin assert (`PMP_ENTRIES == 0 || `PMP_ENTRIES==16 || `PMP_ENTRIES==64) else $error("Illegal number of PMP entries"); + assert (`F_SUPPORTED || ~`D_SUPPORTED) else $error("Can't support double without supporting float"); end endmodule @@ -949,3 +951,13 @@ module instrNameDecTB( default: name = "ILLEGAL"; endcase endmodule + +module logging( + input logic clk, reset, + input logic [31:0] HADDR, + input logic [1:0] HTRANS); + + always @(posedge clk) + if (HTRANS != 2'b00 && HADDR == 0) + $display("Warning: access to memory address 0\n"); +endmodule diff --git a/wally-pipelined/testbench/testbench-linux.sv b/wally-pipelined/testbench/testbench-linux.sv index 8f8a5d44..18ef74ff 100644 --- a/wally-pipelined/testbench/testbench-linux.sv +++ b/wally-pipelined/testbench/testbench-linux.sv @@ -334,6 +334,8 @@ module testbench(); `SCAN_PC(data_file_PCM, scan_file_PCM, trashString, trashString, InstrMExpected, PCMexpected); end + logging logging(clk, reset, dut.uncore.HADDR, dut.uncore.HTRANS); + // ------------------- // Additional Hardware // ------------------- @@ -718,6 +720,16 @@ module testbench(); endfunction endmodule +module logging( + input logic clk, reset, + input logic [31:0] HADDR, + input logic [1:0] HTRANS); + + always @(posedge clk) + if (HTRANS != 2'b00 && HADDR == 0) + $display("Warning: access to memory address 0\n"); +endmodule + module instrTrackerTB( input logic clk, reset, From accbebfa6fa415450efe53e91308bb21ce272044 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 01:40:27 -0400 Subject: [PATCH 09/21] Commented out some unused modules --- wally-pipelined/src/fpu/mult_R4_64_64_cs.sv | 20 ++++-- wally-pipelined/src/fpu/shifter_denorm.sv | 2 + wally-pipelined/src/muldiv/div.sv | 3 +- wally-pipelined/src/uncore/imem.sv | 71 --------------------- 4 files changed, 17 insertions(+), 79 deletions(-) delete mode 100644 wally-pipelined/src/uncore/imem.sv diff --git a/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv b/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv index 7b4d3f64..eca5fadf 100644 --- a/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv +++ b/wally-pipelined/src/fpu/mult_R4_64_64_cs.sv @@ -2,6 +2,7 @@ // It is unsigned and uses Radix-4 Booth encoding. // This file was automatically generated by tdm.pl. +/* module mult64 (x, y, P); input [63:0] x; @@ -18,7 +19,8 @@ module mult64 (x, y, P); //assign P = Pt[127:0]; ldf128 cpa (cout, P, Sum, Carry, 1'b0); -endmodule // mult64 +endmodule // mult64 +*/ module multiplier( y, x, Sum, Carry ); @@ -11612,7 +11614,7 @@ module r4be(x0,x1,x2,sing,doub,neg); endmodule // r4be - +/* // Use maj and two xor2's, with cin being late module fullAdd_xc(cout, s, a, b, cin); @@ -11629,7 +11631,7 @@ module fullAdd_xc(cout, s, a, b, cin); maj MAJ_0_112(cout,a,b,cin); endmodule // fullAdd_xc - +*/ module maj(y, a, b, c); @@ -11645,6 +11647,7 @@ module maj(y, a, b, c); endmodule // maj +/* // 4:2 Weinberger compressor module fourtwo_x(t, S, C, X, Y, Z, W, t_1); @@ -11664,6 +11667,7 @@ module fourtwo_x(t, S, C, X, Y, Z, W, t_1); fullAdd_xc secondCSA_0_160(C,S,W,t_1,intermediate); endmodule // fourtwo_x +*/ module inverter(egress, in); @@ -11767,6 +11771,7 @@ module fullAdd_x(cout,sum,a,b,c); endmodule // fullAdd_x +/* module nand2(egress,in1,in2); output egress; @@ -11800,7 +11805,7 @@ module and3(y,a,b,c); assign y = a&b&c; endmodule // and3 - +*/ module and2(y,a,b); output y; @@ -11810,7 +11815,7 @@ module and2(y,a,b); assign y = a&b; endmodule // and2 - +/* module nor2(egress,in1,in2); output egress; @@ -11902,6 +11907,7 @@ module oai(egress,in1,in2,in3); assign egress = ~(in3 & (in1|in2)); endmodule // oai +*/ module aoi(egress,in1,in2,in3); @@ -11949,7 +11955,7 @@ module fullAdd_i(cout_b,sum_b,a,b,c); sum_b sum_0_32(sum_b,a,b,c,cout_b); endmodule // fullAdd_i - +/* module fullAdd(cout,s,a,b,c); output cout; @@ -11979,7 +11985,7 @@ module blackCell(g_i_j, p_i_j, g_i_k, p_i_k, g_kneg1_j, p_kneg1_j); and2 and_0_48(p_i_j, p_i_k, p_kneg1_j); endmodule // blackCell - +*/ module grayCell(g_i_j, g_i_k, p_i_k, g_kneg1_j); output g_i_j; diff --git a/wally-pipelined/src/fpu/shifter_denorm.sv b/wally-pipelined/src/fpu/shifter_denorm.sv index ed208381..e56b0072 100755 --- a/wally-pipelined/src/fpu/shifter_denorm.sv +++ b/wally-pipelined/src/fpu/shifter_denorm.sv @@ -118,6 +118,7 @@ module barrel_shifter_r57 (Z, Sticky, A, Shift); endmodule // barrel_shifter_r57 +/* module barrel_shifter_r64 (Z, Sticky, A, Shift); input [63:0] A; @@ -160,3 +161,4 @@ module barrel_shifter_r64 (Z, Sticky, A, Shift); assign Sticky = (S != sixtythreezeros); endmodule // barrel_shifter_r64 +*/ \ No newline at end of file diff --git a/wally-pipelined/src/muldiv/div.sv b/wally-pipelined/src/muldiv/div.sv index 3bea0e47..70767dcc 100755 --- a/wally-pipelined/src/muldiv/div.sv +++ b/wally-pipelined/src/muldiv/div.sv @@ -307,7 +307,7 @@ module csa #(parameter WIDTH=8) (input logic [WIDTH-1:0] a, b, c, assign carry = {carry_temp[WIDTH-1:1], 1'b0}; endmodule // csa - +/* module eqcmp #(parameter WIDTH = 8) (input logic [WIDTH-1:0] a, b, output logic y); @@ -315,6 +315,7 @@ module eqcmp #(parameter WIDTH = 8) assign y = (a == b); endmodule // eqcmp +*/ // QST for r=4 module qst4 (input logic [6:0] s, input logic [2:0] d, diff --git a/wally-pipelined/src/uncore/imem.sv b/wally-pipelined/src/uncore/imem.sv deleted file mode 100644 index 85362edf..00000000 --- a/wally-pipelined/src/uncore/imem.sv +++ /dev/null @@ -1,71 +0,0 @@ -/////////////////////////////////////////// -// imem.sv -// -// Written: David_Harris@hmc.edu 9 January 2021 -// Modified: -// -// Purpose: -// -// A component of the Wally configurable RISC-V project. -// -// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, -// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -/////////////////////////////////////////// - -`include "wally-config.vh" - -module imem ( - input logic [`XLEN-1:1] AdrF, - output logic [31:0] InstrF, - output logic [15:0] rd2, // bogus, delete when real multicycle fetch works - output logic InstrAccessFaultF); - - /* verilator lint_off UNDRIVEN */ - logic [`XLEN-1:0] RAM[`TIM_BASE>>(1+`XLEN/32):(`TIM_RANGE+`TIM_BASE)>>(1+`XLEN/32)]; - logic [`XLEN-1:0] bootram[`BOOTTIM_BASE>>(1+`XLEN/32):(`BOOTTIM_RANGE+`BOOTTIM_BASE)>>(1+`XLEN/32)]; - /* verilator lint_on UNDRIVEN */ - logic [31:0] adrbits; // needs to be 32 bits to index RAM - logic [`XLEN-1:0] rd; -// logic [15:0] rd2; - - generate - if (`XLEN==32) assign adrbits = AdrF[31:2]; - else assign adrbits = AdrF[31:3]; - endgenerate - - assign #2 rd = (AdrF < (`TIM_BASE >> 1)) ? bootram[adrbits] : RAM[adrbits]; // busybear: 2 memory options - - // hack right now for unaligned 32-bit instructions - // eventually this will need to cause a stall like a cache miss - // when the instruction wraps around a cache line - // could be optimized to only stall when the instruction wrapping is 32 bits - assign #2 rd2 = (AdrF < (`TIM_BASE >> 1)) ? bootram[adrbits+1][15:0] : RAM[adrbits+1][15:0]; //busybear: 2 memory options - generate - if (`XLEN==32) begin - assign InstrF = AdrF[1] ? {rd2[15:0], rd[31:16]} : rd; - // First, AdrF needs to get its last bit appended back onto it - // Then not-XORing it with TIM_BASE checks if it matches TIM_BASE exactly - // Then ORing it with TIM_RANGE introduces some leeway into the previous check, by allowing the lower bits to be either high or low - - assign InstrAccessFaultF = (~&(({AdrF,1'b0} ~^ `TIM_BASE) | `TIM_RANGE)) & (~&(({AdrF,1'b0} ~^ `BOOTTIM_BASE) | `BOOTTIM_RANGE)); - - end else begin - assign InstrF = AdrF[2] ? (AdrF[1] ? {rd2[15:0], rd[63:48]} : rd[63:32]) - : (AdrF[1] ? rd[47:16] : rd[31:0]); - // - assign InstrAccessFaultF = (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `TIM_BASE | `TIM_RANGE)) & (|AdrF[`XLEN-1:32] | ~&({AdrF[31:1],1'b0} ~^ `BOOTTIM_BASE | `BOOTTIM_RANGE)); - end - endgenerate -endmodule - From ccd9c05303b06a673d3918ec12a2cebbc7b858c5 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 10:51:56 -0400 Subject: [PATCH 10/21] Switched to array notation for pmpchecker --- .../config/buildroot/wally-config.vh | 4 +- .../config/coremark-64i/wally-config.vh | 1 + wally-pipelined/src/mmu/pmpchecker.sv | 49 ++++++++----------- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/wally-pipelined/config/buildroot/wally-config.vh b/wally-pipelined/config/buildroot/wally-config.vh index ace7366d..a535abff 100644 --- a/wally-pipelined/config/buildroot/wally-config.vh +++ b/wally-pipelined/config/buildroot/wally-config.vh @@ -62,9 +62,7 @@ // 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 `define BOOTTIM_SUPPORTED 1'b1 -//`define BOOTTIM_BASE 56'h00000000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder -//`define BOOTTIM_RANGE 56'h00003FFF -`define BOOTTIM_BASE 56'h00001000 // spec had been 0x1000 to 0x2FFF, but dh truncated to 0x1000 to 0x1FFF because upper half seems to be all zeros and this is easier for decoder +`define BOOTTIM_BASE 56'h00001000 `define BOOTTIM_RANGE 56'h00000FFF `define TIM_SUPPORTED 1'b1 `define TIM_BASE 56'h80000000 diff --git a/wally-pipelined/config/coremark-64i/wally-config.vh b/wally-pipelined/config/coremark-64i/wally-config.vh index 17d48344..ae3100c6 100644 --- a/wally-pipelined/config/coremark-64i/wally-config.vh +++ b/wally-pipelined/config/coremark-64i/wally-config.vh @@ -72,6 +72,7 @@ `define PLIC_SUPPORTED 1'b1 `define PLIC_BASE 56'h0C000000 `define PLIC_RANGE 56'h03FFFFFF + // Test modes // Tie GPIO outputs back to inputs diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 96018231..e073a2f1 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -51,43 +51,36 @@ module pmpchecker ( output logic PMPStoreAccessFaultM ); - // verilator lint_off UNOPTFLAT // Bit i is high when the address falls in PMP region i logic EnforcePMP; - logic [7:0] PMPCFG [`PMP_ENTRIES-1:0]; + logic [7:0] PMPCfg[`PMP_ENTRIES-1:0]; logic [`PMP_ENTRIES-1:0] Match; // PMP Entry matches 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:0] NoLowerMatch; // None of the lower PMP entries match - logic [`PMP_ENTRIES:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] - genvar i,j; - - assign PAgePMPAdr[0] = 1'b1; - assign NoLowerMatch[0] = 1'b1; - - generate - // verilator lint_off WIDTH - for (j=0; j<`PMP_ENTRIES; j = j+8) - assign {PMPCFG[j+7], PMPCFG[j+6], PMPCFG[j+5], PMPCFG[j+4], - PMPCFG[j+3], PMPCFG[j+2], PMPCFG[j+1], PMPCFG[j]} = PMPCFG_ARRAY_REGW[j/8]; - // verilator lint_on WIDTH - for (i=0; i<`PMP_ENTRIES; i++) // *** can this be done with array notation? - pmpadrdec pmpadrdec(.PhysicalAddress, - .PMPCfg(PMPCFG[i]), - .PMPAdr(PMPADDR_ARRAY_REGW[i]), - .PAgePMPAdrIn(PAgePMPAdr[i]), - .PAgePMPAdrOut(PAgePMPAdr[i+1]), - .NoLowerMatchIn(NoLowerMatch[i]), - .NoLowerMatchOut(NoLowerMatch[i+1]), - .Match(Match[i]), - .Active(Active[i]), - .L(L[i]), .X(X[i]), .W(W[i]), .R(R[i]) - ); - + // verilator lint_off UNOPTFLAT + logic [`PMP_ENTRIES-1:0] NoLowerMatch; // None of the lower PMP entries match // verilator lint_on UNOPTFLAT + logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] + genvar i,j; + + generate // extract 8-bit chunks from PMPCFG array + for (j=0; j<`PMP_ENTRIES; j = j+8) + assign {PMPCfg[j+7], PMPCfg[j+6], PMPCfg[j+5], PMPCfg[j+4], + PMPCfg[j+3], PMPCfg[j+2], PMPCfg[j+1], PMPCfg[j]} = PMPCFG_ARRAY_REGW[j/8]; endgenerate + pmpadrdec pmpadrdec[`PMP_ENTRIES-1:0]( + .PhysicalAddress, + .PMPCfg, + .PMPAdr(PMPADDR_ARRAY_REGW), + .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), + .PAgePMPAdrOut(PAgePMPAdr), + .NoLowerMatchIn({NoLowerMatch[`PMP_ENTRIES-2:0], 1'b1}), + .NoLowerMatchOut(NoLowerMatch), + .Match, .Active, .L, .X, .W, .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; From 67e191c6f331da334ce821cb4ce2962238ee7470 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 11:39:59 -0400 Subject: [PATCH 11/21] Added support for PMP lock bits in csrm and repartitioned design to pass around 8-bit PMPCFG entries --- wally-pipelined/src/ifu/ifu.sv | 4 +- wally-pipelined/src/lsu/lsu.sv | 4 +- wally-pipelined/src/mmu/mmu.sv | 2 +- wally-pipelined/src/mmu/pmpchecker.sv | 10 +-- wally-pipelined/src/privileged/csr.sv | 2 +- wally-pipelined/src/privileged/csrm.sv | 89 +++++++------------ wally-pipelined/src/privileged/privdec.sv | 4 +- wally-pipelined/src/privileged/privileged.sv | 4 +- wally-pipelined/src/uncore/clint.sv | 6 +- wally-pipelined/src/uncore/dtim.sv | 4 +- wally-pipelined/src/uncore/gpio.sv | 9 +- wally-pipelined/src/uncore/uartPC16550D.sv | 18 ++-- .../src/wally/wallypipelinedhart.sv | 2 +- 13 files changed, 68 insertions(+), 90 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index ddfd88cc..714119e6 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -77,8 +77,8 @@ module ifu ( output logic ITLBMissF, ITLBHitF, // pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], - input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], output logic PMPInstrAccessFaultF, PMAInstrAccessFaultF, output logic ISquashBusAccessF diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index 36d4715f..2a88b25f 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -88,8 +88,8 @@ module lsu ( input logic [31:0] HADDR, // *** replace all of these H inputs with physical adress once pma checkers have been edited to use paddr as well. input logic [2:0] HSIZE, HBURST, input logic HWRITE, - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], - input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker. + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], + input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0], // *** this one especially has a large note attached to it in pmpchecker. output logic PMALoadAccessFaultM, PMAStoreAccessFaultM, output logic PMPLoadAccessFaultM, PMPStoreAccessFaultM, // *** can these be parameterized? we dont need the m stage ones for the immu and vice versa. diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index 8082d01a..303076b0 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -68,7 +68,7 @@ module mmu #(parameter ENTRY_BITS = 3, // PMA checker signals input logic AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM, - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic SquashBusAccess, // *** send to privileged unit diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index e073a2f1..5208032a 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -39,7 +39,7 @@ module pmpchecker ( // this will be understood as a var. However, if we don't supply the `var` // keyword, the compiler warns us that it's interpreting the signal as a var, // which we might not intend. - input var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + input var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], input var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input logic ExecuteAccessF, WriteAccessM, ReadAccessM, @@ -60,19 +60,19 @@ module pmpchecker ( logic [`PMP_ENTRIES-1:0] L, X, W, R; // PMP matches and has flag set // verilator lint_off UNOPTFLAT logic [`PMP_ENTRIES-1:0] NoLowerMatch; // None of the lower PMP entries match - // verilator lint_on UNOPTFLAT + // verilator lint_on UNOPTFLAT logic [`PMP_ENTRIES-1:0] PAgePMPAdr; // for TOR PMP matching, PhysicalAddress > PMPAdr[i] genvar i,j; - + /* generate // extract 8-bit chunks from PMPCFG array for (j=0; j<`PMP_ENTRIES; j = j+8) assign {PMPCfg[j+7], PMPCfg[j+6], PMPCfg[j+5], PMPCfg[j+4], PMPCfg[j+3], PMPCfg[j+2], PMPCfg[j+1], PMPCfg[j]} = PMPCFG_ARRAY_REGW[j/8]; - endgenerate + endgenerate */ pmpadrdec pmpadrdec[`PMP_ENTRIES-1:0]( .PhysicalAddress, - .PMPCfg, + .PMPCfg(PMPCFG_ARRAY_REGW), .PMPAdr(PMPADDR_ARRAY_REGW), .PAgePMPAdrIn({PAgePMPAdr[`PMP_ENTRIES-2:0], 1'b1}), .PAgePMPAdrOut(PAgePMPAdr), diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index dfac5571..ba2362c3 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -60,7 +60,7 @@ module csr #(parameter output logic STATUS_MIE, STATUS_SIE, output logic STATUS_MXR, STATUS_SUM, output logic STATUS_MPRV, - output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input logic [4:0] SetFflagsM, output logic [2:0] FRM_REGW, diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 8c74b951..29cc482f 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -74,7 +74,8 @@ module csrm #(parameter output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW, output logic [`XLEN-1:0] MEDELEG_REGW, MIDELEG_REGW, // 64-bit registers in RV64, or two 32-bit registers in RV32 - output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + //output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input logic [11:0] MIP_REGW, MIE_REGW, output logic WriteMSTATUSM, @@ -87,8 +88,9 @@ module csrm #(parameter logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; - logic [`PMP_ENTRIES/8-1:0] WritePMPCFGM, WritePMPCFGHM ; - logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; + logic [`PMP_ENTRIES-1:0] WritePMPCFGM; + logic [`PMP_ENTRIES-1:0] WritePMPADDRM ; + logic [`PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; localparam MISA_26 = (`MISA) & 32'h03ffffff; @@ -104,30 +106,9 @@ module csrm #(parameter assign WriteMEPCM = MTrapM | (CSRMWriteM && (CSRAdrM == MEPC)) && ~StallW; assign WriteMCAUSEM = MTrapM | (CSRMWriteM && (CSRAdrM == MCAUSE)) && ~StallW; assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)) && ~StallW; -/* assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)) && ~StallW; - assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)) && ~StallW; - assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)) && ~StallW; - assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)) && ~StallW; - assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2)) && ~StallW; - assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3)) && ~StallW; - assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4)) && ~StallW; - assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5)) && ~StallW; - assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6)) && ~StallW; - assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7)) && ~StallW; - assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8)) && ~StallW; - assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9)) && ~StallW; - assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10)) && ~StallW; - assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11)) && ~StallW; - assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)) && ~StallW; - assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)) && ~StallW; - assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)) && ~StallW; - assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)) && ~StallW; */ assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN) && ~StallW; assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT) && ~StallW; - - - assign IllegalCSRMWriteReadonlyM = CSRMWriteM && (CSRAdrM == MVENDORID || CSRAdrM == MARCHID || CSRAdrM == MIMPID || CSRAdrM == MHARTID); // CSRs @@ -164,32 +145,49 @@ module csrm #(parameter genvar i; generate for(i=0; i<`PMP_ENTRIES; i++) begin - assign WritePMPADDRM[i] = (CSRMWriteM && (CSRAdrM == PMPADDR0+i)) && ~StallW; + // when the lock bit is set, don't allow writes to the PMPCFG or PMPADDR + // also, when the lock bit of the next entry is set and the next entry is TOR, don't allow writes to this entry PMPADDR + assign CFGLocked[i] = PMPCFG_ARRAY_REGW[i][7]; + if (i == `PMP_ENTRIES-1) + assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7]; + else + assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01); + + assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~StallW & ~ADDRLocked[i]; flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]); - end - for (i=0; i<`PMP_ENTRIES/8; i++) begin if (`XLEN==64) begin - assign WritePMPCFGM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i)) && ~StallW; - flopenr #(`XLEN) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i]); + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~StallW & ~CFGLocked[i]; + flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]); end else begin - assign WritePMPCFGM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i)) && ~StallW; - assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW; - flopenr #(`XLEN) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][31:0]); - flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]); + assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~StallW & ~CFGLocked[i]; +// assign WritePMPCFGHM[i] = (CSRMWriteM && (CSRAdrM == PMPCFG0+2*i+1)) && ~StallW; + flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]); +// flopenr #(`XLEN) PMPCFGHreg(clk, reset, WritePMPCFGHM[i], CSRWriteValM, PMPCFG_ARRAY_REGW[i][63:32]); end end endgenerate // Read machine mode CSRs // verilator lint_off WIDTH + logic [5:0] entry; always_comb begin IllegalCSRMAccessM = !(`S_SUPPORTED | `U_SUPPORTED & `N_SUPPORTED) && (CSRAdrM == MEDELEG || CSRAdrM == MIDELEG); // trap on DELEG register access when no S or N-mode if (CSRAdrM >= PMPADDR0 && CSRAdrM < PMPADDR0 + `PMP_ENTRIES) // reading a PMP entry CSRMReadValM = PMPADDR_ARRAY_REGW[CSRAdrM - PMPADDR0]; else if (CSRAdrM >= PMPCFG0 && CSRAdrM < PMPCFG0 + `PMP_ENTRIES/4) begin - if (~CSRAdrM[0]) CSRMReadValM = PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0)/2][`XLEN-1:0]; - else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0-1)/2][63:32]}; + if (`XLEN==64) begin + entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64 + CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+7],PMPCFG_ARRAY_REGW[entry+6],PMPCFG_ARRAY_REGW[entry+5],PMPCFG_ARRAY_REGW[entry+4], + PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; + end else begin + entry = (CSRAdrM - PMPCFG0)*4; + CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; + end + + /* + if (~CSRAdrM[0]) CSRMReadValM = {PMPCFG_ARRAY_REGW[]}; + else CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG_ARRAY_REGW[(CSRAdrM - PMPCFG0-1)/2][63:32]};*/ end else case (CSRAdrM) MISA_ADR: CSRMReadValM = MISA_REGW; @@ -212,26 +210,7 @@ module csrm #(parameter MTVAL: CSRMReadValM = MTVAL_REGW; MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MCOUNTINHIBIT:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; -/* PMPCFG0: CSRMReadValM = PMPCFG01_REGW[`XLEN-1:0]; - PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:32]}; - PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0]; - PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:32]}; - PMPADDR0: CSRMReadValM = PMPADDR_ARRAY_REGW[0]; // *** make configurable - PMPADDR1: CSRMReadValM = PMPADDR_ARRAY_REGW[1]; - PMPADDR2: CSRMReadValM = PMPADDR_ARRAY_REGW[2]; - PMPADDR3: CSRMReadValM = PMPADDR_ARRAY_REGW[3]; - PMPADDR4: CSRMReadValM = PMPADDR_ARRAY_REGW[4]; - PMPADDR5: CSRMReadValM = PMPADDR_ARRAY_REGW[5]; - PMPADDR6: CSRMReadValM = PMPADDR_ARRAY_REGW[6]; - PMPADDR7: CSRMReadValM = PMPADDR_ARRAY_REGW[7]; - PMPADDR8: CSRMReadValM = PMPADDR_ARRAY_REGW[8]; - PMPADDR9: CSRMReadValM = PMPADDR_ARRAY_REGW[9]; - PMPADDR10: CSRMReadValM = PMPADDR_ARRAY_REGW[10]; - PMPADDR11: CSRMReadValM = PMPADDR_ARRAY_REGW[11]; - PMPADDR12: CSRMReadValM = PMPADDR_ARRAY_REGW[12]; - PMPADDR13: CSRMReadValM = PMPADDR_ARRAY_REGW[13]; - PMPADDR14: CSRMReadValM = PMPADDR_ARRAY_REGW[14]; - PMPADDR15: CSRMReadValM = PMPADDR_ARRAY_REGW[15]; */ + default: begin CSRMReadValM = 0; IllegalCSRMAccessM = 1; diff --git a/wally-pipelined/src/privileged/privdec.sv b/wally-pipelined/src/privileged/privdec.sv index 1330a62b..621ef9a2 100644 --- a/wally-pipelined/src/privileged/privdec.sv +++ b/wally-pipelined/src/privileged/privdec.sv @@ -38,9 +38,9 @@ module privdec ( // xRET defined in Privileged Spect 3.2.2 assign uretM = PrivilegedM & (InstrM[31:20] == 12'b000000000010) & `N_SUPPORTED; - assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED && + assign sretM = PrivilegedM & (InstrM[31:20] == 12'b000100000010) & `S_SUPPORTED & PrivilegeModeW[0] & ~STATUS_TSR; - assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) && (PrivilegeModeW == `M_MODE); + assign mretM = PrivilegedM & (InstrM[31:20] == 12'b001100000010) & (PrivilegeModeW == `M_MODE); assign ecallM = PrivilegedM & (InstrM[31:20] == 12'b000000000000); assign ebreakM = PrivilegedM & (InstrM[31:20] == 12'b000000000001); diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 5ed8c880..618b3214 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -64,11 +64,11 @@ module privileged ( input logic PMALoadAccessFaultM, PMPLoadAccessFaultM, input logic PMAStoreAccessFaultM, PMPStoreAccessFaultM, - output logic IllegalFPUInstrE, + output logic IllegalFPUInstrE, output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, output logic STATUS_MXR, STATUS_SUM, - output var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0], + output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW ); diff --git a/wally-pipelined/src/uncore/clint.sv b/wally-pipelined/src/uncore/clint.sv index d2014468..80cb28a1 100644 --- a/wally-pipelined/src/uncore/clint.sv +++ b/wally-pipelined/src/uncore/clint.sv @@ -94,7 +94,7 @@ module clint ( if (~HRESETn) begin MTIME <= 0; // MTIMECMP is not reset - end else if (memwrite && entryd == 16'hBFF8) begin + end else if (memwrite & entryd == 16'hBFF8) begin // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed MTIME <= HWDATA; end else MTIME <= MTIME + 1; @@ -125,9 +125,9 @@ module clint ( if (~HRESETn) begin MTIME <= 0; // MTIMECMP is not reset - end else if (memwrite && (entryd == 16'hBFF8)) begin + end else if (memwrite & (entryd == 16'hBFF8)) begin MTIME[31:0] <= HWDATA; - end else if (memwrite && (entryd == 16'hBFFC)) begin + end else if (memwrite & (entryd == 16'hBFFC)) begin // MTIME Counter. Eventually change this to run off separate clock. Synchronization then needed MTIME[63:32]<= HWDATA; end else MTIME <= MTIME + 1; diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index 40864567..c195c551 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -102,13 +102,13 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( always_ff @(posedge HCLK) begin HWADDR <= #1 A; HREADTim0 <= #1 RAM[A[31:3]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; + if (memwrite & risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; end end else begin always_ff @(posedge HCLK) begin HWADDR <= #1 A; HREADTim0 <= #1 RAM[A[31:2]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA; + if (memwrite & risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA; end end endgenerate diff --git a/wally-pipelined/src/uncore/gpio.sv b/wally-pipelined/src/uncore/gpio.sv index bddec8e6..cde55b7a 100644 --- a/wally-pipelined/src/uncore/gpio.sv +++ b/wally-pipelined/src/uncore/gpio.sv @@ -131,19 +131,19 @@ module gpio ( default: Dout <= #1 0; endcase // interrupts - if (memwrite && (entryd == 8'h1C)) + if (memwrite & (entryd == 8'h1C)) rise_ip <= rise_ip & ~Din | (input2d & ~input3d); else rise_ip <= rise_ip | (input2d & ~input3d); - if (memwrite && (entryd == 8'h24)) + if (memwrite & (entryd == 8'h24)) fall_ip <= fall_ip & ~Din | (~input2d & input3d); else fall_ip <= fall_ip | (~input2d & input3d); - if (memwrite && (entryd == 8'h2C)) + if (memwrite & (entryd == 8'h2C)) high_ip <= high_ip & ~Din | input3d; else high_ip <= high_ip | input3d; - if (memwrite && (entryd == 8'h34)) + if (memwrite & (entryd == 8'h34)) low_ip <= low_ip & ~Din | ~input3d; else low_ip <= low_ip | ~input3d; @@ -157,7 +157,6 @@ module gpio ( else assign input0d = GPIOPinsIn & input_en; endgenerate - // *** this costs lots of flops; I suspect they don't need to be resettable, do they? flop #(32) sync1(HCLK,input0d,input1d); flop #(32) sync2(HCLK,input1d,input2d); flop #(32) sync3(HCLK,input2d,input3d); diff --git a/wally-pipelined/src/uncore/uartPC16550D.sv b/wally-pipelined/src/uncore/uartPC16550D.sv index 4ead3f67..62c8ea00 100644 --- a/wally-pipelined/src/uncore/uartPC16550D.sv +++ b/wally-pipelined/src/uncore/uartPC16550D.sv @@ -224,11 +224,11 @@ module uartPC16550D( else rxstate <= #1 UART_IDLE; end // timeout counting - if (~MEMRb && A == 3'b000 && ~DLAB) rxtimeoutcnt <= #1 0; // reset timeout on read + if (~MEMRb & A == 3'b000 & ~DLAB) rxtimeoutcnt <= #1 0; // reset timeout on read else if (fifoenabled & ~rxfifoempty & rxbaudpulse & ~rxfifotimeout) rxtimeoutcnt <= #1 rxtimeoutcnt+1; // *** not right end - assign rxcentered = rxbaudpulse && (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE + assign rxcentered = rxbaudpulse & (rxoversampledcnt == 4'b1000); // implies rxstate = UART_ACTIVE assign rxbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1; // start bit + data bits + (parity bit) + stop bit /////////////////////////////////////////// @@ -267,12 +267,12 @@ module uartPC16550D( rxfifohead <= #1 rxfifohead + 1; end rxdataready <= #1 1; - end else if (~MEMRb && A == 3'b000 && ~DLAB) begin // reading RBR updates ready / pops fifo + end else if (~MEMRb & A == 3'b000 & ~DLAB) begin // reading RBR updates ready / pops fifo if (fifoenabled) begin rxfifotail <= #1 rxfifotail + 1; if (rxfifohead == rxfifotail +1) rxdataready <= #1 0; end else rxdataready <= #1 0; - end else if (~MEMWb && A == 3'b010) // writes to FIFO Control Register + end else if (~MEMWb & A == 3'b010) // writes to FIFO Control Register if (Din[1] | ~Din[0]) begin // rx FIFO reset or FIFO disable clears FIFO contents rxfifohead <= #1 0; rxfifotail <= #1 0; end @@ -326,7 +326,7 @@ module uartPC16550D( txoversampledcnt <= #1 0; txstate <= #1 UART_IDLE; txbitssent <= #1 0; - end else if ((txstate == UART_IDLE) && txsrfull) begin // start transmitting + end else if ((txstate == UART_IDLE) & txsrfull) begin // start transmitting txstate <= #1 UART_ACTIVE; txoversampledcnt <= #1 1; txbitssent <= #1 0; @@ -341,7 +341,7 @@ module uartPC16550D( end assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - assign txnextbit = txbaudpulse && (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE + assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE /////////////////////////////////////////// // transmit holding register, shift register, FIFO @@ -372,7 +372,7 @@ module uartPC16550D( if (~HRESETn) begin txfifohead <= #1 0; txfifotail <= #1 0; txhrfull <= #1 0; txsrfull <= #1 0; TXHR <= #1 0; txsr <= #1 12'hfff; end else begin - if (~MEMWb && A == 3'b000 && ~DLAB) begin // writing transmit holding register or fifo + if (~MEMWb & A == 3'b000 & ~DLAB) begin // writing transmit holding register or fifo if (fifoenabled) begin txfifo[txfifohead] <= #1 Din; txfifohead <= #1 txfifohead + 1; @@ -395,8 +395,8 @@ module uartPC16550D( txsrfull <= #1 1; end end else if (txstate == UART_DONE) txsrfull <= #1 0; // done transmitting shift register - else if (txstate == UART_ACTIVE && txnextbit) txsr <= #1 {txsr[10:0], 1'b1}; // shift txhr - if (!MEMWb && A == 3'b010) // writes to FIFO control register + else if (txstate == UART_ACTIVE & txnextbit) txsr <= #1 {txsr[10:0], 1'b1}; // shift txhr + if (!MEMWb & A == 3'b010) // writes to FIFO control register if (Din[2] | ~Din[0]) begin // tx FIFO reste or FIFO disable clears FIFO contents txfifohead <= #1 0; txfifotail <= #1 0; end diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 978f747f..be59c18b 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -123,7 +123,7 @@ module wallypipelinedhart logic PMAInstrAccessFaultF, PMALoadAccessFaultM, PMAStoreAccessFaultM; logic DSquashBusAccessM, ISquashBusAccessF; var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0]; - var logic [63:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES/8-1:0]; + var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0]; // IMem stalls logic ICacheStallF; From 735f3b421725d39f2489a4a348f2ce31bafe676e Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 12:32:27 -0400 Subject: [PATCH 12/21] Replaced generates with arrays in TLB --- wally-pipelined/src/mmu/pmpchecker.sv | 2 +- wally-pipelined/src/mmu/tlb.sv | 3 ++- wally-pipelined/src/mmu/tlbcam.sv | 14 +++++++++++--- wally-pipelined/src/mmu/tlbram.sv | 9 ++++++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/wally-pipelined/src/mmu/pmpchecker.sv b/wally-pipelined/src/mmu/pmpchecker.sv index 5208032a..ee4b261d 100644 --- a/wally-pipelined/src/mmu/pmpchecker.sv +++ b/wally-pipelined/src/mmu/pmpchecker.sv @@ -70,7 +70,7 @@ module pmpchecker ( PMPCfg[j+3], PMPCfg[j+2], PMPCfg[j+1], PMPCfg[j]} = PMPCFG_ARRAY_REGW[j/8]; endgenerate */ - pmpadrdec pmpadrdec[`PMP_ENTRIES-1:0]( + pmpadrdec pmpadrdecs[`PMP_ENTRIES-1:0]( .PhysicalAddress, .PMPCfg(PMPCFG_ARRAY_REGW), .PMPAdr(PMPADDR_ARRAY_REGW), diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 1cf63906..bd365280 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -95,7 +95,7 @@ module tlb #(parameter ENTRY_BITS = 3, // Index (currently random) to write the next TLB entry logic [ENTRY_BITS-1:0] WriteIndex; - logic [(2**ENTRY_BITS)-1:0] WriteLines; // used as the one-hot encoding of WriteIndex + logic [(2**ENTRY_BITS)-1:0] WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex // Sections of the virtual and physical addresses logic [`VPN_BITS-1:0] VirtualPageNumber; @@ -121,6 +121,7 @@ module tlb #(parameter ENTRY_BITS = 3, // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); + assign WriteEnables = WriteLines & {(2**ENTRY_BITS){TLBWrite}}; // The bus width is always the largest it could be for that XLEN. For example, vpn will be 36 bits wide in rv64 // this, even though it could be 27 bits (SV39) or 36 bits (SV48) wide. When the value of VPN is narrower, diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index bd64afea..e45b124a 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -35,9 +35,9 @@ module tlbcam #(parameter ENTRY_BITS = 3, input logic [KEY_BITS-1:0] VirtualPageNumber, input logic [1:0] PageTypeWriteVal, // input logic [`SVMODE_BITS-1:0] SvMode, // *** may not need to be used. - input logic TLBWrite, +// input logic TLBWrite, input logic TLBFlush, - input logic [2**ENTRY_BITS-1:0] WriteLines, + input logic [2**ENTRY_BITS-1:0] WriteEnables, output logic [ENTRY_BITS-1:0] VPNIndex, output logic [1:0] HitPageType, @@ -55,16 +55,24 @@ module tlbcam #(parameter ENTRY_BITS = 3, // original virtual page number from when the address was written, regardless // of page type. However, matches are determined based on a subset of the // page number segments. + + camline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( + .CAMLineWrite(WriteEnables), + .PageType(PageTypeList), + .Match(Matches), + .*); +/* generate genvar i; for (i = 0; i < NENTRIES; i++) begin camline #(KEY_BITS, SEGMENT_BITS) camline( - .CAMLineWrite(WriteLines[i] && TLBWrite), + .CAMLineWrite(WriteEnables[i]), .PageType(PageTypeList[i]), .Match(Matches[i]), .*); end endgenerate + */ // In case there are multiple matches in the CAM, select only one // *** it might be guaranteed that the CAM will never have multiple matches. diff --git a/wally-pipelined/src/mmu/tlbram.sv b/wally-pipelined/src/mmu/tlbram.sv index 2012ed82..f13666bc 100644 --- a/wally-pipelined/src/mmu/tlbram.sv +++ b/wally-pipelined/src/mmu/tlbram.sv @@ -32,8 +32,8 @@ module tlbram #(parameter ENTRY_BITS = 3) ( input logic [ENTRY_BITS-1:0] VPNIndex, // Index to read from // input logic [ENTRY_BITS-1:0] WriteIndex, // *** unused? input logic [`XLEN-1:0] PTEWriteVal, - input logic TLBWrite, - input logic [2**ENTRY_BITS-1:0] WriteLines, +// input logic TLBWrite, + input logic [2**ENTRY_BITS-1:0] WriteEnables, output logic [`PPN_BITS-1:0] PhysicalPageNumber, output logic [7:0] PTEAccessBits @@ -45,13 +45,16 @@ module tlbram #(parameter ENTRY_BITS = 3) ( logic [`XLEN-1:0] PageTableEntry; // Generate a flop for every entry in the RAM + flopenr #(`XLEN) pteflops[NENTRIES-1:0](clk, reset, WriteEnables, PTEWriteVal, ram); +/* generate genvar i; for (i = 0; i < NENTRIES; i++) begin: tlb_ram_flops - flopenr #(`XLEN) pteflop(clk, reset, WriteLines[i] & TLBWrite, + flopenr #(`XLEN) pteflop(clk, reset, WriteEnables[i], PTEWriteVal, ram[i]); end endgenerate +*/ assign PageTableEntry = ram[VPNIndex]; assign PTEAccessBits = PageTableEntry[7:0]; From 7db2be6dad148df8a8f9b1a8339dac57c550929b Mon Sep 17 00:00:00 2001 From: bbracker Date: Sun, 4 Jul 2021 12:48:13 -0400 Subject: [PATCH 13/21] Make Wally take InstrPageFaultF traps --- wally-pipelined/src/ifu/ifu.sv | 4 ++-- wally-pipelined/src/privileged/trap.sv | 8 ++++---- wally-pipelined/src/wally/wallypipelinedhart.sv | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index ddfd88cc..d3f864e0 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -151,7 +151,7 @@ module ifu ( icache icache(.*, .PCNextF(PCNextFPhys), .PCPF(PCPFmmu), - .WalkerInstrPageFaultF(WalkerInstrPageFaultF)); + .WalkerInstrPageFaultF); flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FlushD ? nop : FinalInstrRawF, nop, InstrRawD); @@ -184,7 +184,7 @@ module ifu ( assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment - flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF); + flopenl #(`XLEN) pcreg(clk, reset, (~StallF & ~ICacheStallF) | WalkerInstrPageFaultF, PCNextF, `RESET_VECTOR, PCF); // branch and jump predictor generate diff --git a/wally-pipelined/src/privileged/trap.sv b/wally-pipelined/src/privileged/trap.sv index af4f1730..b3b657fc 100644 --- a/wally-pipelined/src/privileged/trap.sv +++ b/wally-pipelined/src/privileged/trap.sv @@ -30,7 +30,7 @@ module trap ( input logic clk, reset, input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM, input logic BreakpointFaultM, LoadMisalignedFaultM, StoreMisalignedFaultM, - input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultM, + input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultF, input logic LoadPageFaultM, StorePageFaultM, input logic mretM, sretM, uretM, input logic [1:0] PrivilegeModeW, NextPrivilegeModeM, @@ -69,7 +69,7 @@ module trap ( assign BusTrapM = LoadAccessFaultM | StoreAccessFaultM; assign NonBusTrapM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM | LoadMisalignedFaultM | StoreMisalignedFaultM | - InstrPageFaultM | LoadPageFaultM | StorePageFaultM | + InstrPageFaultF | LoadPageFaultM | StorePageFaultM | BreakpointFaultM | EcallFaultM | InterruptM; assign TrapM = BusTrapM | NonBusTrapM; @@ -121,7 +121,7 @@ module trap ( else if (PendingIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int else if (PendingIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int else if (PendingIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int - else if (InstrPageFaultM) CauseM = 12; + else if (InstrPageFaultF) CauseM = 12; else if (InstrAccessFaultM) CauseM = 1; else if (InstrMisalignedFaultM) CauseM = 0; else if (IllegalInstrFaultM) CauseM = 2; @@ -148,7 +148,7 @@ module trap ( if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM; else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM; else if (StoreMisalignedFaultM) NextFaultMtvalM = MemAdrM; - else if (InstrPageFaultM) NextFaultMtvalM = PCM; + else if (InstrPageFaultF) NextFaultMtvalM = PCM; else if (LoadPageFaultM) NextFaultMtvalM = MemAdrM; else if (StorePageFaultM) NextFaultMtvalM = MemAdrM; else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM}; diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 978f747f..2d442929 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -179,7 +179,7 @@ module wallypipelinedhart ifu ifu(.InstrInF(InstrRData), - .WalkerInstrPageFaultF(WalkerInstrPageFaultF), + .WalkerInstrPageFaultF, .*); // instruction fetch unit: PC, branch prediction, instruction cache ieu ieu(.*); // integer execution unit: integer register file, datapath and controller From 1b39481a16b909461619888b6cc4151036c2563c Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 12:53:52 -0400 Subject: [PATCH 14/21] TLB mux and swizzling cleanup --- wally-pipelined/src/mmu/tlb.sv | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index bd365280..6d8ed46a 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -101,6 +101,7 @@ module tlb #(parameter ENTRY_BITS = 3, logic [`VPN_BITS-1:0] VirtualPageNumber; logic [`PPN_BITS-1:0] PhysicalPageNumber, PhysicalPageNumberMixed; logic [`PA_BITS-1:0] PhysicalAddressFull; + logic [`XLEN+1:0] VAExt; // Sections of the page table entry logic [7:0] PTEAccessBits; @@ -137,7 +138,7 @@ module tlb #(parameter ENTRY_BITS = 3, endgenerate // Whether translation should occur - assign Translate = (SvMode != `NO_TRANSLATE) & (PrivilegeModeW != `M_MODE) & ~ DisableTranslation; + assign Translate = (SvMode != `NO_TRANSLATE) & (PrivilegeModeW != `M_MODE) & ~ DisableTranslation; // *** needs to account for mprv // Determine how the TLB is currently being used // Note that we use ReadAccess for both loads and instruction fetches @@ -155,11 +156,8 @@ module tlb #(parameter ENTRY_BITS = 3, tlbcam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) tlbcam(.*); // unswizzle useful PTE bits - assign PTE_U = PTEAccessBits[4]; - assign PTE_X = PTEAccessBits[3]; - assign PTE_W = PTEAccessBits[2]; - assign PTE_R = PTEAccessBits[1]; - + assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; + // Check whether the access is allowed, page faulting if not. // *** We might not have S mode. generate @@ -198,17 +196,22 @@ module tlb #(parameter ENTRY_BITS = 3, // Provide physical address only on TLBHits to cause catastrophic errors if // garbage address is used. - assign PhysicalAddressFull = (TLBHit) ? - {PhysicalPageNumberMixed, PageOffset} : '0; + assign PhysicalAddressFull = (TLBHit) ? {PhysicalPageNumberMixed, PageOffset} : '0; // Output the hit physical address if translation is currently on. - generate +/* generate if (`XLEN == 32) begin + VirtualAddressPALen = {2'b0, VirtualAddress}; + mux2 #(`PA_BITS) addressmux({2'b0, VirtualAddress}, PhysicalAddressFull, Translate, PhysicalAddress); end else begin + VirtualAddressPALen = VirtualAddress[`PA_BITS-1:0]; mux2 #(`PA_BITS) addressmux(VirtualAddress[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); end - endgenerate + endgenerate*/ + + assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32 + mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); assign TLBHit = CAMHit & TLBAccess; assign TLBMiss = ~TLBHit & ~TLBFlush & Translate & TLBAccess; From 7e22ae973e0c4b4fc0368130481ba1a74c5d0276 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 13:20:29 -0400 Subject: [PATCH 15/21] Fixed MPRV and MXR checks in TLB --- wally-pipelined/src/ifu/ifu.sv | 3 +- wally-pipelined/src/lsu/lsu.sv | 3 +- wally-pipelined/src/mmu/mmu.sv | 3 +- wally-pipelined/src/mmu/tlb.sv | 29 ++++++++++--------- wally-pipelined/src/privileged/csr.sv | 3 +- wally-pipelined/src/privileged/privileged.sv | 6 ++-- .../src/wally/wallypipelinedhart.sv | 3 +- 7 files changed, 28 insertions(+), 22 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 714119e6..65f8a9b8 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -70,7 +70,8 @@ module ifu ( input logic [`XLEN-1:0] PageTableEntryF, input logic [1:0] PageTypeF, input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, input logic ITLBWriteF, ITLBFlushF, input logic WalkerInstrPageFaultF, diff --git a/wally-pipelined/src/lsu/lsu.sv b/wally-pipelined/src/lsu/lsu.sv index 2a88b25f..d7ff78d7 100644 --- a/wally-pipelined/src/lsu/lsu.sv +++ b/wally-pipelined/src/lsu/lsu.sv @@ -75,7 +75,8 @@ module lsu ( input logic [`XLEN-1:0] PageTableEntryM, input logic [1:0] PageTypeM, input logic [`XLEN-1:0] SATP_REGW, // from csr - input logic STATUS_MXR, STATUS_SUM, // from csr + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, input logic DTLBWriteM, output logic DTLBMissM, input logic DisableTranslation, // used to stop intermediate PTE physical addresses being saved to TLB. diff --git a/wally-pipelined/src/mmu/mmu.sv b/wally-pipelined/src/mmu/mmu.sv index 303076b0..e28db2e7 100644 --- a/wally-pipelined/src/mmu/mmu.sv +++ b/wally-pipelined/src/mmu/mmu.sv @@ -34,7 +34,8 @@ module mmu #(parameter ENTRY_BITS = 3, input logic clk, reset, // Current value of satp CSR (from privileged unit) input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 6d8ed46a..9f6a4d25 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -55,7 +55,8 @@ module tlb #(parameter ENTRY_BITS = 3, // Current value of satp CSR (from privileged unit) input logic [`XLEN-1:0] SATP_REGW, - input logic STATUS_MXR, STATUS_SUM, + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, // Current privilege level of the processeor input logic [1:0] PrivilegeModeW, @@ -92,6 +93,7 @@ module tlb #(parameter ENTRY_BITS = 3, // Store current virtual memory mode (SV32, SV39, SV48, ect...) logic [`SVMODE_BITS-1:0] SvMode; + logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV // Index (currently random) to write the next TLB entry logic [ENTRY_BITS-1:0] WriteIndex; @@ -137,16 +139,15 @@ module tlb #(parameter ENTRY_BITS = 3, end endgenerate - // Whether translation should occur - assign Translate = (SvMode != `NO_TRANSLATE) & (PrivilegeModeW != `M_MODE) & ~ DisableTranslation; // *** needs to account for mprv - + // Whether translation should occur; ITLB ignores MPRVW + assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; + // Determine how the TLB is currently being used // Note that we use ReadAccess for both loads and instruction fetches assign ReadAccess = TLBAccessType[1]; assign WriteAccess = TLBAccessType[0]; assign TLBAccess = ReadAccess || WriteAccess; - assign PageOffset = VirtualAddress[11:0]; // TLB entries are evicted according to the LRU algorithm @@ -164,28 +165,30 @@ module tlb #(parameter ENTRY_BITS = 3, if (ITLB == 1) begin logic ImproperPrivilege; + assign EffectivePrivilegeMode = PrivilegeModeW; // ITLB ignores MPRV + // User mode may only execute user mode pages, and supervisor mode may // only execute non-user mode pages. - assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) || - ((PrivilegeModeW == `S_MODE) && PTE_U); + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || + ((EffectivePrivilegeMode == `S_MODE) && PTE_U); assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || ~PTE_X); end else begin logic ImproperPrivilege, InvalidRead, InvalidWrite; + assign EffectivePrivilegeMode = STATUS_MPRV ? STATUS_MPP : PrivilegeModeW; // DTLB uses MPP mode when MPRV is 1 + // User mode may only load/store from user mode pages, and supervisor mode // may only access user mode pages when STATUS_SUM is low. - assign ImproperPrivilege = ((PrivilegeModeW == `U_MODE) && ~PTE_U) || - ((PrivilegeModeW == `S_MODE) && PTE_U && ~STATUS_SUM); + assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || + ((EffectivePrivilegeMode == `S_MODE) && PTE_U && ~STATUS_SUM); // Check for read error. Reads are invalid when the page is not readable // (and executable pages are not readable) or when the page is neither // readable nor executable (and executable pages are readable). - assign InvalidRead = ReadAccess && - ((~STATUS_MXR && ~PTE_R) || (STATUS_MXR && ~PTE_R && PTE_X)); + assign InvalidRead = ReadAccess && ~PTE_R && (~STATUS_MXR | ~PTE_X); // Check for write error. Writes are invalid when the page's write bit is // low. assign InvalidWrite = WriteAccess && ~PTE_W; - assign TLBPageFault = Translate && TLBHit && - (ImproperPrivilege || InvalidRead || InvalidWrite); + assign TLBPageFault = Translate && TLBHit && (ImproperPrivilege || InvalidRead || InvalidWrite); end endgenerate diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index ba2362c3..7162263c 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -58,8 +58,7 @@ module csr #(parameter output logic [`XLEN-1:0] SATP_REGW, output logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW, output logic STATUS_MIE, STATUS_SIE, - output logic STATUS_MXR, STATUS_SUM, - output logic STATUS_MPRV, + output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], input logic [4:0] SetFflagsM, diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 618b3214..90830137 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -67,7 +67,8 @@ module privileged ( output logic IllegalFPUInstrE, output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, - output logic STATUS_MXR, STATUS_SUM, + output logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + output logic [1:0] STATUS_MPP, output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW @@ -94,8 +95,7 @@ module privileged ( logic MTrapM, STrapM, UTrapM; logic InterruptM; - logic [1:0] STATUS_MPP; - logic STATUS_SPP, STATUS_TSR, STATUS_MPRV; // **** status mprv is unused outside of the csr module as of 4 June 2021. should it be deleted alltogether from the module, or should I leav the pin here in case someone needs it? + logic STATUS_SPP, STATUS_TSR; logic STATUS_MIE, STATUS_SIE; logic [11:0] MIP_REGW, MIE_REGW, SIP_REGW, SIE_REGW; logic md, sd; diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index be59c18b..33d2e13f 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -112,7 +112,8 @@ module wallypipelinedhart logic ITLBMissF, ITLBHitF; logic DTLBMissM, DTLBHitM; logic [`XLEN-1:0] SATP_REGW; - logic STATUS_MXR, STATUS_SUM; + logic STATUS_MXR, STATUS_SUM, STATUS_MPRV; + logic [1:0] STATUS_MPP; logic [1:0] PrivilegeModeW; logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM; logic [1:0] PageTypeF, PageTypeM; From c9364b884032c8238a5693013ac7d725d3c189b4 Mon Sep 17 00:00:00 2001 From: bbracker Date: Sun, 4 Jul 2021 13:31:30 -0400 Subject: [PATCH 16/21] Revert "Make Wally take InstrPageFaultF traps" This reverts commit 7db2be6dad148df8a8f9b1a8339dac57c550929b. --- wally-pipelined/src/ifu/ifu.sv | 4 ++-- wally-pipelined/src/privileged/trap.sv | 8 ++++---- wally-pipelined/src/wally/wallypipelinedhart.sv | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index e0a6a354..714119e6 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -151,7 +151,7 @@ module ifu ( icache icache(.*, .PCNextF(PCNextFPhys), .PCPF(PCPFmmu), - .WalkerInstrPageFaultF); + .WalkerInstrPageFaultF(WalkerInstrPageFaultF)); flopenl #(32) AlignedInstrRawDFlop(clk, reset | reset_q, ~StallD, FlushD ? nop : FinalInstrRawF, nop, InstrRawD); @@ -184,7 +184,7 @@ module ifu ( assign PCNextF = {UnalignedPCNextF[`XLEN-1:1], 1'b0}; // hart-SPEC p. 21 about 16-bit alignment - flopenl #(`XLEN) pcreg(clk, reset, (~StallF & ~ICacheStallF) | WalkerInstrPageFaultF, PCNextF, `RESET_VECTOR, PCF); + flopenl #(`XLEN) pcreg(clk, reset, ~StallF & ~ICacheStallF, PCNextF, `RESET_VECTOR, PCF); // branch and jump predictor generate diff --git a/wally-pipelined/src/privileged/trap.sv b/wally-pipelined/src/privileged/trap.sv index b3b657fc..af4f1730 100644 --- a/wally-pipelined/src/privileged/trap.sv +++ b/wally-pipelined/src/privileged/trap.sv @@ -30,7 +30,7 @@ module trap ( input logic clk, reset, input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM, input logic BreakpointFaultM, LoadMisalignedFaultM, StoreMisalignedFaultM, - input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultF, + input logic LoadAccessFaultM, StoreAccessFaultM, EcallFaultM, InstrPageFaultM, input logic LoadPageFaultM, StorePageFaultM, input logic mretM, sretM, uretM, input logic [1:0] PrivilegeModeW, NextPrivilegeModeM, @@ -69,7 +69,7 @@ module trap ( assign BusTrapM = LoadAccessFaultM | StoreAccessFaultM; assign NonBusTrapM = InstrMisalignedFaultM | InstrAccessFaultM | IllegalInstrFaultM | LoadMisalignedFaultM | StoreMisalignedFaultM | - InstrPageFaultF | LoadPageFaultM | StorePageFaultM | + InstrPageFaultM | LoadPageFaultM | StorePageFaultM | BreakpointFaultM | EcallFaultM | InterruptM; assign TrapM = BusTrapM | NonBusTrapM; @@ -121,7 +121,7 @@ module trap ( else if (PendingIntsM[9]) CauseM = (1 << (`XLEN-1)) + 9; // Supervisor External Int else if (PendingIntsM[1]) CauseM = (1 << (`XLEN-1)) + 1; // Supervisor Sw Int else if (PendingIntsM[5]) CauseM = (1 << (`XLEN-1)) + 5; // Supervisor Timer Int - else if (InstrPageFaultF) CauseM = 12; + else if (InstrPageFaultM) CauseM = 12; else if (InstrAccessFaultM) CauseM = 1; else if (InstrMisalignedFaultM) CauseM = 0; else if (IllegalInstrFaultM) CauseM = 2; @@ -148,7 +148,7 @@ module trap ( if (InstrMisalignedFaultM) NextFaultMtvalM = InstrMisalignedAdrM; else if (LoadMisalignedFaultM) NextFaultMtvalM = MemAdrM; else if (StoreMisalignedFaultM) NextFaultMtvalM = MemAdrM; - else if (InstrPageFaultF) NextFaultMtvalM = PCM; + else if (InstrPageFaultM) NextFaultMtvalM = PCM; else if (LoadPageFaultM) NextFaultMtvalM = MemAdrM; else if (StorePageFaultM) NextFaultMtvalM = MemAdrM; else if (IllegalInstrFaultM) NextFaultMtvalM = {{(`XLEN-32){1'b0}}, InstrM}; diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index ffc67d89..be59c18b 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -179,7 +179,7 @@ module wallypipelinedhart ifu ifu(.InstrInF(InstrRData), - .WalkerInstrPageFaultF, + .WalkerInstrPageFaultF(WalkerInstrPageFaultF), .*); // instruction fetch unit: PC, branch prediction, instruction cache ieu ieu(.*); // integer execution unit: integer register file, datapath and controller From 152923e5526a315a7a900e55977b282e40587003 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 14:30:56 -0400 Subject: [PATCH 17/21] TLB minor organization --- wally-pipelined/src/mmu/tlb.sv | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 9f6a4d25..1c28aa9c 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -119,8 +119,9 @@ module tlb #(parameter ENTRY_BITS = 3, // Whether the virtual address has a match in the CAM logic CAMHit; - // Grab the sv mode from SATP + // Grab the sv mode from SATP and determine whether translation should occur assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; + assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); @@ -139,8 +140,6 @@ module tlb #(parameter ENTRY_BITS = 3, end endgenerate - // Whether translation should occur; ITLB ignores MPRVW - assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Determine how the TLB is currently being used // Note that we use ReadAccess for both loads and instruction fetches From 81742ef9e28d4a8247138c52e67690351141ac71 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 14:37:53 -0400 Subject: [PATCH 18/21] TLB cleanup --- wally-pipelined/src/mmu/tlb.sv | 10 ++++------ .../{physicalpagemask.sv => tlbphysicalpagemask.sv} | 9 ++++----- 2 files changed, 8 insertions(+), 11 deletions(-) rename wally-pipelined/src/mmu/{physicalpagemask.sv => tlbphysicalpagemask.sv} (93%) diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 1c28aa9c..a4326ce8 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -121,6 +121,7 @@ module tlb #(parameter ENTRY_BITS = 3, // Grab the sv mode from SATP and determine whether translation should occur assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; + assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines @@ -152,6 +153,7 @@ module tlb #(parameter ENTRY_BITS = 3, // TLB entries are evicted according to the LRU algorithm tlblru #(ENTRY_BITS) lru(.*); + // TLB memory tlbram #(ENTRY_BITS) tlbram(.*); tlbcam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) tlbcam(.*); @@ -164,8 +166,6 @@ module tlb #(parameter ENTRY_BITS = 3, if (ITLB == 1) begin logic ImproperPrivilege; - assign EffectivePrivilegeMode = PrivilegeModeW; // ITLB ignores MPRV - // User mode may only execute user mode pages, and supervisor mode may // only execute non-user mode pages. assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || @@ -174,8 +174,6 @@ module tlb #(parameter ENTRY_BITS = 3, end else begin logic ImproperPrivilege, InvalidRead, InvalidWrite; - assign EffectivePrivilegeMode = STATUS_MPRV ? STATUS_MPP : PrivilegeModeW; // DTLB uses MPP mode when MPRV is 1 - // User mode may only load/store from user mode pages, and supervisor mode // may only access user mode pages when STATUS_SUM is low. assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) && ~PTE_U) || @@ -194,11 +192,11 @@ module tlb #(parameter ENTRY_BITS = 3, // Replace segments of the virtual page number with segments of the physical // page number. For 4 KB pages, the entire virtual page number is replaced. // For superpages, some segments are considered offsets into a larger page. - physicalpagemask PageNumberMixer(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); + tlbphysicalpagemask PageMask(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); // Provide physical address only on TLBHits to cause catastrophic errors if // garbage address is used. - assign PhysicalAddressFull = (TLBHit) ? {PhysicalPageNumberMixed, PageOffset} : '0; + assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; // Output the hit physical address if translation is currently on. /* generate diff --git a/wally-pipelined/src/mmu/physicalpagemask.sv b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv similarity index 93% rename from wally-pipelined/src/mmu/physicalpagemask.sv rename to wally-pipelined/src/mmu/tlbphysicalpagemask.sv index b1f77e2d..858c3939 100644 --- a/wally-pipelined/src/mmu/physicalpagemask.sv +++ b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// physicalpagemask.sv +// tlbphysicalpagemask.sv // // Written: David Harris and kmacsaigoren@hmc.edu 7 June 2021 // Modified: @@ -40,13 +40,11 @@ module physicalpagemask ( logic [`PPN_BITS-1:0] ZeroExtendedVPN; logic [`PPN_BITS-1:0] PageNumberMask; - assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. - generate if (`XLEN == 32) begin always_comb case (PageType[0]) - // *** the widths of these constansts are hardocded here to match `PPN_BITS in the wally-constants file. + // the widths of these constansts are hardocded here to match `PPN_BITS in the wally-constants file. 0: PageNumberMask = 22'h3FFFFF; // kilopage: 22 bits of PPN, 0 bits of VPN 1: PageNumberMask = 22'h3FFC00; // megapage: 12 bits of PPN, 10 bits of VPN endcase @@ -57,7 +55,7 @@ module physicalpagemask ( 1: PageNumberMask = 44'hFFFFFFFFE00; // megapage: 35 bits of PPN, 9 bits of VPN 2: PageNumberMask = 44'hFFFFFFC0000; // gigapage: 26 bits of PPN, 18 bits of VPN 3: PageNumberMask = 44'hFFFF8000000; // terapage: 17 bits of PPN, 27 bits of VPN - // *** make sure that this doesnt break when using sv39. In that case, all of these + // Bus widths accomodate SV48. In SV39, all of these // busses are the widths for sv48, but extra bits should be zeroed out by the mux // in the tlb when it generates VPN from the full virtualadress. endcase @@ -65,6 +63,7 @@ module physicalpagemask ( endgenerate // merge low segments of VPN with high segments of PPN decided by the pagetype. + assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. assign MixedPageNumber = (ZeroExtendedVPN & ~PageNumberMask) | (PPN & PageNumberMask); endmodule From c281539f36adbd0fbd281445b7caf9c40a998496 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 14:59:04 -0400 Subject: [PATCH 19/21] TLB cleanup --- wally-pipelined/src/mmu/priorityencoder.sv | 2 +- wally-pipelined/src/mmu/tlb.sv | 29 +++++-------------- wally-pipelined/src/mmu/tlbcam.sv | 22 +++----------- .../src/mmu/{camline.sv => tlbcamline.sv} | 8 ++--- .../src/mmu/tlbphysicalpagemask.sv | 2 +- wally-pipelined/src/mmu/tlbram.sv | 11 +------ 6 files changed, 19 insertions(+), 55 deletions(-) rename wally-pipelined/src/mmu/{camline.sv => tlbcamline.sv} (93%) diff --git a/wally-pipelined/src/mmu/priorityencoder.sv b/wally-pipelined/src/mmu/priorityencoder.sv index d56da3d6..44ce88da 100644 --- a/wally-pipelined/src/mmu/priorityencoder.sv +++ b/wally-pipelined/src/mmu/priorityencoder.sv @@ -31,7 +31,7 @@ `include "wally-config.vh" -module priorityencoder #(parameter BINARY_BITS = 3) ( +module tlbpriority #(parameter BINARY_BITS = 3) ( input logic [2**BINARY_BITS - 1:0] onehot, output logic [BINARY_BITS - 1:0] binary ); diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index a4326ce8..8aaf6570 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -148,7 +148,6 @@ module tlb #(parameter ENTRY_BITS = 3, assign WriteAccess = TLBAccessType[0]; assign TLBAccess = ReadAccess || WriteAccess; - assign PageOffset = VirtualAddress[11:0]; // TLB entries are evicted according to the LRU algorithm tlblru #(ENTRY_BITS) lru(.*); @@ -157,11 +156,15 @@ module tlb #(parameter ENTRY_BITS = 3, tlbram #(ENTRY_BITS) tlbram(.*); tlbcam #(ENTRY_BITS, `VPN_BITS, `VPN_SEGMENT_BITS) tlbcam(.*); + // Replace segments of the virtual page number with segments of the physical + // page number. For 4 KB pages, the entire virtual page number is replaced. + // For superpages, some segments are considered offsets into a larger page. + tlbphysicalpagemask PageMask(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); + // unswizzle useful PTE bits assign {PTE_U, PTE_X, PTE_W, PTE_R} = PTEAccessBits[4:1]; // Check whether the access is allowed, page faulting if not. - // *** We might not have S mode. generate if (ITLB == 1) begin logic ImproperPrivilege; @@ -189,28 +192,12 @@ module tlb #(parameter ENTRY_BITS = 3, end endgenerate - // Replace segments of the virtual page number with segments of the physical - // page number. For 4 KB pages, the entire virtual page number is replaced. - // For superpages, some segments are considered offsets into a larger page. - tlbphysicalpagemask PageMask(VirtualPageNumber, PhysicalPageNumber, HitPageType, PhysicalPageNumberMixed); - - // Provide physical address only on TLBHits to cause catastrophic errors if - // garbage address is used. - assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; // Output the hit physical address if translation is currently on. -/* generate - if (`XLEN == 32) begin - VirtualAddressPALen = {2'b0, VirtualAddress}; - - mux2 #(`PA_BITS) addressmux({2'b0, VirtualAddress}, PhysicalAddressFull, Translate, PhysicalAddress); - end else begin - VirtualAddressPALen = VirtualAddress[`PA_BITS-1:0]; - mux2 #(`PA_BITS) addressmux(VirtualAddress[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); - end - endgenerate*/ - + // Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal assign VAExt = {2'b00, VirtualAddress}; // extend length of virtual address if necessary for RV32 + assign PageOffset = VirtualAddress[11:0]; + assign PhysicalAddressFull = TLBHit ? {PhysicalPageNumberMixed, PageOffset} : '0; mux2 #(`PA_BITS) addressmux(VAExt[`PA_BITS-1:0], PhysicalAddressFull, Translate, PhysicalAddress); assign TLBHit = CAMHit & TLBAccess; diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index e45b124a..07ec38ff 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -34,8 +34,6 @@ module tlbcam #(parameter ENTRY_BITS = 3, input logic clk, reset, input logic [KEY_BITS-1:0] VirtualPageNumber, input logic [1:0] PageTypeWriteVal, -// input logic [`SVMODE_BITS-1:0] SvMode, // *** may not need to be used. -// input logic TLBWrite, input logic TLBFlush, input logic [2**ENTRY_BITS-1:0] WriteEnables, @@ -56,23 +54,11 @@ module tlbcam #(parameter ENTRY_BITS = 3, // of page type. However, matches are determined based on a subset of the // page number segments. - camline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( + tlbcamline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( .CAMLineWrite(WriteEnables), - .PageType(PageTypeList), - .Match(Matches), - .*); -/* - generate - genvar i; - for (i = 0; i < NENTRIES; i++) begin - camline #(KEY_BITS, SEGMENT_BITS) camline( - .CAMLineWrite(WriteEnables[i]), - .PageType(PageTypeList[i]), - .Match(Matches[i]), - .*); - end - endgenerate - */ + .PageType(PageTypeList), + .Match(Matches), + .*); // In case there are multiple matches in the CAM, select only one // *** it might be guaranteed that the CAM will never have multiple matches. diff --git a/wally-pipelined/src/mmu/camline.sv b/wally-pipelined/src/mmu/tlbcamline.sv similarity index 93% rename from wally-pipelined/src/mmu/camline.sv rename to wally-pipelined/src/mmu/tlbcamline.sv index 6e3f705c..3e882cf1 100644 --- a/wally-pipelined/src/mmu/camline.sv +++ b/wally-pipelined/src/mmu/tlbcamline.sv @@ -1,5 +1,5 @@ /////////////////////////////////////////// -// camline.sv +// tlbcamline.sv // // Written: tfleming@hmc.edu & jtorrey@hmc.edu 6 April 2021 // Modified: kmacsaigoren@hmc.edu 1 June 2021 @@ -28,7 +28,7 @@ `include "wally-config.vh" -module camline #(parameter KEY_BITS = 20, +module tlbcamline #(parameter KEY_BITS = 20, parameter SEGMENT_BITS = 10) ( input logic clk, reset, @@ -85,12 +85,12 @@ module camline #(parameter KEY_BITS = 20, assign {Key3, Key2, Key1, Key0} = Key; // Calculate the actual match value based on the input vpn and the page type. - // For example, a gigapage in SV only cares about VPN[2], so VPN[0] and VPN[1] + // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] // should automatically match. assign Match0 = (Query0 == Key0) || (PageType > 2'd0); // least signifcant section assign Match1 = (Query1 == Key1) || (PageType > 2'd1); assign Match2 = (Query2 == Key2) || (PageType > 2'd2); - assign Match3 = (Query3 == Key3); // *** this should always match in sv39 since both vPN3 and key3 are zeroed by the pagetable walker before getting to the cam + assign Match3 = (Query3 == Key3); // this should always match in sv39 since both vPN3 and key3 are zeroed by the pagetable walker before getting to the cam assign Match = Match0 & Match1 & Match2 & Match3 & Valid; end diff --git a/wally-pipelined/src/mmu/tlbphysicalpagemask.sv b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv index 858c3939..dd791e48 100644 --- a/wally-pipelined/src/mmu/tlbphysicalpagemask.sv +++ b/wally-pipelined/src/mmu/tlbphysicalpagemask.sv @@ -28,7 +28,7 @@ `include "wally-config.vh" -module physicalpagemask ( +module tlbphysicalpagemask ( input logic [`VPN_BITS-1:0] VPN, input logic [`PPN_BITS-1:0] PPN, input logic [1:0] PageType, diff --git a/wally-pipelined/src/mmu/tlbram.sv b/wally-pipelined/src/mmu/tlbram.sv index f13666bc..9482cd6f 100644 --- a/wally-pipelined/src/mmu/tlbram.sv +++ b/wally-pipelined/src/mmu/tlbram.sv @@ -46,16 +46,7 @@ module tlbram #(parameter ENTRY_BITS = 3) ( // Generate a flop for every entry in the RAM flopenr #(`XLEN) pteflops[NENTRIES-1:0](clk, reset, WriteEnables, PTEWriteVal, ram); -/* - generate - genvar i; - for (i = 0; i < NENTRIES; i++) begin: tlb_ram_flops - flopenr #(`XLEN) pteflop(clk, reset, WriteEnables[i], - PTEWriteVal, ram[i]); - end - endgenerate -*/ - + assign PageTableEntry = ram[VPNIndex]; assign PTEAccessBits = PageTableEntry[7:0]; assign PhysicalPageNumber = PageTableEntry[`PPN_BITS+9:10]; From 8337d6df68466a3e8631d77d981257dc28072c7f Mon Sep 17 00:00:00 2001 From: David Harris Date: Sun, 4 Jul 2021 16:33:13 -0400 Subject: [PATCH 20/21] Reorganized TLB to use one-hot read/write select signals to eliminate decoders and encoders --- wally-pipelined/src/mmu/tlb.sv | 11 ++-- wally-pipelined/src/mmu/tlbcam.sv | 13 ++--- wally-pipelined/src/mmu/tlbcamline.sv | 4 +- wally-pipelined/src/mmu/tlblru.sv | 21 ++++---- .../{priorityencoder.sv => tlbpriority.sv} | 50 +++++++------------ wally-pipelined/src/mmu/tlbram.sv | 40 ++++++++++++--- 6 files changed, 77 insertions(+), 62 deletions(-) rename wally-pipelined/src/mmu/{priorityencoder.sv => tlbpriority.sv} (62%) diff --git a/wally-pipelined/src/mmu/tlb.sv b/wally-pipelined/src/mmu/tlb.sv index 8aaf6570..2741f958 100644 --- a/wally-pipelined/src/mmu/tlb.sv +++ b/wally-pipelined/src/mmu/tlb.sv @@ -88,6 +88,8 @@ module tlb #(parameter ENTRY_BITS = 3, output logic TLBPageFault ); + localparam NENTRIES = 2**ENTRY_BITS; + logic Translate; logic TLBAccess, ReadAccess, WriteAccess; @@ -95,9 +97,8 @@ module tlb #(parameter ENTRY_BITS = 3, logic [`SVMODE_BITS-1:0] SvMode; logic [1:0] EffectivePrivilegeMode; // privilege mode, possibly modified by MPRV - // Index (currently random) to write the next TLB entry - logic [ENTRY_BITS-1:0] WriteIndex; - logic [(2**ENTRY_BITS)-1:0] WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex + //logic [ENTRY_BITS-1:0] WriteIndex; + logic [NENTRIES-1:0] ReadLines, WriteLines, WriteEnables; // used as the one-hot encoding of WriteIndex // Sections of the virtual and physical addresses logic [`VPN_BITS-1:0] VirtualPageNumber; @@ -113,7 +114,7 @@ module tlb #(parameter ENTRY_BITS = 3, logic PTE_U, PTE_X, PTE_W, PTE_R; // Pattern location in the CAM and type of page hit - logic [ENTRY_BITS-1:0] VPNIndex; + //ogic [ENTRY_BITS-1:0] VPNIndex; logic [1:0] HitPageType; // Whether the virtual address has a match in the CAM @@ -125,7 +126,7 @@ module tlb #(parameter ENTRY_BITS = 3, assign Translate = (SvMode != `NO_TRANSLATE) & (EffectivePrivilegeMode != `M_MODE) & ~ DisableTranslation; // Decode the integer encoded WriteIndex into the one-hot encoded WriteLines - decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); + //decoder #(ENTRY_BITS) writedecoder(WriteIndex, WriteLines); assign WriteEnables = WriteLines & {(2**ENTRY_BITS){TLBWrite}}; // The bus width is always the largest it could be for that XLEN. For example, vpn will be 36 bits wide in rv64 diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index 07ec38ff..f10442cd 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -37,7 +37,8 @@ module tlbcam #(parameter ENTRY_BITS = 3, input logic TLBFlush, input logic [2**ENTRY_BITS-1:0] WriteEnables, - output logic [ENTRY_BITS-1:0] VPNIndex, + //output logic [ENTRY_BITS-1:0] VPNIndex, + output logic [2**ENTRY_BITS-1:0] ReadLines, output logic [1:0] HitPageType, output logic CAMHit ); @@ -56,16 +57,16 @@ module tlbcam #(parameter ENTRY_BITS = 3, tlbcamline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( .CAMLineWrite(WriteEnables), - .PageType(PageTypeList), - .Match(Matches), + .MatchedPageType(PageTypeList), // *** change name to agree + .Match(ReadLines), // *** change name to agree .*); // In case there are multiple matches in the CAM, select only one // *** it might be guaranteed that the CAM will never have multiple matches. // If so, this is just an encoder - priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); + //priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); - assign CAMHit = |Matches & ~TLBFlush; - assign HitPageType = PageTypeList[VPNIndex]; + assign CAMHit = |ReadLines & ~TLBFlush; + assign HitPageType = PageTypeList.or; // applies OR to elements of the (NENTRIES x 2) array to get 2-bit result endmodule diff --git a/wally-pipelined/src/mmu/tlbcamline.sv b/wally-pipelined/src/mmu/tlbcamline.sv index 3e882cf1..2eaa3a01 100644 --- a/wally-pipelined/src/mmu/tlbcamline.sv +++ b/wally-pipelined/src/mmu/tlbcamline.sv @@ -50,13 +50,14 @@ module tlbcamline #(parameter KEY_BITS = 20, // PageType == 2'b01 --> megapage // PageType == 2'b10 --> gigapage // PageType == 2'b11 --> terapage - output logic [1:0] PageType, // *** should this be the stored version or the always updated one? + output logic [1:0] MatchedPageType, // *** should this be the stored version or the always updated one? output logic Match ); // This entry has KEY_BITS for the key plus one valid bit. logic Valid; logic [KEY_BITS-1:0] Key; + logic [1:0] PageType; // Split up key and query into sections for each page table level. @@ -98,6 +99,7 @@ module tlbcamline #(parameter KEY_BITS = 20, // On a write, update the type of the page referred to by this line. flopenr #(2) pagetypeflop(clk, reset, CAMLineWrite, PageTypeWriteVal, PageType); + assign MatchedPageType = PageType & {2{Match}}; //mux2 #(2) pagetypemux(StoredPageType, PageTypeWrite, CAMLineWrite, PageType); // On a write, set the valid bit high and update the stored key. diff --git a/wally-pipelined/src/mmu/tlblru.sv b/wally-pipelined/src/mmu/tlblru.sv index e86598f7..f1ac4db2 100644 --- a/wally-pipelined/src/mmu/tlblru.sv +++ b/wally-pipelined/src/mmu/tlblru.sv @@ -28,11 +28,9 @@ module tlblru #(parameter ENTRY_BITS = 3) ( input logic clk, reset, input logic TLBWrite, input logic TLBFlush, - input logic [ENTRY_BITS-1:0] VPNIndex, + input logic [2**ENTRY_BITS-1:0] ReadLines, input logic CAMHit, - input logic [2**ENTRY_BITS-1:0] WriteLines, - - output logic [ENTRY_BITS-1:0] WriteIndex + output logic [2**ENTRY_BITS-1:0] WriteLines ); localparam NENTRIES = 2**ENTRY_BITS; @@ -41,26 +39,27 @@ module tlblru #(parameter ENTRY_BITS = 3) ( logic [NENTRIES-1:0] RUBits, RUBitsNext, RUBitsAccessed; // One-hot encodings of which line is being accessed - logic [NENTRIES-1:0] ReadLineOneHot, AccessLineOneHot; + logic [NENTRIES-1:0] AccessLines; // High if the next access causes all RU bits to be 1 logic AllUsed; // Convert indices to one-hot encodings - decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); + //decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); // Find the first line not recently used - priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); + tlbpriority #(NENTRIES) nru(~RUBits, WriteLines); + //priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); // Access either the hit line or written line - assign AccessLineOneHot = (TLBWrite) ? WriteLines : ReadLineOneHot; + assign AccessLines = TLBWrite ? WriteLines : ReadLines; // Raise the bit of the recently accessed line - assign RUBitsAccessed = AccessLineOneHot | RUBits; + assign RUBitsAccessed = AccessLines | RUBits; // Determine whether we need to reset the RU bits to all zeroes - assign AllUsed = &(RUBitsAccessed); - assign RUBitsNext = (AllUsed) ? AccessLineOneHot : RUBitsAccessed; + assign AllUsed = &RUBitsAccessed; + assign RUBitsNext = AllUsed ? AccessLines : RUBitsAccessed; // *** seems it should set to 0, not to AccessLines // Update LRU state on any TLB hit or write flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), diff --git a/wally-pipelined/src/mmu/priorityencoder.sv b/wally-pipelined/src/mmu/tlbpriority.sv similarity index 62% rename from wally-pipelined/src/mmu/priorityencoder.sv rename to wally-pipelined/src/mmu/tlbpriority.sv index 44ce88da..a061f622 100644 --- a/wally-pipelined/src/mmu/priorityencoder.sv +++ b/wally-pipelined/src/mmu/tlbpriority.sv @@ -1,16 +1,15 @@ /////////////////////////////////////////// -// priorityencoder.sv +// tlbpriority.sv // // Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021 -// Based on implementation from https://www.allaboutcircuits.com/ip-cores/communication-controller/priority-encoder/ -// *** Give proper LGPL attribution for above source // Modified: Teo Ene 15 Apr 2021: // Temporarily removed paramterized priority encoder for non-parameterized one // To get synthesis working quickly // Kmacsaigoren@hmc.edu 28 May 2021: // Added working version of parameterized priority encoder. +// David_Harris@Hmc.edu switched to one-hot output // -// Purpose: One-hot encoding to binary encoder +// Purpose: Priority circuit to choose most significant one-hot output // // A component of the Wally configurable RISC-V project. // @@ -31,35 +30,20 @@ `include "wally-config.vh" -module tlbpriority #(parameter BINARY_BITS = 3) ( - input logic [2**BINARY_BITS - 1:0] onehot, - output logic [BINARY_BITS - 1:0] binary +module tlbpriority #(parameter ENTRIES = 8) ( + input logic [ENTRIES-1:0] a, + output logic [ENTRIES-1:0] y ); + // verilator lint_off UNOPTFLAT + logic [ENTRIES-1:0] nolower; - integer i; - always_comb begin - binary = 0; - for (i = 0; i < 2**BINARY_BITS; i++) begin - // verilator lint_off WIDTH - if (onehot[i]) binary = i; // prioritizes the most significant bit - // verilator lint_on WIDTH - end - end - // *** triple check synthesizability here - - // Ideally this mimics the following: - /* - always_comb begin - casex (one_hot) - 1xx ... x: binary = BINARY_BITS - 1; - 01x ... x: binary = BINARY_BITS - 2; - 001 ... x: binary = BINARY_BITS - 3; - - {...} - - 00 ... 1xx: binary = 2; - 00 ... 01x: binary = 1; - 00 ... 001: binary = 0; - end - */ + // generate thermometer code mask + genvar i; + generate + assign nolower[0] = 1; + for (i=1; i Date: Sun, 4 Jul 2021 17:01:22 -0400 Subject: [PATCH 21/21] Restructured TLB Read as AND-OR operation with one-hot match/read line --- wally-pipelined/src/mmu/tlbcam.sv | 9 +++---- wally-pipelined/src/mmu/tlbcamline.sv | 16 +++++------ wally-pipelined/src/mmu/tlblru.sv | 19 +++----------- wally-pipelined/src/mmu/tlbram.sv | 31 +--------------------- wally-pipelined/src/mmu/tlbramline.sv | 38 +++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 58 deletions(-) create mode 100644 wally-pipelined/src/mmu/tlbramline.sv diff --git a/wally-pipelined/src/mmu/tlbcam.sv b/wally-pipelined/src/mmu/tlbcam.sv index f10442cd..ef64e0d6 100644 --- a/wally-pipelined/src/mmu/tlbcam.sv +++ b/wally-pipelined/src/mmu/tlbcam.sv @@ -45,8 +45,7 @@ module tlbcam #(parameter ENTRY_BITS = 3, localparam NENTRIES = 2**ENTRY_BITS; - - logic [1:0] PageTypeList [NENTRIES-1:0]; + logic [1:0] PageTypeRead [NENTRIES-1:0]; logic [NENTRIES-1:0] Matches; // Create NENTRIES CAM lines, each of which will independently consider @@ -56,8 +55,8 @@ module tlbcam #(parameter ENTRY_BITS = 3, // page number segments. tlbcamline #(KEY_BITS, SEGMENT_BITS) camlines[NENTRIES-1:0]( - .CAMLineWrite(WriteEnables), - .MatchedPageType(PageTypeList), // *** change name to agree + .WriteEnable(WriteEnables), + .PageTypeRead, // *** change name to agree .Match(ReadLines), // *** change name to agree .*); @@ -67,6 +66,6 @@ module tlbcam #(parameter ENTRY_BITS = 3, //priorityencoder #(ENTRY_BITS) matchencoder(Matches, VPNIndex); assign CAMHit = |ReadLines & ~TLBFlush; - assign HitPageType = PageTypeList.or; // applies OR to elements of the (NENTRIES x 2) array to get 2-bit result + assign HitPageType = PageTypeRead.or; // applies OR to elements of the (NENTRIES x 2) array to get 2-bit result endmodule diff --git a/wally-pipelined/src/mmu/tlbcamline.sv b/wally-pipelined/src/mmu/tlbcamline.sv index 2eaa3a01..605d8f30 100644 --- a/wally-pipelined/src/mmu/tlbcamline.sv +++ b/wally-pipelined/src/mmu/tlbcamline.sv @@ -39,7 +39,7 @@ module tlbcamline #(parameter KEY_BITS = 20, input logic [KEY_BITS-1:0] VirtualPageNumber, // Signals to write a new entry to this line - input logic CAMLineWrite, + input logic WriteEnable, input logic [1:0] PageTypeWriteVal, // Flush this line (set valid to 0) @@ -50,7 +50,7 @@ module tlbcamline #(parameter KEY_BITS = 20, // PageType == 2'b01 --> megapage // PageType == 2'b10 --> gigapage // PageType == 2'b11 --> terapage - output logic [1:0] MatchedPageType, // *** should this be the stored version or the always updated one? + output logic [1:0] PageTypeRead, // *** should this be the stored version or the always updated one? output logic Match ); @@ -59,11 +59,12 @@ module tlbcamline #(parameter KEY_BITS = 20, logic [KEY_BITS-1:0] Key; logic [1:0] PageType; - // Split up key and query into sections for each page table level. logic [SEGMENT_BITS-1:0] Key0, Key1, Query0, Query1; logic Match0, Match1; + // *** need to add ASID and G bit support + generate if (`XLEN == 32) begin @@ -98,15 +99,14 @@ module tlbcamline #(parameter KEY_BITS = 20, endgenerate // On a write, update the type of the page referred to by this line. - flopenr #(2) pagetypeflop(clk, reset, CAMLineWrite, PageTypeWriteVal, PageType); - assign MatchedPageType = PageType & {2{Match}}; - //mux2 #(2) pagetypemux(StoredPageType, PageTypeWrite, CAMLineWrite, PageType); + flopenr #(2) pagetypeflop(clk, reset, WriteEnable, PageTypeWriteVal, PageType); + assign PageTypeRead = PageType & {2{Match}}; // On a write, set the valid bit high and update the stored key. // On a flush, zero the valid bit and leave the key unchanged. // *** Might we want to update stored key right away to output match on the // write cycle? (using a mux) - flopenrc #(1) validbitflop(clk, reset, TLBFlush, CAMLineWrite, 1'b1, Valid); - flopenr #(KEY_BITS) keyflop(clk, reset, CAMLineWrite, VirtualPageNumber, Key); + flopenrc #(1) validbitflop(clk, reset, TLBFlush, WriteEnable, 1'b1, Valid); + flopenr #(KEY_BITS) keyflop(clk, reset, WriteEnable, VirtualPageNumber, Key); endmodule diff --git a/wally-pipelined/src/mmu/tlblru.sv b/wally-pipelined/src/mmu/tlblru.sv index f1ac4db2..5dc1f846 100644 --- a/wally-pipelined/src/mmu/tlblru.sv +++ b/wally-pipelined/src/mmu/tlblru.sv @@ -44,25 +44,14 @@ module tlblru #(parameter ENTRY_BITS = 3) ( // High if the next access causes all RU bits to be 1 logic AllUsed; - // Convert indices to one-hot encodings - //decoder #(ENTRY_BITS) readdecoder(VPNIndex, ReadLineOneHot); - // Find the first line not recently used tlbpriority #(NENTRIES) nru(~RUBits, WriteLines); - //priorityencoder #(ENTRY_BITS) firstnru(~RUBits, WriteIndex); - // Access either the hit line or written line + // Track recently used lines, updating on a CAM Hit or TLB write assign AccessLines = TLBWrite ? WriteLines : ReadLines; - - // Raise the bit of the recently accessed line assign RUBitsAccessed = AccessLines | RUBits; - - // Determine whether we need to reset the RU bits to all zeroes - assign AllUsed = &RUBitsAccessed; - assign RUBitsNext = AllUsed ? AccessLines : RUBitsAccessed; // *** seems it should set to 0, not to AccessLines - - // Update LRU state on any TLB hit or write - flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), - RUBitsNext, RUBits); + assign AllUsed = &RUBitsAccessed; // if all recently used, then clear to none + assign RUBitsNext = AllUsed ? 0 : RUBitsAccessed; + flopenrc #(NENTRIES) lrustate(clk, reset, TLBFlush, (CAMHit || TLBWrite), RUBitsNext, RUBits); endmodule diff --git a/wally-pipelined/src/mmu/tlbram.sv b/wally-pipelined/src/mmu/tlbram.sv index 70e7bb6c..f70cb44c 100644 --- a/wally-pipelined/src/mmu/tlbram.sv +++ b/wally-pipelined/src/mmu/tlbram.sv @@ -41,42 +41,13 @@ module tlbram #(parameter ENTRY_BITS = 3) ( localparam NENTRIES = 2**ENTRY_BITS; - //logic [`XLEN-1:0] ram[NENTRIES-1:0]; logic [`XLEN-1:0] RamRead[NENTRIES-1:0]; logic [`XLEN-1:0] PageTableEntry; -// logic [ENTRY_BITS-1:0] VPNIndex; - // Generate a flop for every entry in the RAM - //flopenr #(`XLEN) pteflops[NENTRIES-1:0](clk, reset, WriteEnables, PTEWriteVal, ram); tlbramline #(`XLEN) tlblineram[NENTRIES-1:0](clk, reset, ReadLines, WriteEnables, PTEWriteVal, RamRead); -/* - // temporary code for read - // verilator lint_off WIDTH - integer i; - generate - always_comb begin - VPNIndex = 0; - for (i=0; i