aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2021-05-20 11:52:21 -0700
committerGitHub <noreply@github.com>2021-05-20 11:52:21 -0700
commit09cfdaacd9322cf0ac94818d8c852e1f4dc5bc4f (patch)
treeb37e4ba16400da9d8ec616e98bb3b7fbdd5136b3
parent069ccc6b8677889f24c259a6b8b267f2233a7dfe (diff)
downloadriscv-tests-09cfdaacd9322cf0ac94818d8c852e1f4dc5bc4f.zip
riscv-tests-09cfdaacd9322cf0ac94818d8c852e1f4dc5bc4f.tar.gz
riscv-tests-09cfdaacd9322cf0ac94818d8c852e1f4dc5bc4f.tar.bz2
Test multiple heterogeneous spike instances. (#338)
-rwxr-xr-xdebug/gdbserver.py28
-rw-r--r--debug/targets.py25
-rw-r--r--debug/targets/RISC-V/spike-multi.py22
-rw-r--r--debug/targets/RISC-V/spike32.py4
-rw-r--r--debug/targets/RISC-V/spike64.py5
-rw-r--r--debug/testlib.py49
6 files changed, 70 insertions, 63 deletions
diff --git a/debug/gdbserver.py b/debug/gdbserver.py
index ea5bb22..d4b7078 100755
--- a/debug/gdbserver.py
+++ b/debug/gdbserver.py
@@ -87,6 +87,10 @@ class InfoTest(GdbTest):
continue
if re.search(r"Disabling abstract command writes to CSRs.", line):
continue
+ if re.search(
+ r"keep_alive.. was not invoked in the \d+ ms timelimit.",
+ line):
+ continue
k, v = line.strip().split()
info[k] = v
assertEqual(int(info.get("hart.xlen")), self.hart.xlen)
@@ -184,7 +188,7 @@ class CustomRegisterTest(SimpleRegisterTest):
return self.target.implements_custom_test
def check_custom(self, magic):
- regs = {k: v for k, v in self.gdb.info_registers("all").items()
+ regs = {k: v for k, v in self.gdb.info_registers("all", ops=20).items()
if k.startswith("custom")}
assertEqual(set(regs.keys()),
set(("custom1",
@@ -796,7 +800,8 @@ class MemorySampleTest(DebugTest):
self.gdb.p("i=123")
@staticmethod
- def check_incrementing_samples(raw_samples, check_addr, tolerance=0x100000):
+ def check_incrementing_samples(raw_samples, check_addr,
+ tolerance=0x200000):
first_timestamp = None
end = None
total_samples = 0
@@ -871,7 +876,7 @@ class MemorySampleMixed(MemorySampleTest):
raw_samples = self.collect_samples()
self.check_incrementing_samples(raw_samples, addr["j"],
- tolerance=0x200000)
+ tolerance=0x400000)
self.check_samples_equal(raw_samples, addr["i32"], 0xdeadbeef)
self.check_samples_equal(raw_samples, addr["i64"], 0x1122334455667788)
@@ -935,7 +940,7 @@ class Semihosting(GdbSingleHartTest):
self.gdb.b("main:begin")
self.gdb.c()
- self.gdb.p('filename="%s"' % temp.name)
+ self.gdb.p('filename="%s"' % temp.name, ops=2)
self.exit()
contents = open(temp.name, "r").readlines()
@@ -1431,6 +1436,8 @@ class WriteCsrs(RegsTest):
assertEqual(123, self.gdb.p("$csr832"))
class DownloadTest(GdbTest):
+ compile_args = ("programs/infinite_loop.S", )
+
def setup(self):
# pylint: disable=attribute-defined-outside-init
length = min(2**18, max(2**10, self.hart.ram_size - 2048))
@@ -1463,9 +1470,16 @@ class DownloadTest(GdbTest):
if self.crc < 0:
self.crc += 2**32
- self.binary = self.target.compile(self.hart, self.download_c.name,
- "programs/checksum.c")
- self.gdb.global_command("file %s" % self.binary)
+ compiled = {}
+ for hart in self.target.harts:
+ key = hart.system
+ if key not in compiled:
+ compiled[key] = self.target.compile(hart, self.download_c.name,
+ "programs/checksum.c")
+ self.gdb.select_hart(hart)
+ self.gdb.command("file %s" % compiled.get(key))
+
+ self.gdb.select_hart(self.hart)
def test(self):
self.gdb.load()
diff --git a/debug/targets.py b/debug/targets.py
index be45c62..dd0175e 100644
--- a/debug/targets.py
+++ b/debug/targets.py
@@ -44,12 +44,19 @@ class Hart:
# jumpers.
reset_vectors = []
- def __init__(self, system=None):
- """system is set to an identifier of the system this hart belongs to.
- Harts within the same system are assumed to share memory, and to have
- unique hartids within that system. So for most cases the default
- value of None is fine."""
- self.system = system
+ # system is set to an identifier of the system this hart belongs to. Harts
+ # within the same system are assumed to share memory, and to have unique
+ # hartids within that system. So for most cases the default value of None
+ # is fine.
+ system = None
+
+ def __init__(self, misa=None, system=None, link_script_path=None):
+ if misa:
+ self.misa = misa
+ if system:
+ self.system = system
+ if link_script_path:
+ self.link_script_path = link_script_path
def extensionSupported(self, letter):
# target.misa is set by testlib.ExamineTarget
@@ -162,10 +169,10 @@ class Target:
freertos=test.freertos())
def do_compile(self, hart, *sources):
- binary_name = "%s_%s-%d" % (
+ binary_name = "%s_%s-%x" % (
self.name,
os.path.basename(os.path.splitext(sources[0])[0]),
- hart.xlen)
+ hart.misa)
if Target.isolate:
self.temporary_binary = tempfile.NamedTemporaryFile(
prefix=binary_name + "_")
@@ -203,7 +210,7 @@ class Target:
return binary_name
def compile(self, hart, *sources):
- while True:
+ for _ in range(2):
try:
return self.do_compile(hart, *sources)
except testlib.CompileError as e:
diff --git a/debug/targets/RISC-V/spike-multi.py b/debug/targets/RISC-V/spike-multi.py
index 9e85a35..816677b 100644
--- a/debug/targets/RISC-V/spike-multi.py
+++ b/debug/targets/RISC-V/spike-multi.py
@@ -2,16 +2,14 @@ import targets
import testlib
import spike32 # pylint: disable=import-error
-#import spike64 # pylint: disable=import-error
+import spike64 # pylint: disable=import-error
class multispike(targets.Target):
harts = [
spike32.spike32_hart(misa=0x4034112d, system=0),
spike32.spike32_hart(misa=0x4034112d, system=0),
- spike32.spike32_hart(misa=0x4034112d, system=1),
- spike32.spike32_hart(misa=0x4034112d, system=1)]
- #spike64.spike64_hart(misa=0x8000000000341129),
- #spike64.spike64_hart(misa=0x8000000000341129)]
+ spike64.spike64_hart(misa=0x8000000000341129, system=1),
+ spike64.spike64_hart(misa=0x8000000000341129, system=1)]
openocd_config_path = "spike-multi.cfg"
# Increased timeout because we use abstract_rti to artificially slow things
# down.
@@ -25,15 +23,11 @@ class multispike(targets.Target):
# requires vlen==slen.
return testlib.MultiSpike(
[
-# testlib.Spike(self, isa="RV64IMAFDV", abstract_rti=30,
-# support_hasel=False, support_abstract_csr=False,
-# vlen=512, elen=64, slen=512, harts=self.harts[:2]),
- testlib.Spike(self, isa="RV32IMAFDCV", dmi_rti=4,
+ testlib.Spike(self, isa="RV64IMAFDV",
+ support_hasel=False, support_abstract_csr=False,
+ vlen=512, elen=64, slen=512, harts=self.harts[2:]),
+ testlib.Spike(self, isa="RV32IMAFDCV",
support_abstract_csr=True, support_haltgroups=False,
# elen must be at least 64 because D is supported.
- elen=64, harts=self.harts[2:]),
- testlib.Spike(self, isa="RV32IMAFDCV", dmi_rti=4,
- support_abstract_csr=True, support_haltgroups=False,
- # elen must be at least 64 because D is supported.
- elen=64, harts=self.harts[2:])
+ elen=64, harts=self.harts[:2]),
])
diff --git a/debug/targets/RISC-V/spike32.py b/debug/targets/RISC-V/spike32.py
index 6256574..17d28fb 100644
--- a/debug/targets/RISC-V/spike32.py
+++ b/debug/targets/RISC-V/spike32.py
@@ -10,10 +10,6 @@ class spike32_hart(targets.Hart):
reset_vectors = [0x1000]
link_script_path = "spike32.lds"
- def __init__(self, misa, system=0):
- super().__init__(system=system)
- self.misa = misa
-
class spike32(targets.Target):
harts = [spike32_hart(misa=0x4034112d)]
openocd_config_path = "spike-1.cfg"
diff --git a/debug/targets/RISC-V/spike64.py b/debug/targets/RISC-V/spike64.py
index 4313968..31088ff 100644
--- a/debug/targets/RISC-V/spike64.py
+++ b/debug/targets/RISC-V/spike64.py
@@ -9,10 +9,7 @@ class spike64_hart(targets.Hart):
instruction_hardware_breakpoint_count = 4
reset_vectors = [0x1000]
link_script_path = "spike64.lds"
-
- def __init__(self, misa=0x8000000000141125, system=0):
- super().__init__(system=system)
- self.misa = misa
+ misa = 0x8000000000141125
class spike64(targets.Target):
harts = [spike64_hart()]
diff --git a/debug/testlib.py b/debug/testlib.py
index cde6597..107c2dc 100644
--- a/debug/testlib.py
+++ b/debug/testlib.py
@@ -559,16 +559,14 @@ class Gdb:
11, 149, 107, 163, 73, 47, 43, 173, 7, 109, 101, 103, 191, 2, 139,
97, 193, 157, 3, 29, 79, 113, 5, 89, 19, 37, 71, 179, 59, 137, 53)
- def __init__(self, target, ports,
- cmd="riscv64-unknown-elf-gdb",
- timeout=60, binary=None):
+ def __init__(self, target, ports, cmd=None, timeout=60, binaries=None):
assert ports
self.target = target
self.ports = ports
- self.cmd = cmd
+ self.cmd = cmd or "riscv64-unknown-elf-gdb"
self.timeout = timeout
- self.binary = binary
+ self.binaries = binaries or [None] * len(ports)
self.reset_delay_index = 0
self.stack = []
@@ -582,14 +580,15 @@ class Gdb:
self.logfiles.append(logfile)
if print_log_names:
real_stdout.write("Temporary gdb log: %s\n" % logfile.name)
- child = pexpect.spawn(cmd)
+ child = pexpect.spawn(self.cmd)
child.logfile = logfile
- child.logfile.write(("+ %s\n" % cmd).encode())
+ child.logfile.write(("+ %s\n" % self.cmd).encode())
self.children.append(child)
self.active_child = self.children[0]
def connect(self):
- for port, child in zip(self.ports, self.children):
+ for port, child, binary in zip(self.ports, self.children,
+ self.binaries):
self.select_child(child)
self.wait()
self.command("set style enabled off", reset_delays=None)
@@ -602,8 +601,9 @@ class Gdb:
reset_delays=None)
self.command("target extended-remote localhost:%d" % port, ops=10,
reset_delays=None)
- if self.binary:
- self.command("file %s" % self.binary)
+ if binary:
+ output = self.command("file %s" % binary)
+ assertIn("Reading symbols", output)
threads = self.threads()
for t in threads:
hartid = None
@@ -778,8 +778,8 @@ class Gdb:
value = shlex.split(output.split('=')[-1].strip())[1]
return value
- def info_registers(self, group=""):
- output = self.command("info registers %s" % group, ops=5)
+ def info_registers(self, group="", ops=5):
+ output = self.command("info registers %s" % group, ops=ops)
result = {}
for line in output.splitlines():
m = re.match(r"(\w+)\s+({.*})(?:\s+(\(.*\)))?", line)
@@ -846,8 +846,6 @@ class Gdb:
if m:
threads.append(Thread(*m.groups()))
assert threads
- #>>>if not threads:
- #>>> threads.append(Thread('1', '1', 'Default', '???'))
return threads
def thread(self, thread):
@@ -1002,6 +1000,7 @@ def print_log(path):
print_log_handle(path, open(path, "r"))
class BaseTest:
+ # pylint: disable=too-many-instance-attributes
compiled = {}
def __init__(self, target, hart=None):
@@ -1015,6 +1014,7 @@ class BaseTest:
self.binary = None
self.start = 0
self.logs = []
+ self.binaries = []
def early_applicable(self):
"""Return a false value if the test has determined it cannot run
@@ -1033,11 +1033,14 @@ class BaseTest:
def compile(self):
compile_args = getattr(self, 'compile_args', None)
+ self.binaries = []
if compile_args:
- if compile_args not in BaseTest.compiled:
- BaseTest.compiled[compile_args] = \
- self.target.compile(self.hart, *compile_args)
- self.binary = BaseTest.compiled.get(compile_args)
+ for hart in self.target.harts:
+ key = (compile_args, hart.misa)
+ if key not in BaseTest.compiled:
+ BaseTest.compiled[key] = \
+ self.target.compile(hart, *compile_args)
+ self.binaries.append(BaseTest.compiled.get(key))
def classSetup(self):
self.compile()
@@ -1061,7 +1064,7 @@ class BaseTest:
def run(self):
"""
- If compile_args is set, compile a program and set self.binary.
+ If compile_args is set, compile a program and set self.binaries.
Call setup().
@@ -1132,12 +1135,8 @@ class GdbTest(BaseTest):
def classSetup(self):
BaseTest.classSetup(self)
- if gdb_cmd:
- self.gdb = Gdb(self.target, self.server.gdb_ports, gdb_cmd,
- timeout=self.target.timeout_sec, binary=self.binary)
- else:
- self.gdb = Gdb(self.target, self.server.gdb_ports,
- timeout=self.target.timeout_sec, binary=self.binary)
+ self.gdb = Gdb(self.target, self.server.gdb_ports, cmd=gdb_cmd,
+ timeout=self.target.timeout_sec, binaries=self.binaries)
self.logs += self.gdb.lognames()
self.gdb.connect()