added stepping functionality to the debugger
This commit is contained in:
parent
521cb73ad6
commit
39d5212d3d
@ -25,6 +25,7 @@ class CPU:
|
||||
self.exit = False
|
||||
self.exit_code = 0
|
||||
self.conf = conf
|
||||
self.active_debug = False # if a debugging session is currently runnign
|
||||
|
||||
# setup MMU, registers and syscall handlers
|
||||
self.mmu = MMU(conf)
|
||||
@ -66,7 +67,30 @@ class CPU:
|
||||
|
||||
self.__run()
|
||||
|
||||
def __run(self):
|
||||
def continue_from_debugger(self, verbose=True):
|
||||
"""
|
||||
dalled from the debugger to continue running
|
||||
"""
|
||||
self.__run(verbose)
|
||||
|
||||
def step(self):
|
||||
if self.exit:
|
||||
print(FMT_CPU + "Program exited with code {}".format(self.exit_code) + FMT_NONE)
|
||||
else:
|
||||
try:
|
||||
self.cycle += 1
|
||||
ins = self.mmu.read_ins(self.pc)
|
||||
print("Running instruction {} from 0x{:08X}".format(ins, self.pc))
|
||||
self.pc += 1
|
||||
self.__run_instruction(ins)
|
||||
except LaunchDebuggerException:
|
||||
print(FMT_CPU + "[CPU] Returning to debugger!" + FMT_NONE)
|
||||
except RiscemuBaseException as ex:
|
||||
self.pc -= 1
|
||||
print(ex.message())
|
||||
|
||||
|
||||
def __run(self, verbose=False):
|
||||
if self.pc <= 0:
|
||||
return False
|
||||
ins = None
|
||||
@ -74,14 +98,22 @@ class CPU:
|
||||
while not self.exit:
|
||||
self.cycle += 1
|
||||
ins = self.mmu.read_ins(self.pc)
|
||||
if verbose:
|
||||
print(FMT_CPU + " Running 0x{:08X}:{} {}".format(self.pc, FMT_NONE, ins))
|
||||
self.pc += 1
|
||||
self.__run_instruction(ins)
|
||||
except RiscemuBaseException as ex:
|
||||
print(FMT_ERROR + "[CPU] excpetion caught at 0x{:08X}: {}:".format(self.pc-1, ins) + FMT_NONE)
|
||||
print(" " + ex.message())
|
||||
if not isinstance(ex, LaunchDebuggerException):
|
||||
print(FMT_ERROR + "[CPU] excpetion caught at 0x{:08X}: {}:".format(self.pc-1, ins) + FMT_NONE)
|
||||
print(ex.message())
|
||||
self.pc -= 1
|
||||
|
||||
if self.active_debug:
|
||||
print(FMT_CPU + "[CPU] Returning to debugger!" + FMT_NONE)
|
||||
return
|
||||
if self.conf.debug_on_exception:
|
||||
launch_debug_session(self, self.mmu, self.regs,
|
||||
"Exception encountered, launching debug:".format(self.pc-1))
|
||||
"Exception encountered, launching debug:")
|
||||
|
||||
print()
|
||||
print(FMT_CPU + "Program exited with code {}".format(self.exit_code) + FMT_NONE)
|
||||
|
@ -134,3 +134,9 @@ class NumberFormatException(RiscemuBaseException):
|
||||
self.__class__.__name__,
|
||||
self.msg
|
||||
)
|
||||
|
||||
|
||||
# this exception is not printed and simply signals that an interactive debugging session is
|
||||
class LaunchDebuggerException(RiscemuBaseException):
|
||||
def message(self):
|
||||
return ""
|
||||
|
@ -1,31 +1,46 @@
|
||||
import typing
|
||||
from .Registers import Registers
|
||||
if typing.TYPE_CHECKING:
|
||||
from . import *
|
||||
|
||||
|
||||
def launch_debug_session(cpu: 'CPU', mmu: 'MMU', reg: 'Registers', prompt=""):
|
||||
if not cpu.conf.debug_instruction:
|
||||
if not cpu.conf.debug_instruction or cpu.active_debug:
|
||||
return
|
||||
import code
|
||||
import readline
|
||||
import rlcompleter
|
||||
|
||||
# setup some aliases
|
||||
cpu.active_debug = True
|
||||
|
||||
# setup some aliases:
|
||||
registers = reg
|
||||
regs = reg
|
||||
memory = mmu
|
||||
mem = mmu
|
||||
syscall_interface = cpu.syscall_int
|
||||
|
||||
# setup helper functions:
|
||||
def dump(what, *args, **kwargs):
|
||||
if isinstance(what, Registers):
|
||||
regs.dump(*args, **kwargs)
|
||||
else:
|
||||
mmu.dump(what, *args, **kwargs)
|
||||
|
||||
def ins():
|
||||
print("Current instruction at 0x{:08X}:".format(cpu.pc))
|
||||
return mmu.read_ins(cpu.pc)
|
||||
|
||||
def cont(verbose=True):
|
||||
cpu.continue_from_debugger(verbose)
|
||||
|
||||
def step():
|
||||
cpu.step()
|
||||
|
||||
sess_vars = globals()
|
||||
sess_vars.update(locals())
|
||||
|
||||
readline.set_completer(rlcompleter.Completer(sess_vars).complete)
|
||||
readline.parse_and_bind("tab: complete")
|
||||
code.InteractiveConsole(sess_vars).interact(banner=prompt, exitmsg="Resuming simulation")
|
||||
code.InteractiveConsole(sess_vars).interact(banner=prompt, exitmsg="Exiting debugger")
|
||||
cpu.active_debug = False
|
||||
|
@ -271,7 +271,10 @@ class RV32I(InstructionSet):
|
||||
|
||||
def instruction_sbreak(self, ins: 'LoadedInstruction'):
|
||||
ASSERT_LEN(ins.args, 0)
|
||||
launch_debug_session(self.cpu, self.mmu, self.regs, "Debug instruction encountered at 0x{:08X}".format(self.pc))
|
||||
if self.cpu.active_debug:
|
||||
print("Debug instruction encountered at 0x{:08X}".format(self.pc-1))
|
||||
raise LaunchDebuggerException()
|
||||
launch_debug_session(self.cpu, self.mmu, self.regs, "Debug instruction encountered at 0x{:08X}".format(self.pc-1))
|
||||
|
||||
def instruction_nop(self, ins: 'LoadedInstruction'):
|
||||
ASSERT_LEN(ins.args, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user