From f2604797fb94179926fd23f5fa3565440f704bfc Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Wed, 24 Mar 2021 21:58:33 -0400 Subject: [PATCH 1/6] Add all PMP addr registers --- wally-pipelined/src/privileged/csrm.sv | 64 +++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/wally-pipelined/src/privileged/csrm.sv b/wally-pipelined/src/privileged/csrm.sv index 44a840dd5..73c42608a 100644 --- a/wally-pipelined/src/privileged/csrm.sv +++ b/wally-pipelined/src/privileged/csrm.sv @@ -51,7 +51,20 @@ module csrm #(parameter PMPCFG2 = 12'h3A2, PMPCFG3 = 12'h3A3, PMPADDR0 = 12'h3B0, - //... more physical memory protection + PMPADDR1 = 12'h3B1, + PMPADDR2 = 12'h3B2, + PMPADDR3 = 12'h3B3, + PMPADDR4 = 12'h3B4, + PMPADDR5 = 12'h3B5, + PMPADDR6 = 12'h3B6, + PMPADDR7 = 12'h3B7, + PMPADDR8 = 12'h3B8, + PMPADDR9 = 12'h3B9, + PMPADDR10 = 12'h3BA, + PMPADDR11 = 12'h3BB, + PMPADDR12 = 12'h3BC, + PMPADDR13 = 12'h3BD, + PMPADDR14 = 12'h3BE, PMPADDR15 = 12'h3BF, TSELECT = 12'h7A0, TDATA1 = 12'h7A1, @@ -77,7 +90,8 @@ module csrm #(parameter logic [`XLEN-1:0] MISA_REGW; logic [`XLEN-1:0] MSCRATCH_REGW,MCAUSE_REGW, MTVAL_REGW; logic [63:0] PMPCFG01_REGW, PMPCFG23_REGW; // 64-bit registers in RV64, or two 32-bit registers in RV32 - logic [`XLEN-1:0] PMPADDR0_REGW; // will need to add more + logic [`XLEN-1:0] PMPADDR_ARRAY_REGW [0:15]; // *** Might have to make 16 individual registers + //logic [`XLEN-1:0] PMPADDR0_REGW; logic [`XLEN-1:0] zero = 0; logic [31:0] allones = {32{1'b1}}; logic [`XLEN-1:0] MEDELEG_MASK = ~(zero | 1'b1 << 11); // medeleg[11] hardwired to zero per Privileged Spec 3.1.8 @@ -86,7 +100,7 @@ module csrm #(parameter logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; logic WritePMPCFG0M, WritePMPCFG2M; - logic WritePMPADDR0M; + logic WritePMPADDRM [0:15]; logic [25:0] MISAbits = `MISA; // MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally @@ -103,7 +117,22 @@ module csrm #(parameter assign WriteMTVALM = MTrapM | (CSRMWriteM && (CSRAdrM == MTVAL)); assign WritePMPCFG0M = (CSRMWriteM && (CSRAdrM == PMPCFG0)); assign WritePMPCFG2M = (CSRMWriteM && (CSRAdrM == PMPCFG2)); - assign WritePMPADDR0M = (CSRMWriteM && (CSRAdrM == PMPADDR0)); + assign WritePMPADDRM[0] = (CSRMWriteM && (CSRAdrM == PMPADDR0)); + assign WritePMPADDRM[1] = (CSRMWriteM && (CSRAdrM == PMPADDR1)); + assign WritePMPADDRM[2] = (CSRMWriteM && (CSRAdrM == PMPADDR2)); + assign WritePMPADDRM[3] = (CSRMWriteM && (CSRAdrM == PMPADDR3)); + assign WritePMPADDRM[4] = (CSRMWriteM && (CSRAdrM == PMPADDR4)); + assign WritePMPADDRM[5] = (CSRMWriteM && (CSRAdrM == PMPADDR5)); + assign WritePMPADDRM[6] = (CSRMWriteM && (CSRAdrM == PMPADDR6)); + assign WritePMPADDRM[7] = (CSRMWriteM && (CSRAdrM == PMPADDR7)); + assign WritePMPADDRM[8] = (CSRMWriteM && (CSRAdrM == PMPADDR8)); + assign WritePMPADDRM[9] = (CSRMWriteM && (CSRAdrM == PMPADDR9)); + assign WritePMPADDRM[10] = (CSRMWriteM && (CSRAdrM == PMPADDR10)); + assign WritePMPADDRM[11] = (CSRMWriteM && (CSRAdrM == PMPADDR11)); + assign WritePMPADDRM[12] = (CSRMWriteM && (CSRAdrM == PMPADDR12)); + assign WritePMPADDRM[13] = (CSRMWriteM && (CSRAdrM == PMPADDR13)); + assign WritePMPADDRM[14] = (CSRMWriteM && (CSRAdrM == PMPADDR14)); + assign WritePMPADDRM[15] = (CSRMWriteM && (CSRAdrM == PMPADDR15)); assign WriteMCOUNTERENM = CSRMWriteM && (CSRAdrM == MCOUNTEREN); assign WriteMCOUNTINHIBITM = CSRMWriteM && (CSRAdrM == MCOUNTINHIBIT); @@ -132,7 +161,15 @@ module csrm #(parameter flopenl #(32) MCOUNTERENreg(clk, reset, WriteMCOUNTERENM, CSRWriteValM[31:0], allones, MCOUNTEREN_REGW); endgenerate flopenl #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], allones, MCOUNTINHIBIT_REGW); - flopenr #(`XLEN) PMPADDR0reg(clk, reset, WritePMPADDR0M, CSRWriteValM, PMPADDR0_REGW); + + // There are 16 PMPADDR registers, each of which has its own flop + generate + genvar i; + for (i = 0; i < 16; i++) begin: pmp_flop + flopenr #(`XLEN) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM, PMPADDR_ARRAY_REGW[i]); + end + endgenerate + // PMPCFG registers are a pair of 64-bit in RV64 and four 32-bit in RV32 generate if (`XLEN==64) begin @@ -175,7 +212,22 @@ module csrm #(parameter PMPCFG1: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG01_REGW[63:31]}; PMPCFG2: CSRMReadValM = PMPCFG23_REGW[`XLEN-1:0]; PMPCFG3: CSRMReadValM = {{(`XLEN-32){1'b0}}, PMPCFG23_REGW[63:31]}; - PMPADDR0: CSRMReadValM = PMPADDR0_REGW; + PMPADDR0: CSRMReadValM = PMPADDR_ARRAY_REGW[0]; + 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; From d52c71086adb7ed77c11e0f80ac287b8a94f7afb Mon Sep 17 00:00:00 2001 From: bbracker Date: Thu, 25 Mar 2021 02:23:30 -0400 Subject: [PATCH 2/6] added 1 tick delay to dtim flops --- wally-pipelined/src/uncore/dtim.sv | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wally-pipelined/src/uncore/dtim.sv b/wally-pipelined/src/uncore/dtim.sv index a5c4574ee..29d938f1a 100644 --- a/wally-pipelined/src/uncore/dtim.sv +++ b/wally-pipelined/src/uncore/dtim.sv @@ -85,15 +85,15 @@ module dtim #(parameter BASE=0, RANGE = 65535) ( generate if (`XLEN == 64) begin always_ff @(posedge HCLK) begin - HWADDR <= A; - HREADTim0 <= RAM[A[31:3]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= HWDATA; + HWADDR <= #1 A; + HREADTim0 <= #1 RAM[A[31:3]]; + if (memwrite && risingHREADYTim) RAM[HWADDR[31:3]] <= #1 HWDATA; end end else begin always_ff @(posedge HCLK) begin - HWADDR <= A; - HREADTim0 <= RAM[A[31:2]]; - if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= HWDATA; + HWADDR <= #1 A; + HREADTim0 <= #1 RAM[A[31:2]]; + if (memwrite && risingHREADYTim) RAM[HWADDR[31:2]] <= #1 HWDATA; end end endgenerate From 95bf1e26b811879c12b49c5d39e8b2526cd2311b Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Thu, 25 Mar 2021 02:37:50 -0400 Subject: [PATCH 3/6] Add vscode and pycache folders to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index de0e5e82b..8c40fe780 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ .nfs* +__pycache__/ +.vscode/ + #vsim work files to ignore transcript vsim.wlf From 89a2fe57417da9a6a11710f1977214f957bd7dc9 Mon Sep 17 00:00:00 2001 From: Thomas Fleming Date: Thu, 25 Mar 2021 02:48:40 -0400 Subject: [PATCH 4/6] Finish finite state machines for page table walker --- wally-pipelined/src/ebu/ahblite.sv | 84 +++--- wally-pipelined/src/ebu/pagetablewalker.sv | 246 +++++++++++++++--- wally-pipelined/src/privileged/privileged.sv | 12 +- .../src/wally/wallypipelinedhart.sv | 3 +- 4 files changed, 270 insertions(+), 75 deletions(-) diff --git a/wally-pipelined/src/ebu/ahblite.sv b/wally-pipelined/src/ebu/ahblite.sv index 201378666..90ef018b3 100644 --- a/wally-pipelined/src/ebu/ahblite.sv +++ b/wally-pipelined/src/ebu/ahblite.sv @@ -48,7 +48,7 @@ module ahblite ( input logic [1:0] MemSizeM, // Signals from MMU input logic [`XLEN-1:0] MMUPAdr, - input logic MMUTranslate, + input logic MMUTranslate, MMUTranslationComplete, output logic [`XLEN-1:0] MMUReadPTE, output logic MMUReady, // Return from bus @@ -75,7 +75,8 @@ module ahblite ( ); logic GrantData; - logic [2:0] ISize; + logic [31:0] AccessAddress; + logic [2:0] AccessSize, PTESize, ISize; logic [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData; logic IReady, DReady; logic CaptureDataM; @@ -89,47 +90,69 @@ module ahblite ( // Data accesses have priority over instructions. However, if a data access comes // while an instruction read is occuring, the instruction read finishes before // the data access can take place. - typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE} statetype; + typedef enum {IDLE, MEMREAD, MEMWRITE, INSTRREAD, INSTRREADC, ATOMICREAD, ATOMICWRITE, MMUTRANSLATE, MMUIDLE} statetype; statetype BusState, NextBusState; flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState); always_comb case (BusState) - IDLE: if (AtomicM[1]) NextBusState = ATOMICREAD; - else if (MemReadM) NextBusState = MEMREAD; // Memory has pirority over instructions - else if (MemWriteM) NextBusState = MEMWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; - ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD; - else NextBusState = ATOMICWRITE; - ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; - MEMREAD: if (~HREADY) NextBusState = MEMREAD; - else if (InstrReadF) NextBusState = INSTRREADC; - else NextBusState = IDLE; - MEMWRITE: if (~HREADY) NextBusState = MEMWRITE; - else if (InstrReadF) NextBusState = INSTRREAD; - else NextBusState = IDLE; + IDLE: if (MMUTranslate) NextBusState = MMUTRANSLATE; + else if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions + else if (MemWriteM) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + MMUTRANSLATE: if (~HREADY) NextBusState = MMUTRANSLATE; + else NextBusState = MMUIDLE; + // *** Could the MMUIDLE state just be the normal idle state? + // Do we trust MMUTranslate to be high exactly when we need translation? + MMUIDLE: if (~MMUTranslationComplete) + NextBusState = MMUTRANSLATE; + else if (AtomicM[1]) NextBusState = ATOMICREAD; + else if (MemReadM) NextBusState = MEMREAD; // Memory has priority over instructions + else if (MemWriteM) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + ATOMICREAD: if (~HREADY) NextBusState = ATOMICREAD; + else NextBusState = ATOMICWRITE; + ATOMICWRITE: if (~HREADY) NextBusState = ATOMICWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; + MEMREAD: if (~HREADY) NextBusState = MEMREAD; + else if (InstrReadF) NextBusState = INSTRREADC; + else NextBusState = IDLE; + MEMWRITE: if (~HREADY) NextBusState = MEMWRITE; + else if (InstrReadF) NextBusState = INSTRREAD; + else NextBusState = IDLE; INSTRREAD: - if (~HREADY) NextBusState = INSTRREAD; - else NextBusState = IDLE; // if (InstrReadF still high) - INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage. - else NextBusState = IDLE; + if (~HREADY) NextBusState = INSTRREAD; + else NextBusState = IDLE; // if (InstrReadF still high) + INSTRREADC: if (~HREADY) NextBusState = INSTRREADC; // "C" for "competing", meaning please don't mess up the memread in the W stage. + else NextBusState = IDLE; endcase // stall signals assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || - (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); - assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC); - + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) || + (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); + // *** Could get finer grained stalling if we distinguish between MMU + // instruction address translation and data address translation + assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC) || + (NextBusState == MMUTRANSLATE) || (NextBusState == MMUIDLE); + // bus outputs assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || - (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); - assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0]; + (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE); + assign #1 AccessAddress = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0]; + assign #1 HADDR = (MMUTranslate) ? MMUPAdr[31:0] : AccessAddress; + generate + if (`XLEN == 32) assign PTESize = 3'b010; // in rv32, PTEs are 4 bytes + else assign PTESize = 3'b011; // in rv64, PTEs are 8 bytes + endgenerate assign ISize = 3'b010; // 32 bit instructions for now; later improve for filling cache with full width; ignored on reads anyway - assign #1 HSIZE = GrantData ? {1'b0, MemSizeM} : ISize; + assign #1 AccessSize = (GrantData) ? {1'b0, MemSizeM} : ISize; + assign #1 HSIZE = (MMUTranslate) ? PTESize : AccessSize; assign HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH assign HPROT = 4'b0011; // not used; see Section 3.7 assign HTRANS = (NextBusState != IDLE) ? 2'b10 : 2'b00; // NONSEQ if reading or writing, IDLE otherwise @@ -145,7 +168,10 @@ module ahblite ( // Route signals to Instruction and Data Caches // *** assumes AHBW = XLEN + assign #1 MMUReady = (NextBusState == MMUIDLE); + assign InstrRData = HRDATA; + assign MMUReadPTE = HRDATA; assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021 assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) || ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE)); diff --git a/wally-pipelined/src/ebu/pagetablewalker.sv b/wally-pipelined/src/ebu/pagetablewalker.sv index 2ba2b78c6..16bb9ae26 100644 --- a/wally-pipelined/src/ebu/pagetablewalker.sv +++ b/wally-pipelined/src/ebu/pagetablewalker.sv @@ -32,25 +32,29 @@ module pagetablewalker ( input logic [`XLEN-1:0] SATP_REGW, + input logic MemWriteM, input logic ITLBMissF, DTLBMissM, input logic [`XLEN-1:0] PCF, MemAdrM, output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM, output logic ITLBWriteF, DTLBWriteM, // *** handshake to tlbs probably not needed, since stalls take effect - // output logic TranslationComplete + output logic MMUTranslationComplete, // Signals from and to ahblite input logic [`XLEN-1:0] MMUReadPTE, input logic MMUReady, output logic [`XLEN-1:0] MMUPAdr, - output logic MMUTranslate + output logic MMUTranslate, + + // Faults + output logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM ); logic SvMode; logic [`PPN_BITS-1:0] BasePageTablePPN; - logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE; + logic [`XLEN-1:0] DirectInstrPTE, DirectMemPTE, TranslationVAdr; logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111}; @@ -73,71 +77,233 @@ module pagetablewalker ( end endgenerate - flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF); - flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM); + //flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF); + //flopenr #(`XLEN) datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM); - flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF); - flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM); + //flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF); + //flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM); + + // Prefer data address translations over instruction address translations + assign TranslationVAdr = (DTLBMissM) ? MemAdrM : PCF; + assign MMUTranslate = DTLBMissM || ITLBMissF; -/* generate if (`XLEN == 32) begin assign SvMode = SATP_REGW[31]; - logic VPN1 [9:0] = TranslationVAdr[31:22]; - logic VPN0 [9:0] = TranslationVAdr[21:12]; // *** could optimize by not passing offset? + logic [9:0] VPN1 = TranslationVAdr[31:22]; + logic [9:0] VPN0 = TranslationVAdr[21:12]; // *** could optimize by not passing offset? - logic TranslationPAdr [33:0]; + logic [33:0] TranslationPAdr; + logic [21:0] CurrentPPN; - typedef enum {IDLE, DATA_LEVEL1, DATA_LEVEL0, DATA_LEAF, DATA FAULT} statetype; + logic Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid; + logic ValidPTE, AccessAlert, MegapageMisaligned, BadMegapage, LeafPTE; + + typedef enum {IDLE, LEVEL1, LEVEL0, LEAF, FAULT} statetype; statetype WalkerState, NextWalkerState; - always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) WalkerState <= #1 IDLE; - else WalkerState <= #1 NextWalkerState; + // *** Do we need a synchronizer here for walker to talk to ahblite? + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); always_comb begin - NextWalkerState = 'X; case (WalkerState) - IDLE: if (TLBMissM) NextWalkerState = LEVEL1; - else NextWalkerState = IDLE; - LEVEL1: if (HREADY && ValidEntry) NextWalkerState = LEVEL0; - else if (HREADY) NextWalkerState = FAULT; - else NextWalkerState = LEVEL1; - LEVEL2: if (HREADY && ValidEntry) NextWalkerState = LEAF; - else if (HREADY) NextWalkerState = FAULT; - else NextWalkerState = LEVEL2; - LEAF: NextWalkerState = IDLE; + IDLE: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; + // else if (~ValidPTE || (LeafPTE && BadMegapage)) + // NextWalkerState = FAULT; + // *** Leave megapage implementation for later + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; + else NextWalkerState = FAULT; + LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; + else if (ValidPTE && LeafPTE && ~AccessAlert) + NextWalkerState = LEAF; + else NextWalkerState = FAULT; + LEAF: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + FAULT: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; endcase end - always_ff @(posedge HCLK, negedge HRESETn) - if (~HRESETn) begin + // unswizzle PTE bits + assign {Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid} = MMUReadPTE[7:0]; + + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign MegapageMisaligned = |(CurrentPPN[9:0]); + assign LeafPTE = Executable | Writable | Readable; + assign ValidPTE = Valid && ~(Writable && ~Readable); + assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty); + assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + + // *** Should translate this flop block into our flop module notation + always_ff @(posedge clk, negedge reset) + if (reset) begin TranslationPAdr <= '0; PageTableEntryF <= '0; - TranslationComplete <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; end else begin // default values + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; case (NextWalkerState) - LEVEL1: TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00}; - LEVEL2: TranslationPAdr <= {CurrentPPN, VPN0, 2'b00}; + LEVEL1: begin + TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00}; + end + LEVEL0: begin + TranslationPAdr <= {CurrentPPN, VPN0, 2'b00}; + end LEAF: begin - PageTableEntryF <= CurrentPageTableEntry; - TranslationComplete <= '1; - end + PageTableEntryF <= MMUReadPTE; + PageTableEntryM <= MMUReadPTE; + MMUTranslationComplete <= '1; + DTLBWriteM <= DTLBMissM; + ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions + end + FAULT: begin + InstrPageFaultM <= ~DTLBMissM; + LoadPageFaultM <= DTLBMissM && ~MemWriteM; + StorePageFaultM <= DTLBMissM && MemWriteM; + end endcase end - assign #1 Translate = (NextWalkerState == LEVEL1); + // Interpret inputs from ahblite + assign CurrentPPN = MMUReadPTE[31:10]; + + // Assign outputs to ahblite + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign MMUPAdr = TranslationPAdr[31:0]; + end else begin - // sv39 not yet implemented assign SvMode = SATP_REGW[63]; + + logic [8:0] VPN2 = TranslationVAdr[38:30]; + logic [8:0] VPN1 = TranslationVAdr[29:21]; + logic [8:0] VPN0 = TranslationVAdr[20:12]; // *** could optimize by not passing offset? + + logic [55:0] TranslationPAdr; + logic [43:0] CurrentPPN; + + logic Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid; + logic ValidPTE, AccessAlert, GigapageMisaligned, MegapageMisaligned, + BadGigapage, BadMegapage, LeafPTE; + + typedef enum {IDLE, LEVEL2, LEVEL1, LEVEL0, LEAF, FAULT} statetype; + statetype WalkerState, NextWalkerState; + + // *** Do we need a synchronizer here for walker to talk to ahblite? + flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState); + + always_comb begin + case (WalkerState) + IDLE: if (MMUTranslate) NextWalkerState = LEVEL1; + else NextWalkerState = IDLE; + LEVEL2: if (~MMUReady) NextWalkerState = LEVEL2; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL1; + else NextWalkerState = FAULT; + LEVEL1: if (~MMUReady) NextWalkerState = LEVEL1; + // else if (~ValidPTE || (LeafPTE && BadMegapage)) + // NextWalkerState = FAULT; + // *** Leave megapage implementation for later + // else if (ValidPTE && LeafPTE) NextWalkerState = LEAF; + else if (ValidPTE && ~LeafPTE) NextWalkerState = LEVEL0; + else NextWalkerState = FAULT; + LEVEL0: if (~MMUReady) NextWalkerState = LEVEL0; + else if (ValidPTE && LeafPTE && ~AccessAlert) + NextWalkerState = LEAF; + else NextWalkerState = FAULT; + LEAF: if (MMUTranslate) NextWalkerState = LEVEL2; + else NextWalkerState = IDLE; + FAULT: if (MMUTranslate) NextWalkerState = LEVEL2; + else NextWalkerState = IDLE; + endcase + end + + // unswizzle PTE bits + assign {Dirty, Accessed, Global, User, + Executable, Writable, Readable, Valid} = MMUReadPTE[7:0]; + + // A megapage is a Level 1 leaf page. This page must have zero PPN[0]. + assign GigapageMisaligned = |(CurrentPPN[17:0]); + assign MegapageMisaligned = |(CurrentPPN[8:0]); + assign LeafPTE = Executable | Writable | Readable; + assign ValidPTE = Valid && ~(Writable && ~Readable); + assign AccessAlert = ~Accessed || (MemWriteM && ~Dirty); + assign BadGigapage = GigapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + assign BadMegapage = MegapageMisaligned || AccessAlert; // *** Implement better access/dirty scheme + + // *** Should translate this flop block into our flop module notation + always_ff @(posedge clk, negedge reset) + if (reset) begin + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; + end else begin + // default values + TranslationPAdr <= '0; + PageTableEntryF <= '0; + MMUTranslationComplete <= '0; + DTLBWriteM <= '0; + ITLBWriteF <= '0; + InstrPageFaultM <= '0; + LoadPageFaultM <= '0; + StorePageFaultM <= '0; + case (NextWalkerState) + LEVEL2: begin + TranslationPAdr <= {BasePageTablePPN, VPN2, 3'b00}; + end + LEVEL1: begin + TranslationPAdr <= {CurrentPPN, VPN1, 3'b00}; + end + LEVEL0: begin + TranslationPAdr <= {CurrentPPN, VPN0, 3'b00}; + end + LEAF: begin + PageTableEntryF <= MMUReadPTE; + PageTableEntryM <= MMUReadPTE; + MMUTranslationComplete <= '1; + DTLBWriteM <= DTLBMissM; + ITLBWriteF <= ~DTLBMissM; // Prefer data over instructions + end + FAULT: begin + InstrPageFaultM <= ~DTLBMissM; + LoadPageFaultM <= DTLBMissM && ~MemWriteM; + StorePageFaultM <= DTLBMissM && MemWriteM; + end + endcase + end + + // Interpret inputs from ahblite + assign CurrentPPN = MMUReadPTE[53:10]; + + // Assign outputs to ahblite + // *** Currently truncate address to 32 bits. This must be changed if + // we support larger physical address spaces + assign MMUPAdr = TranslationPAdr[31:0]; end endgenerate - // rv32 case - - -*/ - endmodule \ No newline at end of file diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index c967d2629..16a3d5db0 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -39,6 +39,7 @@ module privileged ( input logic InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM, input logic [3:0] InstrClassM, input logic PrivilegedM, + input logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM, input logic InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD, input logic LoadMisalignedFaultM, LoadAccessFaultM, input logic StoreMisalignedFaultM, StoreAccessFaultM, @@ -48,7 +49,7 @@ module privileged ( output logic [1:0] PrivilegeModeW, output logic [`XLEN-1:0] SATP_REGW, output logic [2:0] FRM_REGW, - input logic FlushD, FlushE, FlushM, StallD, StallW + input logic FlushD, FlushE, FlushM, StallD, StallW, StallE, StallM ); logic [1:0] NextPrivilegeModeM; @@ -65,7 +66,6 @@ module privileged ( logic IllegalInstrFaultM; logic BreakpointFaultM, EcallFaultM; - logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM; logic MTrapM, STrapM, UTrapM; logic [1:0] STATUS_MPP; @@ -119,9 +119,11 @@ module privileged ( assign BreakpointFaultM = ebreakM; // could have other causes too assign EcallFaultM = ecallM; - assign InstrPageFaultM = 0; - assign LoadPageFaultM = 0; - assign StorePageFaultM = 0; + // *** Page faults now driven by page table walker. Might need to make the + // below signals ORs of a walker fault and a tlb fault if both of those come in + // assign InstrPageFaultM = 0; + // assign LoadPageFaultM = 0; + // assign StorePageFaultM = 0; // pipeline fault signals flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD); diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index 5975015ff..67ef8b204 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -76,6 +76,7 @@ module wallypipelinedhart ( logic InstrMisalignedFaultM; logic DataMisalignedM; logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD; + logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM; logic LoadMisalignedFaultM, LoadAccessFaultM; logic StoreMisalignedFaultM, StoreAccessFaultM; logic [`XLEN-1:0] InstrMisalignedAdrM; @@ -98,7 +99,7 @@ module wallypipelinedhart ( logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM; logic [`XLEN-1:0] MMUPAdr, MMUReadPTE; - logic MMUTranslate, MMUReady; + logic MMUTranslate, MMUTranslationComplete, MMUReady; // bus interface to dmem logic MemReadM, MemWriteM; From 1158b3aa73b081488bc162f20a93872ba1cfc5fc Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 25 Mar 2021 11:21:31 -0400 Subject: [PATCH 5/6] Added PPA README --- wally-pipelined/ppa/config/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 wally-pipelined/ppa/config/README.md diff --git a/wally-pipelined/ppa/config/README.md b/wally-pipelined/ppa/config/README.md new file mode 100644 index 000000000..62a48d5f6 --- /dev/null +++ b/wally-pipelined/ppa/config/README.md @@ -0,0 +1 @@ +Configuration for power/performance/area experiments, per process From 7c3963547dabf934f69b579dd847c8bbcac83a1a Mon Sep 17 00:00:00 2001 From: Teo Ene Date: Thu, 25 Mar 2021 10:23:21 -0500 Subject: [PATCH 6/6] Config file for ppa experiments --- wally-pipelined/ppa/config/README.md | 1 - wally-pipelined/ppa/config/config.sv | 1 + wally-pipelined/ppa/ppa.sv | 5 +---- 3 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 wally-pipelined/ppa/config/README.md create mode 100644 wally-pipelined/ppa/config/config.sv diff --git a/wally-pipelined/ppa/config/README.md b/wally-pipelined/ppa/config/README.md deleted file mode 100644 index 62a48d5f6..000000000 --- a/wally-pipelined/ppa/config/README.md +++ /dev/null @@ -1 +0,0 @@ -Configuration for power/performance/area experiments, per process diff --git a/wally-pipelined/ppa/config/config.sv b/wally-pipelined/ppa/config/config.sv new file mode 100644 index 000000000..b9f94a0e4 --- /dev/null +++ b/wally-pipelined/ppa/config/config.sv @@ -0,0 +1 @@ +`define LIB SKY130 diff --git a/wally-pipelined/ppa/ppa.sv b/wally-pipelined/ppa/ppa.sv index ac82fbe77..84ae7d971 100644 --- a/wally-pipelined/ppa/ppa.sv +++ b/wally-pipelined/ppa/ppa.sv @@ -2,9 +2,6 @@ // Teo Ene & David_Harris@hmc.edu 25 Feb 2021 // Measure PPA of various building blocks -// replace this with the tools setting a library path to a config/skl130 directory containing config.vh -`define LIB SKL130 - module top( input logic a1, input logic [7:0] a8, b8, @@ -49,7 +46,7 @@ endmodule module INVX2(input logic a, output logic y); generate - if (LIB == SKL130) + if (LIB == SKY130) sky130_osu_sc_12T_ms__inv_2 inv(a, y); else if (LIB == SKL90) scc9gena_inv_2 inv(a, y)