import testlib
+class Hart(object):
+ # XLEN of the hart. May be overridden with --32 or --64 command line
+ # options.
+ xlen = 0
+
+ # Will be autodetected (by running ExamineTarget) if left unset. Set to
+ # save a little time.
+ misa = None
+
+ # Path to linker script relative to the .py file where the target is
+ # defined. Defaults to <name>.lds.
+ link_script_path = None
+
+ # Implements dmode in tdata1 as described in the spec. Harts 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
+
+ # Address where a r/w/x block of RAM starts, together with its size.
+ ram = None
+ ram_size = None
+
+ # Number of instruction triggers the hart supports.
+ instruction_hardware_breakpoint_count = 0
+
+ # Defaults to target-<index>
+ name = None
+
+ # When reset, the PC must be at one of the values listed here.
+ # This is a list because on some boards the reset vector depends on
+ # jumpers.
+ reset_vectors = []
+
+ 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
+
class Target(object):
# pylint: disable=too-many-instance-attributes
+ # List of Hart object instances, one for each hart in the target.
+ harts = []
+
# 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
-
# GDB remotetimeout setting.
timeout_sec = 2
+ # Timeout waiting for the server to start up. This is different than the
+ # GDB timeout, which is how long GDB waits for commands to execute.
+ # The server_timeout is how long this script waits for the server to be
+ # ready for GDB connections.
+ server_timeout_sec = 60
+
# Path to OpenOCD configuration file relative to the .py file where the
# target is defined. Defaults to <name>.cfg.
openocd_config_path = None
- # Path to linker script relative to the .py file where the target is
- # defined. Defaults to <name>.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 = []
+ # Supports mtime at 0x2004000
+ supports_clint_mtime = True
+
# Internal variables:
directory = None
temporary_files = []
- temporary_binary = None
def __init__(self, path, parsed):
# Path to module.
self.directory = os.path.dirname(path)
self.server_cmd = parsed.server_cmd
self.sim_cmd = parsed.sim_cmd
- self.isolate = parsed.isolate
+ self.temporary_binary = None
+ Target.isolate = parsed.isolate
if not self.name:
self.name = type(self).__name__
# Default OpenOCD config file to <name>.cfg
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 <name>.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)
+ for i, hart in enumerate(self.harts):
+ hart.index = i
+ if not hasattr(hart, 'id'):
+ hart.id = i
+ if not hart.name:
+ hart.name = "%s-%d" % (self.name, i)
+ # Default link script to <name>.lds
+ if not hart.link_script_path:
+ hart.link_script_path = "%s.lds" % self.name
+ hart.link_script_path = os.path.join(self.directory,
+ hart.link_script_path)
def create(self):
"""Create the target out of thin air, eg. start a simulator."""
def server(self):
"""Start the debug server that gdb connects to, eg. OpenOCD."""
return testlib.Openocd(server_cmd=self.server_cmd,
- config=self.openocd_config_path)
+ config=self.openocd_config_path,
+ timeout=self.server_timeout_sec)
- def compile(self, *sources):
+ def compile(self, hart, *sources):
binary_name = "%s_%s-%d" % (
self.name,
os.path.basename(os.path.splitext(sources[0])[0]),
- self.xlen)
- if self.isolate:
+ hart.xlen)
+ if Target.isolate:
self.temporary_binary = tempfile.NamedTemporaryFile(
prefix=binary_name + "_")
binary_name = self.temporary_binary.name
Target.temporary_files.append(self.temporary_binary)
- march = "rv%dima" % self.xlen
+ march = "rv%dima" % hart.xlen
for letter in "fdc":
- if self.extensionSupported(letter):
+ if hart.extensionSupported(letter):
march += letter
testlib.compile(sources +
("programs/entry.S", "programs/init.c",
+ "-DNHARTS=%d" % len(self.harts),
"-I", "../env",
"-march=%s" % march,
- "-T", self.link_script_path,
+ "-T", hart.link_script_path,
"-nostartfiles",
"-mcmodel=medany",
- "-DXLEN=%d" % self.xlen,
+ "-DXLEN=%d" % hart.xlen,
"-o", binary_name),
- xlen=self.xlen)
+ xlen=hart.xlen)
return binary_name
- 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):
parser.add_argument("target", help=".py file that contains definition for "
"the target to test with.")
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",
- help="Force the target to be 32-bit.")
- xlen_group.add_argument("--64", action="store_const", const=64, dest="xlen",
- help="Force the target to be 64-bit.")
+ xlen_group.add_argument("--32", action="store_const", const=32,
+ dest="xlen", default=0, help="Force the target to be 32-bit.")
+ xlen_group.add_argument("--64", action="store_const", const=64,
+ dest="xlen", default=0, help="Force the target to be 64-bit.")
parser.add_argument("--isolate", action="store_true",
help="Try to run in such a way that multiple instances can run at "
found = []
for name in dir(module):
definition = getattr(module, name)
- if type(definition) == type and issubclass(definition, Target):
+ if isinstance(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)
+ t = found[0](parsed.target, parsed)
+ assert t.harts, "%s doesn't have any harts defined!" % t.name
+ if parsed.xlen > 0:
+ for h in t.harts:
+ if h.xlen == 0:
+ h.xlen = parsed.xlen
+ elif h.xlen != parsed.xlen:
+ raise Exception("The target hart specified an XLEN of %d, but "\
+ "the command line specified an XLEN of %d. They must "\
+ "match." % (h.xlen, parsed.xlen))
+
+ return t