Provide opt-in wedge debugging info

When DEBUG_WEDGE is defined, expose the last committed and next in the
reorder buffer PC and corresponding instruction via DMI registers, since
even when the core is wedged and we can't read GPRs etc we can still
interact with the debug module itself. Hopefully this proves useful for
debugging wedges.
This commit is contained in:
Jessica Clarke
2020-07-07 23:59:35 +01:00
parent 40f8109263
commit 68d3bd484e
10 changed files with 174 additions and 2 deletions

View File

@@ -161,6 +161,10 @@ interface CommitStage;
method Bool is_debug_halted;
method Action debug_resume;
`endif
`ifdef DEBUG_WEDGE
(* always_enabled *)
method Tuple2#(CapMem, Bit#(32)) debugLastInst;
`endif
endinterface
// we apply actions the end of commit rule
@@ -620,6 +624,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
endfunction
`endif
`ifdef DEBUG_WEDGE
Reg#(CapMem) rg_last_pcc <- mkReg(unpack(0));
Reg#(Bit#(32)) rg_last_inst <- mkReg(0);
`endif
// TODO Currently we don't check spec bits == 0 when we commit an
// instruction. This is because killings of wrong path instructions are
// done in a single cycle. However, when we make killings distributed or
@@ -779,6 +788,13 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
x, no_fflags, no_mstatus, tagged Valid trap_updates, no_ret_updates);
`endif
rg_serial_num <= rg_serial_num + 1;
`ifdef DEBUG_WEDGE
Bool is_exception = trap.trap matches tagged Interrupt .i ? False : True;
if (is_exception) begin
rg_last_pcc <= trap.pc;
rg_last_inst <= trap.orig_inst;
end
`endif
// system consistency
// TODO spike flushes TLB here, but perhaps it is because spike's TLB
@@ -945,6 +961,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
x, no_fflags, new_mstatus, no_trap_updates, m_ret_updates);
`endif
rg_serial_num <= rg_serial_num + 1;
`ifdef DEBUG_WEDGE
rg_last_pcc <= x.pc;
rg_last_inst <= x.orig_inst;
`endif
// rename stage only sends out system inst when ROB is empty, so no
// need to flush ROB again
@@ -1068,6 +1088,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
// (whereas the 'fflags' variable does just one update after superscalar retirement).
Bit #(5) po_fflags = ?;
Data po_mstatus = ?;
`endif
`ifdef DEBUG_WEDGE
CapMem last_pcc = rg_last_pcc;
Bit#(32) last_inst = rg_last_inst;
`endif
// compute what actions to take
for(Integer i = 0; i < valueof(SupSize); i = i+1) begin
@@ -1110,6 +1134,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
no_trap_updates, no_ret_updates);
`endif
instret = instret + 1;
`ifdef DEBUG_WEDGE
last_pcc = x.pc;
last_inst = x.orig_inst;
`endif
// inst can be committed, deq it
rob.deqPort[i].deq;
@@ -1163,6 +1191,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
end
end
rg_serial_num <= rg_serial_num + instret;
`ifdef DEBUG_WEDGE
rg_last_pcc <= last_pcc;
rg_last_inst <= last_inst;
`endif
// write FPU csr
if(csrf.fpuInstNeedWr(fflags, will_dirty_fpu_state)) begin
@@ -1281,4 +1313,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage);
endmethod
`endif
`ifdef DEBUG_WEDGE
method Tuple2#(CapMem, Bit#(32)) debugLastInst;
return tuple2(rg_last_pcc, rg_last_inst);
endmethod
`endif
endmodule

View File

@@ -661,6 +661,11 @@ interface SupReorderBuffer#(numeric type aluExeNum, numeric type fpuMulDivExeNum
method Bool isFull_ehrPort0;
interface ROB_SpeculationUpdate specUpdate;
`ifdef DEBUG_WEDGE
(* always_enabled *)
method Tuple2#(CapMem, Bit#(32)) debugNextInst;
`endif
endinterface
typedef struct {
@@ -1305,4 +1310,10 @@ module mkSupReorderBuffer#(
end
endmethod
endinterface
`ifdef DEBUG_WEDGE
method Tuple2#(CapMem, Bit#(32)) debugNextInst;
return tuple2(fifo_first[0].pc, fifo_first[0].orig_inst);
endmethod
`endif
endmodule