mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
This version passes the regression test and solves issue #200. wfi's implemenation is changed so that wfi does not take an interrupt in the Memory stage. Instead it advances to the Writeback stage then traps.
This commit is contained in:
parent
bc877e9ca7
commit
e4aebbaaa5
@ -50,8 +50,8 @@ module hazard (
|
|||||||
|
|
||||||
// WFI logic
|
// WFI logic
|
||||||
flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW);
|
flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW);
|
||||||
assign WFIStallM = wfiW & ~IntPendingM; // WFI waiting for an interrupt or timeout
|
assign WFIStallM = wfiM & ~IntPendingM; // WFI waiting for an interrupt or timeout
|
||||||
assign WFIInterruptedM = wfiW & IntPendingM; // WFI detects a pending interrupt. Retire WFI; trap if interrupt is enabled.
|
assign WFIInterruptedM = wfiM & IntPendingM; // WFI detects a pending interrupt. Retire WFI; trap if interrupt is enabled.
|
||||||
|
|
||||||
// stalls and flushes
|
// stalls and flushes
|
||||||
// loads: stall for one cycle if the subsequent instruction depends on the load
|
// loads: stall for one cycle if the subsequent instruction depends on the load
|
||||||
@ -76,8 +76,8 @@ module hazard (
|
|||||||
assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE;
|
assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE;
|
||||||
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
||||||
assign FlushMCause = TrapM | RetM | CSRWriteFenceM;
|
assign FlushMCause = TrapM | RetM | CSRWriteFenceM;
|
||||||
//assign FlushWCause = TrapM & ~WFIInterruptedM;
|
assign FlushWCause = TrapM & ~WFIInterruptedM;
|
||||||
assign FlushWCause = TrapM;
|
//assign FlushWCause = TrapM;
|
||||||
|
|
||||||
// Stall causes
|
// Stall causes
|
||||||
// Most data depenency stalls are identified in the decode stage
|
// Most data depenency stalls are identified in the decode stage
|
||||||
@ -90,13 +90,13 @@ module hazard (
|
|||||||
assign StallFCause = '0;
|
assign StallFCause = '0;
|
||||||
assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | FPUStallD) & ~FlushDCause;
|
assign StallDCause = (LoadStallD | StoreStallD | MDUStallD | CSRRdStallD | FCvtIntStallD | FPUStallD) & ~FlushDCause;
|
||||||
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
|
assign StallECause = (DivBusyE | FDivBusyE) & ~FlushECause;
|
||||||
//assign StallMCause = WFIStallM & ~FlushMCause;
|
assign StallMCause = WFIStallM & ~FlushMCause;
|
||||||
assign StallMCause = '0;
|
//assign StallMCause = '0;
|
||||||
// Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1.
|
// Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1.
|
||||||
// assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause;
|
// assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause;
|
||||||
// Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out.
|
// Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out.
|
||||||
//assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause);
|
assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause);
|
||||||
assign StallWCause = (IFUStallF & ~FlushDCause) | ((LSUStallM | WFIStallM) & ~FlushWCause);
|
//assign StallWCause = (IFUStallF & ~FlushDCause) | ((LSUStallM | WFIStallM) & ~FlushWCause);
|
||||||
|
|
||||||
// Stall each stage for cause or if the next stage is stalled
|
// Stall each stage for cause or if the next stage is stalled
|
||||||
// coverage off: StallFCause is always 0
|
// coverage off: StallFCause is always 0
|
||||||
|
@ -39,6 +39,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic CSRReadM, CSRWriteM, // read or write CSR
|
input logic CSRReadM, CSRWriteM, // read or write CSR
|
||||||
input logic TrapM, // trap is occurring
|
input logic TrapM, // trap is occurring
|
||||||
input logic mretM, sretM, wfiM, // return or WFI instruction
|
input logic mretM, sretM, wfiM, // return or WFI instruction
|
||||||
|
output logic wfiW,
|
||||||
input logic IntPendingM, // at least one interrupt is pending and could occur if enabled
|
input logic IntPendingM, // at least one interrupt is pending and could occur if enabled
|
||||||
input logic InterruptM, // interrupt is occurring
|
input logic InterruptM, // interrupt is occurring
|
||||||
input logic ExceptionM, // interrupt is occurring
|
input logic ExceptionM, // interrupt is occurring
|
||||||
@ -200,13 +201,10 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// CSR Write values
|
// CSR Write values
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
logic [P.XLEN-1:0] PCW; // *** can optimize out it's just PCM for all now.
|
|
||||||
logic wfiW;
|
|
||||||
flopenr #(P.XLEN) PCWReg(clk, reset, ~StallW, PCM, PCW);
|
|
||||||
flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW);
|
flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW);
|
||||||
|
|
||||||
assign CSRAdrM = InstrM[31:20];
|
assign CSRAdrM = InstrM[31:20];
|
||||||
assign UnalignedNextEPCM = TrapM ? ((wfiW & IntPendingM) ? PCW+4 : PCM) : CSRWriteValM;
|
assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM;
|
||||||
assign NextEPCM = P.C_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment
|
assign NextEPCM = P.C_SUPPORTED ? {UnalignedNextEPCM[P.XLEN-1:1], 1'b0} : {UnalignedNextEPCM[P.XLEN-1:2], 2'b00}; // 3.1.15 alignment
|
||||||
assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]};
|
assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[P.XLEN-1], CSRWriteValM[3:0]};
|
||||||
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
|
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
module privdec import cvw::*; #(parameter cvw_t P) (
|
module privdec import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic StallM,
|
input logic StallM, StallW, FlushW,
|
||||||
input logic [31:15] InstrM, // privileged instruction function field
|
input logic [31:15] InstrM, // privileged instruction function field
|
||||||
input logic PrivilegedM, // is this a privileged instruction (from IEU controller)
|
input logic PrivilegedM, // is this a privileged instruction (from IEU controller)
|
||||||
input logic IllegalIEUFPUInstrM, // Not a legal IEU instruction
|
input logic IllegalIEUFPUInstrM, // Not a legal IEU instruction
|
||||||
@ -75,6 +75,8 @@ module privdec import cvw::*; #(parameter cvw_t P) (
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// WFI timeout Privileged Spec 3.1.6.5
|
// WFI timeout Privileged Spec 3.1.6.5
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
logic wfiW; // *** need to merge with others
|
||||||
|
flopenrc #(1) wfiWReg(clk, reset, FlushW, ~StallW, wfiM, wfiW); // *** remove
|
||||||
|
|
||||||
if (P.U_SUPPORTED) begin:wfi
|
if (P.U_SUPPORTED) begin:wfi
|
||||||
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
|
logic [P.WFI_TIMEOUT_BIT:0] WFICount, WFICountPlus1;
|
||||||
|
@ -115,12 +115,14 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic ExceptionM; // Memory stage instruction caused a fault
|
logic ExceptionM; // Memory stage instruction caused a fault
|
||||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||||
|
|
||||||
|
logic wfiW;
|
||||||
|
|
||||||
// track the current privilege level
|
// track the current privilege level
|
||||||
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
privmode #(P) privmode(.clk, .reset, .StallW, .TrapM, .mretM, .sretM, .DelegateM,
|
||||||
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
.STATUS_MPP, .STATUS_SPP, .NextPrivilegeModeM, .PrivilegeModeW);
|
||||||
|
|
||||||
// decode privileged instructions
|
// decode privileged instructions
|
||||||
privdec #(P) pmd(.clk, .reset, .StallM, .InstrM(InstrM[31:15]),
|
privdec #(P) pmd(.clk, .reset, .StallM, .StallW, .FlushW, .InstrM(InstrM[31:15]),
|
||||||
.PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM,
|
.PrivilegedM, .IllegalIEUFPUInstrM, .IllegalCSRAccessM,
|
||||||
.PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM,
|
.PrivilegeModeW, .STATUS_TSR, .STATUS_TVM, .STATUS_TW, .IllegalInstrFaultM,
|
||||||
.EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .wfiM, .sfencevmaM);
|
.EcallFaultM, .BreakpointFaultM, .sretM, .mretM, .wfiM, .sfencevmaM);
|
||||||
@ -128,7 +130,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Control and Status Registers
|
// Control and Status Registers
|
||||||
csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW,
|
csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW,
|
||||||
.InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF,
|
.InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrM, .PC2NextF,
|
||||||
.CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .IntPendingM, .InterruptM,
|
.CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .wfiM, .wfiW, .IntPendingM, .InterruptM,
|
||||||
.MTimerInt, .MExtInt, .SExtInt, .MSwInt,
|
.MTimerInt, .MExtInt, .SExtInt, .MSwInt,
|
||||||
.MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD,
|
.MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD,
|
||||||
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .BPWrongM,
|
.BPDirPredWrongM, .BTAWrongM, .RASPredPCWrongM, .BPWrongM,
|
||||||
@ -156,5 +158,5 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
.mretM, .sretM, .PrivilegeModeW,
|
.mretM, .sretM, .PrivilegeModeW,
|
||||||
.MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE,
|
.MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE,
|
||||||
.InstrValidM, .CommittedM, .CommittedF,
|
.InstrValidM, .CommittedM, .CommittedF,
|
||||||
.TrapM, .RetM, .wfiM, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
.TrapM, .RetM, .wfiM, .wfiW, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -33,7 +33,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM,
|
input logic LoadAccessFaultM, StoreAmoAccessFaultM, EcallFaultM, InstrPageFaultM,
|
||||||
input logic LoadPageFaultM, StoreAmoPageFaultM, // various trap sources
|
input logic LoadPageFaultM, StoreAmoPageFaultM, // various trap sources
|
||||||
input logic mretM, sretM, // return instructions
|
input logic mretM, sretM, // return instructions
|
||||||
input logic wfiM, // wait for interrupt instruction
|
input logic wfiM, wfiW, // wait for interrupt instruction
|
||||||
input logic [1:0] PrivilegeModeW, // current privilege mode
|
input logic [1:0] PrivilegeModeW, // current privilege mode
|
||||||
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs
|
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs
|
||||||
input logic [15:0] MEDELEG_REGW, // exception delegation SR
|
input logic [15:0] MEDELEG_REGW, // exception delegation SR
|
||||||
@ -68,7 +68,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign Committed = CommittedM | CommittedF;
|
assign Committed = CommittedM | CommittedF;
|
||||||
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
|
||||||
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
|
||||||
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
|
assign InterruptM = (|ValidIntsM) & InstrValidM & (~wfiM | wfiW); // suppress interrupt if the memory system has partially processed a request.
|
||||||
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
assign DelegateM = P.S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
|
||||||
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
(PrivilegeModeW == P.U_MODE | PrivilegeModeW == P.S_MODE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user