Merge pull request #117 from davidharrishmc/dev

ZMMUL support and MMU cleanup
This commit is contained in:
Ross Thompson 2023-02-27 09:46:40 -06:00 committed by GitHub
commit 1f10092f8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 107 additions and 89 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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