overhaul of debugging info printing

float_support
Anton Lydike 3 years ago
parent d0c5abe845
commit d09b7a5cb1

@ -19,4 +19,5 @@ class RunConfig:
# allowed syscalls
scall_input: bool = True
scall_fs: bool = False
verbosity: int = 0

@ -6,8 +6,6 @@ import time
def _window_loop(textIO: 'TextIO'):
#textIO.set_sg_window(None)
#return
try:
import PySimpleGUI as sg
@ -30,10 +28,9 @@ def _window_loop(textIO: 'TextIO'):
col.contents_changed()
except ImportError:
print("[TextIO] module works best with PySimpleGui!")
print("[TextIO] window disabled - please install PySimpleGui!")
textIO.set_sg_window(None)
class TextIO(IOModule):
def __init__(self, addr: int, buflen: int = 128):
super(TextIO, self).__init__(addr, buflen + 4)

@ -6,7 +6,7 @@ SPDX-License-Identifier: MIT
from .Config import RunConfig
from .Executable import Executable, LoadedExecutable, LoadedMemorySection, LoadedInstruction, MemoryFlags
from .helpers import align_addr
from .helpers import align_addr, int_from_bytes
from .Exceptions import OutOfMemoryException, InvalidAllocationException
from .colors import *
from typing import Dict, List, Tuple, Optional
@ -109,7 +109,8 @@ class MMU:
raise InvalidAllocationException('Invalid size request', name, req_size, flag)
if req_size > self.max_alloc_size:
raise InvalidAllocationException('Cannot allocate more than {} bytes at a time'.format(self.max_alloc_size), name, req_size, flag)
raise InvalidAllocationException('Cannot allocate more than {} bytes at a time'.format(self.max_alloc_size),
name, req_size, flag)
base = align_addr(self.first_free_addr)
size = align_addr(req_size)
@ -203,6 +204,9 @@ class MMU:
if symb in b.symbols:
print(" Found local symbol {}: 0x{:X} in {}".format(symb, b.symbols[symb], b.name))
def read_int(self, addr: int) -> int:
return int_from_bytes(self.read(addr, 4))
def __repr__(self):
return "MMU(\n\t{}\n)".format(
"\n\t".join(repr(x) for x in self.sections)

@ -8,6 +8,7 @@ import typing
from .Registers import Registers
from .colors import FMT_DEBUG, FMT_NONE
from .Executable import LoadedInstruction
from .helpers import *
if typing.TYPE_CHECKING:
from . import *
@ -36,6 +37,9 @@ def launch_debug_session(cpu: 'CPU', mmu: 'MMU', reg: 'Registers', prompt=""):
else:
mmu.dump(what, *args, **kwargs)
def dump_stack(*args, **kwargs):
mmu.dump(regs.get('sp'), *args, **kwargs)
def ins():
print("Current instruction at 0x{:08X}:".format(cpu.pc))
return mmu.read_ins(cpu.pc)

@ -9,7 +9,7 @@ from .ElfLoader import ElfInstruction, ElfLoadedMemorySection, InstructionAccess
from ..decoder import decode
from ..IO.IOModule import IOModule
from .privmodes import PrivModes
from ..colors import FMT_ERROR, FMT_NONE
from ..colors import FMT_ERROR, FMT_NONE, FMT_MEM
import json
from functools import lru_cache
@ -117,3 +117,10 @@ class MemoryImageMMU(PrivMMU):
if addr >= val:
return "{}{:+x} ({}:{})".format(sym, addr - val, sec.owner, sec.name)
return "{}:{}{:+x}".format(sec.owner, sec.name, addr - sec.base)
def symbol(self, symb: str):
print(FMT_MEM + "Looking up symbol {}".format(symb))
for owner, symbs in self.debug_info['symbols'].items():
if symb in symbs:
print(" Hit in {}: {} = {}".format(owner, symb, symbs[symb]))
print(FMT_NONE, end="")

@ -83,11 +83,7 @@ class PrivCPU(CPU):
if isinstance(ex, LaunchDebuggerException):
self.launch_debug = True
self.pc += self.INS_XLEN
else:
print(FMT_ERROR + "[CPU] exception caught at 0x{:08X}: {}:".format(self.pc - 1, ins) + FMT_NONE)
print(ex.message())
if self.conf.debug_on_exception:
self.launch_debug = True
if self.exit:
print()
print(FMT_CPU + "Program exited with code {}".format(self.exit_code) + FMT_NONE)
@ -114,7 +110,7 @@ class PrivCPU(CPU):
def run(self, verbose: bool = False):
print(FMT_CPU + '[CPU] Started running from 0x{:08X} ({})'.format(self.pc, "kernel") + FMT_NONE)
self._time_start = time.perf_counter_ns() // self.TIME_RESOLUTION_NS
self._run(verbose)
self._run(self.conf.verbosity > 1)
def _init_csr(self):
# set up CSR
@ -162,8 +158,6 @@ class PrivCPU(CPU):
def _handle_trap(self, trap: CpuTrap):
# implement trap handling!
self.pending_traps.append(trap)
print(FMT_CPU + "Trap {} encountered at {} (0x{:x})".format(trap, self.mmu.translate_address(self.pc), self.pc) + FMT_NONE)
def step(self, verbose=True):
try:
@ -178,6 +172,15 @@ class PrivCPU(CPU):
self.pc += self.INS_XLEN
except CpuTrap as trap:
self._handle_trap(trap)
if trap.interrupt == 0 and not isinstance(trap, EcallTrap):
print(FMT_CPU + "[CPU] Trap {} encountered at {} (0x{:x})".format(
trap,
self.mmu.translate_address(self.pc),
self.pc
) + FMT_NONE)
if self.conf.debug_on_exception:
raise LaunchDebuggerException()
self.pc += self.INS_XLEN
def _timer_step(self):
if not self._time_interrupt_enabled:
@ -193,7 +196,7 @@ class PrivCPU(CPU):
# TODO: actually select based on the official ranking
trap = self.pending_traps.pop() # use the most recent trap
if not isinstance(trap, TimerInterrupt) or True:
print(FMT_CPU + "[CPU] [{}] taking trap {}!".format(self.cycle, trap) + FMT_NONE)
print(FMT_CPU + "[CPU] taking trap {}!".format(trap) + FMT_NONE)
if trap.priv != PrivModes.MACHINE:
print(FMT_CPU + "[CPU] Trap not targeting machine mode encountered! - undefined behaviour!" + FMT_NONE)
@ -206,7 +209,7 @@ class PrivCPU(CPU):
self.csr.set_mstatus('mpp', self.mode.value)
self.csr.set_mstatus('mie', 0)
self.csr.set('mcause', trap.mcause)
self.csr.set('mepc', self.pc)
self.csr.set('mepc', self.pc - self.INS_XLEN)
self.csr.set('mtval', trap.mtval)
self.mode = trap.priv
mtvec = self.csr.get('mtvec')
@ -244,4 +247,3 @@ class PrivCPU(CPU):
def record_perf_profile(self):
self._perf_counters.append((time.perf_counter_ns(), self.cycle))

@ -22,6 +22,7 @@ class PrivMMU(MMU):
def translate_address(self, addr: int):
return ""
class LoadedElfMMU(PrivMMU):
def __init__(self, elf: ElfExecutable):
super().__init__(conf=RunConfig())

@ -79,15 +79,16 @@ class PrivRV32I(RV32I):
mepc = self.cpu.csr.get('mepc')
self.cpu.pc = mepc - self.cpu.INS_XLEN
sec = self.mmu.get_sec_containing(mepc)
if sec is not None:
print(FMT_CPU + "[CPU] [{}] returning to mode {} in {} (0x{:x})".format(
self.cpu.cycle,
PrivModes(mpp).name,
self.mmu.translate_address(mepc),
mepc
) + FMT_NONE)
self.regs.dump_reg_a()
if self.cpu.conf.verbosity > 0:
sec = self.mmu.get_sec_containing(mepc)
if sec is not None:
print(FMT_CPU + "[CPU] returning to mode {} in {} (0x{:x})".format(
PrivModes(mpp).name,
self.mmu.translate_address(mepc),
mepc
) + FMT_NONE)
if self.cpu.conf.verbosity > 1:
self.regs.dump_reg_a()
def instruction_uret(self, ins: 'LoadedInstruction'):
raise IllegalInstructionTrap(ins)
@ -139,7 +140,7 @@ class PrivRV32I(RV32I):
ASSERT_LEN(ins.args, 2)
reg = ins.get_reg(0)
addr = ins.get_imm(1)
if reg == 'ra' and self.cpu.mode == PrivModes.USER:
if reg == 'ra' and self.cpu.mode == PrivModes.USER and self.cpu.conf.verbosity > 1:
print(FMT_CPU + 'Jumping to {} (0x{:x})'.format(
self.mmu.translate_address(self.pc + addr),
self.pc + addr

@ -3,9 +3,6 @@ from .ImageLoader import MemoryImageMMU
from .PrivMMU import LoadedElfMMU
from .ElfLoader import ElfExecutable
from ..Tokenizer import RiscVInput
from ..ExecutableParser import ExecutableParser
import sys
if __name__ == '__main__':
@ -15,8 +12,9 @@ if __name__ == '__main__':
parser.add_argument('--kernel', type=str, help='Kernel elf loaded with user programs', nargs='?')
parser.add_argument('--image', type=str, help='Memory image containing kernel', nargs='?')
parser.add_argument('--debug-exceptions', help='Launch the interactive debugger when an exception is generated', action='store_true')
parser.add_argument('-v', '--verbose', help="Verbose output", action='store_true')
parser.add_argument('-v', '--verbose', help="Verbosity level (can be used multiple times)", action='count', default=0)
args = parser.parse_args()
mmu = None
@ -30,8 +28,8 @@ if __name__ == '__main__':
print("You must specify one of --kernel or --image for running in privilege mode!")
sys.exit(1)
cpu = PrivCPU(RunConfig(), mmu)
cpu.run(args.verbose)
cpu = PrivCPU(RunConfig(verbosity=args.verbose, debug_on_exception=args.debug_exceptions), mmu)
cpu.run()

Loading…
Cancel
Save