mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge pull request #117 from davidharrishmc/dev
ZMMUL support and MMU cleanup
This commit is contained in:
		
						commit
						c5d98d5465
					
				| @ -136,6 +136,7 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 1 | `define SVADU_SUPPORTED 1 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -145,6 +145,7 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 1 | `define SVADU_SUPPORTED 1 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -139,6 +139,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -138,6 +138,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -139,6 +139,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -138,6 +138,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -141,6 +141,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -141,6 +141,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -141,6 +141,7 @@ | |||||||
| `define BTB_SIZE 10 | `define BTB_SIZE 10 | ||||||
| 
 | 
 | ||||||
| `define SVADU_SUPPORTED 0 | `define SVADU_SUPPORTED 0 | ||||||
|  | `define ZMMUL_SUPPORTED 0 | ||||||
| 
 | 
 | ||||||
| // FPU division architecture | // FPU division architecture | ||||||
| `define RADIX 32'h4 | `define RADIX 32'h4 | ||||||
|  | |||||||
| @ -150,14 +150,14 @@ module controller( | |||||||
|                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 |                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 | ||||||
|       7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000) |       7'b0110011: if (Funct7D == 7'b0000000 | Funct7D == 7'b0100000) | ||||||
|                       ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type 
 |                       ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_0_0_0_0_0_00_0; // R-type 
 | ||||||
|                   else if (Funct7D == 7'b0000001 & `M_SUPPORTED) |                   else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2]))) | ||||||
|                       ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
 |                       ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_0_0_0_0_1_00_0; // Multiply/divide
 | ||||||
|                   else |                   else | ||||||
|                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 |                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 | ||||||
|       7'b0110111:     ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
 |       7'b0110111:     ControlsD = `CTRLW'b1_100_01_00_000_0_0_0_1_0_0_0_0_0_00_0; // lui
 | ||||||
|       7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64) |       7'b0111011: if ((Funct7D == 7'b0000000 | Funct7D == 7'b0100000) & `XLEN == 64) | ||||||
|                       ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
 |                       ControlsD = `CTRLW'b1_000_00_00_000_0_1_0_0_1_0_0_0_0_00_0; // R-type W instructions for RV64i
 | ||||||
|                   else if (Funct7D == 7'b0000001 & `M_SUPPORTED & `XLEN == 64) |                   else if (Funct7D == 7'b0000001 & (`M_SUPPORTED | (`ZMMUL_SUPPORTED & ~Funct3D[2])) & `XLEN == 64) | ||||||
|                       ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
 |                       ControlsD = `CTRLW'b1_000_00_00_011_0_0_0_0_1_0_0_0_1_00_0; // W-type Multiply/Divide
 | ||||||
|                   else |                   else | ||||||
|                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 |                       ControlsD = `CTRLW'b0_000_00_00_000_0_0_0_0_0_0_0_0_0_00_1; // Non-implemented instruction
 | ||||||
|  | |||||||
| @ -88,7 +88,7 @@ module ifu ( | |||||||
|   input logic [1:0] 		STATUS_MPP,                               // Status CSR: previous machine privilege level
 |   input logic [1:0] 		STATUS_MPP,                               // Status CSR: previous machine privilege level
 | ||||||
|   input logic               sfencevmaM,                               // Virtual memory address fence, invalidate TLB entries
 |   input logic               sfencevmaM,                               // Virtual memory address fence, invalidate TLB entries
 | ||||||
|   output logic 				ITLBMissF,                                // ITLB miss causes HPTW (hardware pagetable walker) walk
 |   output logic 				ITLBMissF,                                // ITLB miss causes HPTW (hardware pagetable walker) walk
 | ||||||
|   output logic              InstrDAPageFaultF,                        // ITLB hit needs to update dirty or access bits
 |   output logic              InstrUpdateDAF,                        // ITLB hit needs to update dirty or access bits
 | ||||||
|   input  var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],         // PMP configuration from privileged unit
 |   input  var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],         // PMP configuration from privileged unit
 | ||||||
|   input  var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0],  // PMP address from privileged unit
 |   input  var logic [`XLEN-1:0] PMPADDR_ARRAY_REGW[`PMP_ENTRIES-1:0],  // PMP address from privileged unit
 | ||||||
|   output logic 				InstrAccessFaultF,                        // Instruction access fault 
 |   output logic 				InstrAccessFaultF,                        // Instruction access fault 
 | ||||||
| @ -145,7 +145,7 @@ module ifu ( | |||||||
| 
 | 
 | ||||||
|   if(`C_SUPPORTED) begin : Spill |   if(`C_SUPPORTED) begin : Spill | ||||||
|     spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF, |     spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF, | ||||||
|       .InstrDAPageFaultF, .IFUCacheBusStallD, .ITLBMissF, .PCNextFSpill, .PCFSpill, .SelNextSpillF, .PostSpillInstrRawF, .CompressedF); |       .InstrUpdateDAF, .IFUCacheBusStallD, .ITLBMissF, .PCNextFSpill, .PCFSpill, .SelNextSpillF, .PostSpillInstrRawF, .CompressedF); | ||||||
|   end else begin : NoSpill |   end else begin : NoSpill | ||||||
|     assign PCNextFSpill = PCNextF; |     assign PCNextFSpill = PCNextF; | ||||||
|     assign PCFSpill = PCF; |     assign PCFSpill = PCF; | ||||||
| @ -185,12 +185,12 @@ module ifu ( | |||||||
|          .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), |          .InstrAccessFaultF, .LoadAccessFaultM(), .StoreAmoAccessFaultM(), | ||||||
|          .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), |          .InstrPageFaultF, .LoadPageFaultM(), .StoreAmoPageFaultM(), | ||||||
|          .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), |          .LoadMisalignedFaultM(), .StoreAmoMisalignedFaultM(), | ||||||
|          .DAPageFault(InstrDAPageFaultF), |          .UpdateDA(InstrUpdateDAF), | ||||||
|          .AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0), |          .AtomicAccessM(1'b0),.ExecuteAccessF(1'b1), .WriteAccessM(1'b0), .ReadAccessM(1'b0), | ||||||
|          .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); |          .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); | ||||||
| 
 | 
 | ||||||
|   end else begin |   end else begin | ||||||
|     assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrDAPageFaultF} = '0; |     assign {ITLBMissF, InstrAccessFaultF, InstrPageFaultF, InstrUpdateDAF} = '0; | ||||||
|     assign PCPF = PCFExt[`PA_BITS-1:0]; |     assign PCPF = PCFExt[`PA_BITS-1:0]; | ||||||
|     assign CacheableF = '1; |     assign CacheableF = '1; | ||||||
|     assign SelIROM = '0; |     assign SelIROM = '0; | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ module spill #( | |||||||
|   input logic [31:0] 	   InstrRawF,         // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
 |   input logic [31:0] 	   InstrRawF,         // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
 | ||||||
