mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Block traps in debug mode
This commit is contained in:
parent
372904c6d9
commit
bf4bdd46af
@ -23,7 +23,7 @@
|
||||
`define OP_FAILED 2'b10
|
||||
`define OP_BUSY 2'b11
|
||||
|
||||
// DMI register Address Width
|
||||
// DMI Bus Address Width
|
||||
`define DMI_ADDR_WIDTH 7
|
||||
|
||||
// Debug Module Debug Bus Register Addresses
|
||||
|
@ -43,22 +43,21 @@ module dmc (
|
||||
input logic AckHaveReset, // Clears HaveReset status
|
||||
input logic ExecProgBuf, // Updates PC to progbuf and resumes core
|
||||
|
||||
output logic DebugMode,
|
||||
output logic DebugMode, // Sets state in DM and controls masking of interrupts
|
||||
output logic [2:0] DebugCause, // Reason Hart entered debug mode
|
||||
output logic ResumeAck, // Signals Hart has been resumed
|
||||
output logic HaveReset, // Signals Hart has been reset
|
||||
output logic DebugStall, // Stall signal goes to hazard unit
|
||||
|
||||
output logic EnterDebugMode, // Store PCNextF in DPC when entering Debug Mode
|
||||
output logic ExitDebugMode, // Updates PCNextF with the current value of DPC
|
||||
output logic DCall, // Store PCNextF in DPC when entering Debug Mode
|
||||
output logic DRet, // Updates PCNextF with the current value of DPC
|
||||
output logic ForceBreakPoint // Causes artificial ebreak that puts core in debug mode
|
||||
);
|
||||
`include "debug.vh"
|
||||
|
||||
enum logic [1:0] {RUNNING, EXECPROGBUF, HALTED, STEP} State;
|
||||
|
||||
enum logic [1:0] {RUNNING, HALTED, STEP} State;
|
||||
|
||||
localparam E2M_CYCLE_COUNT = 3;
|
||||
localparam E2M_CYCLE_COUNT = 4;
|
||||
logic [$clog2(E2M_CYCLE_COUNT+1)-1:0] Counter;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
@ -73,8 +72,8 @@ module dmc (
|
||||
assign DebugMode = (State != RUNNING);
|
||||
assign DebugStall = (State == HALTED);
|
||||
|
||||
assign EnterDebugMode = (State == RUNNING) & (ebreakM & ebreakEn) | ForceBreakPoint;
|
||||
assign ExitDebugMode = (State == HALTED) & (ResumeReq | ExecProgBuf);
|
||||
assign DCall = ((State == RUNNING) | (State == EXECPROGBUF)) & ((ebreakM & ebreakEn) | ForceBreakPoint);
|
||||
assign DRet = (State == HALTED) & (ResumeReq | ExecProgBuf);
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
@ -92,6 +91,14 @@ module dmc (
|
||||
end
|
||||
end
|
||||
|
||||
// Similar to RUNNING, but DebugMode isn't deasserted
|
||||
EXECPROGBUF : begin
|
||||
if (ebreakM & ebreakEn) begin
|
||||
State <= HALTED;
|
||||
DebugCause <= `CAUSE_EBREAK;
|
||||
end
|
||||
end
|
||||
|
||||
HALTED : begin
|
||||
if (ResumeReq) begin
|
||||
if (Step) begin
|
||||
@ -102,7 +109,7 @@ module dmc (
|
||||
ResumeAck <= 1;
|
||||
end
|
||||
end else if (ExecProgBuf) begin
|
||||
State <= RUNNING;
|
||||
State <= EXECPROGBUF;
|
||||
ResumeAck <= 1;
|
||||
end
|
||||
end
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
module hazard import cvw::*; #(parameter cvw_t P) (
|
||||
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
|
||||
input logic ExitDebugMode,
|
||||
input logic DRet,
|
||||
input logic StructuralStallD,
|
||||
input logic LSUStallM, IFUStallF,
|
||||
input logic FPUStallD,
|
||||
@ -71,9 +71,9 @@ module hazard import cvw::*; #(parameter cvw_t P) (
|
||||
// Branch misprediction is found in the Execute stage and must flush the next two instructions.
|
||||
// However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete
|
||||
// When a WFI is interrupted and causes a trap, it flushes the rest of the pipeline but not the W stage, because the WFI needs to commit
|
||||
assign FlushDCause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM | BPWrongE;
|
||||
assign FlushECause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
||||
assign FlushMCause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM;
|
||||
assign FlushDCause = TrapM | RetM | DRet | CSRWriteFenceM | BPWrongE;
|
||||
assign FlushECause = TrapM | RetM | DRet | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
||||
assign FlushMCause = TrapM | RetM | DRet | CSRWriteFenceM;
|
||||
assign FlushWCause = TrapM & ~WFIInterruptedM;
|
||||
|
||||
// Stall causes
|
||||
@ -91,7 +91,7 @@ module hazard import cvw::*; #(parameter cvw_t P) (
|
||||
// Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1.
|
||||
// assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause;
|
||||
// Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out.
|
||||
assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | (DebugStall & ~ExitDebugMode);
|
||||
assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | (DebugStall & ~DRet);
|
||||
|
||||
// Stall each stage for cause or if the next stage is stalled
|
||||
// coverage off: StallFCause is always 0
|
||||
|
@ -97,7 +97,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
output logic ICacheAccess, // Report I$ read to performance counters
|
||||
output logic ICacheMiss, // Report I$ miss to performance counters
|
||||
// Debug Mode logic
|
||||
input logic ExitDebugMode,
|
||||
input logic DRet,
|
||||
input logic ProgBuffScanEn,
|
||||
// Debug scan chain
|
||||
input logic [3:0] ProgBufAddr,
|
||||
@ -336,7 +336,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
||||
else assign PC2NextF = PC1NextF;
|
||||
|
||||
|
||||
mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, (RetM | ExitDebugMode)}, UnalignedPCNextF);
|
||||
mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, (RetM | DRet)}, UnalignedPCNextF);
|
||||
mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF);
|
||||
flopen #(P.XLEN) pcreg(clk, ~StallF | reset, PCNextF, PCF);
|
||||
|
||||
|
@ -99,8 +99,8 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
output logic ebreakEn,
|
||||
output logic Step,
|
||||
output logic [P.XLEN-1:0] DPC,
|
||||
input logic EnterDebugMode,
|
||||
input logic ExitDebugMode,
|
||||
input logic DCall,
|
||||
input logic DRet,
|
||||
input logic ExecProgBuf,
|
||||
// Debug scan chain
|
||||
input logic DebugSel,
|
||||
@ -189,7 +189,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
if (P.DEBUG_SUPPORTED) begin
|
||||
always_comb
|
||||
if (ExecProgBuf) EPCM = P.PROGBUF_BASE;
|
||||
else if (ExitDebugMode) EPCM = DPC;
|
||||
else if (DRet) EPCM = DPC;
|
||||
else if (mretM) EPCM = MEPC_REGW;
|
||||
else EPCM = SEPC_REGW;
|
||||
end else begin
|
||||
@ -318,7 +318,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
||||
if (P.DEBUG_SUPPORTED) begin:csrd
|
||||
csrd #(P) csrd(.clk, .reset, .DebugMode, .PrivilegeModeW,
|
||||
.CSRWriteDM, .CSRAdrM(CSRAdrDM), .CSRWriteValM(CSRWriteValDM), .CSRDReadValM, .IllegalCSRDAccessM,
|
||||
.DebugCause, .ebreakEn, .Step, .DPC, .PCM, .EnterDebugMode);
|
||||
.DebugCause, .ebreakEn, .Step, .DPC, .PCM, .DCall);
|
||||
end else begin
|
||||
assign CSRDReadValM = '0;
|
||||
assign IllegalCSRDAccessM = 1'b1; // Debug isn't supported
|
||||
|
@ -36,7 +36,7 @@ module csrd import cvw::*; #(parameter cvw_t P) (
|
||||
output logic [P.XLEN-1:0] CSRDReadValM,
|
||||
output logic IllegalCSRDAccessM,
|
||||
input logic [P.XLEN-1:0] PCM,
|
||||
input logic EnterDebugMode,
|
||||
input logic DCall,
|
||||
input logic [2:0] DebugCause,
|
||||
output logic ebreakEn,
|
||||
output logic Step,
|
||||
@ -70,7 +70,8 @@ module csrd import cvw::*; #(parameter cvw_t P) (
|
||||
logic [1:0] Prv;
|
||||
|
||||
|
||||
assign ebreakEn = ebreakM; // Only support ebreak from M mode
|
||||
//assign ebreakEn = ebreakM; // Only support ebreak from M mode
|
||||
assign ebreakEn = 1'b1; // OpenOCD doesn't set ebreakM???? ebreakM; // Only support ebreak from M mode
|
||||
assign CSRDWriteM = CSRWriteDM & (PrivilegeModeW == P.M_MODE) & DebugMode;
|
||||
|
||||
assign WriteDCSRM = CSRDWriteM & (CSRAdrM == DCSR_ADDR);
|
||||
@ -80,7 +81,7 @@ module csrd import cvw::*; #(parameter cvw_t P) (
|
||||
if (reset) begin
|
||||
Prv <= 2'h3;
|
||||
Cause <= 3'h0;
|
||||
end else if (EnterDebugMode) begin
|
||||
end else if (DCall) begin
|
||||
Prv <= PrivilegeModeW;
|
||||
Cause <= DebugCause;
|
||||
end
|
||||
@ -91,8 +92,8 @@ module csrd import cvw::*; #(parameter cvw_t P) (
|
||||
assign DCSR = {DebugVer, 10'b0, ebreakVS, ebreakVU, ebreakM, 1'b0, ebreakS, ebreakU, StepIE,
|
||||
StopCount, StopTime, Cause, V, MPrvEn, NMIP, Step, Prv};
|
||||
|
||||
assign DPCWriteVal = EnterDebugMode ? PCM : CSRWriteValM;
|
||||
flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | EnterDebugMode, DPCWriteVal, DPC); // TODO: reset to something sane (0x80000000?)
|
||||
assign DPCWriteVal = DCall ? PCM : CSRWriteValM;
|
||||
flopenr #(P.XLEN) DPCreg (clk, reset, WriteDPCM | DCall, DPCWriteVal, DPC);
|
||||
|
||||
always_comb begin
|
||||
CSRDReadValM = '0;
|
||||
|
@ -105,8 +105,8 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [2:0] DebugCause,
|
||||
output logic Step,
|
||||
output logic [P.XLEN-1:0] DPC,
|
||||
input logic EnterDebugMode,
|
||||
input logic ExitDebugMode,
|
||||
input logic DCall,
|
||||
input logic DRet,
|
||||
input logic ExecProgBuf,
|
||||
// Debug scan chain
|
||||
input logic DebugSel,
|
||||
@ -167,7 +167,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
||||
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE,
|
||||
.EPCM, .TrapVectorM,
|
||||
.CSRReadValW, .IllegalCSRAccessM, .BigEndianM,
|
||||
.DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .EnterDebugMode, .ExitDebugMode, .ExecProgBuf,
|
||||
.DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .DCall, .DRet, .ExecProgBuf,
|
||||
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
|
||||
|
||||
// pipeline early-arriving trap sources
|
||||
@ -182,6 +182,6 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
||||
.LoadAccessFaultM, .StoreAmoAccessFaultM, .EcallFaultM, .InstrPageFaultM,
|
||||
.LoadPageFaultM, .StoreAmoPageFaultM, .PrivilegeModeW,
|
||||
.MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .MEDELEG_REGW, .STATUS_MIE, .STATUS_SIE,
|
||||
.InstrValidM, .CommittedM, .CommittedF,
|
||||
.InstrValidM, .CommittedM, .CommittedF, .DebugMode,
|
||||
.TrapM, .wfiM, .wfiW, .InterruptM, .ExceptionM, .IntPendingM, .DelegateM, .CauseM);
|
||||
endmodule
|
||||
|
@ -40,6 +40,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
||||
input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables
|
||||
input logic InstrValidM, // current instruction is valid, not flushed
|
||||
input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted
|
||||
input logic DebugMode, // Ignore all interrupts in debug mode
|
||||
output logic TrapM, // Trap is occurring
|
||||
output logic InterruptM, // Interrupt is occurring
|
||||
output logic ExceptionM, // exception is occurring
|
||||
@ -88,7 +89,9 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
||||
BreakpointFaultM | EcallFaultM |
|
||||
LoadAccessFaultM | StoreAmoAccessFaultM;
|
||||
// coverage on
|
||||
assign TrapM = (ExceptionM & ~CommittedF) | InterruptM;
|
||||
//assign TrapM = (ExceptionM & ~CommittedF) | InterruptM;
|
||||
// Debug Test
|
||||
assign TrapM = DebugMode ? BreakpointFaultM : (ExceptionM & ~CommittedF) | InterruptM;
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Cause priority defined in privileged spec
|
||||
|
@ -199,8 +199,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// Debug mode logic
|
||||
logic [P.XLEN-1:0] DPC;
|
||||
logic ExitDebugMode;
|
||||
logic EnterDebugMode;
|
||||
logic DRet;
|
||||
logic DCall;
|
||||
logic [2:0] DebugCause;
|
||||
logic ForceBreakPoint;
|
||||
// Debug register scan chain interconnects
|
||||
@ -228,7 +228,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissOrUpdateAF,
|
||||
// pmp/pma (inside mmu) signals.
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF,
|
||||
.ExitDebugMode, .ProgBuffScanEn, .ProgBufAddr, .ProgBufScanIn(DebugScanIn),
|
||||
.DRet, .ProgBuffScanEn, .ProgBufAddr, .ProgBufScanIn(DebugScanIn),
|
||||
.DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1]));
|
||||
|
||||
// integer execution unit: integer register file, datapath and controller
|
||||
@ -312,7 +312,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// global stall and flush control
|
||||
hazard #(P) hzu(
|
||||
.BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .ExitDebugMode,
|
||||
.BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .DRet,
|
||||
.StructuralStallD,
|
||||
.LSUStallM, .IFUStallF,
|
||||
.FPUStallD,
|
||||
@ -327,7 +327,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.clk, .reset,
|
||||
.Step, .ebreakM, .ebreakEn, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset,
|
||||
.ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall, .ExecProgBuf,
|
||||
.EnterDebugMode, .ExitDebugMode, .ForceBreakPoint);
|
||||
.DCall, .DRet, .ForceBreakPoint);
|
||||
end else begin
|
||||
assign DebugStall = 1'b0;
|
||||
end
|
||||
@ -355,7 +355,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
||||
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
|
||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .ebreakM,
|
||||
.ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .EnterDebugMode, .ExitDebugMode, .ExecProgBuf,
|
||||
.ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .DCall, .DRet, .ExecProgBuf,
|
||||
.DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut));
|
||||
if (P.DEBUG_SUPPORTED) begin
|
||||
flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));
|
||||
|
Loading…
Reference in New Issue
Block a user