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,15 +90,27 @@ 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
 | 
			
		||||
      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;
 | 
			
		||||
@ -121,15 +134,25 @@ module ahblite (
 | 
			
		||||
 | 
			
		||||
  // 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];
 | 
			
		||||
  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;
 | 
			
		||||
          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;
 | 
			
		||||
          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
 | 
			
		||||
      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;
 | 
			
		||||
              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