|   input logic 			   IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
 |   input logic 			   IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
 | ||||||
|   input logic 			   ITLBMissF,         // ITLB miss, ignore memory request
 |   input logic 			   ITLBMissF,         // ITLB miss, ignore memory request
 | ||||||
|   input logic 			   InstrDAPageFaultF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
 |   input logic 			   InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
 | ||||||
|   output logic [`XLEN-1:0] PCNextFSpill,      // The next PCF for one of the two memory addresses of the spill
 |   output logic [`XLEN-1:0] PCNextFSpill,      // The next PCF for one of the two memory addresses of the spill
 | ||||||
|   output logic [`XLEN-1:0] PCFSpill,          // PCF for one of the two memory addresses of the spill
 |   output logic [`XLEN-1:0] PCFSpill,          // PCF for one of the two memory addresses of the spill
 | ||||||
|   output logic 			   SelNextSpillF,     // During the transition between the two spill operations, the IFU should stall the pipeline
 |   output logic 			   SelNextSpillF,     // During the transition between the two spill operations, the IFU should stall the pipeline
 | ||||||
| @ -77,7 +77,7 @@ module spill #( | |||||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 |   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
|   assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1]; |   assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1]; | ||||||
|   assign TakeSpillF = SpillF & ~IFUCacheBusStallD & ~(ITLBMissF | (`SVADU_SUPPORTED & InstrDAPageFaultF)); |   assign TakeSpillF = SpillF & ~IFUCacheBusStallD & ~(ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF)); | ||||||
|    |    | ||||||
|   always_ff @(posedge clk) |   always_ff @(posedge clk) | ||||||
|     if (reset | FlushD)    CurrState <= #1 STATE_READY; |     if (reset | FlushD)    CurrState <= #1 STATE_READY; | ||||||
|  | |||||||
| @ -81,7 +81,7 @@ module lsu ( | |||||||
|   input  logic [1:0]          STATUS_MPP,                           // Machine previous privilege mode
 |   input  logic [1:0]          STATUS_MPP,                           // Machine previous privilege mode
 | ||||||
|   input  logic [`XLEN-1:0]    PCFSpill,                                  // Fetch PC 
 |   input  logic [`XLEN-1:0]    PCFSpill,                                  // Fetch PC 
 | ||||||
|   input  logic                ITLBMissF,                            // ITLB miss causes HPTW (hardware pagetable walker) walk
 |   input  logic                ITLBMissF,                            // ITLB miss causes HPTW (hardware pagetable walker) walk
 | ||||||
|   input  logic                InstrDAPageFaultF,                    // ITLB hit needs to update dirty or access bits
 |   input  logic                InstrUpdateDAF,                    // ITLB hit needs to update dirty or access bits
 | ||||||
|   output logic [`XLEN-1:0]    PTE,                                  // Page table entry write to ITLB
 |   output logic [`XLEN-1:0]    PTE,                                  // Page table entry write to ITLB
 | ||||||
|   output logic [1:0]          PageType,                             // Type of page table entry to write to ITLB
 |   output logic [1:0]          PageType,                             // Type of page table entry to write to ITLB
 | ||||||
|   output logic                ITLBWriteF,                           // Write PTE to ITLB
 |   output logic                ITLBWriteF,                           // Write PTE to ITLB
 | ||||||
| @ -127,7 +127,7 @@ module lsu ( | |||||||
| 
 | 
 | ||||||
|   logic                     DTLBMissM;                              // DTLB miss causes HPTW walk
 |   logic                     DTLBMissM;                              // DTLB miss causes HPTW walk
 | ||||||
|   logic                     DTLBWriteM;                             // Writes PTE and PageType to DTLB
 |   logic                     DTLBWriteM;                             // Writes PTE and PageType to DTLB
 | ||||||
|   logic                     DataDAPageFaultM;                       // DTLB hit needs to update dirty or access bits
 |   logic                     DataUpdateDAM;                       // DTLB hit needs to update dirty or access bits
 | ||||||
|   logic                     LSULoadAccessFaultM;                    // Load acces fault
 |   logic                     LSULoadAccessFaultM;                    // Load acces fault
 | ||||||
|   logic 					LSUStoreAmoAccessFaultM;                // Store access fault
 |   logic 					LSUStoreAmoAccessFaultM;                // Store access fault
 | ||||||
|   logic                     IgnoreRequestTLB;                       // On either ITLB or DTLB miss, ignore miss so HPTW can handle
 |   logic                     IgnoreRequestTLB;                       // On either ITLB or DTLB miss, ignore miss so HPTW can handle
 | ||||||
| @ -151,7 +151,7 @@ module lsu ( | |||||||
| 
 | 
 | ||||||
|   if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED |   if(`VIRTMEM_SUPPORTED) begin : VIRTMEM_SUPPORTED | ||||||
|     hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, |     hptw hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF, | ||||||
|       .DTLBMissM, .DTLBWriteM, .InstrDAPageFaultF, .DataDAPageFaultM, |       .DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM, | ||||||
|       .FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill, |       .FlushW, .DCacheStallM, .SATP_REGW, .PCFSpill, | ||||||
|       .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, |       .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW, | ||||||
|       .ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
 |       .ReadDataM(ReadDataM[`XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
 | ||||||
| @ -196,7 +196,7 @@ module lsu ( | |||||||
|       .StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,  |       .StoreAmoAccessFaultM(LSUStoreAmoAccessFaultM), .InstrPageFaultF(), .LoadPageFaultM,  | ||||||
| 	  .StoreAmoPageFaultM, | 	  .StoreAmoPageFaultM, | ||||||
|       .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,   // *** these faults need to be supressed during hptw.
 |       .LoadMisalignedFaultM, .StoreAmoMisalignedFaultM,   // *** these faults need to be supressed during hptw.
 | ||||||
|       .DAPageFault(DataDAPageFaultM), |       .UpdateDA(DataUpdateDAM), | ||||||
|       .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),  |       .AtomicAccessM(|LSUAtomicM), .ExecuteAccessF(1'b0),  | ||||||
|       .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), |       .WriteAccessM(PreLSURWM[0]), .ReadAccessM(PreLSURWM[1]), | ||||||
|       .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); |       .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW); | ||||||
|  | |||||||
| @ -51,16 +51,18 @@ module mdu( | |||||||
| 	// Divider
 | 	// Divider
 | ||||||
| 	// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
 | 	// Start a divide when a new division instruction is received and the divider isn't already busy or finishing
 | ||||||
| 	// When IDIV_ON_FPU is set, use the FPU divider instead
 | 	// When IDIV_ON_FPU is set, use the FPU divider instead
 | ||||||
| 	if (`IDIV_ON_FPU) begin   | 	// In ZMMUL, with M_SUPPORTED = 0, omit the divider
 | ||||||
|  | 	if ((`IDIV_ON_FPU) || (!`M_SUPPORTED)) begin:nodiv   | ||||||
| 	  assign QuotM = 0; | 	  assign QuotM = 0; | ||||||
| 	  assign RemM = 0; | 	  assign RemM = 0; | ||||||
| 	  assign DivBusyE = 0; | 	  assign DivBusyE = 0; | ||||||
| 	end else begin | 	end else begin:div | ||||||
| 		intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,  | 		intdivrestoring div(.clk, .reset, .StallM, .FlushE, .DivSignedE(~Funct3E[0]), .W64E, .IntDivE,  | ||||||
| 							.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM); | 							.ForwardedSrcAE, .ForwardedSrcBE, .DivBusyE, .QuotM, .RemM); | ||||||
| 	end | 	end | ||||||
| 		 | 		 | ||||||
| 	// Result multiplexer
 | 	// Result multiplexer
 | ||||||
|  | 	// For ZMMUL, QuotM and RemM are tied to 0, so the mux automatically simplifies
 | ||||||
| 	always_comb | 	always_comb | ||||||
| 		case (Funct3M)	    | 		case (Funct3M)	    | ||||||
| 			3'b000: PrelimResultM = ProdM[`XLEN-1:0];					// mul
 | 			3'b000: PrelimResultM = ProdM[`XLEN-1:0];					// mul
 | ||||||
|  | |||||||
| @ -49,8 +49,8 @@ module hptw ( | |||||||
| 	input  logic                ITLBMissF, | 	input  logic                ITLBMissF, | ||||||
| 	input  logic                DTLBMissM, | 	input  logic                DTLBMissM, | ||||||
| 	input  logic                FlushW, | 	input  logic                FlushW, | ||||||
| 	input  logic                InstrDAPageFaultF, | 	input  logic                InstrUpdateDAF, | ||||||
| 	input  logic                DataDAPageFaultM, | 	input  logic                DataUpdateDAM, | ||||||
| 	output logic [`XLEN-1:0]    PTE, 								// page table entry to TLBs
 | 	output logic [`XLEN-1:0]    PTE, 								// page table entry to TLBs
 | ||||||
| 	output logic [1:0]          PageType, 					// page type to TLBs
 | 	output logic [1:0]          PageType, 					// page type to TLBs
 | ||||||
| 	output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
 | 	output logic ITLBWriteF, DTLBWriteM, // write TLB with new entry
 | ||||||
| @ -87,21 +87,23 @@ module hptw ( | |||||||
|   logic [`XLEN-1:0] 	   TranslationVAdr; |   logic [`XLEN-1:0] 	   TranslationVAdr; | ||||||
|   logic [`XLEN-1:0] 	   NextPTE; |   logic [`XLEN-1:0] 	   NextPTE; | ||||||
|   logic 				   UpdatePTE; |   logic 				   UpdatePTE; | ||||||
|   logic 				   HPTWDAPageFault; |   logic 				   HPTWUpdateDA; | ||||||
|   logic [`PA_BITS-1:0] 	   HPTWReadAdr; |   logic [`PA_BITS-1:0] 	   HPTWReadAdr; | ||||||
|   logic 				   SelHPTWAdr; |   logic 				   SelHPTWAdr; | ||||||
|   logic [`XLEN+1:0] 	   HPTWAdrExt; |   logic [`XLEN+1:0] 	   HPTWAdrExt; | ||||||
|   logic 				   ITLBMissOrDAFaultF; |   logic 				   ITLBMissOrDAFaultF; | ||||||
|   logic 				   DTLBMissOrDAFaultM; |   logic 				   DTLBMissOrDAFaultM; | ||||||
|  |   logic                    LSUAccessFaultM; | ||||||
|   logic [`PA_BITS-1:0] 	   HPTWAdr; |   logic [`PA_BITS-1:0] 	   HPTWAdr; | ||||||
|   logic [1:0] 			   HPTWRW; |   logic [1:0] 			   HPTWRW; | ||||||
|   logic [2:0] 			   HPTWSize; // 32 or 64 bit access
 |   logic [2:0] 			   HPTWSize; // 32 or 64 bit access
 | ||||||
|   statetype WalkerState, NextWalkerState, InitialWalkerState; |   statetype WalkerState, NextWalkerState, InitialWalkerState; | ||||||
| 
 | 
 | ||||||
|   // map hptw access faults onto either the original LSU load/store fault or instruction access fault
 |   // map hptw access faults onto either the original LSU load/store fault or instruction access fault
 | ||||||
|   assign LoadAccessFaultM 		 = WalkerState == IDLE ? LSULoadAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[1] & ~MemRWM[0]; |   assign LSUAccessFaultM         = LSULoadAccessFaultM | LSUStoreAmoAccessFaultM; | ||||||
|   assign StoreAmoAccessFaultM	 = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : (LSULoadAccessFaultM | LSUStoreAmoAccessFaultM) & DTLBWalk & MemRWM[0]; |   assign LoadAccessFaultM 		 = WalkerState == IDLE ? LSULoadAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[1] & ~MemRWM[0]; | ||||||
|   assign HPTWInstrAccessFaultM = WalkerState == IDLE ? 1'b0: (LSUStoreAmoAccessFaultM | LSULoadAccessFaultM) & ~DTLBWalk; |   assign StoreAmoAccessFaultM	 = WalkerState == IDLE ? LSUStoreAmoAccessFaultM : LSUAccessFaultM & DTLBWalk & MemRWM[0]; | ||||||
|  |   assign HPTWInstrAccessFaultM   = WalkerState == IDLE ? 1'b0: LSUAccessFaultM & ~DTLBWalk; | ||||||
| 
 | 
 | ||||||
| 	// Extract bits from CSRs and inputs
 | 	// Extract bits from CSRs and inputs
 | ||||||
| 	assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; | 	assign SvMode = SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]; | ||||||
| @ -127,8 +129,8 @@ module hptw ( | |||||||
| 
 | 
 | ||||||
|   if(`SVADU_SUPPORTED) begin : hptwwrites |   if(`SVADU_SUPPORTED) begin : hptwwrites | ||||||
|     logic                     ReadAccess, WriteAccess; |     logic                     ReadAccess, WriteAccess; | ||||||
|     logic                     InvalidRead, InvalidWrite; |     logic                     InvalidRead, InvalidWrite, InvalidOp; | ||||||
|     logic                     UpperBitsUnequalPageFault;  |     logic                     UpperBitsUnequal;  | ||||||
|     logic                     OtherPageFault; |     logic                     OtherPageFault; | ||||||
|     logic [1:0]               EffectivePrivilegeMode; |     logic [1:0]               EffectivePrivilegeMode; | ||||||
|     logic                     ImproperPrivilege; |     logic                     ImproperPrivilege; | ||||||
| @ -147,7 +149,7 @@ module hptw ( | |||||||
|     mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);  |     mux2 #(`PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr);  | ||||||
| 
 | 
 | ||||||
|     assign {Dirty, Accessed} = PTE[7:6]; |     assign {Dirty, Accessed} = PTE[7:6]; | ||||||
|     assign WriteAccess = MemRWM[0] | (|AtomicM); |     assign WriteAccess = MemRWM[0]; // implies | (|AtomicM);
 | ||||||
|     assign SetDirty = ~Dirty & DTLBWalk & WriteAccess; |     assign SetDirty = ~Dirty & DTLBWalk & WriteAccess; | ||||||
|     assign ReadAccess = MemRWM[1]; |     assign ReadAccess = MemRWM[1]; | ||||||
| 
 | 
 | ||||||
| @ -157,24 +159,24 @@ module hptw ( | |||||||
| 
 | 
 | ||||||
|     // Check for page faults
 |     // Check for page faults
 | ||||||
| 		vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr),  | 		vm64check vm64check(.SATP_MODE(SATP_REGW[`XLEN-1:`XLEN-`SVMODE_BITS]), .VAdr(TranslationVAdr),  | ||||||
| 	  	.SV39Mode(), .UpperBitsUnequalPageFault); | 	  	.SV39Mode(), .UpperBitsUnequal); | ||||||
|     assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); |     assign InvalidRead = ReadAccess & ~Readable & (~STATUS_MXR | ~Executable); | ||||||
|     assign InvalidWrite = WriteAccess & ~Writable; |     assign InvalidWrite = WriteAccess & ~Writable; | ||||||
|     assign OtherPageFault = DTLBWalk? ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~Valid : | 	assign InvalidOp = DTLBWalk ? (InvalidRead | InvalidWrite) : ~Executable; | ||||||
|                             ImproperPrivilege | ~Executable | UpperBitsUnequalPageFault | Misaligned | ~Valid; |     assign OtherPageFault = ImproperPrivilege | InvalidOp | UpperBitsUnequal | Misaligned | ~Valid; | ||||||
| 
 | 
 | ||||||
|     // hptw needs to know if there is a Dirty or Access fault occuring on this
 |     // hptw needs to know if there is a Dirty or Access fault occuring on this
 | ||||||
|     // memory access.  If there is the PTE needs to be updated seting Access
 |     // memory access.  If there is the PTE needs to be updated seting Access
 | ||||||
|     // and possibly also Dirty.  Dirty is set if the operation is a store/amo.
 |     // and possibly also Dirty.  Dirty is set if the operation is a store/amo.
 | ||||||
|     // However any other fault should not cause the update.
 |     // However any other fault should not cause the update.
 | ||||||
|     assign HPTWDAPageFault = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault; |     assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault; | ||||||
| 
 | 
 | ||||||
|     assign HPTWRW[0] = (WalkerState == UPDATE_PTE); |     assign HPTWRW[0] = (WalkerState == UPDATE_PTE); | ||||||
|     assign UpdatePTE = (WalkerState == LEAF) & HPTWDAPageFault; |     assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA; | ||||||
|   end else begin // block: hptwwrites
 |   end else begin // block: hptwwrites
 | ||||||
|     assign NextPTE = ReadDataM; |     assign NextPTE = ReadDataM; | ||||||
|     assign HPTWAdr = HPTWReadAdr; |     assign HPTWAdr = HPTWReadAdr; | ||||||
|     assign HPTWDAPageFault = '0; |     assign HPTWUpdateDA = '0; | ||||||
|     assign UpdatePTE = '0; |     assign UpdatePTE = '0; | ||||||
|     assign HPTWRW[0] = '0; |     assign HPTWRW[0] = '0; | ||||||
|   end |   end | ||||||
| @ -182,8 +184,8 @@ module hptw ( | |||||||
| 	// Enable and select signals based on states
 | 	// Enable and select signals based on states
 | ||||||
| 	assign StartWalk = (WalkerState == IDLE) & TLBMiss; | 	assign StartWalk = (WalkerState == IDLE) & TLBMiss; | ||||||
| 	assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); | 	assign HPTWRW[1] = (WalkerState == L3_RD) | (WalkerState == L2_RD) | (WalkerState == L1_RD) | (WalkerState == L0_RD); | ||||||
| 	assign DTLBWriteM = (WalkerState == LEAF & ~HPTWDAPageFault) & DTLBWalk; | 	assign DTLBWriteM = (WalkerState == LEAF & ~HPTWUpdateDA) & DTLBWalk; | ||||||
| 	assign ITLBWriteF = (WalkerState == LEAF & ~HPTWDAPageFault) & ~DTLBWalk; | 	assign ITLBWriteF = (WalkerState == LEAF & ~HPTWUpdateDA) & ~DTLBWalk; | ||||||
|    |    | ||||||
| 	// FSM to track PageType based on the levels of the page table traversed
 | 	// FSM to track PageType based on the levels of the page table traversed
 | ||||||
| 	flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType); | 	flopr #(2) PageTypeReg(clk, reset, NextPageType, PageType); | ||||||
| @ -262,7 +264,7 @@ module hptw ( | |||||||
| 					else                                 										NextWalkerState = LEAF; | 					else                                 										NextWalkerState = LEAF; | ||||||
| 			L0_RD: if (DCacheStallM)                     								NextWalkerState = L0_RD; | 			L0_RD: if (DCacheStallM)                     								NextWalkerState = L0_RD; | ||||||
| 				   else                                     							NextWalkerState = LEAF; | 				   else                                     							NextWalkerState = LEAF; | ||||||
| 			LEAF: if (`SVADU_SUPPORTED & HPTWDAPageFault)             NextWalkerState = UPDATE_PTE; | 			LEAF: if (`SVADU_SUPPORTED & HPTWUpdateDA)             NextWalkerState = UPDATE_PTE; | ||||||
| 				  else 																										NextWalkerState = IDLE; | 				  else 																										NextWalkerState = IDLE; | ||||||
| 			UPDATE_PTE: if(DCacheStallM) 		                        		NextWalkerState = UPDATE_PTE; | 			UPDATE_PTE: if(DCacheStallM) 		                        		NextWalkerState = UPDATE_PTE; | ||||||
| 						else 																									NextWalkerState = LEAF; | 						else 																									NextWalkerState = LEAF; | ||||||
| @ -273,8 +275,8 @@ module hptw ( | |||||||
|   assign SelHPTW = WalkerState != IDLE; |   assign SelHPTW = WalkerState != IDLE; | ||||||
|   assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss); |   assign HPTWStall = (WalkerState != IDLE) | (WalkerState == IDLE & TLBMiss); | ||||||
| 
 | 
 | ||||||
|   assign ITLBMissOrDAFaultF = ITLBMissF | (`SVADU_SUPPORTED & InstrDAPageFaultF); |   assign ITLBMissOrDAFaultF = ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF); | ||||||
|   assign DTLBMissOrDAFaultM = DTLBMissM | (`SVADU_SUPPORTED & DataDAPageFaultM);   |   assign DTLBMissOrDAFaultM = DTLBMissM | (`SVADU_SUPPORTED & DataUpdateDAM);   | ||||||
| 
 | 
 | ||||||
|   // HTPW address/data/control muxing
 |   // HTPW address/data/control muxing
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) ( | |||||||
|   // Faults
 |   // Faults
 | ||||||
|   output logic                InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM,  // access fault sources
 |   output logic                InstrAccessFaultF, LoadAccessFaultM, StoreAmoAccessFaultM,  // access fault sources
 | ||||||
|   output logic                InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM,        // page fault sources
 |   output logic                InstrPageFaultF, LoadPageFaultM, StoreAmoPageFaultM,        // page fault sources
 | ||||||
|   output logic                DAPageFault,                                                // page fault due to setting dirty or access bit
 |   output logic                UpdateDA,                                                // page fault due to setting dirty or access bit
 | ||||||
|   output logic                LoadMisalignedFaultM, StoreAmoMisalignedFaultM,             // misaligned fault sources
 |   output logic                LoadMisalignedFaultM, StoreAmoMisalignedFaultM,             // misaligned fault sources
 | ||||||
|   // PMA checker signals
 |   // PMA checker signals
 | ||||||
|   input  logic                 AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,  // access type
 |   input  logic                 AtomicAccessM, ExecuteAccessF, WriteAccessM, ReadAccessM,  // access type
 | ||||||
| @ -70,6 +70,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) ( | |||||||
|   logic                       Translate;                // Translation occurs when virtual memory is active and DisableTranslation is off
 |   logic                       Translate;                // Translation occurs when virtual memory is active and DisableTranslation is off
 | ||||||
|   logic                       TLBHit;                   // Hit in TLB
 |   logic                       TLBHit;                   // Hit in TLB
 | ||||||
|   logic                       TLBPageFault;             // Page fault from TLB
 |   logic                       TLBPageFault;             // Page fault from TLB
 | ||||||
|  |   logic                       ReadNoAmoAccessM;         // Read that is not part of atomic operation causes Load faults.  Otherwise StoreAmo faults
 | ||||||
|    |    | ||||||
|   // only instantiate TLB if Virtual Memory is supported
 |   // only instantiate TLB if Virtual Memory is supported
 | ||||||
|   if (`VIRTMEM_SUPPORTED) begin:tlb |   if (`VIRTMEM_SUPPORTED) begin:tlb | ||||||
| @ -84,7 +85,7 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) ( | |||||||
|           .PrivilegeModeW, .ReadAccess, .WriteAccess, |           .PrivilegeModeW, .ReadAccess, .WriteAccess, | ||||||
|           .DisableTranslation, .PTE, .PageTypeWriteVal, |           .DisableTranslation, .PTE, .PageTypeWriteVal, | ||||||
|           .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,  |           .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,  | ||||||
|           .Translate, .TLBPageFault, .DAPageFault); |           .Translate, .TLBPageFault, .UpdateDA); | ||||||
|   end else begin:tlb// just pass address through as physical
 |   end else begin:tlb// just pass address through as physical
 | ||||||
|     assign Translate = 0; |     assign Translate = 0; | ||||||
|     assign TLBMiss = 0; |     assign TLBMiss = 0; | ||||||
| @ -118,6 +119,8 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) ( | |||||||
|     assign PMPLoadAccessFaultM      = 0; |     assign PMPLoadAccessFaultM      = 0; | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   assign ReadNoAmoAccessM = ReadAccessM & ~WriteAccessM;// AMO causes StoreAmo rather than Load fault
 | ||||||
|  | 
 | ||||||
|   // Access faults
 |   // Access faults
 | ||||||
|   // If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
 |   // If TLB miss and translating we want to not have faults from the PMA and PMP checkers.
 | ||||||
|   assign InstrAccessFaultF    = (PMAInstrAccessFaultF    | PMPInstrAccessFaultF)    & ~TLBMiss; |   assign InstrAccessFaultF    = (PMAInstrAccessFaultF    | PMPInstrAccessFaultF)    & ~TLBMiss; | ||||||
| @ -132,11 +135,11 @@ module mmu #(parameter TLB_ENTRIES = 8, IMMU = 0) ( | |||||||
|       2'b10:  DataMisalignedM = VAdr[1] | VAdr[0]; // lw, sw, flw, fsw, lwu
 |       2'b10:  DataMisalignedM = VAdr[1] | VAdr[0]; // lw, sw, flw, fsw, lwu
 | ||||||
|       2'b11:  DataMisalignedM = |VAdr[2:0];        // ld, sd, fld, fsd
 |       2'b11:  DataMisalignedM = |VAdr[2:0];        // ld, sd, fld, fsd
 | ||||||
|     endcase  |     endcase  | ||||||
|   assign LoadMisalignedFaultM     = DataMisalignedM & ReadAccessM; |   assign LoadMisalignedFaultM     = DataMisalignedM & ReadNoAmoAccessM; | ||||||
|   assign StoreAmoMisalignedFaultM = DataMisalignedM & (WriteAccessM | AtomicAccessM); |   assign StoreAmoMisalignedFaultM = DataMisalignedM & WriteAccessM; | ||||||
| 
 | 
 | ||||||
|   // Specify which type of page fault is occurring
 |   // Specify which type of page fault is occurring
 | ||||||
|   assign InstrPageFaultF    = TLBPageFault & ExecuteAccessF; |   assign InstrPageFaultF    = TLBPageFault & ExecuteAccessF; | ||||||
|   assign LoadPageFaultM     = TLBPageFault & ReadAccessM; |   assign LoadPageFaultM     = TLBPageFault & ReadNoAmoAccessM;  | ||||||
|   assign StoreAmoPageFaultM = TLBPageFault & (WriteAccessM | AtomicAccessM); |   assign StoreAmoPageFaultM = TLBPageFault & WriteAccessM; | ||||||
| endmodule | endmodule | ||||||
|  | |||||||
| @ -72,7 +72,7 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) ( | |||||||
|   output logic                    TLBHit, |   output logic                    TLBHit, | ||||||
|   output logic                    Translate, |   output logic                    Translate, | ||||||
|   output logic                    TLBPageFault, |   output logic                    TLBPageFault, | ||||||
|   output logic                    DAPageFault |   output logic                    UpdateDA | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|   logic [TLB_ENTRIES-1:0]         Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex
 |   logic [TLB_ENTRIES-1:0]         Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex
 | ||||||
| @ -105,7 +105,7 @@ module tlb #(parameter TLB_ENTRIES = 8, ITLB = 0) ( | |||||||
|   tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, |   tlbcontrol #(ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, | ||||||
|     .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, |     .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, | ||||||
|     .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault,  |     .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault,  | ||||||
|     .DAPageFault, .SV39Mode, .Translate); |     .UpdateDA, .SV39Mode, .Translate); | ||||||
| 
 | 
 | ||||||
