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 {