mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	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,
 | 
					  input  logic [1:0]       MemSizeM,
 | 
				
			||||||
  // Signals from MMU
 | 
					  // Signals from MMU
 | 
				
			||||||
  input  logic [`XLEN-1:0] MMUPAdr,
 | 
					  input  logic [`XLEN-1:0] MMUPAdr,
 | 
				
			||||||
  input  logic             MMUTranslate,
 | 
					  input  logic             MMUTranslate, MMUTranslationComplete,
 | 
				
			||||||
  output logic [`XLEN-1:0] MMUReadPTE,
 | 
					  output logic [`XLEN-1:0] MMUReadPTE,
 | 
				
			||||||
  output logic             MMUReady,
 | 
					  output logic             MMUReady,
 | 
				
			||||||
  // Return from bus
 | 
					  // Return from bus
 | 
				
			||||||
@ -75,7 +75,8 @@ module ahblite (
 | 
				
			|||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logic GrantData;
 | 
					  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 [`AHBW-1:0] HRDATAMasked, ReadDataM, ReadDataNewW, ReadDataOldW, WriteData;
 | 
				
			||||||
  logic IReady, DReady;
 | 
					  logic IReady, DReady;
 | 
				
			||||||
  logic CaptureDataM;
 | 
					  logic CaptureDataM;
 | 
				
			||||||
@ -89,15 +90,27 @@ module ahblite (
 | 
				
			|||||||
  // Data accesses have priority over instructions.  However, if a data access comes
 | 
					  // Data accesses have priority over instructions.  However, if a data access comes
 | 
				
			||||||
  // while an instruction read is occuring, the instruction read finishes before
 | 
					  // while an instruction read is occuring, the instruction read finishes before
 | 
				
			||||||
  // the data access can take place.
 | 
					  // 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;
 | 
					  statetype BusState, NextBusState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
 | 
					  flopenl #(.TYPE(statetype)) busreg(HCLK, ~HRESETn, 1'b1, NextBusState, IDLE, BusState);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  always_comb 
 | 
					  always_comb 
 | 
				
			||||||
    case (BusState) 
 | 
					    case (BusState) 
 | 
				
			||||||
      IDLE: if      (AtomicM[1])  NextBusState = ATOMICREAD;
 | 
					      IDLE: if      (MMUTranslate) NextBusState = MMUTRANSLATE;
 | 
				
			||||||
            else if (MemReadM)    NextBusState = MEMREAD;  // Memory has pirority over instructions
 | 
					            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 (MemWriteM)    NextBusState = MEMWRITE;
 | 
				
			||||||
            else if (InstrReadF)   NextBusState = INSTRREAD;
 | 
					            else if (InstrReadF)   NextBusState = INSTRREAD;
 | 
				
			||||||
            else                   NextBusState = IDLE;
 | 
					            else                   NextBusState = IDLE;
 | 
				
			||||||
@ -121,15 +134,25 @@ module ahblite (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // stall signals
 | 
					  // stall signals
 | 
				
			||||||
  assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || 
 | 
					  assign #2 DataStall = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || 
 | 
				
			||||||
                        (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
 | 
					                        (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE) ||
 | 
				
			||||||
  assign #1 InstrStall = (NextBusState == INSTRREAD) || (NextBusState == INSTRREADC);
 | 
					                        (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
 | 
					  //  bus outputs
 | 
				
			||||||
  assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || 
 | 
					  assign #1 GrantData = (NextBusState == MEMREAD) || (NextBusState == MEMWRITE) || 
 | 
				
			||||||
                        (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
 | 
					                        (NextBusState == ATOMICREAD) || (NextBusState == ATOMICWRITE);
 | 
				
			||||||
  assign #1 HADDR = (GrantData) ? MemPAdrM[31:0] : InstrPAdrF[31:0];
 | 
					  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 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 HBURST = 3'b000; // Single burst only supported; consider generalizing for cache fillsfH
 | 
				
			||||||
  assign HPROT = 4'b0011; // not used; see Section 3.7
 | 
					  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
 | 
					  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
 | 
					    // Route signals to Instruction and Data Caches
 | 
				
			||||||
  // *** assumes AHBW = XLEN
 | 
					  // *** assumes AHBW = XLEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  assign #1 MMUReady = (NextBusState == MMUIDLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assign InstrRData = HRDATA;
 | 
					  assign InstrRData = HRDATA;
 | 
				
			||||||
 | 
					  assign MMUReadPTE = HRDATA;
 | 
				
			||||||
  assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
 | 
					  assign ReadDataM = HRDATAMasked; // changed from W to M dh 2/7/2021
 | 
				
			||||||
  assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) ||
 | 
					  assign CaptureDataM = ((BusState == MEMREAD) && (NextBusState != MEMREAD)) ||
 | 
				
			||||||
                        ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE));
 | 
					                        ((BusState == ATOMICREAD) && (NextBusState == ATOMICWRITE));
 | 
				
			||||||
 | 
				
			|||||||
@ -32,25 +32,29 @@ module pagetablewalker (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  input  logic [`XLEN-1:0] SATP_REGW,
 | 
					  input  logic [`XLEN-1:0] SATP_REGW,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  input  logic             MemWriteM,
 | 
				
			||||||
  input  logic             ITLBMissF, DTLBMissM,
 | 
					  input  logic             ITLBMissF, DTLBMissM,
 | 
				
			||||||
  input  logic [`XLEN-1:0] PCF, MemAdrM,
 | 
					  input  logic [`XLEN-1:0] PCF, MemAdrM,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
 | 
					  output logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM,
 | 
				
			||||||
  output logic             ITLBWriteF, DTLBWriteM,
 | 
					  output logic             ITLBWriteF, DTLBWriteM,
 | 
				
			||||||
  // *** handshake to tlbs probably not needed, since stalls take effect
 | 
					  // *** handshake to tlbs probably not needed, since stalls take effect
 | 
				
			||||||
  // output logic             TranslationComplete
 | 
					  output logic             MMUTranslationComplete,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Signals from and to ahblite
 | 
					  // Signals from and to ahblite
 | 
				
			||||||
  input  logic [`XLEN-1:0] MMUReadPTE,
 | 
					  input  logic [`XLEN-1:0] MMUReadPTE,
 | 
				
			||||||
  input  logic             MMUReady,
 | 
					  input  logic             MMUReady,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  output logic [`XLEN-1:0] MMUPAdr,
 | 
					  output logic [`XLEN-1:0] MMUPAdr,
 | 
				
			||||||
  output logic             MMUTranslate
 | 
					  output logic             MMUTranslate,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Faults
 | 
				
			||||||
 | 
					  output logic             InstrPageFaultM, LoadPageFaultM, StorePageFaultM
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logic                 SvMode;
 | 
					  logic                 SvMode;
 | 
				
			||||||
  logic [`PPN_BITS-1:0] BasePageTablePPN;
 | 
					  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};
 | 
					  logic [9:0] DirectPTEFlags = {2'b0, 8'b00001111};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,71 +77,233 @@ module pagetablewalker (
 | 
				
			|||||||
    end
 | 
					    end
 | 
				
			||||||
  endgenerate
 | 
					  endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF);
 | 
					  //flopenr #(`XLEN) instrpte(clk, reset, ITLBMissF, DirectInstrPTE, PageTableEntryF);
 | 
				
			||||||
  flopenr #(`XLEN)  datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM);
 | 
					  //flopenr #(`XLEN)  datapte(clk, reset, DTLBMissM, DirectMemPTE, PageTableEntryM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF);
 | 
					  //flopr #(1) iwritesignal(clk, reset, ITLBMissF, ITLBWriteF);
 | 
				
			||||||
  flopr #(1) dwritesignal(clk, reset, DTLBMissM, DTLBWriteM);
 | 
					  //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
 | 
					  generate
 | 
				
			||||||
    if (`XLEN == 32) begin
 | 
					    if (`XLEN == 32) begin
 | 
				
			||||||
      assign SvMode = SATP_REGW[31];
 | 
					      assign SvMode = SATP_REGW[31];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      logic VPN1 [9:0] = TranslationVAdr[31:22];
 | 
					      logic [9:0] VPN1 = TranslationVAdr[31:22];
 | 
				
			||||||
      logic VPN0 [9:0] = TranslationVAdr[21:12]; // *** could optimize by not passing offset?
 | 
					      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;
 | 
					      statetype WalkerState, NextWalkerState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      always_ff @(posedge HCLK, negedge HRESETn)
 | 
					      // *** Do we need a synchronizer here for walker to talk to ahblite?
 | 
				
			||||||
        if (~HRESETn) WalkerState <= #1 IDLE;
 | 
					      flopenl #(.TYPE(statetype)) mmureg(clk, reset, 1'b1, NextWalkerState, IDLE, WalkerState);
 | 
				
			||||||
        else          WalkerState <= #1 NextWalkerState;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      always_comb begin
 | 
					      always_comb begin
 | 
				
			||||||
        NextWalkerState = 'X;
 | 
					 | 
				
			||||||
        case (WalkerState)
 | 
					        case (WalkerState)
 | 
				
			||||||
          IDLE:   if      (TLBMissM)             NextWalkerState = LEVEL1;
 | 
					          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;
 | 
					                  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;
 | 
					 | 
				
			||||||
        endcase
 | 
					        endcase
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      always_ff @(posedge HCLK, negedge HRESETn)
 | 
					      // unswizzle PTE bits
 | 
				
			||||||
        if (~HRESETn) begin
 | 
					      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;
 | 
					          TranslationPAdr <= '0;
 | 
				
			||||||
          PageTableEntryF <= '0;
 | 
					          PageTableEntryF <= '0;
 | 
				
			||||||
          TranslationComplete <= '0;
 | 
					          MMUTranslationComplete <= '0;
 | 
				
			||||||
 | 
					          DTLBWriteM <= '0;
 | 
				
			||||||
 | 
					          ITLBWriteF <= '0;
 | 
				
			||||||
 | 
					          InstrPageFaultM <= '0;
 | 
				
			||||||
 | 
					          LoadPageFaultM <= '0;
 | 
				
			||||||
 | 
					          StorePageFaultM <= '0;
 | 
				
			||||||
        end else begin
 | 
					        end else begin
 | 
				
			||||||
          // default values
 | 
					          // default values
 | 
				
			||||||
 | 
					          TranslationPAdr <= '0;
 | 
				
			||||||
 | 
					          PageTableEntryF <= '0;
 | 
				
			||||||
 | 
					          MMUTranslationComplete <= '0;
 | 
				
			||||||
 | 
					          DTLBWriteM <= '0;
 | 
				
			||||||
 | 
					          ITLBWriteF <= '0;
 | 
				
			||||||
 | 
					          InstrPageFaultM <= '0;
 | 
				
			||||||
 | 
					          LoadPageFaultM <= '0;
 | 
				
			||||||
 | 
					          StorePageFaultM <= '0;
 | 
				
			||||||
          case (NextWalkerState)
 | 
					          case (NextWalkerState)
 | 
				
			||||||
            LEVEL1: TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00};
 | 
					            LEVEL1: begin
 | 
				
			||||||
            LEVEL2: TranslationPAdr <= {CurrentPPN, VPN0, 2'b00};
 | 
					              TranslationPAdr <= {BasePageTablePPN, VPN1, 2'b00};
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            LEVEL0: begin
 | 
				
			||||||
 | 
					              TranslationPAdr <= {CurrentPPN, VPN0, 2'b00};
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
            LEAF: begin
 | 
					            LEAF: begin
 | 
				
			||||||
              PageTableEntryF <= CurrentPageTableEntry;
 | 
					              PageTableEntryF <= MMUReadPTE;
 | 
				
			||||||
              TranslationComplete <= '1;
 | 
					              PageTableEntryM <= MMUReadPTE;
 | 
				
			||||||
 | 
					              MMUTranslationComplete <= '1;
 | 
				
			||||||
 | 
					              DTLBWriteM <= DTLBMissM;
 | 
				
			||||||
 | 
					              ITLBWriteF <= ~DTLBMissM;  // Prefer data over instructions
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            FAULT: begin
 | 
				
			||||||
 | 
					              InstrPageFaultM <= ~DTLBMissM;
 | 
				
			||||||
 | 
					              LoadPageFaultM <= DTLBMissM && ~MemWriteM;
 | 
				
			||||||
 | 
					              StorePageFaultM <= DTLBMissM && MemWriteM;
 | 
				
			||||||
            end
 | 
					            end
 | 
				
			||||||
          endcase
 | 
					          endcase
 | 
				
			||||||
        end
 | 
					        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
 | 
					    end else begin
 | 
				
			||||||
      // sv39 not yet implemented
 | 
					 | 
				
			||||||
      assign SvMode = SATP_REGW[63];
 | 
					      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
 | 
					    end
 | 
				
			||||||
  endgenerate
 | 
					  endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // rv32 case
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
endmodule
 | 
					endmodule
 | 
				
			||||||
@ -39,6 +39,7 @@ module privileged (
 | 
				
			|||||||
  input  logic             InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
 | 
					  input  logic             InstrValidW, FloatRegWriteW, LoadStallD, BPPredWrongM,
 | 
				
			||||||
  input  logic [3:0]       InstrClassM,
 | 
					  input  logic [3:0]       InstrClassM,
 | 
				
			||||||
  input  logic             PrivilegedM,
 | 
					  input  logic             PrivilegedM,
 | 
				
			||||||
 | 
					  input  logic             InstrPageFaultM, LoadPageFaultM, StorePageFaultM,
 | 
				
			||||||
  input  logic             InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
 | 
					  input  logic             InstrMisalignedFaultM, InstrAccessFaultF, IllegalIEUInstrFaultD,
 | 
				
			||||||
  input  logic             LoadMisalignedFaultM, LoadAccessFaultM,
 | 
					  input  logic             LoadMisalignedFaultM, LoadAccessFaultM,
 | 
				
			||||||
  input  logic             StoreMisalignedFaultM, StoreAccessFaultM,
 | 
					  input  logic             StoreMisalignedFaultM, StoreAccessFaultM,
 | 
				
			||||||
@ -48,7 +49,7 @@ module privileged (
 | 
				
			|||||||
  output logic [1:0]       PrivilegeModeW,
 | 
					  output logic [1:0]       PrivilegeModeW,
 | 
				
			||||||
  output logic [`XLEN-1:0] SATP_REGW,
 | 
					  output logic [`XLEN-1:0] SATP_REGW,
 | 
				
			||||||
  output logic [2:0]       FRM_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;
 | 
					  logic [1:0] NextPrivilegeModeM;
 | 
				
			||||||
@ -65,7 +66,6 @@ module privileged (
 | 
				
			|||||||
  logic IllegalInstrFaultM;
 | 
					  logic IllegalInstrFaultM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logic BreakpointFaultM, EcallFaultM;
 | 
					  logic BreakpointFaultM, EcallFaultM;
 | 
				
			||||||
  logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM;
 | 
					 | 
				
			||||||
  logic MTrapM, STrapM, UTrapM; 
 | 
					  logic MTrapM, STrapM, UTrapM; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logic [1:0] STATUS_MPP;
 | 
					  logic [1:0] STATUS_MPP;
 | 
				
			||||||
@ -119,9 +119,11 @@ module privileged (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  assign BreakpointFaultM = ebreakM; // could have other causes too
 | 
					  assign BreakpointFaultM = ebreakM; // could have other causes too
 | 
				
			||||||
  assign EcallFaultM = ecallM;
 | 
					  assign EcallFaultM = ecallM;
 | 
				
			||||||
  assign InstrPageFaultM = 0;
 | 
					  // *** Page faults now driven by page table walker. Might need to make the
 | 
				
			||||||
  assign LoadPageFaultM = 0;
 | 
					  // below signals ORs of a walker fault and a tlb fault if both of those come in
 | 
				
			||||||
  assign StorePageFaultM = 0;
 | 
					  // assign InstrPageFaultM = 0;
 | 
				
			||||||
 | 
					  // assign LoadPageFaultM = 0;
 | 
				
			||||||
 | 
					  // assign StorePageFaultM = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // pipeline fault signals
 | 
					  // pipeline fault signals
 | 
				
			||||||
  flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD);
 | 
					  flopenrc #(1) faultregD(clk, reset, FlushD, ~StallD, InstrAccessFaultF, InstrAccessFaultD);
 | 
				
			||||||
 | 
				
			|||||||
@ -76,6 +76,7 @@ module wallypipelinedhart (
 | 
				
			|||||||
  logic InstrMisalignedFaultM;
 | 
					  logic InstrMisalignedFaultM;
 | 
				
			||||||
  logic DataMisalignedM;
 | 
					  logic DataMisalignedM;
 | 
				
			||||||
  logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
 | 
					  logic IllegalBaseInstrFaultD, IllegalIEUInstrFaultD;
 | 
				
			||||||
 | 
					  logic InstrPageFaultM, LoadPageFaultM, StorePageFaultM;
 | 
				
			||||||
  logic LoadMisalignedFaultM, LoadAccessFaultM;
 | 
					  logic LoadMisalignedFaultM, LoadAccessFaultM;
 | 
				
			||||||
  logic StoreMisalignedFaultM, StoreAccessFaultM;
 | 
					  logic StoreMisalignedFaultM, StoreAccessFaultM;
 | 
				
			||||||
  logic [`XLEN-1:0] InstrMisalignedAdrM;
 | 
					  logic [`XLEN-1:0] InstrMisalignedAdrM;
 | 
				
			||||||
@ -98,7 +99,7 @@ module wallypipelinedhart (
 | 
				
			|||||||
  logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM;
 | 
					  logic [`XLEN-1:0] PageTableEntryF, PageTableEntryM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  logic [`XLEN-1:0] MMUPAdr, MMUReadPTE;
 | 
					  logic [`XLEN-1:0] MMUPAdr, MMUReadPTE;
 | 
				
			||||||
  logic             MMUTranslate, MMUReady;
 | 
					  logic             MMUTranslate, MMUTranslationComplete, MMUReady;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // bus interface to dmem
 | 
					  // bus interface to dmem
 | 
				
			||||||
  logic             MemReadM, MemWriteM;
 | 
					  logic             MemReadM, MemWriteM;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user