|   tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); |   tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); | ||||||
|   tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS)  |   tlbcam #(TLB_ENTRIES, `VPN_BITS + `ASID_BITS, `VPN_SEGMENT_BITS)  | ||||||
| @ -43,7 +43,7 @@ module tlbcontrol #(parameter ITLB = 0) ( | |||||||
|   output logic                    TLBMiss, |   output logic                    TLBMiss, | ||||||
|   output logic                    TLBHit, |   output logic                    TLBHit, | ||||||
|   output logic                    TLBPageFault, |   output logic                    TLBPageFault, | ||||||
|   output logic                    DAPageFault, |   output logic                    UpdateDA, | ||||||
|   output logic                    SV39Mode, |   output logic                    SV39Mode, | ||||||
|   output logic                    Translate |   output logic                    Translate | ||||||
| ); | ); | ||||||
| @ -52,7 +52,7 @@ module tlbcontrol #(parameter ITLB = 0) ( | |||||||
|   logic [1:0]                     EffectivePrivilegeMode; |   logic [1:0]                     EffectivePrivilegeMode; | ||||||
| 
 | 
 | ||||||
|   logic                           PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits
 |   logic                           PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits
 | ||||||
|   logic                           UpperBitsUnequalPageFault; |   logic                           UpperBitsUnequal; | ||||||
|   logic                           TLBAccess; |   logic                           TLBAccess; | ||||||
|   logic                           ImproperPrivilege; |   logic                           ImproperPrivilege; | ||||||
| 
 | 
 | ||||||
