diff --git a/wally-pipelined/regression/wally-pipelined.do b/wally-pipelined/regression/wally-pipelined.do index 51335b82e..500e1fe61 100644 --- a/wally-pipelined/regression/wally-pipelined.do +++ b/wally-pipelined/regression/wally-pipelined.do @@ -40,7 +40,7 @@ vsim workopt view wave -- display input and output signals as hexidecimal values -do ./wave-dos/default-waves.do +do ./wave-dos/peripheral-waves.do -- Run the Simulation #run 5000 diff --git a/wally-pipelined/regression/wave-dos/peripheral-waves.do b/wally-pipelined/regression/wave-dos/peripheral-waves.do index f92c1af55..3c4945c7d 100644 --- a/wally-pipelined/regression/wave-dos/peripheral-waves.do +++ b/wally-pipelined/regression/wave-dos/peripheral-waves.do @@ -48,6 +48,11 @@ add wave /testbench/dut/hart/ieu/dp/RegWriteW add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/RdW add wave -divider +add wave -hex /testbench/dut/hart/priv/csr/ProposedEPCM +add wave -hex /testbench/dut/hart/priv/csr/TrapM +add wave -hex /testbench/dut/hart/priv/csr/UnalignedNextEPCM +add wave -hex /testbench/dut/hart/priv/csr/genblk1/csrm/WriteMEPCM +add wave -hex /testbench/dut/hart/priv/csr/genblk1/csrm/MEPC_REGW add wave -divider # peripherals diff --git a/wally-pipelined/src/hazard/hazard.sv b/wally-pipelined/src/hazard/hazard.sv index 35aa98358..72857fb34 100644 --- a/wally-pipelined/src/hazard/hazard.sv +++ b/wally-pipelined/src/hazard/hazard.sv @@ -30,16 +30,15 @@ module hazard( input logic reset, // Detect hazards input logic BPPredWrongE, CSRWritePendingDEM, RetM, TrapM, - input logic FPUStallD, LoadStallD, MulDivStallD, CSRRdStallD, + input logic LoadStallD, MulDivStallD, CSRRdStallD, input logic DataStall, ICacheStallF, - input logic FStallD, + input logic FPUStallD, input logic DivBusyE, // Stall & flush outputs output logic StallF, StallD, StallE, StallM, StallW, output logic FlushF, FlushD, FlushE, FlushM, FlushW ); - logic BranchFlushDE; logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; logic FirstUnstalledD, FirstUnstalledE, FirstUnstalledM, FirstUnstalledW; @@ -56,34 +55,29 @@ module hazard( // A stage must stall if the next stage is stalled // If any stages are stalled, the first stage that isn't stalled must flush. - assign BranchFlushDE = BPPredWrongE | RetM | TrapM; - - assign StallFCause = CSRWritePendingDEM & ~(BranchFlushDE); - assign StallDCause = (FPUStallD | LoadStallD | MulDivStallD | CSRRdStallD | FStallD) & ~(BranchFlushDE); // stall in decode if instruction is a load/mul/csr dependent on previous -// assign StallDCause = LoadStallD | MulDivStallD | CSRRdStallD; // stall in decode if instruction is a load/mul/csr dependent on previous + assign StallFCause = CSRWritePendingDEM && ~(TrapM || RetM || BPPredWrongE); + assign StallDCause = (LoadStallD || MulDivStallD || CSRRdStallD || FPUStallD) && ~(TrapM || RetM || BPPredWrongE); // stall in decode if instruction is a load/mul/csr dependent on previous assign StallECause = DivBusyE; assign StallMCause = 0; - assign StallWCause = DataStall | ICacheStallF; + assign StallWCause = DataStall || ICacheStallF; - // Each stage stalls if the next stage is stalled or there is a cause to stall this stage. - assign StallF = StallD | StallFCause; - - assign StallD = StallE | StallDCause; - assign StallE = StallM | StallECause; - assign StallM = StallW | StallMCause; + assign StallF = StallFCause || StallD; + assign StallD = StallDCause || StallE; + assign StallE = StallECause || StallM; + assign StallM = StallMCause || StallW; assign StallW = StallWCause; //assign FirstUnstalledD = (~StallD & StallF & ~MulDivStallD); - assign FirstUnstalledD = (~StallD & StallF); //assign FirstUnstalledE = (~StallE & StallD & ~MulDivStallD); - assign FirstUnstalledE = (~StallE & StallD); - assign FirstUnstalledM = (~StallM & StallE); - assign FirstUnstalledW = (~StallW & StallM);; + assign FirstUnstalledD = (~StallD && StallF); + assign FirstUnstalledE = (~StallE && StallD); + assign FirstUnstalledM = (~StallM && StallE); + assign FirstUnstalledW = (~StallW && StallM); // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush assign FlushF = BPPredWrongE; - assign FlushD = FirstUnstalledD || BranchFlushDE; // PCSrcE |InstrStall | CSRWritePendingDEM | RetM | TrapM; - assign FlushE = FirstUnstalledE || BranchFlushDE; // LoadStallD | PCSrcE | RetM | TrapM; - assign FlushM = FirstUnstalledM || RetM || TrapM; - assign FlushW = FirstUnstalledW | TrapM; + assign FlushD = FirstUnstalledD || TrapM || RetM || BPPredWrongE; + assign FlushE = FirstUnstalledE || TrapM || RetM || BPPredWrongE; + assign FlushM = FirstUnstalledM || TrapM || RetM; + assign FlushW = FirstUnstalledW || TrapM; endmodule diff --git a/wally-pipelined/src/ifu/ifu.sv b/wally-pipelined/src/ifu/ifu.sv index 994288bd8..28f7597e3 100644 --- a/wally-pipelined/src/ifu/ifu.sv +++ b/wally-pipelined/src/ifu/ifu.sv @@ -37,7 +37,8 @@ module ifu ( output logic [`XLEN-1:0] InstrPAdrF, output logic InstrReadF, output logic ICacheStallF, - // Decode + // Decode + output logic [`XLEN-1:0] PCD, // Execute output logic [`XLEN-1:0] PCLinkE, input logic PCSrcE, @@ -47,7 +48,7 @@ module ifu ( // Mem input logic RetM, TrapM, input logic [`XLEN-1:0] PrivilegedNextPCM, - output logic [31:0] InstrD, InstrM, + output logic [31:0] InstrD, InstrE, InstrM, InstrW, output logic [`XLEN-1:0] PCM, output logic [4:0] InstrClassM, output logic BPPredDirWrongM, @@ -76,9 +77,9 @@ module ifu ( logic misaligned, BranchMisalignedFaultE, BranchMisalignedFaultM, TrapMisalignedFaultM; logic PrivilegedChangePCM; logic IllegalCompInstrD; - logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCD, PCW, PCLinkD, PCLinkM, PCNextPF, PCPF; + logic [`XLEN-1:0] PCPlusUpperF, PCPlus2or4F, PCW, PCLinkD, PCLinkM, PCNextPF, PCPF; logic CompressedF; - logic [31:0] InstrRawD, InstrE, InstrW; + logic [31:0] InstrRawD; localparam [31:0] nop = 32'h00000013; // instruction for NOP logic reset_q; // *** look at this later. diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 744b8f9bf..89d71fb5b 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -34,8 +34,8 @@ module csr #(parameter ) ( input logic clk, reset, input logic FlushW, StallD, StallE, StallM, StallW, - input logic [31:0] InstrM, - input logic [`XLEN-1:0] PCM, SrcAM, + input logic [31:0] InstrD,InstrE,InstrM, + input logic [`XLEN-1:0] PCF, PCD, PCE, PCM, SrcAM, input logic InterruptM, input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, input logic TimerIntM, ExtIntM, SwIntM, @@ -47,6 +47,9 @@ module csr #(parameter input logic [4:0] InstrClassM, input logic [1:0] NextPrivilegeModeM, PrivilegeModeW, input logic [`XLEN-1:0] CauseM, NextFaultMtvalM, + input logic BreakpointFaultM, EcallFaultM, + input logic InstrMisalignedFaultM, InstrAccessFaultM, IllegalInstrFaultM, + input logic LoadMisalignedFaultM, StoreMisalignedFaultM, LoadAccessFaultM, StoreAccessFaultM, output logic [1:0] STATUS_MPP, output logic STATUS_SPP, STATUS_TSR, output logic [`XLEN-1:0] MEPC_REGW, SEPC_REGW, UEPC_REGW, UTVEC_REGW, STVEC_REGW, MTVEC_REGW, @@ -65,6 +68,7 @@ module csr #(parameter output logic IllegalCSRAccessM ); + localparam NOP = 32'h13; logic [`XLEN-1:0] CSRMReadValM, CSRSReadValM, CSRUReadValM, CSRNReadValM, CSRCReadValM, CSRReadValM; logic [`XLEN-1:0] CSRSrcM, CSRRWM, CSRRSM, CSRRCM, CSRWriteValM; @@ -73,22 +77,32 @@ module csr #(parameter logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM; - logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, preservedPCM, readPCM, NextCauseM, NextMtvalM; - - always_ff @(posedge clk) begin - preservedPCM <= PCM; - end - - mux2 #(`XLEN) pcmux(PCM, preservedPCM, InterruptM, readPCM); - //flop #(`XLEN) CSRReadPCMreg(clk, reset, PCM, readPCM); + logic MStageFailed; + logic [`XLEN-1:0] ProposedEPCM, UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM; logic [11:0] CSRAdrM; logic [11:0] SIP_REGW, SIE_REGW; //logic [11:0] UIP_REGW, UIE_REGW = 0; // N user-mode exceptions not supported logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM, IllegalCSRNAccessM, InsufficientCSRPrivilegeM; - logic IllegalCSRMWriteReadonlyM; + assign MStageFailed = BreakpointFaultM || EcallFaultM || InstrMisalignedFaultM || InstrAccessFaultM || IllegalInstrFaultM || LoadMisalignedFaultM || StoreMisalignedFaultM || LoadAccessFaultM || StoreAccessFaultM; + always_comb begin + if (MStageFailed) + casez({InstrD==NOP,InstrE==NOP,InstrM==NOP}) + 3'b??0: ProposedEPCM = PCM; + 3'b?01: ProposedEPCM = PCE; + 3'b011: ProposedEPCM = PCD; + 3'b111: ProposedEPCM = PCF; + endcase + else + casez({InstrD==NOP,InstrE==NOP}) + 2'b?0: ProposedEPCM = PCE; + 2'b01: ProposedEPCM = PCD; + 2'b11: ProposedEPCM = PCF; + endcase + end + generate if (`ZCSR_SUPPORTED) begin // modify CSRs @@ -109,7 +123,7 @@ module csr #(parameter // write CSRs assign CSRAdrM = InstrM[31:20]; - assign UnalignedNextEPCM = TrapM ? readPCM : CSRWriteValM; + assign UnalignedNextEPCM = TrapM ? ProposedEPCM : CSRWriteValM; assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment assign NextCauseM = TrapM ? CauseM : CSRWriteValM; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; diff --git a/wally-pipelined/src/privileged/csrsr.sv b/wally-pipelined/src/privileged/csrsr.sv index 8c5c7a3d1..0b36df491 100644 --- a/wally-pipelined/src/privileged/csrsr.sv +++ b/wally-pipelined/src/privileged/csrsr.sv @@ -109,74 +109,74 @@ module csrsr ( // complex register with reset, write enable, and the ability to update other bits in certain cases always_ff @(posedge clk, posedge reset) if (reset) begin - STATUS_SUM_INT <= 0; - STATUS_MPRV_INT <= 0; // Per Priv 3.3 - STATUS_FS_INT <= 0; //2'b01; // busybear: change all these reset values to 0 - STATUS_MPP <= 0; //`M_MODE; - STATUS_SPP <= 0; //1'b1; - STATUS_MPIE <= 0; //1; - STATUS_SPIE <= 0; //`S_SUPPORTED; - STATUS_UPIE <= 0; // `U_SUPPORTED; - STATUS_MIE <= 0; // Per Priv 3.3 - STATUS_SIE <= 0; //`S_SUPPORTED; - STATUS_UIE <= 0; //`U_SUPPORTED; + STATUS_SUM_INT <= #1 0; + STATUS_MPRV_INT <= #1 0; // Per Priv 3.3 + STATUS_FS_INT <= #1 0; //2'b01; // busybear: change all these reset values to 0 + STATUS_MPP <= #1 0; //`M_MODE; + STATUS_SPP <= #1 0; //1'b1; + STATUS_MPIE <= #1 0; //1; + STATUS_SPIE <= #1 0; //`S_SUPPORTED; + STATUS_UPIE <= #1 0; // `U_SUPPORTED; + STATUS_MIE <= #1 0; // Per Priv 3.3 + STATUS_SIE <= #1 0; //`S_SUPPORTED; + STATUS_UIE <= #1 0; //`U_SUPPORTED; end else if (~StallW) begin if (WriteMSTATUSM) begin - STATUS_SUM_INT <= CSRWriteValM[18]; - STATUS_MPRV_INT <= CSRWriteValM[17]; - STATUS_FS_INT <= CSRWriteValM[14:13]; - STATUS_MPP <= STATUS_MPP_NEXT; - STATUS_SPP <= `S_SUPPORTED & CSRWriteValM[8]; - STATUS_MPIE <= CSRWriteValM[7]; - STATUS_SPIE <= `S_SUPPORTED & CSRWriteValM[5]; - STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4]; - STATUS_MIE <= CSRWriteValM[3]; - STATUS_SIE <= `S_SUPPORTED & CSRWriteValM[1]; - STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0]; + STATUS_SUM_INT <= #1 CSRWriteValM[18]; + STATUS_MPRV_INT <= #1 CSRWriteValM[17]; + STATUS_FS_INT <= #1 CSRWriteValM[14:13]; + STATUS_MPP <= #1 STATUS_MPP_NEXT; + STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8]; + STATUS_MPIE <= #1 CSRWriteValM[7]; + STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; + STATUS_UPIE <= #1 `U_SUPPORTED & CSRWriteValM[4]; + STATUS_MIE <= #1 CSRWriteValM[3]; + STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; + STATUS_UIE <= #1 `U_SUPPORTED & CSRWriteValM[0]; end else if (WriteSSTATUSM) begin // write a subset of the STATUS bits - STATUS_SUM_INT <= CSRWriteValM[18]; - STATUS_FS_INT <= CSRWriteValM[14:13]; - STATUS_SPP <= `S_SUPPORTED & CSRWriteValM[8]; - STATUS_SPIE <= `S_SUPPORTED & CSRWriteValM[5]; - STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4]; - STATUS_SIE <= `S_SUPPORTED & CSRWriteValM[1]; - STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0]; + STATUS_SUM_INT <= #1 CSRWriteValM[18]; + STATUS_FS_INT <= #1 CSRWriteValM[14:13]; + STATUS_SPP <= #1 `S_SUPPORTED & CSRWriteValM[8]; + STATUS_SPIE <= #1 `S_SUPPORTED & CSRWriteValM[5]; + STATUS_UPIE <= #1 `U_SUPPORTED & CSRWriteValM[4]; + STATUS_SIE <= #1 `S_SUPPORTED & CSRWriteValM[1]; + STATUS_UIE <= #1 `U_SUPPORTED & CSRWriteValM[0]; end else if (WriteUSTATUSM) begin // write a subset of the STATUS bits - STATUS_FS_INT <= CSRWriteValM[14:13]; - STATUS_UPIE <= `U_SUPPORTED & CSRWriteValM[4]; - STATUS_UIE <= `U_SUPPORTED & CSRWriteValM[0]; + STATUS_FS_INT <= #1 CSRWriteValM[14:13]; + STATUS_UPIE <= #1 `U_SUPPORTED & CSRWriteValM[4]; + STATUS_UIE <= #1 `U_SUPPORTED & CSRWriteValM[0]; end else begin - if (FloatRegWriteW) STATUS_FS_INT <=2'b11; // mark Float State dirty + if (FloatRegWriteW) STATUS_FS_INT <= #12'b11; // mark Float State dirty if (TrapM) begin // Update interrupt enables per Privileged Spec p. 21 // y = PrivilegeModeW // x = NextPrivilegeModeM // Modes: 11 = Machine, 01 = Supervisor, 00 = User if (NextPrivilegeModeM == `M_MODE) begin - STATUS_MPIE <= STATUS_MIE; - STATUS_MIE <= 0; - STATUS_MPP <= PrivilegeModeW; + STATUS_MPIE <= #1 STATUS_MIE; + STATUS_MIE <= #1 0; + STATUS_MPP <= #1 PrivilegeModeW; end else if (NextPrivilegeModeM == `S_MODE) begin - STATUS_SPIE <= STATUS_SIE; - STATUS_SIE <= 0; - STATUS_SPP <= PrivilegeModeW[0]; // *** seems to disagree with P. 56 + STATUS_SPIE <= #1 STATUS_SIE; + STATUS_SIE <= #1 0; + STATUS_SPP <= #1 PrivilegeModeW[0]; // *** seems to disagree with P. 56 end else begin // user mode - STATUS_UPIE <= STATUS_UIE; - STATUS_UIE <= 0; + STATUS_UPIE <= #1 STATUS_UIE; + STATUS_UIE <= #1 0; end end else if (mretM) begin // Privileged 3.1.6.1 - STATUS_MIE <= STATUS_MPIE; - STATUS_MPIE <= 1; - STATUS_MPP <= `U_SUPPORTED ? `U_MODE : `M_MODE; // per spec, not sure why - STATUS_MPRV_INT <= 0; // per 20210108 draft spec + STATUS_MIE <= #1 STATUS_MPIE; + STATUS_MPIE <= #1 1; + STATUS_MPP <= #1 `U_SUPPORTED ? `U_MODE : `M_MODE; // per spec, not sure why + STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec end else if (sretM) begin - STATUS_SIE <= STATUS_SPIE; - STATUS_SPIE <= `S_SUPPORTED; - STATUS_SPP <= 0; // Privileged 4.1.1 - STATUS_MPRV_INT <= 0; // per 20210108 draft spec + STATUS_SIE <= #1 STATUS_SPIE; + STATUS_SPIE <= #1 `S_SUPPORTED; + STATUS_SPP <= #1 0; // Privileged 4.1.1 + STATUS_MPRV_INT <= #1 0; // per 20210108 draft spec end else if (uretM) begin - STATUS_UIE <= STATUS_UPIE; - STATUS_UPIE <= `U_SUPPORTED; + STATUS_UIE <= #1 STATUS_UPIE; + STATUS_UPIE <= #1 `U_SUPPORTED; end // *** add code to track STATUS_FS_INT for dirty floating point registers end diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 2e3af3e2c..41d685c41 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -31,8 +31,8 @@ module privileged ( input logic FlushW, input logic CSRReadM, CSRWriteM, input logic [`XLEN-1:0] SrcAM, - input logic [31:0] InstrM, - input logic [`XLEN-1:0] PCM, + input logic [`XLEN-1:0] PCF,PCD,PCE,PCM, + input logic [31:0] InstrD, InstrE, InstrM, InstrW, output logic [`XLEN-1:0] CSRReadValW, output logic [`XLEN-1:0] PrivilegedNextPCM, output logic RetM, TrapM, diff --git a/wally-pipelined/src/wally/wallypipelinedhart.sv b/wally-pipelined/src/wally/wallypipelinedhart.sv index e49cc6c62..00ae84933 100644 --- a/wally-pipelined/src/wally/wallypipelinedhart.sv +++ b/wally-pipelined/src/wally/wallypipelinedhart.sv @@ -68,8 +68,8 @@ module wallypipelinedhart ( logic [`XLEN-1:0] SrcAM; logic [2:0] Funct3E; // logic [31:0] InstrF; - logic [31:0] InstrD, InstrM; - logic [`XLEN-1:0] PCE, PCM, PCLinkE, PCLinkW; + logic [31:0] InstrD, InstrE, InstrM, InstrW; + logic [`XLEN-1:0] PCD, PCE, PCM, PCLinkE, PCLinkW; logic [`XLEN-1:0] PCTargetE; logic [`XLEN-1:0] CSRReadValW, MulDivResultW; logic [`XLEN-1:0] PrivilegedNextPCM; diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index c5abff91d..ea6939004 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -29,6 +29,7 @@ module testbench(); parameter DEBUG = 0; parameter TESTSPERIPH = 0; // set to 0 for regression + parameter TESTSPRIV = 0; // set to 0 for regression logic clk; logic reset; @@ -516,9 +517,11 @@ string tests32f[] = '{ tests = testsBP64; // testsbp should not run the other tests. It starts at address 0 rather than // 0x8000_0000, the next if must remain an else if. - end else if (TESTSPERIPH) begin + end else if (TESTSPERIPH) tests = tests64periph; - end else begin + else if (TESTSPRIV) + tests = tests64p; + else begin tests = {tests64p,tests64i,tests64periph}; if (`C_SUPPORTED) tests = {tests, tests64ic}; else tests = {tests, tests64iNOc}; @@ -531,9 +534,11 @@ string tests32f[] = '{ //tests = {tests64a, tests}; end else begin // RV32 // *** add the 32 bit bp tests - if (TESTSPERIPH) begin + if (TESTSPERIPH) tests = tests32periph; - end else begin + else if (TESTSPRIV) + tests = tests32p; + else begin tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment if (`C_SUPPORTED % 2 == 1) tests = {tests, tests32ic}; else tests = {tests, tests32iNOc};