X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=debug%2Ftargets.py;h=296b0a95f72929c621b334da11954a8b45dab7ca;hb=6ff97655e7c6922a0e855c030b9f28a2eeba1fe0;hp=3cf972827a148ce62cafa53fdd0a995c8235f437;hpb=6a64f119fbda35f415d0c8238909aba70acc1654;p=riscv-tests.git diff --git a/debug/targets.py b/debug/targets.py index 3cf9728..296b0a9 100644 --- a/debug/targets.py +++ b/debug/targets.py @@ -1,32 +1,78 @@ +import importlib import os.path +import sys import tempfile import testlib class Target(object): - name = "name" + # pylint: disable=too-many-instance-attributes + + # Name of the target. Defaults to the name of the class. + name = None + + # XLEN of the target. May be overridden with --32 or --64 command line + # options. xlen = 0 - directory = None + + # GDB remotetimeout setting. timeout_sec = 2 + + # Path to OpenOCD configuration file relative to the .py file where the + # target is defined. Defaults to .cfg. + openocd_config_path = None + + # Path to linker script relative to the .py file where the target is + # defined. Defaults to .lds. + link_script_path = None + + # Will be autodetected (by running ExamineTarget) if left unset. Set to + # save a little time. + misa = None + + # List of commands that should be executed in gdb after connecting but + # before starting the test. + gdb_setup = [] + + # Implements dmode in tdata1 as described in the spec. Targets that need + # this value set to False are not compliant with the spec (but still usable + # as long as running code doesn't try to mess with triggers set by an + # external debugger). + honors_tdata1_hmode = True + + # Internal variables: + directory = None temporary_files = [] temporary_binary = None - openocd_config = [] - def __init__(self, cmd, run, isolate): - self.cmd = cmd - self.run = run - self.isolate = isolate - - def target(self): - """Start the target, eg. a simulator.""" + def __init__(self, path, parsed): + # Path to module. + self.path = path + self.directory = os.path.dirname(path) + self.server_cmd = parsed.server_cmd + self.sim_cmd = parsed.sim_cmd + self.isolate = parsed.isolate + if not self.name: + self.name = type(self).__name__ + # Default OpenOCD config file to .cfg + if not self.openocd_config_path: + self.openocd_config_path = "%s.cfg" % self.name + self.openocd_config_path = os.path.join(self.directory, + self.openocd_config_path) + # Default link script to .lds + if not self.link_script_path: + self.link_script_path = "%s.lds" % self.name + self.link_script_path = os.path.join(self.directory, + self.link_script_path) + + def create(self): + """Create the target out of thin air, eg. start a simulator.""" pass def server(self): """Start the debug server that gdb connects to, eg. OpenOCD.""" - if self.openocd_config: - return testlib.Openocd(cmd=self.cmd, config=self.openocd_config) - else: - raise NotImplementedError + return testlib.Openocd(server_cmd=self.server_cmd, + config=self.openocd_config_path) def compile(self, *sources): binary_name = "%s_%s-%d" % ( @@ -38,96 +84,37 @@ class Target(object): prefix=binary_name + "_") binary_name = self.temporary_binary.name Target.temporary_files.append(self.temporary_binary) + march = "rv%dima" % self.xlen + for letter in "fdc": + if self.extensionSupported(letter): + march += letter testlib.compile(sources + ("programs/entry.S", "programs/init.c", "-I", "../env", - "-T", "targets/%s/link.lds" % (self.directory or self.name), + "-march=%s" % march, + "-T", self.link_script_path, "-nostartfiles", "-mcmodel=medany", + "-DXLEN=%d" % self.xlen, "-o", binary_name), xlen=self.xlen) return binary_name -class SpikeTarget(Target): - # pylint: disable=abstract-method - directory = "spike" - ram = 0x80010000 - ram_size = 5 * 1024 * 1024 - instruction_hardware_breakpoint_count = 4 - reset_vector = 0x1000 - -class Spike64Target(SpikeTarget): - name = "spike64" - xlen = 64 - - def server(self): - return testlib.Spike(self.cmd, halted=True) - -class Spike32Target(SpikeTarget): - name = "spike32" - xlen = 32 - - def server(self): - return testlib.Spike(self.cmd, halted=True, xlen=32) - -class FreedomE300Target(Target): - name = "freedom-e300" - xlen = 32 - ram = 0x80000000 - ram_size = 16 * 1024 - instruction_hardware_breakpoint_count = 2 - openocd_config = "targets/%s/openocd.cfg" % name - -class FreedomE300SimTarget(Target): - name = "freedom-e300-sim" - xlen = 32 - timeout_sec = 240 - ram = 0x80000000 - ram_size = 256 * 1024 * 1024 - instruction_hardware_breakpoint_count = 2 - openocd_config = "targets/%s/openocd.cfg" % name - - def target(self): - return testlib.VcsSim(simv=self.run, debug=False) - -class FreedomU500Target(Target): - name = "freedom-u500" - xlen = 64 - ram = 0x80000000 - ram_size = 16 * 1024 - instruction_hardware_breakpoint_count = 2 - openocd_config = "targets/%s/openocd.cfg" % name - -class FreedomU500SimTarget(Target): - name = "freedom-u500-sim" - xlen = 64 - timeout_sec = 240 - ram = 0x80000000 - ram_size = 256 * 1024 * 1024 - instruction_hardware_breakpoint_count = 2 - openocd_config = "targets/%s/openocd.cfg" % name - - def target(self): - return testlib.VcsSim(simv=self.run, debug=False) - -targets = [ - Spike32Target, - Spike64Target, - FreedomE300Target, - FreedomU500Target, - FreedomE300SimTarget, - FreedomU500SimTarget] + def extensionSupported(self, letter): + # target.misa is set by testlib.ExamineTarget + if self.misa: + return self.misa & (1 << (ord(letter.upper()) - ord('A'))) + else: + return False def add_target_options(parser): - group = parser.add_mutually_exclusive_group(required=True) - for t in targets: - group.add_argument("--%s" % t.name, action="store_const", const=t, - dest="target") - parser.add_argument("--run", + parser.add_argument("target", help=".py file that contains definition for " + "the target to test with.") + parser.add_argument("--sim_cmd", help="The command to use to start the actual target (e.g. " - "simulation)") - parser.add_argument("--cmd", - help="The command to use to start the debug server.") + "simulation)", default="spike") + parser.add_argument("--server_cmd", + help="The command to use to start the debug server (e.g. OpenOCD)") xlen_group = parser.add_mutually_exclusive_group() xlen_group.add_argument("--32", action="store_const", const=32, dest="xlen", @@ -139,3 +126,20 @@ def add_target_options(parser): help="Try to run in such a way that multiple instances can run at " "the same time. This may make it harder to debug a failure if it " "does occur.") + +def target(parsed): + directory = os.path.dirname(parsed.target) + filename = os.path.basename(parsed.target) + module_name = os.path.splitext(filename)[0] + + sys.path.append(directory) + module = importlib.import_module(module_name) + found = [] + for name in dir(module): + definition = getattr(module, name) + if type(definition) == type and issubclass(definition, Target): + found.append(definition) + assert len(found) == 1, "%s does not define exactly one subclass of " \ + "targets.Target" % parsed.target + + return found[0](parsed.target, parsed)