| @ -64,7 +64,7 @@ module tlbcontrol #(parameter ITLB = 0) ( | |||||||
|   assign TLBAccess = ReadAccess | WriteAccess; |   assign TLBAccess = ReadAccess | WriteAccess; | ||||||
| 
 | 
 | ||||||
|   // Check that upper bits are legal (all 0s or all 1s)
 |   // Check that upper bits are legal (all 0s or all 1s)
 | ||||||
|   vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequalPageFault); |   vm64check vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal); | ||||||
| 
 | 
 | ||||||
|   // unswizzle useful PTE bits
 |   // unswizzle useful PTE bits
 | ||||||
|   assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; |   assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; | ||||||
| @ -77,12 +77,12 @@ module tlbcontrol #(parameter ITLB = 0) ( | |||||||
|     assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | |     assign ImproperPrivilege = ((EffectivePrivilegeMode == `U_MODE) & ~PTE_U) | | ||||||
|       ((EffectivePrivilegeMode == `S_MODE) & PTE_U); |       ((EffectivePrivilegeMode == `S_MODE) & PTE_U); | ||||||
|     if(`SVADU_SUPPORTED) begin : hptwwrites |     if(`SVADU_SUPPORTED) begin : hptwwrites | ||||||
|       assign DAPageFault = Translate & TLBHit & ~PTE_A & ~TLBPageFault; |       assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault; | ||||||
|       assign TLBPageFault = (Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); |       assign TLBPageFault = Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequal | Misaligned | ~PTE_V); | ||||||
|     end else begin |     end else begin | ||||||
|       // fault for software handling if access bit is off
 |       // fault for software handling if access bit is off
 | ||||||
|       assign DAPageFault = ~PTE_A; |       assign UpdateDA = ~PTE_A; | ||||||
|       assign TLBPageFault = (Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); |       assign TLBPageFault = Translate  & TLBHit & (ImproperPrivilege | ~PTE_X | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V); | ||||||
|     end |     end | ||||||
|   end else begin:dtlb // Data TLB fault checking
 |   end else begin:dtlb // Data TLB fault checking
 | ||||||
|     logic InvalidRead, InvalidWrite; |     logic InvalidRead, InvalidWrite; | ||||||
| @ -99,12 +99,12 @@ module tlbcontrol #(parameter ITLB = 0) ( | |||||||
|     // low.
 |     // low.
 | ||||||
|     assign InvalidWrite = WriteAccess & ~PTE_W; |     assign InvalidWrite = WriteAccess & ~PTE_W; | ||||||
|     if(`SVADU_SUPPORTED) begin : hptwwrites |     if(`SVADU_SUPPORTED) begin : hptwwrites | ||||||
|       assign DAPageFault = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;  |       assign UpdateDA = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;  | ||||||
|       assign TLBPageFault =  (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); |       assign TLBPageFault =  (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequal | Misaligned | ~PTE_V)); | ||||||
|     end else begin |     end else begin | ||||||
|       // Fault for software handling if access bit is off or writing a page with dirty bit off
 |       // Fault for software handling if access bit is off or writing a page with dirty bit off
 | ||||||
|       assign DAPageFault = ~PTE_A | WriteAccess & ~PTE_D;  |       assign UpdateDA = ~PTE_A | WriteAccess & ~PTE_D;  | ||||||
|       assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | DAPageFault | UpperBitsUnequalPageFault | Misaligned | ~PTE_V)); |       assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V)); | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| @ -32,7 +32,7 @@ module vm64check ( | |||||||
|   input  logic [`SVMODE_BITS-1:0] SATP_MODE, |   input  logic [`SVMODE_BITS-1:0] SATP_MODE, | ||||||
|   input  logic [`XLEN-1:0]        VAdr, |   input  logic [`XLEN-1:0]        VAdr, | ||||||
|   output logic                    SV39Mode,  |   output logic                    SV39Mode,  | ||||||
|   output logic                    UpperBitsUnequalPageFault |   output logic                    UpperBitsUnequal | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
|   if (`XLEN == 64) begin |   if (`XLEN == 64) begin | ||||||
| @ -42,9 +42,9 @@ module vm64check ( | |||||||
|     logic                           eq_63_47, eq_46_38; |     logic                           eq_63_47, eq_46_38; | ||||||
|     assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]); |     assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]); | ||||||
|     assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);  |     assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);  | ||||||
|     assign UpperBitsUnequalPageFault = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47; |     assign UpperBitsUnequal = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47; | ||||||
|   end else begin |   end else begin | ||||||
|     assign SV39Mode = 0; |     assign SV39Mode = 0; | ||||||
|     assign UpperBitsUnequalPageFault = 0; |     assign UpperBitsUnequal = 0; | ||||||
|   end |   end | ||||||
| endmodule | endmodule | ||||||
| @ -156,7 +156,7 @@ module wallypipelinedcore ( | |||||||
|   logic                          ICacheMiss; |   logic                          ICacheMiss; | ||||||
|   logic                          ICacheAccess; |   logic                          ICacheAccess; | ||||||
|   logic                          BreakpointFaultM, EcallFaultM; |   logic                          BreakpointFaultM, EcallFaultM; | ||||||
|   logic                          InstrDAPageFaultF; |   logic                          InstrUpdateDAF; | ||||||
|   logic                          BigEndianM; |   logic                          BigEndianM; | ||||||
|   logic                          FCvtIntE; |   logic                          FCvtIntE; | ||||||
|   logic                          CommittedF; |   logic                          CommittedF; | ||||||
| @ -184,7 +184,7 @@ module wallypipelinedcore ( | |||||||
|     .PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, |     .PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, | ||||||
|     .STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF, |     .STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF, | ||||||
|     // pmp/pma (inside mmu) signals. 
 |     // pmp/pma (inside mmu) signals. 
 | ||||||
|     .PMPCFG_ARRAY_REGW,  .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrDAPageFaultF);  |     .PMPCFG_ARRAY_REGW,  .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF);  | ||||||
|      |      | ||||||
|   // integer execution unit: integer register file, datapath and controller
 |   // integer execution unit: integer register file, datapath and controller
 | ||||||
|   ieu ieu(.clk, .reset, |   ieu ieu(.clk, .reset, | ||||||
| @ -238,7 +238,7 @@ module wallypipelinedcore ( | |||||||
|     .HPTWInstrAccessFaultM,         // connects to privilege
 |     .HPTWInstrAccessFaultM,         // connects to privilege
 | ||||||
|     .StoreAmoMisalignedFaultM, // connects to privilege
 |     .StoreAmoMisalignedFaultM, // connects to privilege
 | ||||||
|     .StoreAmoAccessFaultM,     // connects to privilege
 |     .StoreAmoAccessFaultM,     // connects to privilege
 | ||||||
|     .InstrDAPageFaultF, |     .InstrUpdateDAF, | ||||||
|     .PCFSpill, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW, |     .PCFSpill, .ITLBMissF, .PTE, .PageType, .ITLBWriteF, .SelHPTW, | ||||||
|     .LSUStallM);                     |     .LSUStallM);                     | ||||||
| 
 | 
 | ||||||
| @ -313,7 +313,7 @@ module wallypipelinedcore ( | |||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   // multiply/divide unit
 |   // multiply/divide unit
 | ||||||
|   if (`M_SUPPORTED) begin:mdu |   if (`M_SUPPORTED | `ZMMUL_SUPPORTED) begin:mdu | ||||||
|     mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW, |     mdu mdu(.clk, .reset, .StallM, .StallW, .FlushE, .FlushM, .FlushW, | ||||||
|       .ForwardedSrcAE, .ForwardedSrcBE,  |       .ForwardedSrcAE, .ForwardedSrcBE,  | ||||||
|       .Funct3E, .Funct3M, .IntDivE, .W64E, |       .Funct3E, .Funct3M, .IntDivE, .W64E, | ||||||
|  | |||||||
| @ -23,40 +23,42 @@ | |||||||
| 
 | 
 | ||||||
| module riscvassertions; | module riscvassertions; | ||||||
|   initial begin |   initial begin | ||||||
|     assert (`PMP_ENTRIES == 0 | `PMP_ENTRIES==16 | `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64"); |     $display("IDIV_ON_FPU = %b M_SUPPORTED %b comb %b\n", `IDIV_ON_FPU, `M_SUPPORTED, ((`IDIV_ON_FPU) || (!`M_SUPPORTED))); | ||||||
|     assert (`S_SUPPORTED | `VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support"); |     assert (`PMP_ENTRIES == 0 || `PMP_ENTRIES==16 || `PMP_ENTRIES==64) else $error("Illegal number of PMP entries: PMP_ENTRIES must be 0, 16, or 64"); | ||||||
|     assert (`IDIV_BITSPERCYCLE == 1 | `IDIV_BITSPERCYCLE==2 | `IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4"); |     assert (`S_SUPPORTED || `VIRTMEM_SUPPORTED == 0) else $error("Virtual memory requires S mode support"); | ||||||
|     assert (`F_SUPPORTED | ~`D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)"); |     assert (`IDIV_BITSPERCYCLE == 1 || `IDIV_BITSPERCYCLE==2 || `IDIV_BITSPERCYCLE==4) else $error("Illegal number of divider bits/cycle: IDIV_BITSPERCYCLE must be 1, 2, or 4"); | ||||||
|     assert (`D_SUPPORTED | ~`Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)"); |     assert (`F_SUPPORTED || ~`D_SUPPORTED) else $error("Can't support double fp (D) without supporting float (F)"); | ||||||
|     assert (`F_SUPPORTED | ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)"); |     assert (`D_SUPPORTED || ~`Q_SUPPORTED) else $error("Can't support quad fp (Q) without supporting double (D)"); | ||||||
|     assert (`DCACHE_SUPPORTED | ~`F_SUPPORTED | `FLEN <= `XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN"); |     assert (`F_SUPPORTED || ~`ZFH_SUPPORTED) else $error("Can't support half-precision fp (ZFH) without supporting float (F)"); | ||||||
|  |     assert (`DCACHE_SUPPORTED || ~`F_SUPPORTED || `FLEN <= `XLEN) else $error("Data cache required to support FLEN > XLEN because AHB bus width is XLEN"); | ||||||
|     assert (`I_SUPPORTED ^ `E_SUPPORTED) else $error("Exactly one of I and E must be supported"); |     assert (`I_SUPPORTED ^ `E_SUPPORTED) else $error("Exactly one of I and E must be supported"); | ||||||
|     assert (`FLEN<=`XLEN | `DCACHE_SUPPORTED | `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported"); |     assert (`FLEN<=`XLEN || `DCACHE_SUPPORTED || `DTIM_SUPPORTED) else $error("Wally does not support FLEN > XLEN unleses data cache or DTIM is supported"); | ||||||
|     assert (`DCACHE_WAYSIZEINBYTES <= 4096 | (!`DCACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); |     assert (`DCACHE_WAYSIZEINBYTES <= 4096 || (!`DCACHE_SUPPORTED) || `VIRTMEM_SUPPORTED == 0) else $error("DCACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); | ||||||
|     assert (`DCACHE_LINELENINBITS >= 128 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); |     assert (`DCACHE_LINELENINBITS >= 128 || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be at least 128 when caches are enabled"); | ||||||
|     assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size"); |     assert (`DCACHE_LINELENINBITS < `DCACHE_WAYSIZEINBYTES*8) else $error("DCACHE_LINELENINBITS must be smaller than way size"); | ||||||
|     assert (`ICACHE_WAYSIZEINBYTES <= 4096 | (!`ICACHE_SUPPORTED) | `VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); |     assert (`ICACHE_WAYSIZEINBYTES <= 4096 || (!`ICACHE_SUPPORTED) || `VIRTMEM_SUPPORTED == 0) else $error("ICACHE_WAYSIZEINBYTES cannot exceed 4 KiB when caches and vitual memory is enabled (to prevent aliasing)"); | ||||||
|     assert (`ICACHE_LINELENINBITS >= 32 | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); |     assert (`ICACHE_LINELENINBITS >= 32 || (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be at least 32 when caches are enabled"); | ||||||
|     assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size"); |     assert (`ICACHE_LINELENINBITS < `ICACHE_WAYSIZEINBYTES*8) else $error("ICACHE_LINELENINBITS must be smaller than way size"); | ||||||
|     assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2"); |     assert (2**$clog2(`DCACHE_LINELENINBITS) == `DCACHE_LINELENINBITS || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must be a power of 2"); | ||||||
|     assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES | (!`DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); |     assert (2**$clog2(`DCACHE_WAYSIZEINBYTES) == `DCACHE_WAYSIZEINBYTES || (!`DCACHE_SUPPORTED)) else $error("DCACHE_WAYSIZEINBYTES must be a power of 2"); | ||||||
|     assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS | (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2"); |     assert (2**$clog2(`ICACHE_LINELENINBITS) == `ICACHE_LINELENINBITS || (!`ICACHE_SUPPORTED)) else $error("ICACHE_LINELENINBITS must be a power of 2"); | ||||||
|     assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES | (!`ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); |     assert (2**$clog2(`ICACHE_WAYSIZEINBYTES) == `ICACHE_WAYSIZEINBYTES || (!`ICACHE_SUPPORTED)) else $error("ICACHE_WAYSIZEINBYTES must be a power of 2"); | ||||||
|     assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2"); |     assert (2**$clog2(`ITLB_ENTRIES) == `ITLB_ENTRIES || `VIRTMEM_SUPPORTED==0) else $error("ITLB_ENTRIES must be a power of 2"); | ||||||
|     assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES | `VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2"); |     assert (2**$clog2(`DTLB_ENTRIES) == `DTLB_ENTRIES || `VIRTMEM_SUPPORTED==0) else $error("DTLB_ENTRIES must be a power of 2"); | ||||||
|     assert (`UNCORE_RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 56'h07FFFFFF"); |     assert (`UNCORE_RAM_RANGE >= 56'h07FFFFFF) else $warning("Some regression tests will fail if UNCORE_RAM_RANGE is less than 56'h07FFFFFF"); | ||||||
| 	  assert (`ZICSR_SUPPORTED == 1 | (`PMP_ENTRIES == 0 & `VIRTMEM_SUPPORTED == 0)) else $error("PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported."); | 	  assert (`ZICSR_SUPPORTED == 1 || (`PMP_ENTRIES == 0 && `VIRTMEM_SUPPORTED == 0)) else $error("PMP_ENTRIES and VIRTMEM_SUPPORTED must be zero if ZICSR not supported."); | ||||||
|     assert (`ZICSR_SUPPORTED == 1 | (`S_SUPPORTED == 0 & `U_SUPPORTED == 0)) else $error("S and U modes not supported if ZICSR not supported"); |     assert (`ZICSR_SUPPORTED == 1 || (`S_SUPPORTED == 0 && `U_SUPPORTED == 0)) else $error("S and U modes not supported if ZICSR not supported"); | ||||||
|     assert (`U_SUPPORTED | (`S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported"); |     assert (`U_SUPPORTED || (`S_SUPPORTED == 0)) else $error ("S mode only supported if U also is supported"); | ||||||
|     assert (`VIRTMEM_SUPPORTED == 0 | (`DTIM_SUPPORTED == 0 & `IROM_SUPPORTED == 0)) else $error("Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses"); |     assert (`VIRTMEM_SUPPORTED == 0 || (`DTIM_SUPPORTED == 0 && `IROM_SUPPORTED == 0)) else $error("Can't simultaneously have virtual memory and DTIM_SUPPORTED/IROM_SUPPORTED because local memories don't translate addresses"); | ||||||
|     assert (`DCACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache"); |     assert (`DCACHE_SUPPORTED || `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs dcache"); | ||||||
|     assert (`ICACHE_SUPPORTED | `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache"); |     assert (`ICACHE_SUPPORTED || `VIRTMEM_SUPPORTED ==0) else $error("Virtual memory needs icache"); | ||||||
|     assert ((`DCACHE_SUPPORTED == 0 & `ICACHE_SUPPORTED == 0) | `BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS_SUPPORTED."); |     assert ((`DCACHE_SUPPORTED == 0 && `ICACHE_SUPPORTED == 0) || `BUS_SUPPORTED) else $error("Dcache and Icache requires DBUS_SUPPORTED."); | ||||||
|     assert (`DCACHE_LINELENINBITS <= `XLEN*16 | (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1"); |     assert (`DCACHE_LINELENINBITS <= `XLEN*16 || (!`DCACHE_SUPPORTED)) else $error("DCACHE_LINELENINBITS must not exceed 16 words because max AHB burst size is 1"); | ||||||
|     assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); |     assert (`DCACHE_LINELENINBITS % 4 == 0) else $error("DCACHE_LINELENINBITS must hold 4, 8, or 16 words"); | ||||||
|     assert (`DCACHE_SUPPORTED | `A_SUPPORTED == 0) else $error("Atomic extension (A) requires cache on Wally."); |     assert (`DCACHE_SUPPORTED || (`A_SUPPORTED == 0)) else $error("Atomic extension (A) requires cache on Wally."); | ||||||
|     assert (`IDIV_ON_FPU == 0 | `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED"); |     assert (`IDIV_ON_FPU == 0 || `F_SUPPORTED) else $error("IDIV on FPU needs F_SUPPORTED"); | ||||||
|     assert (`SSTC_SUPPORTED == 0 | (`S_SUPPORTED)) else $error("SSTC requires S_SUPPORTED"); |     assert (`SSTC_SUPPORTED == 0 || (`S_SUPPORTED)) else $error("SSTC requires S_SUPPORTED"); | ||||||
|  |     assert ((`ZMMUL_SUPPORTED == 0) || (`M_SUPPORTED ==0)) else $error("At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled"); | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user