mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
fix bug with resuming from debug mode
This commit is contained in:
parent
636501e06c
commit
21a51a1c9e
@ -51,15 +51,17 @@ def prog_buff_test(cvw):
|
|||||||
def flow_control_test(cvw):
|
def flow_control_test(cvw):
|
||||||
#time.sleep(70) # wait for OpenSBI
|
#time.sleep(70) # wait for OpenSBI
|
||||||
|
|
||||||
cvw.halt()
|
#cvw.halt()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
#cvw.read_data("DCSR")
|
#cvw.read_data("DCSR")
|
||||||
for _ in range(50):
|
for _ in range(100):
|
||||||
cvw.resume()
|
time.sleep(random.randint(5,10))
|
||||||
|
print("Halting")
|
||||||
cvw.halt()
|
cvw.halt()
|
||||||
|
cvw.resume()
|
||||||
#cvw.step()
|
#cvw.step()
|
||||||
#print(cvw.read_data("PCM"))
|
#print(cvw.read_data("PCM"))
|
||||||
cvw.resume()
|
#cvw.resume()
|
||||||
|
|
||||||
|
|
||||||
def register_rw_test(cvw):
|
def register_rw_test(cvw):
|
||||||
|
@ -26,16 +26,10 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO List:
|
// TODO List:
|
||||||
// add "progbuff" register to overwrite instrF
|
// Ignore wfi instructions in debug mode (overwrite with NOP?)
|
||||||
// overwrite wfi instructions with NOP during DebugMode
|
// mask all interrupts/ignore all traps (except ebreak) in debug mode
|
||||||
// mask all interrupts in debug mode (even NMI)
|
|
||||||
// Ignore traps in debug mode
|
|
||||||
|
|
||||||
// capture CSR read/write failures as convert them to cmderr
|
// capture CSR read/write failures as convert them to cmderr
|
||||||
|
|
||||||
// Flush pipe with NOPs during halt?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module dm import cvw::*; #(parameter cvw_t P) (
|
module dm import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
@ -52,7 +46,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Core control signals
|
// Core control signals
|
||||||
input logic ResumeAck, // Signals Hart has been resumed
|
input logic ResumeAck, // Signals Hart has been resumed
|
||||||
input logic HaveReset, // Signals Hart has been reset
|
input logic HaveReset, // Signals Hart has been reset
|
||||||
input logic DebugStall, // Signals core is halted
|
input logic DebugStall, // Signals core is halted
|
||||||
output logic HaltReq, // Initiates core halt
|
output logic HaltReq, // Initiates core halt
|
||||||
output logic ResumeReq, // Initiates core resume
|
output logic ResumeReq, // Initiates core resume
|
||||||
output logic HaltOnReset, // Halts core immediately on hart reset
|
output logic HaltOnReset, // Halts core immediately on hart reset
|
||||||
@ -76,7 +70,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
// Program Buffer
|
// Program Buffer
|
||||||
output logic [3:0] ProgBufAddr,
|
output logic [3:0] ProgBufAddr,
|
||||||
output logic ProgBuffScanEn,
|
output logic ProgBuffScanEn,
|
||||||
output logic ExecProgBuff
|
output logic ExecProgBuf
|
||||||
);
|
);
|
||||||
`include "debug.vh"
|
`include "debug.vh"
|
||||||
|
|
||||||
@ -106,7 +100,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL,
|
enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL,
|
||||||
W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, W_PROGBUF, READ_ZERO,
|
W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, W_PROGBUF, READ_ZERO,
|
||||||
INVALID} State;
|
INVALID, EXEC_PROGBUF} State;
|
||||||
|
|
||||||
enum logic [2:0] {AC_IDLE, AC_UPDATE, AC_SCAN, AC_CAPTURE, PROGBUFF_WRITE} AcState, NewAcState;
|
enum logic [2:0] {AC_IDLE, AC_UPDATE, AC_SCAN, AC_CAPTURE, PROGBUFF_WRITE} AcState, NewAcState;
|
||||||
|
|
||||||
@ -186,7 +180,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
assign AnyRunning = ~DebugStall;
|
assign AnyRunning = ~DebugStall;
|
||||||
assign AllRunning = ~DebugStall;
|
assign AllRunning = ~DebugStall;
|
||||||
// I believe resumeack is used to determine when a resume is requested but never completes
|
// I believe resumeack is used to determine when a resume is requested but never completes
|
||||||
// It's pretty worthless in this implementation (complain to the debug working group)
|
// It's pretty worthless in this implementation (complain to the riscv debug working group)
|
||||||
assign AllResumeAck = ResumeAck;
|
assign AllResumeAck = ResumeAck;
|
||||||
assign AnyResumeAck = ResumeAck;
|
assign AnyResumeAck = ResumeAck;
|
||||||
|
|
||||||
@ -339,6 +333,9 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
ABST_COMMAND : begin
|
ABST_COMMAND : begin
|
||||||
|
RspOP <= `OP_SUCCESS;
|
||||||
|
State <= ACK;
|
||||||
|
|
||||||
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
||||||
else if (Busy)
|
else if (Busy)
|
||||||
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
||||||
@ -347,16 +344,18 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
else begin
|
else begin
|
||||||
case (ReqData[`CMDTYPE])
|
case (ReqData[`CMDTYPE])
|
||||||
`ACCESS_REGISTER : begin
|
`ACCESS_REGISTER : begin
|
||||||
if (ReqData[`AARSIZE] > $clog2(P.LLEN/8)) // if AARSIZE (encoded) is greater than P.LLEN, set CmdErr, do nothing
|
if (ReqData[`AARSIZE] > $clog2(P.LLEN/8))
|
||||||
CmdErr <= `CMDERR_BUS;
|
CmdErr <= `CMDERR_BUS; // if AARSIZE (encoded) is greater than P.LLEN, set CmdErr, do nothing
|
||||||
else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing
|
|
||||||
else if (InvalidRegNo)
|
else if (InvalidRegNo)
|
||||||
CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing
|
CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing
|
||||||
else if (ReqData[`AARWRITE] & RegReadOnly)
|
else if (ReqData[`AARWRITE] & RegReadOnly)
|
||||||
CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing
|
CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing
|
||||||
else begin
|
else begin
|
||||||
AcWrite <= ReqData[`AARWRITE];
|
if (ReqData[`TRANSFER]) begin
|
||||||
NewAcState <= ~ReqData[`AARWRITE] ? AC_CAPTURE : AC_SCAN;
|
AcWrite <= ReqData[`AARWRITE];
|
||||||
|
NewAcState <= ~ReqData[`AARWRITE] ? AC_CAPTURE : AC_SCAN;
|
||||||
|
end
|
||||||
|
State <= ReqData[`POSTEXEC] ? EXEC_PROGBUF : ACK;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
//`QUICK_ACCESS : State <= QUICK_ACCESS;
|
//`QUICK_ACCESS : State <= QUICK_ACCESS;
|
||||||
@ -364,8 +363,6 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
default : CmdErr <= `CMDERR_NOT_SUPPORTED;
|
default : CmdErr <= `CMDERR_NOT_SUPPORTED;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
RspOP <= `OP_SUCCESS;
|
|
||||||
State <= ACK;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
W_PROGBUF : begin
|
W_PROGBUF : begin
|
||||||
@ -392,9 +389,15 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
INVALID : begin
|
INVALID : begin
|
||||||
RspOP <= `OP_SUCCESS;//`OP_FAILED;
|
RspOP <= `OP_SUCCESS; // openocd cannot recover from `OP_FAILED;
|
||||||
State <= ACK;
|
State <= ACK;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
EXEC_PROGBUF : begin
|
||||||
|
NewAcState <= AC_IDLE;
|
||||||
|
if (~Busy)
|
||||||
|
State <= ACK;
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -442,6 +445,7 @@ module dm import cvw::*; #(parameter cvw_t P) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
assign Busy = ~(AcState == AC_IDLE);
|
assign Busy = ~(AcState == AC_IDLE);
|
||||||
|
assign ExecProgBuf = (State == EXEC_PROGBUF) & ~Busy;
|
||||||
|
|
||||||
// Program Buffer
|
// Program Buffer
|
||||||
assign ProgBuffScanEn = (AcState == PROGBUFF_WRITE);
|
assign ProgBuffScanEn = (AcState == PROGBUFF_WRITE);
|
||||||
|
@ -27,22 +27,11 @@
|
|||||||
// and limitations under the License.
|
// and limitations under the License.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// On HaltReq/eBreak:
|
|
||||||
// store value of NextPC in DPC
|
|
||||||
// trigger trap (flush pipe)
|
|
||||||
// stall pipe
|
|
||||||
|
|
||||||
// On Step:
|
// TODO:
|
||||||
// unstall pipe until instruction receaches M stage
|
// Figure out what is causing resumes from stalls to error out
|
||||||
// goto: HaltReq/eBreak
|
// Calculate correct cycle timing for step
|
||||||
|
// Test progbuf
|
||||||
// On exec_progbuf
|
|
||||||
// change NextPC to progbuf_address (using DPC?)
|
|
||||||
// goto: resume (implicic ebreak will return to debug mode)
|
|
||||||
|
|
||||||
// On Resume:
|
|
||||||
// update NextPC from DPC
|
|
||||||
// Unstall pipe
|
|
||||||
|
|
||||||
module dmc (
|
module dmc (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
@ -53,6 +42,7 @@ module dmc (
|
|||||||
input logic ResumeReq, // Initiates core resume
|
input logic ResumeReq, // Initiates core resume
|
||||||
input logic HaltOnReset, // Halts core immediately on hart reset
|
input logic HaltOnReset, // Halts core immediately on hart reset
|
||||||
input logic AckHaveReset, // Clears HaveReset status
|
input logic AckHaveReset, // Clears HaveReset status
|
||||||
|
input logic ExecProgBuf, // Updates PC to progbuf and resumes core
|
||||||
|
|
||||||
output logic DebugMode,
|
output logic DebugMode,
|
||||||
output logic [2:0] DebugCause, // Reason Hart entered debug mode
|
output logic [2:0] DebugCause, // Reason Hart entered debug mode
|
||||||
@ -66,7 +56,8 @@ module dmc (
|
|||||||
);
|
);
|
||||||
`include "debug.vh"
|
`include "debug.vh"
|
||||||
|
|
||||||
enum logic [2:0] {RUNNING, HALTED, RESUME, STEP, PROGBUF} State;
|
|
||||||
|
enum logic [1:0] {RUNNING, HALTED, STEP} State;
|
||||||
|
|
||||||
localparam E2M_CYCLE_COUNT = 3;
|
localparam E2M_CYCLE_COUNT = 3;
|
||||||
logic [$clog2(E2M_CYCLE_COUNT+1)-1:0] Counter;
|
logic [$clog2(E2M_CYCLE_COUNT+1)-1:0] Counter;
|
||||||
@ -81,10 +72,10 @@ module dmc (
|
|||||||
assign ForceBreakPoint = (State == RUNNING) & HaltReq | (State == STEP) & ~|Counter;
|
assign ForceBreakPoint = (State == RUNNING) & HaltReq | (State == STEP) & ~|Counter;
|
||||||
|
|
||||||
assign DebugMode = (State != RUNNING);
|
assign DebugMode = (State != RUNNING);
|
||||||
assign DebugStall = (State == HALTED) | (State == RESUME);
|
assign DebugStall = (State == HALTED);
|
||||||
|
|
||||||
assign EnterDebugMode = (State == RUNNING) & (ebreakM & ebreakEn) | ForceBreakPoint;
|
assign EnterDebugMode = (State == RUNNING) & (ebreakM & ebreakEn) | ForceBreakPoint;
|
||||||
assign ExitDebugMode = (State == HALTED) & ResumeReq;
|
assign ExitDebugMode = (State == HALTED) & (ResumeReq | ExecProgBuf);
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
@ -104,7 +95,6 @@ module dmc (
|
|||||||
|
|
||||||
HALTED : begin
|
HALTED : begin
|
||||||
if (ResumeReq) begin
|
if (ResumeReq) begin
|
||||||
//State <= RESUME;
|
|
||||||
if (Step) begin
|
if (Step) begin
|
||||||
Counter <= E2M_CYCLE_COUNT;
|
Counter <= E2M_CYCLE_COUNT;
|
||||||
State <= STEP;
|
State <= STEP;
|
||||||
@ -112,21 +102,13 @@ module dmc (
|
|||||||
State <= RUNNING;
|
State <= RUNNING;
|
||||||
ResumeAck <= 1;
|
ResumeAck <= 1;
|
||||||
end
|
end
|
||||||
end
|
end else if (ExecProgBuf) begin
|
||||||
end
|
|
||||||
|
|
||||||
// Wait a cycle to load PCF from DPC before resuming
|
|
||||||
// TODO: test without resume stage
|
|
||||||
RESUME : begin
|
|
||||||
if (Step) begin
|
|
||||||
Counter <= E2M_CYCLE_COUNT;
|
|
||||||
State <= STEP;
|
|
||||||
end else begin
|
|
||||||
State <= RUNNING;
|
State <= RUNNING;
|
||||||
ResumeAck <= 1;
|
ResumeAck <= 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
STEP : begin
|
STEP : begin
|
||||||
if (~|Counter) begin
|
if (~|Counter) begin
|
||||||
DebugCause <= `CAUSE_STEP;
|
DebugCause <= `CAUSE_STEP;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
module hazard import cvw::*; #(parameter cvw_t P) (
|
module hazard import cvw::*; #(parameter cvw_t P) (
|
||||||
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
|
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
|
||||||
|
input logic ExitDebugMode,
|
||||||
input logic StructuralStallD,
|
input logic StructuralStallD,
|
||||||
input logic LSUStallM, IFUStallF,
|
input logic LSUStallM, IFUStallF,
|
||||||
input logic FPUStallD,
|
input logic FPUStallD,
|
||||||
@ -70,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.
|
// 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
|
// 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
|
// 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 | CSRWriteFenceM | BPWrongE;
|
assign FlushDCause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM | BPWrongE;
|
||||||
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
assign FlushECause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
||||||
assign FlushMCause = TrapM | RetM | CSRWriteFenceM;
|
assign FlushMCause = TrapM | RetM | ExitDebugMode | CSRWriteFenceM;
|
||||||
assign FlushWCause = TrapM & ~WFIInterruptedM;
|
assign FlushWCause = TrapM & ~WFIInterruptedM;
|
||||||
|
|
||||||
// Stall causes
|
// Stall causes
|
||||||
@ -90,7 +91,7 @@ module hazard import cvw::*; #(parameter cvw_t P) (
|
|||||||
// 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) | DebugStall;
|
assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | (DebugStall & ~ExitDebugMode);
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -97,7 +97,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic ICacheAccess, // Report I$ read to performance counters
|
output logic ICacheAccess, // Report I$ read to performance counters
|
||||||
output logic ICacheMiss, // Report I$ miss to performance counters
|
output logic ICacheMiss, // Report I$ miss to performance counters
|
||||||
// Debug Mode logic
|
// Debug Mode logic
|
||||||
output logic [P.XLEN-1:0] PCNextF, // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
input logic ExitDebugMode,
|
||||||
input logic ProgBuffScanEn,
|
input logic ProgBuffScanEn,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic [3:0] ProgBufAddr,
|
input logic [3:0] ProgBufAddr,
|
||||||
@ -110,6 +110,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
localparam [31:0] nop = 32'h00000013; // instruction for NOP
|
||||||
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
localparam LINELEN = P.ICACHE_SUPPORTED ? P.ICACHE_LINELENINBITS : P.XLEN;
|
||||||
|
|
||||||
|
logic [P.XLEN-1:0] PCNextF; // Next PCF, selected from Branch predictor, Privilege, or PC+2/4
|
||||||
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
logic [P.XLEN-1:0] PC1NextF; // Branch predictor next PCF
|
||||||
logic [P.XLEN-1:0] PC2NextF; // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
logic [P.XLEN-1:0] PC2NextF; // Selected PC between branch prediction and next valid PC if CSRWriteFence
|
||||||
logic [P.XLEN-1:0] UnalignedPCNextF; // The next PCF, but not aligned to 2 bytes.
|
logic [P.XLEN-1:0] UnalignedPCNextF; // The next PCF, but not aligned to 2 bytes.
|
||||||
@ -332,7 +333,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
else assign PC2NextF = PC1NextF;
|
else assign PC2NextF = PC1NextF;
|
||||||
|
|
||||||
|
|
||||||
mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, RetM}, UnalignedPCNextF);
|
mux3 #(P.XLEN) pcmux3(PC2NextF, EPCM, TrapVectorM, {TrapM, (RetM | ExitDebugMode)}, UnalignedPCNextF);
|
||||||
mux2 #(P.XLEN) pcresetmux({UnalignedPCNextF[P.XLEN-1:1], 1'b0}, P.RESET_VECTOR[P.XLEN-1:0], reset, PCNextF);
|
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);
|
flopen #(P.XLEN) pcreg(clk, ~StallF | reset, PCNextF, PCF);
|
||||||
|
|
||||||
|
@ -99,8 +99,9 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic ebreakEn,
|
output logic ebreakEn,
|
||||||
output logic Step,
|
output logic Step,
|
||||||
output logic [P.XLEN-1:0] DPC,
|
output logic [P.XLEN-1:0] DPC,
|
||||||
input logic ExitDebugMode,
|
|
||||||
input logic EnterDebugMode,
|
input logic EnterDebugMode,
|
||||||
|
input logic ExitDebugMode,
|
||||||
|
input logic ExecProgBuf,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic DebugSel,
|
input logic DebugSel,
|
||||||
input logic [11:0] DebugRegAddr,
|
input logic [11:0] DebugRegAddr,
|
||||||
@ -186,7 +187,11 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||||||
// A trap sets the PC to TrapVector
|
// A trap sets the PC to TrapVector
|
||||||
// A return sets the PC to MEPC or SEPC
|
// A return sets the PC to MEPC or SEPC
|
||||||
if (P.DEBUG_SUPPORTED) begin
|
if (P.DEBUG_SUPPORTED) begin
|
||||||
mux3 #(P.XLEN) epcmux(SEPC_REGW, MEPC_REGW, DPC, {ExitDebugMode,mretM}, EPCM);
|
always_comb
|
||||||
|
if (ExecProgBuf) EPCM = P.PROGBUF_BASE;
|
||||||
|
else if (ExitDebugMode) EPCM = DPC;
|
||||||
|
else if (mretM) EPCM = MEPC_REGW;
|
||||||
|
else EPCM = SEPC_REGW;
|
||||||
end else begin
|
end else begin
|
||||||
mux2 #(P.XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPCM);
|
mux2 #(P.XLEN) epcmux(SEPC_REGW, MEPC_REGW, mretM, EPCM);
|
||||||
end
|
end
|
||||||
|
@ -107,6 +107,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic [P.XLEN-1:0] DPC,
|
output logic [P.XLEN-1:0] DPC,
|
||||||
input logic EnterDebugMode,
|
input logic EnterDebugMode,
|
||||||
input logic ExitDebugMode,
|
input logic ExitDebugMode,
|
||||||
|
input logic ExecProgBuf,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic DebugSel,
|
input logic DebugSel,
|
||||||
input logic [11:0] DebugRegAddr,
|
input logic [11:0] DebugRegAddr,
|
||||||
@ -166,7 +167,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||||||
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE,
|
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE,
|
||||||
.EPCM, .TrapVectorM,
|
.EPCM, .TrapVectorM,
|
||||||
.CSRReadValW, .IllegalCSRAccessM, .BigEndianM,
|
.CSRReadValW, .IllegalCSRAccessM, .BigEndianM,
|
||||||
.DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .EnterDebugMode, .ExitDebugMode,
|
.DebugMode, .DebugCause, .ebreakEn, .Step, .DPC, .EnterDebugMode, .ExitDebugMode, .ExecProgBuf,
|
||||||
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
|
.DebugSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn, .DebugScanIn, .DebugScanOut);
|
||||||
|
|
||||||
// pipeline early-arriving trap sources
|
// pipeline early-arriving trap sources
|
||||||
|
@ -53,7 +53,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
output logic ResumeAck,
|
output logic ResumeAck,
|
||||||
output logic HaveReset,
|
output logic HaveReset,
|
||||||
output logic DebugStall,
|
output logic DebugStall,
|
||||||
input logic ExecProgBuff,
|
input logic ExecProgBuf,
|
||||||
// Debug scan chain
|
// Debug scan chain
|
||||||
input logic DebugScanEn, // puts scannable flops into scan mode
|
input logic DebugScanEn, // puts scannable flops into scan mode
|
||||||
output logic DebugScanOut, // (misc) scan chain data out
|
output logic DebugScanOut, // (misc) scan chain data out
|
||||||
@ -198,7 +198,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic ebreakM;
|
logic ebreakM;
|
||||||
|
|
||||||
// Debug mode logic
|
// Debug mode logic
|
||||||
logic [P.XLEN-1:0] DPC, PCNextF;
|
logic [P.XLEN-1:0] DPC;
|
||||||
logic ExitDebugMode;
|
logic ExitDebugMode;
|
||||||
logic EnterDebugMode;
|
logic EnterDebugMode;
|
||||||
logic [2:0] DebugCause;
|
logic [2:0] DebugCause;
|
||||||
@ -228,7 +228,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissOrUpdateAF,
|
.STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_ADUE, .ITLBWriteF, .sfencevmaM, .ITLBMissOrUpdateAF,
|
||||||
// pmp/pma (inside mmu) signals.
|
// pmp/pma (inside mmu) signals.
|
||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF,
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF,
|
||||||
.PCNextF, .ProgBuffScanEn, .ProgBufAddr, .ProgBufScanIn(DebugScanIn),
|
.ExitDebugMode, .ProgBuffScanEn, .ProgBufAddr, .ProgBufScanIn(DebugScanIn),
|
||||||
.DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1]));
|
.DebugScanEn(DebugScanEn & MiscSel), .DebugScanIn(DebugScanReg[0]), .DebugScanOut(DebugScanReg[1]));
|
||||||
|
|
||||||
// integer execution unit: integer register file, datapath and controller
|
// 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
|
// global stall and flush control
|
||||||
hazard #(P) hzu(
|
hazard #(P) hzu(
|
||||||
.BPWrongE, .CSRWriteFenceM, .RetM, .TrapM,
|
.BPWrongE, .CSRWriteFenceM, .RetM, .TrapM, .ExitDebugMode,
|
||||||
.StructuralStallD,
|
.StructuralStallD,
|
||||||
.LSUStallM, .IFUStallF,
|
.LSUStallM, .IFUStallF,
|
||||||
.FPUStallD,
|
.FPUStallD,
|
||||||
@ -326,7 +326,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
dmc debugcontrol(
|
dmc debugcontrol(
|
||||||
.clk, .reset,
|
.clk, .reset,
|
||||||
.Step, .ebreakM, .ebreakEn, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset,
|
.Step, .ebreakM, .ebreakEn, .HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset,
|
||||||
.ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall,
|
.ResumeAck, .HaveReset, .DebugMode, .DebugCause, .DebugStall, .ExecProgBuf,
|
||||||
.EnterDebugMode, .ExitDebugMode, .ForceBreakPoint);
|
.EnterDebugMode, .ExitDebugMode, .ForceBreakPoint);
|
||||||
end else begin
|
end else begin
|
||||||
assign DebugStall = 1'b0;
|
assign DebugStall = 1'b0;
|
||||||
@ -355,7 +355,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||||||
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
|
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
|
||||||
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
|
||||||
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .ebreakM,
|
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .wfiM, .IntPendingM, .BigEndianM, .ebreakM,
|
||||||
.ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .EnterDebugMode, .ExitDebugMode,
|
.ebreakEn, .ForceBreakPoint, .DebugMode, .DebugCause, .Step, .DPC, .EnterDebugMode, .ExitDebugMode, .ExecProgBuf,
|
||||||
.DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut));
|
.DebugSel(CSRSel), .DebugRegAddr, .DebugCapture, .DebugRegUpdate, .DebugScanEn(DebugScanEn & CSRSel), .DebugScanIn, .DebugScanOut(CSRScanOut));
|
||||||
if (P.DEBUG_SUPPORTED) begin
|
if (P.DEBUG_SUPPORTED) begin
|
||||||
flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));
|
flopenrs #(1) scantrapm (.clk, .reset, .en(DebugCapture), .d(TrapM), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanReg[0]));
|
||||||
|
@ -82,7 +82,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic ResumeAck;
|
logic ResumeAck;
|
||||||
logic HaveReset;
|
logic HaveReset;
|
||||||
logic DebugStall;
|
logic DebugStall;
|
||||||
logic ExecProgBuff;
|
logic ExecProgBuf;
|
||||||
// Debug Module signals
|
// Debug Module signals
|
||||||
logic DebugScanEn;
|
logic DebugScanEn;
|
||||||
logic DebugScanIn;
|
logic DebugScanIn;
|
||||||
@ -108,7 +108,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
|
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
|
||||||
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
|
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
|
||||||
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
|
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
|
||||||
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall, .ExecProgBuff,
|
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall, .ExecProgBuf,
|
||||||
.DebugScanEn, .DebugScanOut(DebugScanIn), .GPRScanOut(GPRScanIn), .FPRScanOut(FPRScanIn), .CSRScanOut(CSRScanIn),
|
.DebugScanEn, .DebugScanOut(DebugScanIn), .GPRScanOut(GPRScanIn), .FPRScanOut(FPRScanIn), .CSRScanOut(CSRScanIn),
|
||||||
.DebugScanIn(DebugScanOut), .MiscSel, .GPRSel, .FPRSel, .CSRSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate,
|
.DebugScanIn(DebugScanOut), .MiscSel, .GPRSel, .FPRSel, .CSRSel, .DebugRegAddr, .DebugCapture, .DebugRegUpdate,
|
||||||
.ProgBufAddr, .ProgBuffScanEn);
|
.ProgBufAddr, .ProgBuffScanEn);
|
||||||
@ -131,7 +131,7 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall,
|
.HaltReq, .ResumeReq, .HaltOnReset, .AckHaveReset, .ResumeAck, .HaveReset, .DebugStall,
|
||||||
.DebugScanEn, .DebugScanIn, .GPRScanIn, .FPRScanIn, .CSRScanIn, .DebugScanOut,
|
.DebugScanEn, .DebugScanIn, .GPRScanIn, .FPRScanIn, .CSRScanIn, .DebugScanOut,
|
||||||
.MiscSel, .GPRSel, .FPRSel, .CSRSel, .RegAddr(DebugRegAddr), .DebugCapture, .DebugRegUpdate,
|
.MiscSel, .GPRSel, .FPRSel, .CSRSel, .RegAddr(DebugRegAddr), .DebugCapture, .DebugRegUpdate,
|
||||||
.ProgBufAddr, .ProgBuffScanEn, .ExecProgBuff);
|
.ProgBufAddr, .ProgBuffScanEn, .ExecProgBuf);
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
Loading…
Reference in New Issue
Block a user