From cd779e1cbeec817be22d0460ad2a4abc4e55e757 Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Wed, 8 Jan 2020 20:17:50 -0500 Subject: [PATCH 1/8] Work in progress: updates to handle stop/step/run from Debug Module --- src_Core/CPU/Core.bsv | 87 +++++- src_Core/CPU/CsrFile.bsv | 88 ++++++ src_Core/CPU/Proc.bsv | 150 ++++++++++- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 254 +++++++++++++++++- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 27 ++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 8 + 6 files changed, 603 insertions(+), 11 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 7f05d80..03631c8 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -84,6 +84,8 @@ import Bypass::*; import CsrFile :: *; +import Cur_Cycle :: *; + interface CoreReq; method Action start( Addr startpc, @@ -138,6 +140,19 @@ interface Core; // Bluespec: external interrupt to enter debug mode method Action setDEIP (Bit #(1) v); + +`ifdef INCLUDE_GDB_CONTROL + method Action halt_to_debug_mode_req; + + (* always_ready *) + method Bool is_debug_halted; + + method Action resume_from_debug_mode; + + method Data csr_read (Bit #(12) csr_addr); + method Action csr_write (Bit #(12) csr_addr, Data data); + +`endif endinterface // fixpoint to instantiate modules @@ -158,7 +173,11 @@ module mkCore#(CoreId coreId)(Core); outOfReset <= True; endrule - Reg#(Bool) started <- mkReg(False); + Reg#(Bool) started <- mkReg(False); // only used for deadlock check + +`ifdef INCLUDE_GDB_CONTROL + Reg#(Bool) rg_debug_halted <- mkReg (False); +`endif // front end FetchStage fetchStage <- mkFetchStage; @@ -512,6 +531,21 @@ module mkCore#(CoreId coreId)(Core); endinterface); CommitStage commitStage <- mkCommitStage(commitInput); + (* mutually_exclusive = "coreFix.aluExe_0.doRegReadAlu, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.aluExe_1.doRegReadAlu, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.aluExe_0.doDispatchAlu, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.aluExe_1.doDispatchAlu, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishIntMul, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishIntDiv, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpFma, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpDiv, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpSqrt, commitStage.rl_enter_debug_mode_flush" *) + (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpSqrt, commitStage.rl_enter_debug_mode_flush" *) + + rule rl_bogus_dummy (False); + // Just to allow the scheduling attributes above + endrule + // send rob enq time to reservation stations (* fire_when_enabled, no_implicit_conditions *) rule sendRobEnqTime; @@ -903,6 +937,19 @@ module mkCore#(CoreId coreId)(Core); endrule `endif +`ifdef INCLUDE_GDB_CONTROL + // ================================================================ + // Stopping into debug mode + + rule rl_debug_halt_actions ((! rg_debug_halted) && commitStage.is_debug_halted); + $display ("%0d: %m.rl_debug_halt_actions", cur_cycle); + rg_debug_halted <= True; + endrule + +`endif + + // ================================================================ + interface CoreReq coreReq; method Action start( Bit#(64) startpc, @@ -910,6 +957,9 @@ module mkCore#(CoreId coreId)(Core); ); fetchStage.start(startpc); started <= True; +`ifdef INCLUDE_GDB_CONTROL + rg_debug_halted <= False; +`endif mmio.setHtifAddrs(toHostAddr, fromHostAddr); // start rename debug commitStage.startRenameDebug; @@ -980,5 +1030,38 @@ module mkCore#(CoreId coreId)(Core); // Bluespec: external interrupt to enter debug mode method Action setDEIP (v) = csrf.setDEIP (v); -endmodule +`ifdef INCLUDE_GDB_CONTROL + method Action halt_to_debug_mode_req () if (! rg_debug_halted); + $display ("%0d: %m.halt_to_debug_mode_req", cur_cycle); + started <= False; + fetchStage.stop; + commitStage.halt_to_debug_mode_req; + endmethod + + method Bool is_debug_halted; + return rg_debug_halted; + endmethod + + method Action resume_from_debug_mode if (rg_debug_halted); + let startpc = csrf.dpc_read; + fetchStage.resume_from_debug_mode (startpc); + commitStage.resume_from_debug_mode; + started <= True; + rg_debug_halted <= False; + + $display ("%0d: %m.resume_from_debug_mode, dpc = 0x%0h", cur_cycle, startpc); + endmethod + + // TODO_DEBUG: was part of method cond: commitStage.is_debug_halted && + method Data csr_read (Bit #(12) csr_addr) if (rg_debug_halted); + return csrf.rd (unpack (csr_addr)); + endmethod + + // TODO_DEBUG: was part of method cond: commitStage.is_debug_halted && + method Action csr_write (Bit #(12) csr_addr, Data data) if (rg_debug_halted); + csrf.csrInstWr (unpack (csr_addr), data); + endmethod +`endif + +endmodule diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 479437c..1e43050 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -37,6 +37,8 @@ import GetPut::*; import BuildVector::*; //import TRNG::*; +import SoC_Map :: *; + interface CsrFile; // Read method Data rd(CSR csr); @@ -90,6 +92,24 @@ interface CsrFile; // terminate method ActionValue#(void) terminate; + +`ifdef INCLUDE_GDB_CONTROL + // Read dpc + method Addr dpc_read (); + + // Update dpc + method Action dpc_write (Addr pc); + + // Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku} + method Bool dcsr_stop_for_break; + + // Check whether to enter Debug Mode based on dcsr.step + method Bool dcsr_stop_for_step; + + // Update 'cause' in DCSR + (* always_ready *) + method Action dcsr_cause_write (Bit #(3) dcsr_cause); +`endif endinterface // Fancy Reg functions @@ -501,6 +521,30 @@ module mkCsrFile #(Data hartid)(CsrFile); StatsCsr stats_module <- mkStatsCsr; Reg#(Data) stats_csr = stats_module.reg_ifc; +`ifdef INCLUDE_GDB_CONTROL + // DCSR is 32b even in RV64 + Bit #(32) dcsr_reset_value = {4'h4, // [31:28] xdebugver + 12'h0, // [27:16] reserved + 1'h0, // [15] ebreakm + 1'h0, // [14] reserved + 1'h0, // [13] ebreaks + 1'h0, // [12] ebreaku + 1'h0, // [11] stepie + 1'h0, // [10] stopcount + 1'h0, // [9] stoptime + 3'h0, // [8:7] cause // WARNING: 0 is non-standard + 1'h0, // [5] reserved + 1'h1, // [4] mprven + 1'h0, // [3] nmip // non-maskable interrupt pending + 1'h0, // [2] step + 2'h3}; // [1:0] prv (machine mode) + + Reg #(Data) rg_dcsr <- mkReg (zeroExtend (dcsr_reset_value)); + Reg #(Data) rg_dpc <- mkReg (truncate (soc_map_struct.pc_reset_value)); + Reg #(Data) rg_dscratch0 <- mkRegU; + Reg #(Data) rg_dscratch1 <- mkRegU; +`endif + `ifdef SECURITY // sanctum machine CSRs @@ -607,6 +651,14 @@ module mkCsrFile #(Data hartid)(CsrFile); CSRmspec: mspec_csr; CSRtrng: trng_csr; `endif + +`ifdef INCLUDE_GDB_CONTROL + CSRdcsr: rg_dcsr; // TODO: take NMI into account (cf. Piccolo/Flute) + CSRdpc: rg_dpc; + CSRdscratch0: rg_dscratch0; + CSRdscratch1: rg_dscratch1; +`endif + default: readOnlyReg(64'b0); endcase); endfunction @@ -856,4 +908,40 @@ module mkCsrFile #(Data hartid)(CsrFile); method doPerfStats = stats_module.doPerfStats; method sendDoStats = stats_module.sendDoStats; method recvDoStats = stats_module.recvDoStats; + + // ---------------- + // Bluespec: + // Methods when Debug Module is present + +`ifdef INCLUDE_GDB_CONTROL + // Read dpc + method Addr dpc_read (); + return rg_dpc; + endmethod + + // Update dpc + method Action dpc_write (Addr pc); + rg_dpc <= pc; + endmethod + + // Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku} + method Bool dcsr_stop_for_break; + return case (prv_reg) + prvM: (rg_dcsr [15] == 1'b1); + prvS: (rg_dcsr [13] == 1'b1); + prvU: (rg_dcsr [12] == 1'b1); + endcase; + endmethod + + // Check whether to enter Debug Mode based on dcsr.step + method Bool dcsr_stop_for_step; + return (rg_dcsr [2] == 1'b1); + endmethod + + // Update 'cause' in DCSR + method Action dcsr_cause_write (Bit #(3) dcsr_cause); + rg_dcsr <= { 32'b0, rg_dcsr [31:9], dcsr_cause, rg_dcsr [5:2], prv_reg }; + endmethod +`endif + endmodule diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index f485003..900b9f8 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -92,6 +92,31 @@ import TV_Info :: *; // ================================================================ +// Major States of CPU + +typedef enum {CPU_RESET1, + CPU_RESET2, + +`ifdef INCLUDE_GDB_CONTROL + CPU_GDB_PAUSING, // On GDB breakpoint, while waiting for fence completion +`endif + CPU_DEBUG_MODE, // Stopped (normally for debugger) + CPU_RUNNING // Normal operation + } CPU_State +deriving (Eq, Bits, FShow); + +function Bool fn_is_running (CPU_State cpu_state); + return ( (cpu_state != CPU_RESET1) + && (cpu_state != CPU_RESET2) +`ifdef INCLUDE_GDB_CONTROL + && (cpu_state != CPU_GDB_PAUSING) + && (cpu_state != CPU_DEBUG_MODE) +`endif + ); +endfunction + +// ================================================================ + (* synthesize *) module mkProc (Proc_IFC); @@ -108,6 +133,11 @@ module mkProc (Proc_IFC); // Verbosity: 0=quiet; 1=instruction trace; 2=more detail Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0); + // ---------------- + // Major CPU states + + Reg #(CPU_State) rg_state <- mkReg (CPU_RESET1); + // ---------------- // Reset requests and responses (TODO: to be implemented) @@ -258,6 +288,8 @@ module mkProc (Proc_IFC); mmio_axi4_adapter.reset; f_reset_rsps.enq (?); + + rg_state <= CPU_RUNNING; endrule // ---------------- @@ -287,6 +319,122 @@ module mkProc (Proc_IFC); end endrule + // ================================================================ + // ================================================================ + // ================================================================ + // DEBUGGER ACCESS + +`ifdef INCLUDE_GDB_CONTROL + + // ---------------- + // Debug Module Run (resume) control + + // Run command when in debug mode + rule rl_debug_run ((f_run_halt_reqs.first == True) + && (! f_gpr_reqs.notEmpty) + && (! f_fpr_reqs.notEmpty) + && (! f_csr_reqs.notEmpty) + && (rg_state == CPU_DEBUG_MODE)); + // if (cfg_verbosity > 1) + $display ("%0d: %m.rl_debug_run", cur_cycle); + + f_run_halt_reqs.deq; + core[0].resume_from_debug_mode; + rg_state <= CPU_RUNNING; + + // Notify debugger that we've started running + f_run_halt_rsps.enq (True); + endrule + + // Run command when already running + rule rl_debug_run_redundant ((f_run_halt_reqs.first == True) + && (! f_gpr_reqs.notEmpty) + && (! f_fpr_reqs.notEmpty) + && (! f_csr_reqs.notEmpty) + && fn_is_running (rg_state)); + // if (cfg_verbosity > 1) + $display ("%0d: %m.rl_debug_run_redundant", cur_cycle); + + f_run_halt_reqs.deq; + + // Notify debugger that we're running + f_run_halt_rsps.enq (True); + endrule + + // ---------------- + // Debug Module Halt control + + rule rl_debug_halt ((f_run_halt_reqs.first == False) && fn_is_running (rg_state)); + // if (cfg_verbosity > 1) + $display ("%0d: %m.rl_debug_halt", cur_cycle); + + f_run_halt_reqs.deq; + + // Debugger 'halt' request (e.g., GDB '^C' command) + core[0].halt_to_debug_mode_req; + + rg_state <= CPU_GDB_PAUSING; + endrule + + rule rl_debug_halted ((rg_state == CPU_GDB_PAUSING) && core [0].is_debug_halted); + // Notify debugger that we've halted + f_run_halt_rsps.enq (False); + // Stop executing rules until ready to restart from debugger + rg_state <= CPU_DEBUG_MODE; + + // if (cfg_verbosity > 1) + $display ("%0d: %m.rl_debug_halted", cur_cycle); + endrule + + rule rl_debug_halt_redundant ((f_run_halt_reqs.first == False) && (! fn_is_running (rg_state))); + // if (cfg_verbosity > 1) + $display ("%0d: %m.rl_debug_halt_redundant", cur_cycle); + + f_run_halt_reqs.deq; + + // Notify debugger that we've 'halted' + f_run_halt_rsps.enq (False); + + $display ("%0d: %m.rl_debug_halt_redundant: CPU already halted; state = ", cur_cycle, fshow (rg_state)); + endrule + + // ---------------- + // Debug Module CSR read/write + + rule rl_debug_read_csr ((rg_state == CPU_DEBUG_MODE) && (! f_csr_reqs.first.write)); + let req <- pop (f_csr_reqs); + Bit #(12) csr_addr = req.address; + let data = core [0].csr_read (csr_addr); + let rsp = DM_CPU_Rsp {ok: True, data: data}; + f_csr_rsps.enq (rsp); + // if (cur_verbosity > 1) + $display ("%m.rl_debug_read_csr: csr %0d => 0x%0h", + csr_addr, data); + endrule + + rule rl_debug_write_csr ((rg_state == CPU_DEBUG_MODE) && f_csr_reqs.first.write); + let req <- pop (f_csr_reqs); + Bit #(12) csr_addr = req.address; + let data = req.data; + core [0].csr_write (csr_addr, data); + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_csr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", csr_addr, data); + endrule + + rule rl_debug_csr_access_busy (rg_state != CPU_DEBUG_MODE); + let req <- pop (f_csr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_csr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%m.rl_debug_csr_access_busy"); + endrule + +`endif + // ================================================================ // ================================================================ // ================================================================ @@ -305,7 +453,7 @@ module mkProc (Proc_IFC); mmioPlatform.start (tohostAddr, fromhostAddr); - $display ("Proc.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h", + $display ("%m.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h", startpc, tohostAddr, fromhostAddr); endmethod diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index dc142d3..d4149b6 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -39,6 +39,8 @@ import StoreBuffer::*; import VerificationPacket::*; import RenameDebugIF::*; +import Cur_Cycle :: *; + typedef struct { // info about the inst blocking at ROB head Addr pc; @@ -112,6 +114,18 @@ interface CommitStage; // rename debug method Action startRenameDebug; interface Get#(RenameErrInfo) renameErr; + +`ifdef INCLUDE_GDB_CONTROL + // Request halt into debug mode + method Action halt_to_debug_mode_req; + + (* always_ready *) + // Becomes true when pipeline is halted + method Bool is_debug_halted; + + method Action resume_from_debug_mode; +`endif + endinterface // we apply actions the end of commit rule @@ -122,6 +136,17 @@ typedef struct { Trap trap; } CommitTrap deriving(Bits, Eq, FShow); +// Bluespec: for debugger run-control +typedef enum { + Run_State_RUNNING // Normal state +`ifdef INCLUDE_GDB_CONTROL + , Run_State_DEBUGGER_HALT // When ready to halt for debugger after stop/step + , Run_State_DEBUGGER_HALT_FLUSH // When flushing state during debugger halt + , Run_State_DEBUGGER_HALTED // When halted for debugger +`endif + } Run_State +deriving (Eq, FShow, Bits); + module mkCommitStage#(CommitInput inIfc)(CommitStage); Bool verbose = False; @@ -129,6 +154,17 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Integer verbosity = 1; Reg #(Bit #(64)) rg_instret <- mkReg (0); + // Bluespec: for debugger run-control + Reg #(Run_State) rg_run_state <- mkReg (Run_State_RUNNING); + +`ifdef INCLUDE_GDB_CONTROL + // rg_stop_req is set True when debugger requests a stop (e.g., GDB ^C) + Reg #(Bool) rg_stop_req <- mkReg (False); + // When going into debug mode, these hold the cause for the break and the resume-PC + Reg #(Bit #(3)) rg_debug_cause <- mkRegU; + Reg #(Addr) rg_debug_pc <- mkRegU; +`endif + // func units ReorderBufferSynth rob = inIfc.robIfc; RegRenamingTable regRenamingTable = inIfc.rtIfc; @@ -338,15 +374,57 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); endaction endfunction +`ifdef INCLUDE_GDB_CONTROL + // ================================================================ + // Bluespec: debugger run-control + // Every time an instruction commits, we check this boolean + // to decide whether we continue running of stop. + + // We halt after committing an instruction if: + // the debugger requested a stop + // or dcsr.step is True + + Maybe #(Bit #(3)) m_debug_stop_step_cause = ( rg_stop_req + ? tagged Valid 3 // Debug Module haltreq + : (csrf.dcsr_stop_for_step + ? tagged Valid 4 // dcsr.step + : tagged Invalid)); + + // ================================================================ + + /* + // Bluespec: debugger run-control + // Rule cond should be identical to doCommitTrap_flush's cond + // except for fn_ebreak_to_debug_mode() + rule doCommitTrap_ebreak_to_debug_mode( + (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control + !isValid(commitTrap) &&& + rob.deqPort[0].deq_data.trap matches tagged Valid .trap &&& + fn_ebreak_to_debug_mode (trap) // Bluespec: debugger run-control + ); + let x = rob.deqPort[0].deq_data; + rg_run_state <= Run_State_DEBUGGER_HALT; + rg_debug_pc <= x.pc; + rg_debug_cause <= 1; // cause: EBREAK + endrule + */ +`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 // pipelined, then we need to check spec bits at commit port. rule doCommitTrap_flush( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control +`endif !isValid(commitTrap) &&& rob.deqPort[0].deq_data.trap matches tagged Valid .trap ); + $display ("%0d: %m.CommitStage.rule_doCommitTrap_flush", cur_cycle); rob.deqPort[0].deq; let x = rob.deqPort[0].deq_data; if(verbose) $display("[doCommitTrap] ", fshow(x)); @@ -404,7 +482,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); doAssert(x.spec_bits == 0, "cannot have spec bits"); endrule - rule doCommitTrap_handle(commitTrap matches tagged Valid .trap); + // This rule's condition is enabled only by the previous rule, doCommitTrap_flush + rule doCommitTrap_handle( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control +`endif + commitTrap matches tagged Valid .trap); + + $display ("%0d: %m.CommitStage.rule_doCommitTrap_handle", cur_cycle); + // reset commitTrap commitTrap <= Invalid; @@ -413,9 +499,31 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); inIfc.commitCsrInstOrInterrupt; end - // trap handling & redirect - let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); - inIfc.redirectPc(new_pc); +`ifdef INCLUDE_GDB_CONTROL + if ((trap.trap == tagged Exception Breakpoint) && csrf.dcsr_stop_for_break) begin + // Don't handle the trap + rg_run_state <= Run_State_DEBUGGER_HALTED; + // Record debug CSRs for later Debugger query and later resumption + csrf.dcsr_cause_write (1); // EBREAK dcsr.cause + csrf.dpc_write (trap.pc); // Where we'll resume on 'continue' + end + else begin + // Handle the trap and redirect + let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); + inIfc.redirectPc (new_pc); + + if (m_debug_stop_step_cause matches tagged Valid .cause) begin + rg_run_state <= Run_State_DEBUGGER_HALTED; + // Record debug CSRs for later Debugger query and later resumption + csrf.dcsr_cause_write (cause); + csrf.dpc_write (new_pc); // Where we'll resume on 'continue' + end + end +`else + // trap handling & redirect + let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); + inIfc.redirectPc(new_pc); +`endif // system consistency // TODO spike flushes TLB here, but perhaps it is because spike's TLB @@ -427,6 +535,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // commit misspeculated load rule doCommitKilledLd( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control +`endif !isValid(commitTrap) &&& !isValid(rob.deqPort[0].deq_data.trap) &&& rob.deqPort[0].deq_data.ldKilled matches tagged Valid .killBy @@ -437,7 +548,19 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // kill everything, redirect, and increment epoch inIfc.killAll; - inIfc.redirectPc(x.pc); + +`ifdef INCLUDE_GDB_CONTROL + // Bluespec: debug run-control + doAssert (x.iType != Ebreak, "CommitStage.rule_doCommitKilledLd iType should not be Ebreak"); + if (m_debug_stop_step_cause matches tagged Valid .cause) begin + rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; + rg_debug_pc <= x.pc; + rg_debug_cause <= cause; + end + else +`endif + inIfc.redirectPc(x.pc); // original (no debugger) + inIfc.incrementEpoch; // the killed Ld should have claimed phy reg, we should not commit it; @@ -461,6 +584,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // commit system inst rule doCommitSystemInst( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control +`endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && @@ -510,7 +636,18 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); else if(x.iType == Mret) begin next_pc <- csrf.mret; end - inIfc.redirectPc(next_pc); + +`ifdef INCLUDE_GDB_CONTROL + // Bluespec: debug run-control + doAssert (x.iType != Ebreak, "CommitStage.rule_doCommitSystemInst iType should not be Ebreak"); + if (m_debug_stop_step_cause matches tagged Valid .cause) begin + rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; + rg_debug_pc <= next_pc; + rg_debug_cause <= cause; + end + else +`endif + inIfc.redirectPc(next_pc); // original (no debugger) // rename stage only sends out system inst when ROB is empty, so no // need to flush ROB again @@ -567,6 +704,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // Lr/Sc/Amo/MMIO cannot proceed to executed until we notify LSQ that it // has reached the commit stage rule notifyLSQCommit( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control +`endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && @@ -585,6 +725,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // commit normal: fire when at least one commit can be done rule doCommitNormalInst( +`ifdef INCLUDE_GDB_CONTROL + (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control +`endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && @@ -596,6 +739,10 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // 2. inst is not ready to commit Bool stop = False; + // Bluespec: debugger run-control + // 3. one instr is committed and debugger halt is requested (due to stop or step) + Bool stop_for_debugger = False; + // We merge writes on FPU csr and apply writes at the end of the rule Bit#(5) fflags = 0; Bool will_dirty_fpu_state = False; @@ -620,7 +767,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // compute what actions to take for(Integer i = 0; i < valueof(SupSize); i = i+1) begin - if(!stop && rob.deqPort[i].canDeq) begin + + if(!stop && (! stop_for_debugger) && rob.deqPort[i].canDeq) begin let x = rob.deqPort[i].deq_data; let inst_tag = rob.deqPort[i].getDeqInstTag; @@ -673,6 +821,35 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); comUserInstCnt = comUserInstCnt + 1; // user space inst end +`ifdef INCLUDE_GDB_CONTROL + if (m_debug_stop_step_cause matches tagged Valid .cause + &&& (comInstCnt != 0)) + begin + $display ("%0d: %m.CommitStage.rule_doCommitNormalInst: Stopping for debugger", cur_cycle); + stop_for_debugger = True; + + // Compute next PC in case of debugger stop. + // Note: AluExePipeline.rule_doFinishAlu does inIfc.rob_setExecuted (... x.controlFlow) + // which updates the rob entry's ppc_vaddr_csrData field with actual + // branch/jump targets, which we retrieve here. + Addr next_pc = ?; + if (x.ppc_vaddr_csrData matches tagged PPC .addr + &&& ((x.iType == J) || (x.iType == Jr) || (x.iType == Br))) + // JAL, JALR, BRANCH + next_pc = addr; + else if (x.orig_inst [1:0] == 2'b11) + // RV32I RV64I + next_pc = x.pc + 4; + else + // RVC + next_pc = x.pc + 2; + + rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; + rg_debug_pc <= next_pc; + rg_debug_cause <= cause; + end +`endif + `ifdef PERF_COUNT // performance counter case(x.iType) @@ -688,7 +865,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif end end - end + end // for-loop for superscalar width rg_instret <= rg_instret + instret; // write FPU csr @@ -736,6 +913,47 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif endrule +`ifdef INCLUDE_GDB_CONTROL + // ================================================================ + // Rules to move into debug mode + + // This rule is like rule doCommitTrap_flush, i.e., a debugger-halt is like an interrupt + rule rl_enter_debug_mode_flush (rg_run_state == Run_State_DEBUGGER_HALT_FLUSH); + $write ("%0d: %m.commitStage.rl_enter_debug_mode:", cur_cycle); + if (rg_debug_cause == 1) $display (" EBREAK"); + else if (rg_debug_cause == 3) $display (" Debugger halt request"); + else if (rg_debug_cause == 4) $display (" Halt after step"); + else $display (" Unknown cause %0d", rg_debug_cause); + + // flush everything. Only increment epoch and stall fetch when we haven + // not done it yet (we may have already done them at rename stage) + inIfc.killAll; + inIfc.incrementEpoch; + inIfc.setFetchWaitRedirect; + + rg_run_state <= Run_State_DEBUGGER_HALT; + endrule + + // This rule is like rule doCommitTrap_handle, except we don't redirect + rule rl_enter_debug_mode_halt (rg_run_state == Run_State_DEBUGGER_HALT); + // system consistency + // TODO spike flushes TLB here, but perhaps it is because spike's TLB + // does not include prv info, and it has to flush when prv changes. + // XXX As approximation, Trap may cause context switch, so flush for + // security + makeSystemConsistent(False, True, False); + + // Record debug CSRs for later Debugger query and later resumption + csrf.dcsr_cause_write (rg_debug_cause); // reason for entering debug mode + csrf.dpc_write (rg_debug_pc); // Where we'll resume on 'continue' + + // Go to HALTED state where no rule fires. + // To re-start, mkCore must call restart method. + rg_run_state <= Run_State_DEBUGGER_HALTED; + endrule + + // ================================================================ +`endif method Data getPerf(ComStagePerfType t); return (case(t) @@ -785,4 +1003,24 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); endmethod interface renameErr = nullGet; `endif + +`ifdef INCLUDE_GDB_CONTROL + // Request halt into debug mode + method Action halt_to_debug_mode_req () if (rg_run_state == Run_State_RUNNING); + $display ("%0d: %m.commitStage.halt_to_debug_mode_req", cur_cycle); + rg_stop_req <= True; + endmethod + + // Becomes true when pipeline is halted + method Bool is_debug_halted; + return (rg_run_state == Run_State_DEBUGGER_HALTED); + endmethod + + method Action resume_from_debug_mode () if (rg_run_state == Run_State_DEBUGGER_HALTED); + $display ("%0d: %m.commitStage.resume_from_debug_mode", cur_cycle); + rg_stop_req <= False; + rg_run_state <= Run_State_RUNNING; + endmethod +`endif + endmodule diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 635d904..31118ff 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -50,6 +50,8 @@ import CCTypes::*; import L1CoCache::*; import MMIOInst::*; +import Cur_Cycle :: *; + // ================================================================ // For fv_decode_C function and related types and definitions @@ -90,6 +92,10 @@ interface FetchStage; // performance interface Perf#(DecStagePerfType) perf; + +`ifdef INCLUDE_GDB_CONTROL + method Action resume_from_debug_mode (Addr new_pc); +`endif endinterface typedef struct { @@ -984,6 +990,7 @@ module mkFetchStage(FetchStage); interface mmioIfc = mmio.toCore; method Action start(Addr start_pc); + $display ("%0d: %m.start (start_pc = 0x%0h)", cur_cycle, start_pc); pc_reg[0] <= start_pc; started <= True; waitForRedirect <= False; @@ -991,6 +998,7 @@ module mkFetchStage(FetchStage); endmethod method Action stop(); started <= False; + $display ("%0d: %m.stop", cur_cycle); endmethod method Action setWaitRedirect; @@ -1095,5 +1103,24 @@ module mkFetchStage(FetchStage); method Bool respValid = perfReqQ.notEmpty; `endif endinterface + +`ifdef INCLUDE_GDB_CONTROL + method Action resume_from_debug_mode (Addr new_pc); + if (verbose) + $display("resume_from_debug_mode: newpc %h, old f_main_epoch %d, new f_main_epoch %d", + new_pc, f_main_epoch, f_main_epoch + 1); + pc_reg[pc_redirect_port] <= new_pc; + f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1; + ehr_pending_straddle[1] <= tagged Invalid; + // redirect comes, stop stalling for redirect + waitForRedirect <= False; + setWaitRedirect_redirect_conflict.wset(?); // conflict with setWaitForRedirect + + // this redirect may be caused by a trap/system inst in commit stage + // we conservatively set wait for flush TODO make this an input parameter + // TODO: do we need this? waitForFlush <= True; + endmethod +`endif + endmodule diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index a3ce618..b4f2d5f 100644 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -269,6 +269,14 @@ typedef enum { // sanctum user CSR CSRtrng = 12'hcc0, // random number for secure boot `endif + +`ifdef INCLUDE_GDB_CONTROL + CSRdcsr = 12'h7B0, // Debug control and status + CSRdpc = 12'h7B1, // Debug PC + CSRdscratch0 = 12'h7B2, // Debug scratch0 + CSRdscratch1 = 12'h7B3, // Debug scratch1 +`endif + // CSR that catches all the unimplemented CSRs. To avoid exception on this, // make it a user non-standard read/write CSR. CSRnone = 12'h8ff From 1278927f517bcb10b9f8943e898637c29c897f05 Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Wed, 8 Jan 2020 20:31:33 -0500 Subject: [PATCH 2/8] Removed a block-commented piece of code --- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index d4149b6..8a86cf2 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -391,27 +391,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); : tagged Invalid)); // ================================================================ - - /* - // Bluespec: debugger run-control - // Rule cond should be identical to doCommitTrap_flush's cond - // except for fn_ebreak_to_debug_mode() - rule doCommitTrap_ebreak_to_debug_mode( - (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control - !isValid(commitTrap) &&& - rob.deqPort[0].deq_data.trap matches tagged Valid .trap &&& - fn_ebreak_to_debug_mode (trap) // Bluespec: debugger run-control - ); - let x = rob.deqPort[0].deq_data; - rg_run_state <= Run_State_DEBUGGER_HALT; - rg_debug_pc <= x.pc; - rg_debug_cause <= 1; // cause: EBREAK - endrule - */ `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 From 27c3c7cb4dafce909fe17102a545ceeb8425a6b3 Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Sun, 12 Jan 2020 22:25:14 -0500 Subject: [PATCH 3/8] Work in progress on Debug Module integration. Got further on start/step/halt --- src_Core/CPU/Core.bsv | 187 ++++++++---- src_Core/CPU/CsrFile.bsv | 27 +- src_Core/CPU/Proc.bsv | 65 ++-- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 288 ++++++------------ .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 38 +-- .../RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv | 1 + .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 75 +++++ src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv | 17 +- 8 files changed, 364 insertions(+), 334 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 03631c8..122c6e9 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -86,6 +86,12 @@ import CsrFile :: *; import Cur_Cycle :: *; +`ifdef SECURITY +`define SECURITY_OR_INCLUDE_GDB_CONTROL +`elsif INCLUDE_GDB_CONTROL +`define SECURITY_OR_INCLUDE_GDB_CONTROL +`endif + interface CoreReq; method Action start( Addr startpc, @@ -142,16 +148,15 @@ interface Core; method Action setDEIP (Bit #(1) v); `ifdef INCLUDE_GDB_CONTROL - method Action halt_to_debug_mode_req; + method Action debug_halt; (* always_ready *) method Bool is_debug_halted; - method Action resume_from_debug_mode; + method Action debug_resume; method Data csr_read (Bit #(12) csr_addr); method Action csr_write (Bit #(12) csr_addr, Data data); - `endif endinterface @@ -164,6 +169,15 @@ interface CoreFixPoint; interface Reg#(Bool) doStatsIfc; endinterface +typedef enum { +`ifdef INCLUDE_GDB_CONTROL + CORE_HALTING, + CORE_HALTED, +`endif + CORE_RUNNING + } Core_Run_State +deriving (Bits, Eq, FShow); + (* synthesize *) module mkCore#(CoreId coreId)(Core); let verbose = False; @@ -173,10 +187,10 @@ module mkCore#(CoreId coreId)(Core); outOfReset <= True; endrule - Reg#(Bool) started <- mkReg(False); // only used for deadlock check + Reg#(Bool) started <- mkReg(False); `ifdef INCLUDE_GDB_CONTROL - Reg#(Bool) rg_debug_halted <- mkReg (False); + Reg #(Core_Run_State) rg_core_run_state <- mkReg (CORE_RUNNING); `endif // front end @@ -403,13 +417,15 @@ module mkCore#(CoreId coreId)(Core); Reg#(Bool) flush_tlbs <- mkReg(False); Reg#(Bool) update_vm_info <- mkReg(False); Reg#(Bool) flush_reservation <- mkReg(False); -`ifdef SECURITY + +`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL Reg#(Bool) flush_caches <- mkReg(False); Reg#(Bool) flush_brpred <- mkReg(False); `else Reg#(Bool) flush_caches <- mkReadOnlyReg(False); Reg#(Bool) flush_brpred <- mkReadOnlyReg(False); `endif + `ifdef SELF_INV_CACHE Reg#(Bool) reconcile_i <- mkReg(False); `else @@ -508,16 +524,48 @@ module mkCore#(CoreId coreId)(Core); method stqEmpty = lsq.stqEmpty; method lsqSetAtCommit = lsq.setAtCommit; method tlbNoPendingReq = iTlb.noPendingReq && dTlb.noPendingReq; - method setFlushTlbs = flush_tlbs._write(True); - method setUpdateVMInfo = update_vm_info._write(True); - method setFlushReservation = flush_reservation._write(True); - method setFlushBrPred = flush_brpred._write(True); - method setFlushCaches = flush_caches._write(True); + + method setFlushTlbs; + action + flush_tlbs <= True; + // $display ("%0d: %m.commitInput.setFlushTlbs", cur_cycle); + endaction + endmethod + + method setUpdateVMInfo; + action + update_vm_info <= True; + // $display ("%0d: %m.commitInput.setUpdateVMInfo", cur_cycle); + endaction + endmethod + + method setFlushReservation; + action + flush_reservation <= True; + // $display ("%0d: %m.commitInput.setFlushReservation", cur_cycle); + endaction + endmethod + + method setFlushBrPred; + action + flush_brpred <= True; + // $display ("%0d: %m.commitInput.setFlushBrPred", cur_cycle); + endaction + endmethod + + method setFlushCaches; + action + flush_caches <= True; + // $display ("%0d: %m.commitInput.setFlushCaches", cur_cycle); + endaction + endmethod + method setReconcileI = reconcile_i._write(True); method setReconcileD = reconcile_d._write(True); method killAll = coreFix.killAll; method redirectPc = fetchStage.redirect; method setFetchWaitRedirect = fetchStage.setWaitRedirect; + method setFetchWaitFlush = fetchStage.setWaitFlush; method incrementEpoch = epochManager.incrementEpoch; method commitCsrInstOrInterrupt = csrInstOrInterruptInflight_commit._write(False); method doStats = coreFix.doStatsIfc._read; @@ -531,21 +579,6 @@ module mkCore#(CoreId coreId)(Core); endinterface); CommitStage commitStage <- mkCommitStage(commitInput); - (* mutually_exclusive = "coreFix.aluExe_0.doRegReadAlu, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.aluExe_1.doRegReadAlu, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.aluExe_0.doDispatchAlu, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.aluExe_1.doDispatchAlu, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishIntMul, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishIntDiv, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpFma, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpDiv, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpSqrt, commitStage.rl_enter_debug_mode_flush" *) - (* mutually_exclusive = "coreFix.fpuMulDivExe_0.doFinishFpSqrt, commitStage.rl_enter_debug_mode_flush" *) - - rule rl_bogus_dummy (False); - // Just to allow the scheduling attributes above - endrule - // send rob enq time to reservation stations (* fire_when_enabled, no_implicit_conditions *) rule sendRobEnqTime; @@ -575,11 +608,13 @@ module mkCore#(CoreId coreId)(Core); if (flush_reservation) begin flush_reservation <= False; dMem.resetLinkAddr; + // $display ("%0d: %m.rule prepareCachesAndTlbs: flushing reservation", cur_cycle); end if (flush_tlbs) begin flush_tlbs <= False; iTlb.flush; dTlb.flush; + // $display ("%0d: %m.rule prepareCachesAndTlbs: flushing iTlb and dTlb", cur_cycle); end if (update_vm_info) begin update_vm_info <= False; @@ -588,10 +623,11 @@ module mkCore#(CoreId coreId)(Core); iTlb.updateVMInfo(vmI); dTlb.updateVMInfo(vmD); l2Tlb.updateVMInfo(vmI, vmD); + // $display ("%0d: %m.rule prepareCachesAndTlbs: updating VMInfo", cur_cycle); end endrule -`ifdef SECURITY +`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL // Use wires to capture flush regs and empty signals. This is ok because // there cannot be any activity to make empty -> not-empty or need-flush -> // no-need-flush when we are trying to flush. @@ -600,6 +636,7 @@ module mkCore#(CoreId coreId)(Core); rule setDoFlushCaches(flush_caches && fetchStage.emptyForFlush && lsq.noWrongPathLoads); doFlushCaches.send; + $display ("%0d: %m.rl_setDoFlushCaches", cur_cycle); endrule rule setDoFlushBrPred(flush_brpred && fetchStage.emptyForFlush); @@ -612,6 +649,7 @@ module mkCore#(CoreId coreId)(Core); flush_caches <= False; iMem.flush; dMem.flush; + $display ("%0d: %m.rule flushCaches (imem and dmem)", cur_cycle); endrule // security flush branch predictors: wait for wrong path inst fetches to @@ -619,6 +657,7 @@ module mkCore#(CoreId coreId)(Core); rule flushBrPred(doFlushBrPred); flush_brpred <= False; fetchStage.flush_predictors; + $display ("%0d: %m.rule flushBrPred", cur_cycle); endrule `endif @@ -663,9 +702,12 @@ module mkCore#(CoreId coreId)(Core); `endif // SELF_INV_CACHE rule readyToFetch( +`ifdef INCLUDE_GDB_CONTROL + (rg_core_run_state == CORE_RUNNING) && +`endif !flush_reservation && !flush_tlbs && !update_vm_info && iTlb.flush_done && dTlb.flush_done -`ifdef SECURITY +`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL && !flush_caches && !flush_brpred && iMem.flush_done && dMem.flush_done && fetchStage.flush_predictors_done @@ -680,6 +722,50 @@ module mkCore#(CoreId coreId)(Core); fetchStage.done_flushing(); endrule +`ifdef INCLUDE_GDB_CONTROL + rule rl_debug_halting((rg_core_run_state == CORE_HALTING) && + !flush_reservation && !flush_tlbs && !update_vm_info + && iTlb.flush_done && dTlb.flush_done + && !flush_caches && !flush_brpred + && iMem.flush_done && dMem.flush_done + && fetchStage.flush_predictors_done +`ifdef SELF_INV_CACHE + && !reconcile_i && iMem.reconcile_done +`ifdef SYSTEM_SELF_INV_L1D + && !reconcile_d +`endif +`endif + && commitStage.is_debug_halted + ); + + fetchStage.done_flushing(); + rg_core_run_state <= CORE_HALTED; + + $display ("%0d: %m.rl_debug_halting", cur_cycle); + endrule +`endif + + /* +`ifdef INCLUDE_GDB_CONTROL + // TODO: DELETE AFTER DEBUGGING + rule rl_flushing_conditions (rg_core_run_state == CORE_HALTING); + $display ("%0d: %m.rl_done_flushing_for_debug_halt", cur_cycle); + $display (" !flush_reservation = %0d, !flush_tlbs = %0d, !update_vm_info = %0d", + !flush_reservation, !flush_tlbs, !update_vm_info); + $display (" iTlb.flush_done = %0d, dTlb.flush_done = %0d", iTlb.flush_done, dTlb.flush_done); + $display (" !flush_caches = %0d !flush_brpred = %0d", !flush_caches, !flush_brpred); + $display (" iMem.flush_done = %0d dMem.flush_done = %0d", iMem.flush_done, dMem.flush_done); + $display (" fetchStage.flush_predictors_done = %0d", fetchStage.flush_predictors_done); +`ifdef SELF_INV_CACHE + $display (" !reconcile_i = %0d, iMem.reconcide_done = %0d", !reconcile_i, iMem.reconcile_done); +`ifdef SYSTEM_SELF_INV_L1D + $display (" reconcile_d = %0d", reconcile_d); +`endif +`endif + endrule +`endif + */ + `ifdef PERF_COUNT // incr cycle count (* fire_when_enabled, no_implicit_conditions *) @@ -937,19 +1023,6 @@ module mkCore#(CoreId coreId)(Core); endrule `endif -`ifdef INCLUDE_GDB_CONTROL - // ================================================================ - // Stopping into debug mode - - rule rl_debug_halt_actions ((! rg_debug_halted) && commitStage.is_debug_halted); - $display ("%0d: %m.rl_debug_halt_actions", cur_cycle); - rg_debug_halted <= True; - endrule - -`endif - - // ================================================================ - interface CoreReq coreReq; method Action start( Bit#(64) startpc, @@ -958,7 +1031,7 @@ module mkCore#(CoreId coreId)(Core); fetchStage.start(startpc); started <= True; `ifdef INCLUDE_GDB_CONTROL - rg_debug_halted <= False; + rg_core_run_state <= CORE_RUNNING; `endif mmio.setHtifAddrs(toHostAddr, fromHostAddr); // start rename debug @@ -1032,34 +1105,34 @@ module mkCore#(CoreId coreId)(Core); method Action setDEIP (v) = csrf.setDEIP (v); `ifdef INCLUDE_GDB_CONTROL - method Action halt_to_debug_mode_req () if (! rg_debug_halted); - $display ("%0d: %m.halt_to_debug_mode_req", cur_cycle); + method Action debug_halt () if (started && (rg_core_run_state == CORE_RUNNING)); + $display ("%0d: %m.debug_halt", cur_cycle); started <= False; - fetchStage.stop; - commitStage.halt_to_debug_mode_req; + renameStage.debug_halt; // start the halt protocol + rg_core_run_state <= CORE_HALTING; endmethod method Bool is_debug_halted; - return rg_debug_halted; + return (rg_core_run_state == CORE_HALTED); endmethod - method Action resume_from_debug_mode if (rg_debug_halted); + method Action debug_resume () if (rg_core_run_state == CORE_HALTED); + renameStage.debug_resume; + commitStage.debug_resume; + let startpc = csrf.dpc_read; - fetchStage.resume_from_debug_mode (startpc); - commitStage.resume_from_debug_mode; - started <= True; - rg_debug_halted <= False; + fetchStage.redirect (startpc); - $display ("%0d: %m.resume_from_debug_mode, dpc = 0x%0h", cur_cycle, startpc); + started <= True; + rg_core_run_state <= CORE_RUNNING; + $display ("%0d: %m.debug_resume, dpc = 0x%0h", cur_cycle, startpc); endmethod - // TODO_DEBUG: was part of method cond: commitStage.is_debug_halted && - method Data csr_read (Bit #(12) csr_addr) if (rg_debug_halted); + method Data csr_read (Bit #(12) csr_addr) if (rg_core_run_state == CORE_HALTED); return csrf.rd (unpack (csr_addr)); endmethod - // TODO_DEBUG: was part of method cond: commitStage.is_debug_halted && - method Action csr_write (Bit #(12) csr_addr, Data data) if (rg_debug_halted); + method Action csr_write (Bit #(12) csr_addr, Data data) if (rg_core_run_state == CORE_HALTED); csrf.csrInstWr (unpack (csr_addr), data); endmethod `endif diff --git a/src_Core/CPU/CsrFile.bsv b/src_Core/CPU/CsrFile.bsv index 1e43050..9b4262b 100644 --- a/src_Core/CPU/CsrFile.bsv +++ b/src_Core/CPU/CsrFile.bsv @@ -101,10 +101,10 @@ interface CsrFile; method Action dpc_write (Addr pc); // Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku} - method Bool dcsr_stop_for_break; + method Bit #(1) dcsr_break_bit; - // Check whether to enter Debug Mode based on dcsr.step - method Bool dcsr_stop_for_step; + // Read dcsr[2], the step bit + method Bit #(1) dcsr_step_bit; // Update 'cause' in DCSR (* always_ready *) @@ -539,10 +539,11 @@ module mkCsrFile #(Data hartid)(CsrFile); 1'h0, // [2] step 2'h3}; // [1:0] prv (machine mode) - Reg #(Data) rg_dcsr <- mkReg (zeroExtend (dcsr_reset_value)); - Reg #(Data) rg_dpc <- mkReg (truncate (soc_map_struct.pc_reset_value)); - Reg #(Data) rg_dscratch0 <- mkRegU; - Reg #(Data) rg_dscratch1 <- mkRegU; + // RV64: dcsr's upper 32b zeroExtended/ignored + Reg #(Data) rg_dcsr <- mkConfigReg (zeroExtend (dcsr_reset_value)); + Reg #(Data) rg_dpc <- mkConfigReg (truncate (soc_map_struct.pc_reset_value)); + Reg #(Data) rg_dscratch0 <- mkConfigRegU; + Reg #(Data) rg_dscratch1 <- mkConfigRegU; `endif `ifdef SECURITY @@ -925,17 +926,17 @@ module mkCsrFile #(Data hartid)(CsrFile); endmethod // Check whether to enter Debug Mode based on dcsr.{ebreakm, ebreaks, ebreaku} - method Bool dcsr_stop_for_break; + method Bit #(1) dcsr_break_bit; return case (prv_reg) - prvM: (rg_dcsr [15] == 1'b1); - prvS: (rg_dcsr [13] == 1'b1); - prvU: (rg_dcsr [12] == 1'b1); + prvM: rg_dcsr [15]; + prvS: rg_dcsr [13]; + prvU: rg_dcsr [12]; endcase; endmethod // Check whether to enter Debug Mode based on dcsr.step - method Bool dcsr_stop_for_step; - return (rg_dcsr [2] == 1'b1); + method Bit #(1) dcsr_step_bit; + return rg_dcsr [2]; endmethod // Update 'cause' in DCSR diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 900b9f8..436733a 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -77,42 +77,29 @@ import SoC_Map :: *; import AXI4_Types :: *; import Fabric_Defs :: *; +`ifdef INCLUDE_TANDEM_VERIF +import TV_Info :: *; +`endif `ifdef INCLUDE_GDB_CONTROL import DM_CPU_Req_Rsp :: *; `endif -`ifdef INCLUDE_TANDEM_VERIF -import TV_Info :: *; -`endif - -`ifdef EXTERNAL_DEBUG_MODULE -`undef INCLUDE_GDB_CONTROL -`endif - // ================================================================ +// CPU run-states +// TODO: Reset from GDB etc. -// Major States of CPU - -typedef enum {CPU_RESET1, - CPU_RESET2, - +typedef enum {CPU_RUNNING // Normal operation `ifdef INCLUDE_GDB_CONTROL - CPU_GDB_PAUSING, // On GDB breakpoint, while waiting for fence completion + , + CPU_ENTERING_DEBUG_MODE, // On GDB breakpoint, while waiting for fence completion + CPU_DEBUG_MODE // Halted for debugger `endif - CPU_DEBUG_MODE, // Stopped (normally for debugger) - CPU_RUNNING // Normal operation } CPU_State deriving (Eq, Bits, FShow); function Bool fn_is_running (CPU_State cpu_state); - return ( (cpu_state != CPU_RESET1) - && (cpu_state != CPU_RESET2) -`ifdef INCLUDE_GDB_CONTROL - && (cpu_state != CPU_GDB_PAUSING) - && (cpu_state != CPU_DEBUG_MODE) -`endif - ); + return (cpu_state == CPU_RUNNING); endfunction // ================================================================ @@ -134,9 +121,9 @@ module mkProc (Proc_IFC); Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0); // ---------------- - // Major CPU states + // CPU run/debug states - Reg #(CPU_State) rg_state <- mkReg (CPU_RESET1); + Reg #(CPU_State) rg_state <- mkReg (CPU_RUNNING); // ---------------- // Reset requests and responses (TODO: to be implemented) @@ -144,21 +131,14 @@ module mkProc (Proc_IFC); FIFOF #(Bit #(0)) f_reset_reqs <- mkFIFOF; FIFOF #(Bit #(0)) f_reset_rsps <- mkFIFOF; +`ifdef INCLUDE_GDB_CONTROL // ---------------- // Communication to/from External debug module (TODO: to be implemented) -`ifdef INCLUDE_GDB_CONTROL - // Debugger run-control FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF; FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF; - // Stop-request from debugger (e.g., GDB ^C or Dsharp 'stop') - Reg #(Bool) rg_stop_req <- mkReg (False); - - // Count instrs after step-request from debugger (via dcsr.step) - Reg #(Bit #(1)) rg_step_count <- mkReg (0); - // Debugger GPR read/write request/response FIFOF #(DM_CPU_Req #(5, XLEN)) f_gpr_reqs <- mkFIFOF1; FIFOF #(DM_CPU_Rsp #(XLEN)) f_gpr_rsps <- mkFIFOF1; @@ -288,8 +268,6 @@ module mkProc (Proc_IFC); mmio_axi4_adapter.reset; f_reset_rsps.enq (?); - - rg_state <= CPU_RUNNING; endrule // ---------------- @@ -339,7 +317,7 @@ module mkProc (Proc_IFC); $display ("%0d: %m.rl_debug_run", cur_cycle); f_run_halt_reqs.deq; - core[0].resume_from_debug_mode; + core[0].debug_resume; rg_state <= CPU_RUNNING; // Notify debugger that we've started running @@ -365,18 +343,18 @@ module mkProc (Proc_IFC); // Debug Module Halt control rule rl_debug_halt ((f_run_halt_reqs.first == False) && fn_is_running (rg_state)); - // if (cfg_verbosity > 1) + // if (cfg_verbosity > 1) $display ("%0d: %m.rl_debug_halt", cur_cycle); f_run_halt_reqs.deq; // Debugger 'halt' request (e.g., GDB '^C' command) - core[0].halt_to_debug_mode_req; + core[0].debug_halt; - rg_state <= CPU_GDB_PAUSING; + rg_state <= CPU_ENTERING_DEBUG_MODE; endrule - rule rl_debug_halted ((rg_state == CPU_GDB_PAUSING) && core [0].is_debug_halted); + rule rl_debug_halted ((rg_state == CPU_ENTERING_DEBUG_MODE) && core [0].is_debug_halted); // Notify debugger that we've halted f_run_halt_rsps.enq (False); // Stop executing rules until ready to restart from debugger @@ -401,7 +379,7 @@ module mkProc (Proc_IFC); // ---------------- // Debug Module CSR read/write - rule rl_debug_read_csr ((rg_state == CPU_DEBUG_MODE) && (! f_csr_reqs.first.write)); + rule rl_debug_csr_read ((rg_state == CPU_DEBUG_MODE) && (! f_csr_reqs.first.write)); let req <- pop (f_csr_reqs); Bit #(12) csr_addr = req.address; let data = core [0].csr_read (csr_addr); @@ -412,7 +390,7 @@ module mkProc (Proc_IFC); csr_addr, data); endrule - rule rl_debug_write_csr ((rg_state == CPU_DEBUG_MODE) && f_csr_reqs.first.write); + rule rl_debug_csr_write ((rg_state == CPU_DEBUG_MODE) && f_csr_reqs.first.write); let req <- pop (f_csr_reqs); Bit #(12) csr_addr = req.address; let data = req.data; @@ -432,7 +410,6 @@ module mkProc (Proc_IFC); // if (cur_verbosity > 1) $display ("%m.rl_debug_csr_access_busy"); endrule - `endif // ================================================================ @@ -453,7 +430,7 @@ module mkProc (Proc_IFC); mmioPlatform.start (tohostAddr, fromhostAddr); - $display ("%m.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h", + $display ("Proc.start: startpc = 0x%0h, tohostAddr = 0x%0h, fromhostAddr = %0h", startpc, tohostAddr, fromhostAddr); endmethod diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 8a86cf2..1d80057 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -88,6 +88,7 @@ interface CommitInput; method Action killAll; method Action redirectPc(Addr trap_pc); method Action setFetchWaitRedirect; + method Action setFetchWaitFlush; method Action incrementEpoch; // record if we commit a CSR inst or interrupt method Action commitCsrInstOrInterrupt; @@ -116,14 +117,8 @@ interface CommitStage; interface Get#(RenameErrInfo) renameErr; `ifdef INCLUDE_GDB_CONTROL - // Request halt into debug mode - method Action halt_to_debug_mode_req; - - (* always_ready *) - // Becomes true when pipeline is halted method Bool is_debug_halted; - - method Action resume_from_debug_mode; + method Action debug_resume; `endif endinterface @@ -136,17 +131,16 @@ typedef struct { Trap trap; } CommitTrap deriving(Bits, Eq, FShow); -// Bluespec: for debugger run-control -typedef enum { - Run_State_RUNNING // Normal state `ifdef INCLUDE_GDB_CONTROL - , Run_State_DEBUGGER_HALT // When ready to halt for debugger after stop/step - , Run_State_DEBUGGER_HALT_FLUSH // When flushing state during debugger halt - , Run_State_DEBUGGER_HALTED // When halted for debugger -`endif + +typedef enum { + RUN_STATE_RUNNING, // Normal state + RUN_STATE_DEBUGGER_HALTED // When halted for debugger } Run_State deriving (Eq, FShow, Bits); +`endif + module mkCommitStage#(CommitInput inIfc)(CommitStage); Bool verbose = False; @@ -154,15 +148,9 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); Integer verbosity = 1; Reg #(Bit #(64)) rg_instret <- mkReg (0); - // Bluespec: for debugger run-control - Reg #(Run_State) rg_run_state <- mkReg (Run_State_RUNNING); `ifdef INCLUDE_GDB_CONTROL - // rg_stop_req is set True when debugger requests a stop (e.g., GDB ^C) - Reg #(Bool) rg_stop_req <- mkReg (False); - // When going into debug mode, these hold the cause for the break and the resume-PC - Reg #(Bit #(3)) rg_debug_cause <- mkRegU; - Reg #(Addr) rg_debug_pc <- mkRegU; + Reg #(Run_State) rg_run_state <- mkReg (RUN_STATE_RUNNING); `endif // func units @@ -375,22 +363,44 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); endfunction `ifdef INCLUDE_GDB_CONTROL - // ================================================================ - // Bluespec: debugger run-control - // Every time an instruction commits, we check this boolean - // to decide whether we continue running of stop. + // Maintain system consistency when halting into debug mode + // This code is patterned after 'makeSystemConsistent' above + function Action makeSystemConsistent_for_debug_mode; + action + inIfc.setFlushTlbs; - // We halt after committing an instruction if: - // the debugger requested a stop - // or dcsr.step is True + // notify TLB to keep update of CSR changes + inIfc.setUpdateVMInfo; + // always wait store buffer and SQ to be empty + when(inIfc.stbEmpty && inIfc.stqEmpty, noAction); + // We wait TLB to finish all requests and become sync with memory. + // Notice that currently TLB is read only, so TLB is always in sync + // with memory (i.e., there is no write to commit to memory). Since all + // insts have been killed, nothing can be issued to D TLB at this time. + // Since fetch stage is set to wait for redirect, fetch1 stage is + // stalled, and nothing can be issued to I TLB at this time. + // Therefore, we just need to make sure that I and D TLBs are not + // handling any miss req. Besides, when I and D TLBs do not have any + // miss req, L2 TLB must be idling. + when(inIfc.tlbNoPendingReq, noAction); + // yield load reservation in cache + inIfc.setFlushReservation; - Maybe #(Bit #(3)) m_debug_stop_step_cause = ( rg_stop_req - ? tagged Valid 3 // Debug Module haltreq - : (csrf.dcsr_stop_for_step - ? tagged Valid 4 // dcsr.step - : tagged Invalid)); + inIfc.setFlushBrPred; + inIfc.setFlushCaches; - // ================================================================ +`ifdef SELF_INV_CACHE + // reconcile I$ + if(reconcileI) begin + inIfc.setReconcileI; + end +`ifdef SYSTEM_SELF_INV_L1D + // FIXME is this reconcile of D$ necessary? + inIfc.setReconcileD; +`endif +`endif + endaction + endfunction `endif // TODO Currently we don't check spec bits == 0 when we commit an @@ -400,12 +410,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); rule doCommitTrap_flush( `ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control + (rg_run_state == RUN_STATE_RUNNING) &&& `endif !isValid(commitTrap) &&& rob.deqPort[0].deq_data.trap matches tagged Valid .trap ); - $display ("%0d: %m.CommitStage.rule_doCommitTrap_flush", cur_cycle); rob.deqPort[0].deq; let x = rob.deqPort[0].deq_data; if(verbose) $display("[doCommitTrap] ", fshow(x)); @@ -463,15 +472,12 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); doAssert(x.spec_bits == 0, "cannot have spec bits"); endrule - // This rule's condition is enabled only by the previous rule, doCommitTrap_flush rule doCommitTrap_handle( `ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control + (rg_run_state == RUN_STATE_RUNNING) &&& `endif commitTrap matches tagged Valid .trap); - $display ("%0d: %m.CommitStage.rule_doCommitTrap_handle", cur_cycle); - // reset commitTrap commitTrap <= Invalid; @@ -480,44 +486,58 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); inIfc.commitCsrInstOrInterrupt; end -`ifdef INCLUDE_GDB_CONTROL - if ((trap.trap == tagged Exception Breakpoint) && csrf.dcsr_stop_for_break) begin - // Don't handle the trap - rg_run_state <= Run_State_DEBUGGER_HALTED; - // Record debug CSRs for later Debugger query and later resumption - csrf.dcsr_cause_write (1); // EBREAK dcsr.cause - csrf.dpc_write (trap.pc); // Where we'll resume on 'continue' - end - else begin - // Handle the trap and redirect - let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); - inIfc.redirectPc (new_pc); + Bool debugger_halt = False; - if (m_debug_stop_step_cause matches tagged Valid .cause) begin - rg_run_state <= Run_State_DEBUGGER_HALTED; - // Record debug CSRs for later Debugger query and later resumption - csrf.dcsr_cause_write (cause); - csrf.dpc_write (new_pc); // Where we'll resume on 'continue' +`ifdef INCLUDE_GDB_CONTROL + if ((trap.trap == tagged Interrupt DebugHalt) + || (trap.trap == tagged Interrupt DebugStep) + || ((trap.trap == tagged Exception Breakpoint) && (csrf.dcsr_break_bit == 1'b1))) + begin + debugger_halt = True; + + // Flush everything (tlbs, caches, reservation, branch predictor); + // reconcilei and I; update VM info. + makeSystemConsistent_for_debug_mode; + + // Save values in debugger CSRs + Bit #(3) dcsr_cause = ( (trap.trap == tagged Interrupt DebugHalt) + ? 3 + : ( (trap.trap == tagged Interrupt DebugStep) + ? 4 + : 1)); + csrf.dcsr_cause_write (dcsr_cause); + csrf.dpc_write (trap.pc); + + // Tell fetch stage to wait for redirect + // Note: rule doCommitTrap_flush may have done this already; redundant call is ok. + inIfc.setFetchWaitRedirect; + inIfc.setFetchWaitFlush; + + // Go to quiescent state until debugger resumes execution + rg_run_state <= RUN_STATE_DEBUGGER_HALTED; + + $display ("%0d: %m.commitStage.doCommitTrap_handle; debugger halt:", cur_cycle); end - end -`else - // trap handling & redirect - let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); - inIfc.redirectPc(new_pc); `endif - // system consistency - // TODO spike flushes TLB here, but perhaps it is because spike's TLB - // does not include prv info, and it has to flush when prv changes. - // XXX As approximation, Trap may cause context switch, so flush for - // security - makeSystemConsistent(False, True, False); + if (! debugger_halt) begin + // trap handling & redirect + let new_pc <- csrf.trap(trap.trap, trap.pc, trap.addr); + inIfc.redirectPc(new_pc); + + // system consistency + // TODO spike flushes TLB here, but perhaps it is because spike's TLB + // does not include prv info, and it has to flush when prv changes. + // XXX As approximation, Trap may cause context switch, so flush for + // security + makeSystemConsistent(False, True, False); + end endrule // commit misspeculated load rule doCommitKilledLd( `ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) &&& // Bluespec: debugger run-control + (rg_run_state == RUN_STATE_RUNNING) &&& `endif !isValid(commitTrap) &&& !isValid(rob.deqPort[0].deq_data.trap) &&& @@ -529,19 +549,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // kill everything, redirect, and increment epoch inIfc.killAll; - -`ifdef INCLUDE_GDB_CONTROL - // Bluespec: debug run-control - doAssert (x.iType != Ebreak, "CommitStage.rule_doCommitKilledLd iType should not be Ebreak"); - if (m_debug_stop_step_cause matches tagged Valid .cause) begin - rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; - rg_debug_pc <= x.pc; - rg_debug_cause <= cause; - end - else -`endif - inIfc.redirectPc(x.pc); // original (no debugger) - + inIfc.redirectPc(x.pc); inIfc.incrementEpoch; // the killed Ld should have claimed phy reg, we should not commit it; @@ -566,7 +574,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // commit system inst rule doCommitSystemInst( `ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control + (rg_run_state == RUN_STATE_RUNNING) && `endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && @@ -617,18 +625,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); else if(x.iType == Mret) begin next_pc <- csrf.mret; end - -`ifdef INCLUDE_GDB_CONTROL - // Bluespec: debug run-control - doAssert (x.iType != Ebreak, "CommitStage.rule_doCommitSystemInst iType should not be Ebreak"); - if (m_debug_stop_step_cause matches tagged Valid .cause) begin - rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; - rg_debug_pc <= next_pc; - rg_debug_cause <= cause; - end - else -`endif - inIfc.redirectPc(next_pc); // original (no debugger) + inIfc.redirectPc(next_pc); // rename stage only sends out system inst when ROB is empty, so no // need to flush ROB again @@ -685,9 +682,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // Lr/Sc/Amo/MMIO cannot proceed to executed until we notify LSQ that it // has reached the commit stage rule notifyLSQCommit( -`ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control -`endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && !isValid(rob.deqPort[0].deq_data.ldKilled) && @@ -707,7 +701,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // commit normal: fire when at least one commit can be done rule doCommitNormalInst( `ifdef INCLUDE_GDB_CONTROL - (rg_run_state == Run_State_RUNNING) && // Bluespec: debugger run-control + (rg_run_state == RUN_STATE_RUNNING) && `endif !isValid(commitTrap) && !isValid(rob.deqPort[0].deq_data.trap) && @@ -720,10 +714,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // 2. inst is not ready to commit Bool stop = False; - // Bluespec: debugger run-control - // 3. one instr is committed and debugger halt is requested (due to stop or step) - Bool stop_for_debugger = False; - // We merge writes on FPU csr and apply writes at the end of the rule Bit#(5) fflags = 0; Bool will_dirty_fpu_state = False; @@ -748,8 +738,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // compute what actions to take for(Integer i = 0; i < valueof(SupSize); i = i+1) begin - - if(!stop && (! stop_for_debugger) && rob.deqPort[i].canDeq) begin + if(!stop && rob.deqPort[i].canDeq) begin let x = rob.deqPort[i].deq_data; let inst_tag = rob.deqPort[i].getDeqInstTag; @@ -802,35 +791,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); comUserInstCnt = comUserInstCnt + 1; // user space inst end -`ifdef INCLUDE_GDB_CONTROL - if (m_debug_stop_step_cause matches tagged Valid .cause - &&& (comInstCnt != 0)) - begin - $display ("%0d: %m.CommitStage.rule_doCommitNormalInst: Stopping for debugger", cur_cycle); - stop_for_debugger = True; - - // Compute next PC in case of debugger stop. - // Note: AluExePipeline.rule_doFinishAlu does inIfc.rob_setExecuted (... x.controlFlow) - // which updates the rob entry's ppc_vaddr_csrData field with actual - // branch/jump targets, which we retrieve here. - Addr next_pc = ?; - if (x.ppc_vaddr_csrData matches tagged PPC .addr - &&& ((x.iType == J) || (x.iType == Jr) || (x.iType == Br))) - // JAL, JALR, BRANCH - next_pc = addr; - else if (x.orig_inst [1:0] == 2'b11) - // RV32I RV64I - next_pc = x.pc + 4; - else - // RVC - next_pc = x.pc + 2; - - rg_run_state <= Run_State_DEBUGGER_HALT_FLUSH; - rg_debug_pc <= next_pc; - rg_debug_cause <= cause; - end -`endif - `ifdef PERF_COUNT // performance counter case(x.iType) @@ -846,7 +806,7 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif end end - end // for-loop for superscalar width + end rg_instret <= rg_instret + instret; // write FPU csr @@ -894,48 +854,6 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif endrule -`ifdef INCLUDE_GDB_CONTROL - // ================================================================ - // Rules to move into debug mode - - // This rule is like rule doCommitTrap_flush, i.e., a debugger-halt is like an interrupt - rule rl_enter_debug_mode_flush (rg_run_state == Run_State_DEBUGGER_HALT_FLUSH); - $write ("%0d: %m.commitStage.rl_enter_debug_mode:", cur_cycle); - if (rg_debug_cause == 1) $display (" EBREAK"); - else if (rg_debug_cause == 3) $display (" Debugger halt request"); - else if (rg_debug_cause == 4) $display (" Halt after step"); - else $display (" Unknown cause %0d", rg_debug_cause); - - // flush everything. Only increment epoch and stall fetch when we haven - // not done it yet (we may have already done them at rename stage) - inIfc.killAll; - inIfc.incrementEpoch; - inIfc.setFetchWaitRedirect; - - rg_run_state <= Run_State_DEBUGGER_HALT; - endrule - - // This rule is like rule doCommitTrap_handle, except we don't redirect - rule rl_enter_debug_mode_halt (rg_run_state == Run_State_DEBUGGER_HALT); - // system consistency - // TODO spike flushes TLB here, but perhaps it is because spike's TLB - // does not include prv info, and it has to flush when prv changes. - // XXX As approximation, Trap may cause context switch, so flush for - // security - makeSystemConsistent(False, True, False); - - // Record debug CSRs for later Debugger query and later resumption - csrf.dcsr_cause_write (rg_debug_cause); // reason for entering debug mode - csrf.dpc_write (rg_debug_pc); // Where we'll resume on 'continue' - - // Go to HALTED state where no rule fires. - // To re-start, mkCore must call restart method. - rg_run_state <= Run_State_DEBUGGER_HALTED; - endrule - - // ================================================================ -`endif - method Data getPerf(ComStagePerfType t); return (case(t) `ifdef PERF_COUNT @@ -986,21 +904,13 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif `ifdef INCLUDE_GDB_CONTROL - // Request halt into debug mode - method Action halt_to_debug_mode_req () if (rg_run_state == Run_State_RUNNING); - $display ("%0d: %m.commitStage.halt_to_debug_mode_req", cur_cycle); - rg_stop_req <= True; - endmethod - - // Becomes true when pipeline is halted method Bool is_debug_halted; - return (rg_run_state == Run_State_DEBUGGER_HALTED); + return (rg_run_state == RUN_STATE_DEBUGGER_HALTED); endmethod - method Action resume_from_debug_mode () if (rg_run_state == Run_State_DEBUGGER_HALTED); - $display ("%0d: %m.commitStage.resume_from_debug_mode", cur_cycle); - rg_stop_req <= False; - rg_run_state <= Run_State_RUNNING; + method Action debug_resume () if (rg_run_state == RUN_STATE_DEBUGGER_HALTED); + rg_run_state <= RUN_STATE_RUNNING; + $display ("%0d: %m.commitStage.debug_resume", cur_cycle); endmethod `endif diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 31118ff..1cc7753 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -50,7 +50,7 @@ import CCTypes::*; import L1CoCache::*; import MMIOInst::*; -import Cur_Cycle :: *; +import Cur_Cycle :: *; // ================================================================ // For fv_decode_C function and related types and definitions @@ -76,6 +76,9 @@ interface FetchStage; // redirection methods method Action setWaitRedirect; method Action redirect(Addr pc); +`ifdef INCLUDE_GDB_CONTROL + method Action setWaitFlush; +`endif method Action done_flushing(); method Action train_predictors( Addr pc, Addr next_pc, IType iType, Bool taken, @@ -92,10 +95,6 @@ interface FetchStage; // performance interface Perf#(DecStagePerfType) perf; - -`ifdef INCLUDE_GDB_CONTROL - method Action resume_from_debug_mode (Addr new_pc); -`endif endinterface typedef struct { @@ -990,7 +989,6 @@ module mkFetchStage(FetchStage); interface mmioIfc = mmio.toCore; method Action start(Addr start_pc); - $display ("%0d: %m.start (start_pc = 0x%0h)", cur_cycle, start_pc); pc_reg[0] <= start_pc; started <= True; waitForRedirect <= False; @@ -998,7 +996,6 @@ module mkFetchStage(FetchStage); endmethod method Action stop(); started <= False; - $display ("%0d: %m.stop", cur_cycle); endmethod method Action setWaitRedirect; @@ -1017,6 +1014,14 @@ module mkFetchStage(FetchStage); // we conservatively set wait for flush TODO make this an input parameter waitForFlush <= True; endmethod + +`ifdef INCLUDE_GDB_CONTROL + method Action setWaitFlush; + waitForFlush <= True; + $display ("%0d.%m.FetchStage.setWaitFlush", cur_cycle); + endmethod +`endif + method Action done_flushing() if (waitForFlush); // signal that the pipeline can resume fetching waitForFlush <= False; @@ -1103,24 +1108,5 @@ module mkFetchStage(FetchStage); method Bool respValid = perfReqQ.notEmpty; `endif endinterface - -`ifdef INCLUDE_GDB_CONTROL - method Action resume_from_debug_mode (Addr new_pc); - if (verbose) - $display("resume_from_debug_mode: newpc %h, old f_main_epoch %d, new f_main_epoch %d", - new_pc, f_main_epoch, f_main_epoch + 1); - pc_reg[pc_redirect_port] <= new_pc; - f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1; - ehr_pending_straddle[1] <= tagged Invalid; - // redirect comes, stop stalling for redirect - waitForRedirect <= False; - setWaitRedirect_redirect_conflict.wset(?); // conflict with setWaitForRedirect - - // this redirect may be caused by a trap/system inst in commit stage - // we conservatively set wait for flush TODO make this an input parameter - // TODO: do we need this? waitForFlush <= True; - endmethod -`endif - endmodule diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv index 8570554..b28d241 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/ProcConfig.bsv @@ -36,6 +36,7 @@ `define a True `define f True `define d True +`define c True //`define NUM_CORES 1 // defined in make file diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index 960edde..052cf65 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -48,6 +48,8 @@ import ReservationStationMem::*; import ReservationStationFpuMulDiv::*; import SplitLSQ::*; +import Cur_Cycle :: *; + typedef struct { FetchDebugState fetch; EpochDebugState epoch; @@ -83,6 +85,11 @@ interface RenameStage; // deadlock check interface Get#(RenameStuck) renameInstStuck; interface Get#(RenameStuck) renameCorrectPathStuck; + +`ifdef INCLUDE_GDB_CONTROL + method Action debug_halt; + method Action debug_resume; +`endif endinterface module mkRenameStage#(RenameInput inIfc)(RenameStage); @@ -153,6 +160,23 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); endrule `endif +`ifdef INCLUDE_GDB_CONTROL + // Is set to Valid DebugHalt on debugger halt request + // Is set to Valid DebugStep on dcsr[stepbit]==1 and one instruction has been processed. + // Note (step): 1st instruction is guaranteed architectural, cannot possibly be speculative. + // Note (step): 1st instruction may trap; we halt pointing at the trap vector + Reg #(Maybe #(Interrupt)) rg_m_halt_req <- mkReg (tagged Invalid); + + function Action fa_step_check; + action + if (csrf.dcsr_step_bit == 1'b1) begin + rg_m_halt_req <= tagged Valid DebugStep; + $display ("%0d: %m.fa_step_check: rg_m_halt_req <= tagged Valid DebugStep", cur_cycle); + end + endaction + endfunction +`endif + // kill wrong path inst // XXX we have to make this a separate rule instead of merging it with rename correct path // This is because the rename correct path rule is conflict with other rules that redirect @@ -234,6 +258,13 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && (mstatus_tw == 1'b1) && (csrf.decodeInfo.prv < prvM)); +`ifdef INCLUDE_GDB_CONTROL + if (rg_m_halt_req matches tagged Valid .cause) begin + // Stop due to debugger halt or step + trap = tagged Valid (tagged Interrupt cause); + end else +`endif + if (isValid(x.cause)) begin // previously found exception trap = tagged Valid (tagged Exception fromMaybe(?, x.cause)); @@ -273,6 +304,14 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && rob.isEmpty // stall for ROB empty ); fetchStage.pipelines[0].deq; +`ifdef INCLUDE_GDB_CONTROL + fa_step_check; + + if (firstTrap == tagged Valid (tagged Interrupt DebugHalt)) + $display ("%0d: %m.doRenaming_Trap: DebugHalt", cur_cycle); + else if (firstTrap == tagged Valid (tagged Interrupt DebugStep)) + $display ("%0d: %m.doRenaming_Trap: DebugStep", cur_cycle); +`endif let x = fetchStage.pipelines[0].first; let pc = x.pc; let orig_inst = x.orig_inst; @@ -379,6 +418,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && rob.isEmpty // stall for ROB empty ); fetchStage.pipelines[0].deq; +`ifdef INCLUDE_GDB_CONTROL + fa_step_check; +`endif let x = fetchStage.pipelines[0].first; let pc = x.pc; let orig_inst = x.orig_inst; @@ -522,6 +564,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && rob.isEmpty // stall for ROB empty to process mem inst ); fetchStage.pipelines[0].deq; +`ifdef INCLUDE_GDB_CONTROL + fa_step_check; +`endif let x = fetchStage.pipelines[0].first; let pc = x.pc; let orig_inst = x.orig_inst; @@ -685,6 +730,11 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // (c) It is system inst (we handle system inst in a separate rule) // (d) It does not have enough resource Bool stop = False; +`ifdef INCLUDE_GDB_CONTROL + // (e) One rename has been done and dcsr.step is set + Bool debug_step = False; +`endif + // We automatically stop after an inst cannot be deq from fetch stage // because canDeq signal for sup-fifo is consecutive @@ -733,6 +783,13 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); Addr fallthrough_pc = ((orig_inst[1:0] == 2'b11) ? pc + 4 : pc + 2); +`ifdef INCLUDE_GDB_CONTROL + if ((i != 0) && (csrf.dcsr_step_bit == 1'b1)) begin + stop = True; + debug_step = True; + end +`endif + // check for wrong path, if wrong path, don't process it, leave to the other rule in next cycle if(!epochManager.checkEpoch[i].check(main_epoch)) begin stop = True; @@ -986,6 +1043,11 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); end end +`ifdef INCLUDE_GDB_CONTROL + if (debug_step) + rg_m_halt_req <= tagged Valid DebugStep; +`endif + // only fire this rule if we make some progress // otherwise this rule may block other rules forever when(doCorrectPath, noAction); @@ -1026,4 +1088,17 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); default: 0; endcase); endmethod + +`ifdef INCLUDE_GDB_CONTROL + method Action debug_halt () if (rg_m_halt_req == tagged Invalid); + rg_m_halt_req <= tagged Valid DebugHalt; + $display ("%0d: %m.renameStage.debug_halt", cur_cycle); + endmethod + + method Action debug_resume () if (rg_m_halt_req != tagged Invalid); + rg_m_halt_req <= tagged Invalid; + $display ("%0d: %m.renameStage.debug_resume", cur_cycle); + endmethod +`endif + endmodule diff --git a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv index b4f2d5f..5072908 100644 --- a/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv +++ b/src_Core/RISCY_OOO/procs/lib/ProcTypes.bsv @@ -99,7 +99,7 @@ typedef struct { instance DefaultValue#(RiscVISASubset); function RiscVISASubset defaultValue = RiscVISASubset { s: True, u: True, - m: `m , a: `a , f: `f , d: `d + m: `m , a: `a , f: `f , d: `d, c: `c }; endinstance @@ -454,13 +454,20 @@ typedef enum { MachineTimer = 4'd7, UserExternal = 4'd8, SupervisorExternel = 4'd9, - MachineExternal = 4'd11, + MachineExternal = 4'd11 + +`ifdef INCLUDE_GDB_CONTROL + , DebugHalt = 4'd14, // Debugger halt command (^C in GDB) + DebugStep = 4'd15 // dcsr.step is set and 1 instr has been processed +`endif - DebugExternal = 4'd14 // Bluespec: for debug mode } Interrupt deriving(Bits, Eq, FShow); -// typedef 12 InterruptNum; -typedef 15 InterruptNum; // Bluespec: extended to 15 bits for debug interrupt +`ifdef INCLUDE_GDB_CONTROL +typedef 16 InterruptNum; // With debugger +`else +typedef 12 InterruptNum; // Without debugger +`endif // Traps are either an exception or an interrupt typedef union tagged { From dcfb285c29e8d973f3a90636246c951ba13da03f Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Mon, 13 Jan 2020 15:34:27 -0500 Subject: [PATCH 4/8] Work-in-progress. Now able to single-step from debugger. --- src_Core/CPU/Core.bsv | 100 ++++++++++++------ src_Core/CPU/Proc.bsv | 88 ++++++++++++++- .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 14 +-- .../RISCY_OOO/procs/RV64G_OOO/SynthParam.bsv | 5 +- 4 files changed, 161 insertions(+), 46 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 122c6e9..18352ff 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -155,8 +155,14 @@ interface Core; method Action debug_resume; - method Data csr_read (Bit #(12) csr_addr); + method Data csr_read (Bit #(12) csr_addr); method Action csr_write (Bit #(12) csr_addr, Data data); + method Data gpr_read (Bit #(5) gpr_addr); + method Action gpr_write (Bit #(5) gpr_addr, Data data); +`ifdef ISA_F + method Data fpr_read (Bit #(5) fpr_addr); + method Action fpr_write (Bit #(5) fpr_addr, Data data); +`endif `endif endinterface @@ -171,7 +177,6 @@ endinterface typedef enum { `ifdef INCLUDE_GDB_CONTROL - CORE_HALTING, CORE_HALTED, `endif CORE_RUNNING @@ -720,42 +725,27 @@ module mkCore#(CoreId coreId)(Core); `endif ); fetchStage.done_flushing(); - endrule `ifdef INCLUDE_GDB_CONTROL - rule rl_debug_halting((rg_core_run_state == CORE_HALTING) && - !flush_reservation && !flush_tlbs && !update_vm_info - && iTlb.flush_done && dTlb.flush_done - && !flush_caches && !flush_brpred - && iMem.flush_done && dMem.flush_done - && fetchStage.flush_predictors_done -`ifdef SELF_INV_CACHE - && !reconcile_i && iMem.reconcile_done -`ifdef SYSTEM_SELF_INV_L1D - && !reconcile_d + if (commitStage.is_debug_halted) begin + started <= False; + rg_core_run_state <= CORE_HALTED; + $display ("%0d: %m.rule readyToFetch: debug halt", cur_cycle); + end `endif -`endif - && commitStage.is_debug_halted - ); - - fetchStage.done_flushing(); - rg_core_run_state <= CORE_HALTED; - - $display ("%0d: %m.rl_debug_halting", cur_cycle); endrule -`endif /* -`ifdef INCLUDE_GDB_CONTROL - // TODO: DELETE AFTER DEBUGGING - rule rl_flushing_conditions (rg_core_run_state == CORE_HALTING); - $display ("%0d: %m.rl_done_flushing_for_debug_halt", cur_cycle); + rule rl_readyToFetch_conds_debug + $display ("%0d: %m.rl_readyToFetch_conds_debug:", cur_cycle); $display (" !flush_reservation = %0d, !flush_tlbs = %0d, !update_vm_info = %0d", !flush_reservation, !flush_tlbs, !update_vm_info); $display (" iTlb.flush_done = %0d, dTlb.flush_done = %0d", iTlb.flush_done, dTlb.flush_done); +`ifdef SECURITY_OR_INCLUDE_GDB_CONTROL $display (" !flush_caches = %0d !flush_brpred = %0d", !flush_caches, !flush_brpred); $display (" iMem.flush_done = %0d dMem.flush_done = %0d", iMem.flush_done, dMem.flush_done); $display (" fetchStage.flush_predictors_done = %0d", fetchStage.flush_predictors_done); +`endif `ifdef SELF_INV_CACHE $display (" !reconcile_i = %0d, iMem.reconcide_done = %0d", !reconcile_i, iMem.reconcile_done); `ifdef SYSTEM_SELF_INV_L1D @@ -763,7 +753,6 @@ module mkCore#(CoreId coreId)(Core); `endif `endif endrule -`endif */ `ifdef PERF_COUNT @@ -1107,9 +1096,7 @@ module mkCore#(CoreId coreId)(Core); `ifdef INCLUDE_GDB_CONTROL method Action debug_halt () if (started && (rg_core_run_state == CORE_RUNNING)); $display ("%0d: %m.debug_halt", cur_cycle); - started <= False; renameStage.debug_halt; // start the halt protocol - rg_core_run_state <= CORE_HALTING; endmethod method Bool is_debug_halted; @@ -1117,13 +1104,13 @@ module mkCore#(CoreId coreId)(Core); endmethod method Action debug_resume () if (rg_core_run_state == CORE_HALTED); - renameStage.debug_resume; - commitStage.debug_resume; - let startpc = csrf.dpc_read; fetchStage.redirect (startpc); - started <= True; + renameStage.debug_resume; + commitStage.debug_resume; + + started <= True; rg_core_run_state <= CORE_RUNNING; $display ("%0d: %m.debug_resume, dpc = 0x%0h", cur_cycle, startpc); endmethod @@ -1135,6 +1122,53 @@ module mkCore#(CoreId coreId)(Core); method Action csr_write (Bit #(12) csr_addr, Data data) if (rg_core_run_state == CORE_HALTED); csrf.csrInstWr (unpack (csr_addr), data); endmethod + + method Data gpr_read (Bit #(5) gpr_addr) if (rg_core_run_state == CORE_HALTED); + let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), + src2: ?, + src3: ?, + dst: ?}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + let data = rf.read [debuggerPort].rd1 (phy_rindx); + return data; + endmethod + + method Action gpr_write (Bit #(5) gpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); + let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), + src2: ?, + src3: ?, + dst: ?}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + rf.write [debuggerPort].wr (phy_rindx, data); + $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", gpr_addr, data, phy_rindx); + endmethod + +`ifdef ISA_F + method Data fpr_read (Bit #(5) fpr_addr) if (rg_core_run_state == CORE_HALTED); + let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), + src2: ?, + src3: ?, + dst: ?}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + let data = 0; // TODO: rf.read [debuggerPort].rd1 (phy_rindx); + return data; + endmethod + + method Action fpr_write (Bit #(5) fpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); + let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), + src2: ?, + src3: ?, + dst: ?}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + // TODO: rf.write [debuggerPort].wr (phy_rindx, data); + $display ("%m.fpr_write (%0d, %0x), phy_rindx %0d", fpr_addr, data, phy_rindx); + endmethod +`endif + `endif endmodule diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 436733a..d28004e 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -349,12 +349,13 @@ module mkProc (Proc_IFC); f_run_halt_reqs.deq; // Debugger 'halt' request (e.g., GDB '^C' command) + // This is just like an interrupt. core[0].debug_halt; - - rg_state <= CPU_ENTERING_DEBUG_MODE; endrule - rule rl_debug_halted ((rg_state == CPU_ENTERING_DEBUG_MODE) && core [0].is_debug_halted); + // Monitors when we've reached halted state while running (halt, + // step or EBREAK) and notifies DM + rule rl_debug_halted (fn_is_running (rg_state) && core [0].is_debug_halted); // Notify debugger that we've halted f_run_halt_rsps.enq (False); // Stop executing rules until ready to restart from debugger @@ -373,7 +374,8 @@ module mkProc (Proc_IFC); // Notify debugger that we've 'halted' f_run_halt_rsps.enq (False); - $display ("%0d: %m.rl_debug_halt_redundant: CPU already halted; state = ", cur_cycle, fshow (rg_state)); + $display ("%0d: %m.rl_debug_halt_redundant: CPU already halted; state = ", + cur_cycle, fshow (rg_state)); endrule // ---------------- @@ -410,6 +412,84 @@ module mkProc (Proc_IFC); // if (cur_verbosity > 1) $display ("%m.rl_debug_csr_access_busy"); endrule + + // ---------------- + // Debug Module GPR read/write + + rule rl_debug_read_gpr ((rg_state == CPU_DEBUG_MODE) && (! f_gpr_reqs.first.write)); + let req <- pop (f_gpr_reqs); + Bit #(5) regname = req.address; + + let data = core [0].gpr_read (regname); + + let rsp = DM_CPU_Rsp {ok: True, data: data}; + f_gpr_rsps.enq (rsp); + if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", + mcycle, regname, data); + endrule + + rule rl_debug_write_gpr ((rg_state == CPU_DEBUG_MODE) && f_gpr_reqs.first.write); + let req <- pop (f_gpr_reqs); + Bit #(5) regname = req.address; + let data = req.data; + core [0].gpr_write (regname, data); + + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_gpr_rsps.enq (rsp); + + if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", + mcycle, regname, data); + endrule + + rule rl_debug_gpr_access_busy (rg_state != CPU_DEBUG_MODE); + let req <- pop (f_gpr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_gpr_rsps.enq (rsp); + + if (cur_verbosity > 1) $display ("%0d: %m.rl_debug_gpr_access_busy", mcycle); + endrule + + // ---------------- + // Debug Module FPR read/write + +`ifdef ISA_F + rule rl_debug_read_fpr ((rg_state == CPU_DEBUG_MODE) && (! f_fpr_reqs.first.write)); + let req <- pop (f_fpr_reqs); + Bit #(5) regname = req.address; + let data = core [0].fpr_read (regname); + let rsp = DM_CPU_Rsp {ok: True, data: data}; + f_fpr_rsps.enq (rsp); + if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", + mcycle, regname, data); + endrule + + rule rl_debug_write_fpr ((rg_state == CPU_DEBUG_MODE) && f_fpr_reqs.first.write); + let req <- pop (f_fpr_reqs); + Bit #(5) regname = req.address; + let data = req.data; + core [0].fpr_write (regname, data); + + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_fpr_rsps.enq (rsp); + + if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", + mcycle, regname, data); + endrule + + rule rl_debug_fpr_access_busy (rg_state != CPU_DEBUG_MODE); + let req <- pop (f_fpr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_fpr_rsps.enq (rsp); + + if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_fpr_access_busy", mcycle); + endrule +`endif + `endif // ================================================================ diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index 052cf65..c8e91f5 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -171,7 +171,7 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); action if (csrf.dcsr_step_bit == 1'b1) begin rg_m_halt_req <= tagged Valid DebugStep; - $display ("%0d: %m.fa_step_check: rg_m_halt_req <= tagged Valid DebugStep", cur_cycle); + $display ("%0d: %m.renameStage.fa_step_check: rg_m_halt_req <= tagged Valid DebugStep", cur_cycle); end endaction endfunction @@ -260,8 +260,8 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); `ifdef INCLUDE_GDB_CONTROL if (rg_m_halt_req matches tagged Valid .cause) begin - // Stop due to debugger halt or step - trap = tagged Valid (tagged Interrupt cause); + // Stop due to debugger halt or step + trap = tagged Valid (tagged Interrupt cause); end else `endif @@ -308,9 +308,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); fa_step_check; if (firstTrap == tagged Valid (tagged Interrupt DebugHalt)) - $display ("%0d: %m.doRenaming_Trap: DebugHalt", cur_cycle); + $display ("%0d: %m.renameStage.doRenaming_Trap: DebugHalt", cur_cycle); else if (firstTrap == tagged Valid (tagged Interrupt DebugStep)) - $display ("%0d: %m.doRenaming_Trap: DebugStep", cur_cycle); + $display ("%0d: %m.renameStage.doRenaming_Trap: DebugStep", cur_cycle); `endif let x = fetchStage.pipelines[0].first; let pc = x.pc; @@ -1092,12 +1092,12 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); `ifdef INCLUDE_GDB_CONTROL method Action debug_halt () if (rg_m_halt_req == tagged Invalid); rg_m_halt_req <= tagged Valid DebugHalt; - $display ("%0d: %m.renameStage.debug_halt", cur_cycle); + $display ("%0d: %m.renameStage.renameStage.debug_halt", cur_cycle); endmethod method Action debug_resume () if (rg_m_halt_req != tagged Invalid); rg_m_halt_req <= tagged Invalid; - $display ("%0d: %m.renameStage.debug_resume", cur_cycle); + $display ("%0d: %m.renameStage.renameStage.debug_resume", cur_cycle); endmethod `endif diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/SynthParam.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/SynthParam.bsv index aaeb447..3c6b3cb 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/SynthParam.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/SynthParam.bsv @@ -35,8 +35,8 @@ typedef TDiv#(SupSize, 2) FpuMulDivExeNum; // Phy RFile // write: Alu < FpuMulDiv < Mem // read: Alu, FpuMulDiv, Mem -typedef TAdd#(1, TAdd#(FpuMulDivExeNum, AluExeNum)) RFileWrPortNum; -typedef TAdd#(1, TAdd#(FpuMulDivExeNum, AluExeNum)) RFileRdPortNum; +typedef TAdd#(2, TAdd#(FpuMulDivExeNum, AluExeNum)) RFileWrPortNum; +typedef TAdd#(2, TAdd#(FpuMulDivExeNum, AluExeNum)) RFileRdPortNum; // sb lazy lookup num: same as RFile read, becaues all pipelines recv bypass typedef RFileRdPortNum SbLazyLookupPortNum; @@ -65,6 +65,7 @@ Integer memWrAggrPort = 1 + valueof(FpuMulDivExeNum) + valueof(AluExeNum); function Integer aluRdPort(Integer i) = i; function Integer fpuMulDivRdPort(Integer i) = valueof(AluExeNum) + i; Integer memRdPort = valueof(FpuMulDivExeNum) + valueof(AluExeNum); +Integer debuggerPort = memRdPort + 1; // ports for correct spec, ordering doesn't matter typedef TAdd#(2, AluExeNum) CorrectSpecPortNum; From 2807edf1b2ff8f402558f027530cba1b26b2247c Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Mon, 13 Jan 2020 21:22:54 -0500 Subject: [PATCH 5/8] Work-in-progress on integrating Debug Module --- src_Core/CPU/Core.bsv | 38 +++++++++++------------ src_Core/CPU/Proc.bsv | 70 +++++++++++++++++++++---------------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 18352ff..b47cfdb 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -157,11 +157,11 @@ interface Core; method Data csr_read (Bit #(12) csr_addr); method Action csr_write (Bit #(12) csr_addr, Data data); - method Data gpr_read (Bit #(5) gpr_addr); - method Action gpr_write (Bit #(5) gpr_addr, Data data); + method Data gpr_read (Bit #(5) gpr_addr); + method Action gpr_write (Bit #(5) gpr_addr, Data data); `ifdef ISA_F - method Data fpr_read (Bit #(5) fpr_addr); - method Action fpr_write (Bit #(5) fpr_addr, Data data); + method Data fpr_read (Bit #(5) fpr_addr); + method Action fpr_write (Bit #(5) fpr_addr, Data data); `endif `endif endinterface @@ -1128,9 +1128,9 @@ module mkCore#(CoreId coreId)(Core); src2: ?, src3: ?, dst: ?}; - let rename_result = regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); - let data = rf.read [debuggerPort].rd1 (phy_rindx); + let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); + let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); return data; endmethod @@ -1139,21 +1139,21 @@ module mkCore#(CoreId coreId)(Core); src2: ?, src3: ?, dst: ?}; - let rename_result = regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); - rf.write [debuggerPort].wr (phy_rindx, data); - $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", gpr_addr, data, phy_rindx); + let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); + // rf.write [debuggerPort].wr (phy_rindx, data); + // $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", gpr_addr, data, phy_rindx); endmethod `ifdef ISA_F - method Data fpr_read (Bit #(5) fpr_addr) if (rg_core_run_state == CORE_HALTED); + method Data fpr_read (Bit #(5) fpr_addr) if (rg_core_run_state == CORE_HALTED); let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), src2: ?, src3: ?, dst: ?}; - let rename_result = regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); - let data = 0; // TODO: rf.read [debuggerPort].rd1 (phy_rindx); + let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); + let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); return data; endmethod @@ -1162,10 +1162,10 @@ module mkCore#(CoreId coreId)(Core); src2: ?, src3: ?, dst: ?}; - let rename_result = regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); - // TODO: rf.write [debuggerPort].wr (phy_rindx, data); - $display ("%m.fpr_write (%0d, %0x), phy_rindx %0d", fpr_addr, data, phy_rindx); + let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); + // rf.write [debuggerPort].wr (phy_rindx, data); + // $display ("%m.fpr_write (%0d, %0x), phy_rindx %0d", fpr_addr, data, phy_rindx); endmethod `endif diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index d28004e..f2ed17e 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -388,8 +388,7 @@ module mkProc (Proc_IFC); let rsp = DM_CPU_Rsp {ok: True, data: data}; f_csr_rsps.enq (rsp); // if (cur_verbosity > 1) - $display ("%m.rl_debug_read_csr: csr %0d => 0x%0h", - csr_addr, data); + $display ("%0d: %m.rl_debug_read_csr: csr %0d => 0x%0h", cur_cycle, csr_addr, data); endrule rule rl_debug_csr_write ((rg_state == CPU_DEBUG_MODE) && f_csr_reqs.first.write); @@ -401,7 +400,7 @@ module mkProc (Proc_IFC); f_csr_rsps.enq (rsp); // if (cur_verbosity > 1) - $display ("%m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", csr_addr, data); + $display ("%0d: %m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", cur_cycle, csr_addr, data); endrule rule rl_debug_csr_access_busy (rg_state != CPU_DEBUG_MODE); @@ -410,37 +409,36 @@ module mkProc (Proc_IFC); f_csr_rsps.enq (rsp); // if (cur_verbosity > 1) - $display ("%m.rl_debug_csr_access_busy"); + $display ("%0d: %m.rl_debug_csr_access_busy", cur_cycle); endrule // ---------------- // Debug Module GPR read/write - rule rl_debug_read_gpr ((rg_state == CPU_DEBUG_MODE) && (! f_gpr_reqs.first.write)); + rule rl_debug_gpr_read ((rg_state == CPU_DEBUG_MODE) && (! f_gpr_reqs.first.write)); let req <- pop (f_gpr_reqs); - Bit #(5) regname = req.address; + Bit #(5) regnum = req.address; - let data = core [0].gpr_read (regname); + let data_out = core [0].gpr_read (regnum); - let rsp = DM_CPU_Rsp {ok: True, data: data}; + let rsp = DM_CPU_Rsp {ok: True, data: data_out}; f_gpr_rsps.enq (rsp); - if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", - mcycle, regname, data); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); endrule - rule rl_debug_write_gpr ((rg_state == CPU_DEBUG_MODE) && f_gpr_reqs.first.write); + rule rl_debug_gpr_write ((rg_state == CPU_DEBUG_MODE) && f_gpr_reqs.first.write); let req <- pop (f_gpr_reqs); - Bit #(5) regname = req.address; - let data = req.data; - core [0].gpr_write (regname, data); + Bit #(5) regnum = req.address; + let data_in = req.data; + + core [0].gpr_write (regnum, data_in); let rsp = DM_CPU_Rsp {ok: True, data: ?}; f_gpr_rsps.enq (rsp); - if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", - mcycle, regname, data); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); endrule rule rl_debug_gpr_access_busy (rg_state != CPU_DEBUG_MODE); @@ -448,36 +446,38 @@ module mkProc (Proc_IFC); let rsp = DM_CPU_Rsp {ok: False, data: ?}; f_gpr_rsps.enq (rsp); - if (cur_verbosity > 1) $display ("%0d: %m.rl_debug_gpr_access_busy", mcycle); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_gpr_access_busy", cur_cycle); endrule // ---------------- // Debug Module FPR read/write `ifdef ISA_F - rule rl_debug_read_fpr ((rg_state == CPU_DEBUG_MODE) && (! f_fpr_reqs.first.write)); + rule rl_debug_fpr_read ((rg_state == CPU_DEBUG_MODE) && (! f_fpr_reqs.first.write)); let req <- pop (f_fpr_reqs); - Bit #(5) regname = req.address; - let data = core [0].fpr_read (regname); - let rsp = DM_CPU_Rsp {ok: True, data: data}; + Bit #(5) regnum = req.address; + + let data_out = core [0].fpr_read (regnum); + + let rsp = DM_CPU_Rsp {ok: True, data: data_out}; f_fpr_rsps.enq (rsp); - if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", - mcycle, regname, data); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); endrule - rule rl_debug_write_fpr ((rg_state == CPU_DEBUG_MODE) && f_fpr_reqs.first.write); + rule rl_debug_fpr_write ((rg_state == CPU_DEBUG_MODE) && f_fpr_reqs.first.write); let req <- pop (f_fpr_reqs); - Bit #(5) regname = req.address; - let data = req.data; - core [0].fpr_write (regname, data); + Bit #(5) regnum = req.address; + let data_in = req.data; + + core [0].fpr_write (regnum, data_in); let rsp = DM_CPU_Rsp {ok: True, data: ?}; f_fpr_rsps.enq (rsp); - if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", - mcycle, regname, data); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); endrule rule rl_debug_fpr_access_busy (rg_state != CPU_DEBUG_MODE); @@ -485,8 +485,8 @@ module mkProc (Proc_IFC); let rsp = DM_CPU_Rsp {ok: False, data: ?}; f_fpr_rsps.enq (rsp); - if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_fpr_access_busy", mcycle); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_fpr_access_busy", cur_cycle); endrule `endif From 2e909a90a91865ce917bbde768c4b431551bad88 Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Tue, 14 Jan 2020 23:29:32 -0500 Subject: [PATCH 6/8] Work-in-progress integrating Debug Module. Now able to load ELF file from debugger and execute it --- src_Core/CPU/Core.bsv | 24 +-- src_Core/CPU/Proc.bsv | 8 +- src_Core/CPU/Proc_IFC.bsv | 2 + src_Core/Core/CoreW.bsv | 9 +- .../RISCY_OOO/procs/lib/LLCDmaConnect.bsv | 149 ++++++++++++++---- 5 files changed, 143 insertions(+), 49 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index b47cfdb..378a18a 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -1125,9 +1125,9 @@ module mkCore#(CoreId coreId)(Core); method Data gpr_read (Bit #(5) gpr_addr) if (rg_core_run_state == CORE_HALTED); let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), - src2: ?, - src3: ?, - dst: ?}; + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); @@ -1136,9 +1136,9 @@ module mkCore#(CoreId coreId)(Core); method Action gpr_write (Bit #(5) gpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), - src2: ?, - src3: ?, - dst: ?}; + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); // rf.write [debuggerPort].wr (phy_rindx, data); @@ -1148,9 +1148,9 @@ module mkCore#(CoreId coreId)(Core); `ifdef ISA_F method Data fpr_read (Bit #(5) fpr_addr) if (rg_core_run_state == CORE_HALTED); let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), - src2: ?, - src3: ?, - dst: ?}; + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); @@ -1159,9 +1159,9 @@ module mkCore#(CoreId coreId)(Core); method Action fpr_write (Bit #(5) fpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), - src2: ?, - src3: ?, - dst: ?}; + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); // rf.write [debuggerPort].wr (phy_rindx, data); diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index f2ed17e..98945dd 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -195,16 +195,18 @@ module mkProc (Proc_IFC); tlbToMem[i] = core[i].tlbToMem; end + /* // Stub out memLoader (TODO: can be Debug Module's access) let memLoaderStub = interface MemLoaderMemClient; interface memReq = nullFifoDeq; interface respSt = nullFifoEnq; endinterface; + */ - mkLLCDmaConnect(llc.dma, memLoaderStub, tlbToMem); + let llc__mem_server <- mkLLCDmaConnect(llc.dma, tlbToMem); // ================================================================ - // interface LLC to AXI4 + // interface Back-side of LLC to AXI4 LLC_AXI4_Adapter_IFC llc_axi4_adapter <- mkLLC_AXi4_Adapter (llc.to_mem); @@ -584,6 +586,8 @@ module mkProc (Proc_IFC); // CSR access interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps); + + interface debug_module_mem_server = llc__mem_server; `endif endmodule: mkProc diff --git a/src_Core/CPU/Proc_IFC.bsv b/src_Core/CPU/Proc_IFC.bsv index 48e7f49..13e93a5 100644 --- a/src_Core/CPU/Proc_IFC.bsv +++ b/src_Core/CPU/Proc_IFC.bsv @@ -99,6 +99,8 @@ interface Proc_IFC; // CSR access interface Server #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_server; + + interface AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) debug_module_mem_server; `endif endinterface diff --git a/src_Core/Core/CoreW.bsv b/src_Core/Core/CoreW.bsv index 4272b1b..9cb5a71 100644 --- a/src_Core/Core/CoreW.bsv +++ b/src_Core/Core/CoreW.bsv @@ -411,8 +411,9 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources)); mkConnection (fabric_2x3.v_to_slaves [plic_slave_num], plic.axi4_slave); // TODO: This slave can be connected to mkLLCDmaConnect for Debug Module System Bus Access - AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) dummy_slave = dummy_AXI4_Slave_ifc; - mkConnection (fabric_2x3.v_to_slaves [near_mem_io_slave_num], dummy_slave); + // AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) dummy_slave = dummy_AXI4_Slave_ifc; + // mkConnection (fabric_2x3.v_to_slaves [near_mem_io_slave_num], dummy_slave); + mkConnection (fabric_2x3.v_to_slaves [near_mem_io_slave_num], proc.debug_module_mem_server); // ================================================================ // Connect external interrupt lines from PLIC to CPU @@ -557,8 +558,8 @@ module mkFabric_2x3 (Fabric_2x3_IFC); // Any addr is legal, and there is only one slave to service it. function Tuple2 #(Bool, Slave_Num_2x3) fn_addr_to_slave_num_2x3 (Fabric_Addr addr); - if ( (soc_map.m_near_mem_io_addr_base <= addr) - && (addr < soc_map.m_near_mem_io_addr_lim)) + if ( (soc_map.m_mem0_controller_addr_base <= addr) + && (addr < soc_map.m_mem0_controller_addr_lim)) return tuple2 (True, near_mem_io_slave_num); else if ( (soc_map.m_plic_addr_base <= addr) diff --git a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv index edae865..eb62489 100644 --- a/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv +++ b/src_Core/RISCY_OOO/procs/lib/LLCDmaConnect.bsv @@ -1,4 +1,16 @@ +// This file is a modified version of: RISCY_OOO/procs/lib/LLCDmaConnect.bsv +// The original module had, as 2nd parameter, MemLoaderMemClient memLoader +// The memLoader assumed only write-transactions (to load memory), and +// discarded load responses. + +// Here, the module instead offers an AXI4_Slave interface to be +// connected to the AXI4_Master of the Debug Module. +// This axi4_slave accepts and responds to both read and write transactions. + +// Modifications Copyright (c) 2020 Bluespec, Inc. + +// Original copyright: // Copyright (c) 2017 Massachusetts Institute of Technology // // Permission is hereby granted, free of charge, to any person @@ -26,6 +38,7 @@ import GetPut::*; import Vector::*; import BuildVector::*; import FIFO::*; +import FIFOF::*; import Assert::*; import Types::*; @@ -37,6 +50,10 @@ import MemLoader::*; import CrossBar::*; import MemLoader::*; +import AXI4_Types :: *; +import Fabric_Defs :: *; +import Semi_FIFOF :: *; + typedef struct { CoreId core; TlbMemReqId id; @@ -48,15 +65,44 @@ typedef union tagged { TlbDmaReqId Tlb; } LLCDmaReqId deriving(Bits, Eq, FShow); -module mkLLCDmaConnect#( +// For writing, position a 4-byte value and 4-bit byte-enable into a 64-byte line and 64-bit line-byte-enable +function Tuple3 #(Addr, Line, LineByteEn) fn_line_and_byteen_from_word (Addr addr, Bit #(64) data); + Vector #(16, Bit #(32)) line_words = replicate (0); + Vector #(16, Bit #(4)) line_word_byteens = replicate (0); + Bit #(4) word_index = addr [5:2]; + line_words [word_index] = ((addr [2] == 0) ? data [31:0] : data [63:32]); + line_word_byteens [word_index] = 4'b1111; + Addr line_addr = { addr [63:6], 6'b0 }; + return tuple3 (line_addr, + unpack (pack (line_words)), + unpack (pack (line_word_byteens))); +endfunction + +// For reading, extract a 4-byte value from a 64-byte line +function Bit #(64) fn_word_from_line (Line line, Bit #(4) word_in_line); + Vector #(16, Bit #(32)) line_words = unpack (pack (line)); + Bit #(32) w = line_words [word_in_line]; + Bit #(64) dw = ((word_in_line [0] == 0) ? { 32'b0, w } : { w, 32'b0 }); + return dw; +endfunction + +module mkLLCDmaConnect #( DmaServer#(LLCDmaReqId) llc, - MemLoaderMemClient memLoader, + // MemLoaderMemClient memLoader, // REPLACED BY AXI4_Slave_interface Vector#(CoreNum, TlbMemClient) tlb -)(Empty) provisos ( +)(AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User)) provisos ( Alias#(dmaRqT, DmaRq#(LLCDmaReqId)) ); Bool verbose = False; + Integer verbosity = 0; + + // When debugger reads a word, request a line from LLC, and remember word-in-line here + FIFOF #(Bit #(4)) f_word_in_line <- mkFIFOF; + + // Slave transactor for requests from Debug Module + AXI4_Slave_Xactor_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) axi4_slave_xactor <- mkAXI4_Slave_Xactor; + // helper functions for cross bar function XBarDstInfo#(Bit#(0), Tuple2#(CoreId, TlbMemReq)) getTlbDst(CoreId core, TlbMemReq r); return XBarDstInfo {idx: 0, data: tuple2(core, r)}; @@ -83,24 +129,46 @@ module mkLLCDmaConnect#( }; endfunction - // send req to LLC - rule sendMemLoaderReqToLLC; - memLoader.memReq.deq; - let r = memLoader.memReq.first; - dmaRqT req = DmaRq { - addr: r.addr, - byteEn: r.byteEn, - data: r.data, - id: MemLoader (r.id) - }; - llc.memReq.enq(req); - if(verbose) begin - $display("[LLCDmaConnnect sendMemLoaderReqToLLC] ", - fshow(r), " ; ", fshow(req)); - end + rule sendMemLoaderReqToLLC_wr; // write requests + let wr_addr <- pop_o (axi4_slave_xactor.o_wr_addr); + let wr_data <- pop_o (axi4_slave_xactor.o_wr_data); + match { .line_addr, .line_data, .line_byteen } = fn_line_and_byteen_from_word (wr_addr.awaddr, wr_data.wdata); + dmaRqT req = DmaRq {addr: line_addr, + byteEn: line_byteen, + data: line_data, + id: tagged MemLoader (?) // TODO: change uniformly to wr_addr.awid + }; + llc.memReq.enq(req); + + if (verbosity != 0) begin + $display("[LLCDmaConnect sendMemLoaderReqToLLC_wr]"); + $display (" ", fshow (wr_addr)); + $display (" ", fshow (wr_data)); + $display (" ", fshow (req)); + end endrule - (* descending_urgency = "sendMemLoaderReqToLLC, sendTlbReqToLLC" *) + rule sendMemLoaderReqToLLC_rd; // read requests + let rd_addr <- pop_o (axi4_slave_xactor.o_rd_addr); + Addr line_addr = { rd_addr.araddr [63:6], 6'b0 }; + dmaRqT req = DmaRq {addr: line_addr, + byteEn: replicate (False), + data: ?, + id: MemLoader (?) // TODO: change uniformly to rd_addr.awid + }; + llc.memReq.enq(req); + Bit #(4) word_in_line = rd_addr.araddr [5:2]; + f_word_in_line.enq (word_in_line); + + if (verbosity != 0) begin + $display("[LLCDmaConnect sendMemLoaderReqToLLC_rd]"); + $display (" ", fshow (rd_addr)); + $display (" ", fshow (req)); + end + endrule + + (* descending_urgency = "sendMemLoaderReqToLLC_wr, sendTlbReqToLLC" *) + (* descending_urgency = "sendMemLoaderReqToLLC_rd, sendTlbReqToLLC" *) rule sendTlbReqToLLC; let {c, r} <- toGet(tlbQ).get; let req = getTlbDmaReq(c, r); @@ -112,12 +180,22 @@ module mkLLCDmaConnect#( // send Ld resp from LLC rule sendLdRespToMemLoader(llc.respLd.first.id matches tagged MemLoader .id); - llc.respLd.deq; - if(verbose) begin - $display("[LLCDmaConnect sendLdRespToMemLoader] ", - fshow(llc.respLd.first)); - end - doAssert(False, "No mem loader ld"); + let resp = llc.respLd.first; + llc.respLd.deq; + let word_in_line = f_word_in_line.first; + f_word_in_line.deq; + AXI4_Rd_Data #(Wd_Id, Wd_Data, Wd_User) + rd_data = AXI4_Rd_Data {rid: 0, // TODO: change uniformly to Fabric_Id + rdata: fn_word_from_line (resp.data, word_in_line), + rresp: axi4_resp_okay, + rlast: True, + ruser: ?}; + axi4_slave_xactor.i_rd_data.enq (rd_data); + if (verbosity != 0) begin + $display ("[LLCDmaConnect sendLdRespToMemLoader]"); + $display (" ", fshow (resp)); + $display (" ", fshow (rd_data)); + end endrule rule sendLdRespToTlb(llc.respLd.first.id matches tagged Tlb .id); @@ -135,12 +213,19 @@ module mkLLCDmaConnect#( // send St resp from LLC rule sendStRespToMemLoader(llc.respSt.first matches tagged MemLoader .id); - llc.respSt.deq; - memLoader.respSt.enq(id); - if(verbose) begin - $display("[LLCDmaConnect sendStRespToMemLoader] ", - fshow(llc.respSt.first)); - end + let resp = llc.respSt.first; + llc.respSt.deq; + AXI4_Wr_Resp #(Wd_Id, Wd_User) + wr_resp = AXI4_Wr_Resp {bid: 0, // TODO: change uniformly to Fabric_id + bresp: axi4_resp_okay, + buser: ?}; + axi4_slave_xactor.i_wr_resp.enq (wr_resp); + + if (verbosity != 0) begin + $display ("[LLCDmaConnect sendStRespToMemLoader]"); + $display (" ", fshow (resp)); + $display (" ", fshow (wr_resp)); + end endrule rule sendStRespToTlb(llc.respSt.first matches tagged Tlb .id); @@ -150,4 +235,6 @@ module mkLLCDmaConnect#( end doAssert(False, "No TLB st"); endrule + + return axi4_slave_xactor.axi_side; endmodule From 16cb92e2c132805bf74b19e2db8af686d7006d38 Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Wed, 15 Jan 2020 15:54:50 -0500 Subject: [PATCH 7/8] Register reads now working. All functionality is in; need testing, cleanup, merge into master. --- src_Core/CPU/Core.bsv | 252 ++++++++++++++---- src_Core/CPU/Proc.bsv | 149 +---------- .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 15 ++ 3 files changed, 215 insertions(+), 201 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 378a18a..f1f6106 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -84,7 +84,18 @@ import Bypass::*; import CsrFile :: *; -import Cur_Cycle :: *; +// ================================================================ +// Toooba + +import Cur_Cycle :: *; +import FIFOF :: *; +import GetPut_Aux :: *; + +`ifdef INCLUDE_GDB_CONTROL +import DM_CPU_Req_Rsp :: *; +`endif + +// ================================================================ `ifdef SECURITY `define SECURITY_OR_INCLUDE_GDB_CONTROL @@ -155,14 +166,14 @@ interface Core; method Action debug_resume; - method Data csr_read (Bit #(12) csr_addr); - method Action csr_write (Bit #(12) csr_addr, Data data); - method Data gpr_read (Bit #(5) gpr_addr); - method Action gpr_write (Bit #(5) gpr_addr, Data data); + interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_gpr_mem_server; `ifdef ISA_F - method Data fpr_read (Bit #(5) fpr_addr); - method Action fpr_write (Bit #(5) fpr_addr, Data data); + // FPR access + interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_fpr_mem_server; `endif + + // CSR access + interface Server #(DM_CPU_Req #(12, 64), DM_CPU_Rsp #(64)) hart0_csr_mem_server; `endif endinterface @@ -195,7 +206,8 @@ module mkCore#(CoreId coreId)(Core); Reg#(Bool) started <- mkReg(False); `ifdef INCLUDE_GDB_CONTROL - Reg #(Core_Run_State) rg_core_run_state <- mkReg (CORE_RUNNING); + // Using a ConfigReg since scheduling of reads/writes not critical (TODO: verify this) + Reg #(Core_Run_State) rg_core_run_state <- mkConfigReg (CORE_RUNNING); `endif // front end @@ -517,6 +529,9 @@ module mkCore#(CoreId coreId)(Core); `endif endmethod method doStats = coreFix.doStatsIfc._read; +`ifdef INCLUDE_GDB_CONTROL + method Bool core_is_running = (rg_core_run_state == CORE_RUNNING); +`endif endinterface); RenameStage renameStage <- mkRenameStage(renameInput); @@ -1012,6 +1027,173 @@ module mkCore#(CoreId coreId)(Core); endrule `endif +`ifdef INCLUDE_GDB_CONTROL + // ================================================================ + // DEBUG MODULE INTERFACE + + // ---------------- + // Debug Module GPR read/write + + FIFOF #(DM_CPU_Req #(5, 64)) f_gpr_reqs <- mkFIFOF1; + FIFOF #(DM_CPU_Rsp #(64)) f_gpr_rsps <- mkFIFOF1; + + rule rl_debug_gpr_read ( (rg_core_run_state == CORE_HALTED) + && f_gpr_reqs.notEmpty + && (! f_gpr_reqs.first.write)); + let req <- pop (f_gpr_reqs); + Bit #(5) regnum = req.address; + + let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr regnum), + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + let data_out = rf.read [debuggerPort].rd1 (phy_rindx); + + let rsp = DM_CPU_Rsp {ok: True, data: data_out}; + f_gpr_rsps.enq (rsp); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); + endrule + + rule rl_debug_gpr_write ( (rg_core_run_state == CORE_HALTED) + && f_gpr_reqs.notEmpty + && f_gpr_reqs.first.write); + let req <- pop (f_gpr_reqs); + Bit #(5) regnum = req.address; + let data_in = req.data; + + let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr regnum), + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + rf.write [debuggerPort].wr (phy_rindx, data_in); + $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", regnum, data_in, phy_rindx); + + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_gpr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); + endrule + + rule rl_debug_gpr_access_busy (rg_core_run_state != CORE_HALTED); + let req <- pop (f_gpr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_gpr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_gpr_access_busy", cur_cycle); + endrule + +`ifdef ISA_F + // ---------------- + // Debug Module FPR read/write + + FIFOF #(DM_CPU_Req #(5, 64)) f_fpr_reqs <- mkFIFOF1; + FIFOF #(DM_CPU_Rsp #(64)) f_fpr_rsps <- mkFIFOF1; + + rule rl_debug_fpr_read ( (rg_core_run_state == CORE_HALTED) + && (! f_gpr_reqs.notEmpty) // prioritize gpr reqs + && (! f_fpr_reqs.first.write)); + let req <- pop (f_fpr_reqs); + Bit #(5) regnum = req.address; + + let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu regnum), + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + let data_out = rf.read [debuggerPort].rd1 (phy_rindx); + + let rsp = DM_CPU_Rsp {ok: True, data: data_out}; + f_fpr_rsps.enq (rsp); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); + endrule + + rule rl_debug_fpr_write ( (rg_core_run_state == CORE_HALTED) + && (! f_gpr_reqs.notEmpty) // prioritize gpr reqs + && f_fpr_reqs.first.write); + let req <- pop (f_fpr_reqs); + Bit #(5) regnum = req.address; + let data_in = req.data; + + let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu regnum), + src2: tagged Invalid, + src3: tagged Invalid, + dst: tagged Invalid}; + let rename_result = regRenamingTable.rename[0].getRename (arch_regs); + let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); + rf.write [debuggerPort].wr (phy_rindx, data_in); + $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", regnum, data_in, phy_rindx); + + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_fpr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); + endrule + + rule rl_debug_fpr_access_busy (rg_core_run_state != CORE_HALTED); + let req <- pop (f_fpr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_fpr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_fpr_access_busy", cur_cycle); + endrule +`endif + + // ---------------- + // Debug Module CSR read/write + + // Debugger CSR read/write request/response + FIFOF #(DM_CPU_Req #(12, 64)) f_csr_reqs <- mkFIFOF1; + FIFOF #(DM_CPU_Rsp #(64)) f_csr_rsps <- mkFIFOF1; + + rule rl_debug_csr_read ( (rg_core_run_state == CORE_HALTED) + && (! f_csr_reqs.first.write)); + let req <- pop (f_csr_reqs); + Bit #(12) csr_addr = req.address; + let data_out = csrf.rd (unpack (csr_addr)); + + let rsp = DM_CPU_Rsp {ok: True, data: data_out}; + f_csr_rsps.enq (rsp); + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_read_csr: csr %0d => 0x%0h", cur_cycle, csr_addr, data_out); + endrule + + rule rl_debug_csr_write ( (rg_core_run_state == CORE_HALTED) + && f_csr_reqs.first.write); + let req <- pop (f_csr_reqs); + Bit #(12) csr_addr = req.address; + let data_in = req.data; + csrf.csrInstWr (unpack (csr_addr), data_in); + + let rsp = DM_CPU_Rsp {ok: True, data: ?}; + f_csr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", cur_cycle, csr_addr, data_in); + endrule + + rule rl_debug_csr_access_busy (rg_core_run_state != CORE_HALTED); + let req <- pop (f_csr_reqs); + let rsp = DM_CPU_Rsp {ok: False, data: ?}; + f_csr_rsps.enq (rsp); + + // if (cur_verbosity > 1) + $display ("%0d: %m.rl_debug_csr_access_busy", cur_cycle); + endrule + + // ================================================================ +`endif + interface CoreReq coreReq; method Action start( Bit#(64) startpc, @@ -1115,60 +1297,14 @@ module mkCore#(CoreId coreId)(Core); $display ("%0d: %m.debug_resume, dpc = 0x%0h", cur_cycle, startpc); endmethod - method Data csr_read (Bit #(12) csr_addr) if (rg_core_run_state == CORE_HALTED); - return csrf.rd (unpack (csr_addr)); - endmethod - - method Action csr_write (Bit #(12) csr_addr, Data data) if (rg_core_run_state == CORE_HALTED); - csrf.csrInstWr (unpack (csr_addr), data); - endmethod - - method Data gpr_read (Bit #(5) gpr_addr) if (rg_core_run_state == CORE_HALTED); - let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), - src2: tagged Invalid, - src3: tagged Invalid, - dst: tagged Invalid}; - let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); - let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); - return data; - endmethod - - method Action gpr_write (Bit #(5) gpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); - let arch_regs = ArchRegs {src1: tagged Valid (tagged Gpr gpr_addr), - src2: tagged Invalid, - src3: tagged Invalid, - dst: tagged Invalid}; - let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); - // rf.write [debuggerPort].wr (phy_rindx, data); - // $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", gpr_addr, data, phy_rindx); - endmethod + interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps); `ifdef ISA_F - method Data fpr_read (Bit #(5) fpr_addr) if (rg_core_run_state == CORE_HALTED); - let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), - src2: tagged Invalid, - src3: tagged Invalid, - dst: tagged Invalid}; - let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); - let data = ?; // rf.read [debuggerPort].rd1 (phy_rindx); - return data; - endmethod - - method Action fpr_write (Bit #(5) fpr_addr, Data data) if (rg_core_run_state == CORE_HALTED); - let arch_regs = ArchRegs {src1: tagged Valid (tagged Fpu fpr_addr), - src2: tagged Invalid, - src3: tagged Invalid, - dst: tagged Invalid}; - let rename_result = ?; // regRenamingTable.rename[0].getRename (arch_regs); - let phy_rindx = ?; // fromMaybe (?, rename_result.phy_regs.src1); - // rf.write [debuggerPort].wr (phy_rindx, data); - // $display ("%m.fpr_write (%0d, %0x), phy_rindx %0d", fpr_addr, data, phy_rindx); - endmethod + interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps); `endif + // CSR access + interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps); `endif endmodule diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 98945dd..24c209b 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -139,20 +139,6 @@ module mkProc (Proc_IFC); FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF; FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF; - // Debugger GPR read/write request/response - FIFOF #(DM_CPU_Req #(5, XLEN)) f_gpr_reqs <- mkFIFOF1; - FIFOF #(DM_CPU_Rsp #(XLEN)) f_gpr_rsps <- mkFIFOF1; - -`ifdef ISA_F - // Debugger FPR read/write request/response - FIFOF #(DM_CPU_Req #(5, FLEN)) f_fpr_reqs <- mkFIFOF1; - FIFOF #(DM_CPU_Rsp #(FLEN)) f_fpr_rsps <- mkFIFOF1; -`endif - - // Debugger CSR read/write request/response - FIFOF #(DM_CPU_Req #(12, XLEN)) f_csr_reqs <- mkFIFOF1; - FIFOF #(DM_CPU_Rsp #(XLEN)) f_csr_rsps <- mkFIFOF1; - `endif // ---------------- @@ -195,14 +181,7 @@ module mkProc (Proc_IFC); tlbToMem[i] = core[i].tlbToMem; end - /* - // Stub out memLoader (TODO: can be Debug Module's access) - let memLoaderStub = interface MemLoaderMemClient; - interface memReq = nullFifoDeq; - interface respSt = nullFifoEnq; - endinterface; - */ - + // Note: mkLLCDmaConnect is Toooba version, different from riscy-ooo version let llc__mem_server <- mkLLCDmaConnect(llc.dma, tlbToMem); // ================================================================ @@ -311,9 +290,7 @@ module mkProc (Proc_IFC); // Run command when in debug mode rule rl_debug_run ((f_run_halt_reqs.first == True) - && (! f_gpr_reqs.notEmpty) - && (! f_fpr_reqs.notEmpty) - && (! f_csr_reqs.notEmpty) + // && (! f_csr_reqs.notEmpty) && (rg_state == CPU_DEBUG_MODE)); // if (cfg_verbosity > 1) $display ("%0d: %m.rl_debug_run", cur_cycle); @@ -328,9 +305,7 @@ module mkProc (Proc_IFC); // Run command when already running rule rl_debug_run_redundant ((f_run_halt_reqs.first == True) - && (! f_gpr_reqs.notEmpty) - && (! f_fpr_reqs.notEmpty) - && (! f_csr_reqs.notEmpty) + // && (! f_csr_reqs.notEmpty) && fn_is_running (rg_state)); // if (cfg_verbosity > 1) $display ("%0d: %m.rl_debug_run_redundant", cur_cycle); @@ -380,118 +355,6 @@ module mkProc (Proc_IFC); cur_cycle, fshow (rg_state)); endrule - // ---------------- - // Debug Module CSR read/write - - rule rl_debug_csr_read ((rg_state == CPU_DEBUG_MODE) && (! f_csr_reqs.first.write)); - let req <- pop (f_csr_reqs); - Bit #(12) csr_addr = req.address; - let data = core [0].csr_read (csr_addr); - let rsp = DM_CPU_Rsp {ok: True, data: data}; - f_csr_rsps.enq (rsp); - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_read_csr: csr %0d => 0x%0h", cur_cycle, csr_addr, data); - endrule - - rule rl_debug_csr_write ((rg_state == CPU_DEBUG_MODE) && f_csr_reqs.first.write); - let req <- pop (f_csr_reqs); - Bit #(12) csr_addr = req.address; - let data = req.data; - core [0].csr_write (csr_addr, data); - let rsp = DM_CPU_Rsp {ok: True, data: ?}; - f_csr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", cur_cycle, csr_addr, data); - endrule - - rule rl_debug_csr_access_busy (rg_state != CPU_DEBUG_MODE); - let req <- pop (f_csr_reqs); - let rsp = DM_CPU_Rsp {ok: False, data: ?}; - f_csr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_csr_access_busy", cur_cycle); - endrule - - // ---------------- - // Debug Module GPR read/write - - rule rl_debug_gpr_read ((rg_state == CPU_DEBUG_MODE) && (! f_gpr_reqs.first.write)); - let req <- pop (f_gpr_reqs); - Bit #(5) regnum = req.address; - - let data_out = core [0].gpr_read (regnum); - - let rsp = DM_CPU_Rsp {ok: True, data: data_out}; - f_gpr_rsps.enq (rsp); - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); - endrule - - rule rl_debug_gpr_write ((rg_state == CPU_DEBUG_MODE) && f_gpr_reqs.first.write); - let req <- pop (f_gpr_reqs); - Bit #(5) regnum = req.address; - let data_in = req.data; - - core [0].gpr_write (regnum, data_in); - - let rsp = DM_CPU_Rsp {ok: True, data: ?}; - f_gpr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); - endrule - - rule rl_debug_gpr_access_busy (rg_state != CPU_DEBUG_MODE); - let req <- pop (f_gpr_reqs); - let rsp = DM_CPU_Rsp {ok: False, data: ?}; - f_gpr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_gpr_access_busy", cur_cycle); - endrule - - // ---------------- - // Debug Module FPR read/write - -`ifdef ISA_F - rule rl_debug_fpr_read ((rg_state == CPU_DEBUG_MODE) && (! f_fpr_reqs.first.write)); - let req <- pop (f_fpr_reqs); - Bit #(5) regnum = req.address; - - let data_out = core [0].fpr_read (regnum); - - let rsp = DM_CPU_Rsp {ok: True, data: data_out}; - f_fpr_rsps.enq (rsp); - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); - endrule - - rule rl_debug_fpr_write ((rg_state == CPU_DEBUG_MODE) && f_fpr_reqs.first.write); - let req <- pop (f_fpr_reqs); - Bit #(5) regnum = req.address; - let data_in = req.data; - - core [0].fpr_write (regnum, data_in); - - let rsp = DM_CPU_Rsp {ok: True, data: ?}; - f_fpr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); - endrule - - rule rl_debug_fpr_access_busy (rg_state != CPU_DEBUG_MODE); - let req <- pop (f_fpr_reqs); - let rsp = DM_CPU_Rsp {ok: False, data: ?}; - f_fpr_rsps.enq (rsp); - - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_fpr_access_busy", cur_cycle); - endrule -`endif - `endif // ================================================================ @@ -577,15 +440,15 @@ module mkProc (Proc_IFC); endinterface // GPR access - interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps); + interface Server hart0_gpr_mem_server = core[0].hart0_gpr_mem_server; `ifdef ISA_F // FPR access - interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps); + interface Server hart0_fpr_mem_server = core[0].hart0_fpr_mem_server; `endif // CSR access - interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps); + interface Server hart0_csr_mem_server = core[0].hart0_csr_mem_server; interface debug_module_mem_server = llc__mem_server; `endif diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index c8e91f5..dbf78e73 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -77,6 +77,9 @@ interface RenameInput; method Bool checkDeadlock; // performance method Bool doStats; +`ifdef INCLUDE_GDB_CONTROL + method Bool core_is_running; +`endif endinterface interface RenameStage; @@ -302,6 +305,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && epochManager.checkEpoch[0].check(fetchStage.pipelines[0].first.main_epoch) // correct path && isValid(firstTrap) // take trap && rob.isEmpty // stall for ROB empty +`ifdef INCLUDE_GDB_CONTROL + && inIfc.core_is_running +`endif ); fetchStage.pipelines[0].deq; `ifdef INCLUDE_GDB_CONTROL @@ -416,6 +422,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && !isValid(firstTrap) // not trap && firstReplay // system inst needs replay && rob.isEmpty // stall for ROB empty +`ifdef INCLUDE_GDB_CONTROL + && inIfc.core_is_running +`endif ); fetchStage.pipelines[0].deq; `ifdef INCLUDE_GDB_CONTROL @@ -562,6 +571,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); // turn off speculation for mem inst only, and first inst is mem && (specNonMem && firstMem) && rob.isEmpty // stall for ROB empty to process mem inst +`ifdef INCLUDE_GDB_CONTROL + && inIfc.core_is_running +`endif ); fetchStage.pipelines[0].deq; `ifdef INCLUDE_GDB_CONTROL @@ -722,6 +734,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); && (!specNone || rob.isEmpty) // don't process mem inst if we don't allow speculation for mem inst only && !(specNonMem && firstMem) +`endif +`ifdef INCLUDE_GDB_CONTROL + && inIfc.core_is_running `endif ); // we stop superscalar rename when an instruction cannot be processed: From 56698d469e556e5ff27716cfe70525a176a3d0ed Mon Sep 17 00:00:00 2001 From: rsnikhil Date: Thu, 16 Jan 2020 14:36:19 -0500 Subject: [PATCH 8/8] Integration of Debug_Module basically complete (except resume-after-break, details follow) Stop, set breakpoint: working, stopping successfully. Step: working: stops after a step. Continue (resume) working after Stop and Step, but not after stop by breakpoint (needs debugging) Read/Write GPRs, FPRs, CSRs, memory working. --- src_Core/CPU/Core.bsv | 184 ++++++++++++------ src_Core/CPU/Proc.bsv | 139 ++----------- src_Core/CPU/Proc_IFC.bsv | 14 +- src_Core/Core/CoreW.bsv | 10 +- .../RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv | 6 +- 5 files changed, 146 insertions(+), 207 deletions(-) diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index f1f6106..e9c5fec 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -159,20 +159,11 @@ interface Core; method Action setDEIP (Bit #(1) v); `ifdef INCLUDE_GDB_CONTROL - method Action debug_halt; - - (* always_ready *) - method Bool is_debug_halted; - - method Action debug_resume; - - interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_gpr_mem_server; + interface Server #(Bool, Bool) hart0_run_halt_server; + interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_gpr_mem_server; `ifdef ISA_F - // FPR access - interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_fpr_mem_server; + interface Server #(DM_CPU_Req #(5, 64), DM_CPU_Rsp #(64)) hart0_fpr_mem_server; `endif - - // CSR access interface Server #(DM_CPU_Req #(12, 64), DM_CPU_Rsp #(64)) hart0_csr_mem_server; `endif endinterface @@ -188,6 +179,7 @@ endinterface typedef enum { `ifdef INCLUDE_GDB_CONTROL + CORE_HALTING, CORE_HALTED, `endif CORE_RUNNING @@ -744,8 +736,8 @@ module mkCore#(CoreId coreId)(Core); `ifdef INCLUDE_GDB_CONTROL if (commitStage.is_debug_halted) begin started <= False; - rg_core_run_state <= CORE_HALTED; - $display ("%0d: %m.rule readyToFetch: debug halt", cur_cycle); + rg_core_run_state <= CORE_HALTING; + $display ("%0d: %m.rule readyToFetch: halting for debug mode", cur_cycle); end `endif endrule @@ -1031,7 +1023,9 @@ module mkCore#(CoreId coreId)(Core); // ================================================================ // DEBUG MODULE INTERFACE - // ---------------- + Bool show_DM_interactions = True; // for debugging the interactions + + // ---------------------------------------------------------------- // Debug Module GPR read/write FIFOF #(DM_CPU_Req #(5, 64)) f_gpr_reqs <- mkFIFOF1; @@ -1053,7 +1047,8 @@ module mkCore#(CoreId coreId)(Core); let rsp = DM_CPU_Rsp {ok: True, data: data_out}; f_gpr_rsps.enq (rsp); - // if (cur_verbosity > 1) + + if (show_DM_interactions) $display ("%0d: %m.rl_debug_read_gpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); endrule @@ -1071,26 +1066,26 @@ module mkCore#(CoreId coreId)(Core); let rename_result = regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); rf.write [debuggerPort].wr (phy_rindx, data_in); - $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", regnum, data_in, phy_rindx); let rsp = DM_CPU_Rsp {ok: True, data: ?}; f_gpr_rsps.enq (rsp); - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_gpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_gpr_write: reg %0d <= 0x%0h (phy_rindx = %0d)", + cur_cycle, regnum, data_in, phy_rindx); endrule - rule rl_debug_gpr_access_busy (rg_core_run_state != CORE_HALTED); + rule rl_debug_gpr_access_busy (rg_core_run_state == CORE_RUNNING); let req <- pop (f_gpr_reqs); let rsp = DM_CPU_Rsp {ok: False, data: ?}; f_gpr_rsps.enq (rsp); - // if (cur_verbosity > 1) + if (show_DM_interactions) $display ("%0d: %m.rl_debug_gpr_access_busy", cur_cycle); endrule `ifdef ISA_F - // ---------------- + // ---------------------------------------------------------------- // Debug Module FPR read/write FIFOF #(DM_CPU_Req #(5, 64)) f_fpr_reqs <- mkFIFOF1; @@ -1112,7 +1107,8 @@ module mkCore#(CoreId coreId)(Core); let rsp = DM_CPU_Rsp {ok: True, data: data_out}; f_fpr_rsps.enq (rsp); - // if (cur_verbosity > 1) + + if (show_DM_interactions) $display ("%0d: %m.rl_debug_read_fpr: reg %0d => 0x%0h", cur_cycle, regnum, data_out); endrule @@ -1130,26 +1126,28 @@ module mkCore#(CoreId coreId)(Core); let rename_result = regRenamingTable.rename[0].getRename (arch_regs); let phy_rindx = fromMaybe (?, rename_result.phy_regs.src1); rf.write [debuggerPort].wr (phy_rindx, data_in); - $display ("%m.gpr_write (%0d, %0x), phy_rindx %0d", regnum, data_in, phy_rindx); let rsp = DM_CPU_Rsp {ok: True, data: ?}; f_fpr_rsps.enq (rsp); - // if (cur_verbosity > 1) - $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h", cur_cycle, regnum, data_in); + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_write_fpr: reg %0d <= 0x%0h (phy_rindx %0d)", + cur_cycle, regnum, data_in, phy_rindx); endrule - rule rl_debug_fpr_access_busy (rg_core_run_state != CORE_HALTED); + rule rl_debug_fpr_access_busy ( (rg_core_run_state == CORE_RUNNING) + && f_fpr_reqs.notEmpty); + let req <- pop (f_fpr_reqs); let rsp = DM_CPU_Rsp {ok: False, data: ?}; f_fpr_rsps.enq (rsp); - // if (cur_verbosity > 1) + if (show_DM_interactions) $display ("%0d: %m.rl_debug_fpr_access_busy", cur_cycle); endrule `endif - // ---------------- + // ---------------------------------------------------------------- // Debug Module CSR read/write // Debugger CSR read/write request/response @@ -1164,7 +1162,8 @@ module mkCore#(CoreId coreId)(Core); let rsp = DM_CPU_Rsp {ok: True, data: data_out}; f_csr_rsps.enq (rsp); - // if (cur_verbosity > 1) + + if (show_DM_interactions) $display ("%0d: %m.rl_debug_read_csr: csr %0d => 0x%0h", cur_cycle, csr_addr, data_out); endrule @@ -1178,19 +1177,107 @@ module mkCore#(CoreId coreId)(Core); let rsp = DM_CPU_Rsp {ok: True, data: ?}; f_csr_rsps.enq (rsp); - // if (cur_verbosity > 1) + if (show_DM_interactions) $display ("%0d: %m.rl_debug_write_csr: csr 0x%0h <= 0x%0h", cur_cycle, csr_addr, data_in); endrule - rule rl_debug_csr_access_busy (rg_core_run_state != CORE_HALTED); + rule rl_debug_csr_access_busy (rg_core_run_state == CORE_RUNNING); let req <- pop (f_csr_reqs); let rsp = DM_CPU_Rsp {ok: False, data: ?}; f_csr_rsps.enq (rsp); - // if (cur_verbosity > 1) + if (show_DM_interactions) $display ("%0d: %m.rl_debug_csr_access_busy", cur_cycle); endrule + // ---------------------------------------------------------------- + // Debug Module run-halt control + + FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF; + FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF; + Reg #(Bool) rg_sent_halt_rsp <- mkReg (False); + + // ---------------- + // Debug Module Halt control + + rule rl_debug_halt_req ( (rg_core_run_state == CORE_RUNNING) + && (f_run_halt_reqs.first == False)); + f_run_halt_reqs.deq; + + // Debugger 'halt' request (e.g., GDB '^C' command) + // This is initiated just like an interrupt. + renameStage.debug_halt_req; + rg_sent_halt_rsp <= False; + + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_halt_req", cur_cycle); + endrule + + rule rl_debug_halt_req_already_halted ( (rg_core_run_state != CORE_RUNNING) + && (f_run_halt_reqs.first == False)); + f_run_halt_reqs.deq; + + // Notify debugger that we've 'halted' + f_run_halt_rsps.enq (False); + + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_halt_req_already_halted", cur_cycle); + endrule + + // Monitors when we've reached halted state while running + // (due to halt, step or EBREAK) and notifies DM + rule rl_debug_halted (rg_core_run_state == CORE_HALTING); + // Notify debugger that we've halted + f_run_halt_rsps.enq (False); + rg_core_run_state <= CORE_HALTED; + + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_halted", cur_cycle); + endrule + + // ---------------- + // Debug Module Resume (run) control + + // Resume command when in debug mode + rule rl_debug_resume ( (rg_core_run_state == CORE_HALTED) + && (f_run_halt_reqs.first == True) + + // prioritise gpr/fpr/csr read/write requests before resuming + && (! f_gpr_reqs.notEmpty) +`ifdef ISA_F + && (! f_fpr_reqs.notEmpty) +`endif + && (! f_csr_reqs.notEmpty)); + + f_run_halt_reqs.deq; + + let startpc = csrf.dpc_read; + fetchStage.redirect (startpc); + renameStage.debug_resume; + commitStage.debug_resume; + + started <= True; + rg_core_run_state <= CORE_RUNNING; + + // Notify debugger that we've started running + f_run_halt_rsps.enq (True); + + if (show_DM_interactions) + $display ("%0d: %m.debug_resume, dpc = 0x%0h", cur_cycle, startpc); + endrule + + // Run command when already running + rule rl_debug_run_redundant ( (rg_core_run_state == CORE_RUNNING) + && (f_run_halt_reqs.first == True)); + f_run_halt_reqs.deq; + + // Notify debugger that we're running + f_run_halt_rsps.enq (True); + + if (show_DM_interactions) + $display ("%0d: %m.rl_debug_run_redundant", cur_cycle); + endrule + // ================================================================ `endif @@ -1276,35 +1363,12 @@ module mkCore#(CoreId coreId)(Core); method Action setDEIP (v) = csrf.setDEIP (v); `ifdef INCLUDE_GDB_CONTROL - method Action debug_halt () if (started && (rg_core_run_state == CORE_RUNNING)); - $display ("%0d: %m.debug_halt", cur_cycle); - renameStage.debug_halt; // start the halt protocol - endmethod - - method Bool is_debug_halted; - return (rg_core_run_state == CORE_HALTED); - endmethod - - method Action debug_resume () if (rg_core_run_state == CORE_HALTED); - let startpc = csrf.dpc_read; - fetchStage.redirect (startpc); - - renameStage.debug_resume; - commitStage.debug_resume; - - started <= True; - rg_core_run_state <= CORE_RUNNING; - $display ("%0d: %m.debug_resume, dpc = 0x%0h", cur_cycle, startpc); - endmethod - - interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps); - + interface Server hart0_run_halt_server = toGPServer (f_run_halt_reqs, f_run_halt_rsps); + interface Server hart0_gpr_mem_server = toGPServer (f_gpr_reqs, f_gpr_rsps); `ifdef ISA_F - interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps); + interface Server hart0_fpr_mem_server = toGPServer (f_fpr_reqs, f_fpr_rsps); `endif - - // CSR access - interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps); + interface Server hart0_csr_mem_server = toGPServer (f_csr_reqs, f_csr_rsps); `endif endmodule diff --git a/src_Core/CPU/Proc.bsv b/src_Core/CPU/Proc.bsv index 24c209b..3d0ee9f 100644 --- a/src_Core/CPU/Proc.bsv +++ b/src_Core/CPU/Proc.bsv @@ -85,23 +85,6 @@ import TV_Info :: *; import DM_CPU_Req_Rsp :: *; `endif -// ================================================================ -// CPU run-states -// TODO: Reset from GDB etc. - -typedef enum {CPU_RUNNING // Normal operation -`ifdef INCLUDE_GDB_CONTROL - , - CPU_ENTERING_DEBUG_MODE, // On GDB breakpoint, while waiting for fence completion - CPU_DEBUG_MODE // Halted for debugger -`endif - } CPU_State -deriving (Eq, Bits, FShow); - -function Bool fn_is_running (CPU_State cpu_state); - return (cpu_state == CPU_RUNNING); -endfunction - // ================================================================ (* synthesize *) @@ -120,27 +103,12 @@ module mkProc (Proc_IFC); // Verbosity: 0=quiet; 1=instruction trace; 2=more detail Reg #(Bit #(4)) cfg_verbosity <- mkConfigReg (0); - // ---------------- - // CPU run/debug states - - Reg #(CPU_State) rg_state <- mkReg (CPU_RUNNING); - // ---------------- // Reset requests and responses (TODO: to be implemented) FIFOF #(Bit #(0)) f_reset_reqs <- mkFIFOF; FIFOF #(Bit #(0)) f_reset_rsps <- mkFIFOF; -`ifdef INCLUDE_GDB_CONTROL - // ---------------- - // Communication to/from External debug module (TODO: to be implemented) - - // Debugger run-control - FIFOF #(Bool) f_run_halt_reqs <- mkFIFOF; - FIFOF #(Bool) f_run_halt_rsps <- mkFIFOF; - -`endif - // ---------------- // Tandem Verification (TODO: to be implemented) @@ -182,7 +150,7 @@ module mkProc (Proc_IFC); end // Note: mkLLCDmaConnect is Toooba version, different from riscy-ooo version - let llc__mem_server <- mkLLCDmaConnect(llc.dma, tlbToMem); + let llc_mem_server <- mkLLCDmaConnect(llc.dma, tlbToMem); // ================================================================ // interface Back-side of LLC to AXI4 @@ -278,85 +246,6 @@ module mkProc (Proc_IFC); end endrule - // ================================================================ - // ================================================================ - // ================================================================ - // DEBUGGER ACCESS - -`ifdef INCLUDE_GDB_CONTROL - - // ---------------- - // Debug Module Run (resume) control - - // Run command when in debug mode - rule rl_debug_run ((f_run_halt_reqs.first == True) - // && (! f_csr_reqs.notEmpty) - && (rg_state == CPU_DEBUG_MODE)); - // if (cfg_verbosity > 1) - $display ("%0d: %m.rl_debug_run", cur_cycle); - - f_run_halt_reqs.deq; - core[0].debug_resume; - rg_state <= CPU_RUNNING; - - // Notify debugger that we've started running - f_run_halt_rsps.enq (True); - endrule - - // Run command when already running - rule rl_debug_run_redundant ((f_run_halt_reqs.first == True) - // && (! f_csr_reqs.notEmpty) - && fn_is_running (rg_state)); - // if (cfg_verbosity > 1) - $display ("%0d: %m.rl_debug_run_redundant", cur_cycle); - - f_run_halt_reqs.deq; - - // Notify debugger that we're running - f_run_halt_rsps.enq (True); - endrule - - // ---------------- - // Debug Module Halt control - - rule rl_debug_halt ((f_run_halt_reqs.first == False) && fn_is_running (rg_state)); - // if (cfg_verbosity > 1) - $display ("%0d: %m.rl_debug_halt", cur_cycle); - - f_run_halt_reqs.deq; - - // Debugger 'halt' request (e.g., GDB '^C' command) - // This is just like an interrupt. - core[0].debug_halt; - endrule - - // Monitors when we've reached halted state while running (halt, - // step or EBREAK) and notifies DM - rule rl_debug_halted (fn_is_running (rg_state) && core [0].is_debug_halted); - // Notify debugger that we've halted - f_run_halt_rsps.enq (False); - // Stop executing rules until ready to restart from debugger - rg_state <= CPU_DEBUG_MODE; - - // if (cfg_verbosity > 1) - $display ("%0d: %m.rl_debug_halted", cur_cycle); - endrule - - rule rl_debug_halt_redundant ((f_run_halt_reqs.first == False) && (! fn_is_running (rg_state))); - // if (cfg_verbosity > 1) - $display ("%0d: %m.rl_debug_halt_redundant", cur_cycle); - - f_run_halt_reqs.deq; - - // Notify debugger that we've 'halted' - f_run_halt_rsps.enq (False); - - $display ("%0d: %m.rl_debug_halt_redundant: CPU already halted; state = ", - cur_cycle, fshow (rg_state)); - endrule - -`endif - // ================================================================ // ================================================================ // ================================================================ @@ -430,27 +319,23 @@ module mkProc (Proc_IFC); // Optional interface to Debug Module `ifdef INCLUDE_GDB_CONTROL - // run-control, other - interface Server hart0_server_run_halt = toGPServer (f_run_halt_reqs, f_run_halt_rsps); + // run/halt, gpr, mem and csr control goes to core + interface Server hart0_run_halt_server = core [0].hart0_run_halt_server; + interface Server hart0_gpr_mem_server = core[0].hart0_gpr_mem_server; +`ifdef ISA_F + interface Server hart0_fpr_mem_server = core[0].hart0_fpr_mem_server; +`endif + interface Server hart0_csr_mem_server = core[0].hart0_csr_mem_server; + // mem access goes to LLC (stays coherent with CPU pipeline). + interface debug_module_mem_server = llc_mem_server; + + // We don't implement 'other' functionality interface Put hart0_put_other_req; method Action put (Bit #(4) req); cfg_verbosity <= req; endmethod endinterface - - // GPR access - interface Server hart0_gpr_mem_server = core[0].hart0_gpr_mem_server; - -`ifdef ISA_F - // FPR access - interface Server hart0_fpr_mem_server = core[0].hart0_fpr_mem_server; -`endif - - // CSR access - interface Server hart0_csr_mem_server = core[0].hart0_csr_mem_server; - - interface debug_module_mem_server = llc__mem_server; `endif endmodule: mkProc diff --git a/src_Core/CPU/Proc_IFC.bsv b/src_Core/CPU/Proc_IFC.bsv index 13e93a5..202394e 100644 --- a/src_Core/CPU/Proc_IFC.bsv +++ b/src_Core/CPU/Proc_IFC.bsv @@ -85,22 +85,16 @@ interface Proc_IFC; // Optional interface to Debug Module `ifdef INCLUDE_GDB_CONTROL - // run-control, other - interface Server #(Bool, Bool) hart0_server_run_halt; - interface Put #(Bit #(4)) hart0_put_other_req; - - // GPR access + interface Server #(Bool, Bool) hart0_run_halt_server; interface Server #(DM_CPU_Req #(5, XLEN), DM_CPU_Rsp #(XLEN)) hart0_gpr_mem_server; - `ifdef ISA_F - // FPR access interface Server #(DM_CPU_Req #(5, FLEN), DM_CPU_Rsp #(FLEN)) hart0_fpr_mem_server; `endif - - // CSR access interface Server #(DM_CPU_Req #(12, XLEN), DM_CPU_Rsp #(XLEN)) hart0_csr_mem_server; + interface AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) debug_module_mem_server; - interface AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) debug_module_mem_server; + // Non-standard + interface Put #(Bit #(4)) hart0_put_other_req; `endif endinterface diff --git a/src_Core/Core/CoreW.bsv b/src_Core/Core/CoreW.bsv index 9cb5a71..4bb29f2 100644 --- a/src_Core/Core/CoreW.bsv +++ b/src_Core/Core/CoreW.bsv @@ -206,7 +206,7 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources)); `ifdef INCLUDE_GDB_CONTROL `ifndef EXTERNAL_DEBUG_MODULE // DM to CPU connections for run-control and other misc requests - mkConnection (debug_module.hart0_client_run_halt, proc.hart0_server_run_halt); + mkConnection (debug_module.hart0_client_run_halt, proc.hart0_run_halt_server); mkConnection (debug_module.hart0_get_other_req, proc.hart0_put_other_req); `endif `endif @@ -230,8 +230,8 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources)); rg_fromhost_addr); endrule - rule rl_hart0_server_run_halt; - let tmp <- proc.hart0_server_run_halt.response.get; + rule rl_hart0_run_halt_server; + let tmp <- proc.hart0_run_halt_server.response.get; endrule Reg#(Bool) hart0_halt <- mkReg(False); @@ -409,10 +409,6 @@ module mkCoreW (CoreW_IFC #(N_External_Interrupt_Sources)); // Slaves on the local 2x3 fabric // default slave is taken out directly to the Core interface mkConnection (fabric_2x3.v_to_slaves [plic_slave_num], plic.axi4_slave); - - // TODO: This slave can be connected to mkLLCDmaConnect for Debug Module System Bus Access - // AXI4_Slave_IFC #(Wd_Id, Wd_Addr, Wd_Data, Wd_User) dummy_slave = dummy_AXI4_Slave_ifc; - // mkConnection (fabric_2x3.v_to_slaves [near_mem_io_slave_num], dummy_slave); mkConnection (fabric_2x3.v_to_slaves [near_mem_io_slave_num], proc.debug_module_mem_server); // ================================================================ diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv index dbf78e73..dbc89ce 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/RenameStage.bsv @@ -90,7 +90,7 @@ interface RenameStage; interface Get#(RenameStuck) renameCorrectPathStuck; `ifdef INCLUDE_GDB_CONTROL - method Action debug_halt; + method Action debug_halt_req; method Action debug_resume; `endif endinterface @@ -1105,9 +1105,9 @@ module mkRenameStage#(RenameInput inIfc)(RenameStage); endmethod `ifdef INCLUDE_GDB_CONTROL - method Action debug_halt () if (rg_m_halt_req == tagged Invalid); + method Action debug_halt_req () if (rg_m_halt_req == tagged Invalid); rg_m_halt_req <= tagged Valid DebugHalt; - $display ("%0d: %m.renameStage.renameStage.debug_halt", cur_cycle); + $display ("%0d: %m.renameStage.renameStage.debug_halt_req", cur_cycle); endmethod method Action debug_resume () if (rg_m_halt_req != tagged Invalid);