forked from Github_Repos/cvw
		
	Finish finite state machines for page table walker
This commit is contained in:
		
							parent
							
								
									7367052e76
								
							
						
					
					
						commit
						e3900bd0fa
					
				| @ -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)); | ||||
|  | ||||
| @ -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 | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user