diff --git a/test/test_cpu.py b/test/test_cpu.py deleted file mode 100644 index 7a151d9bf..000000000 --- a/test/test_cpu.py +++ /dev/null @@ -1,72 +0,0 @@ -# -# This file is part of LiteX. -# -# Copyright (c) 2021 Navaneeth Bhardwaj -# SPDX-License-Identifier: BSD-2-Clause - -import unittest -import pexpect -import sys -import os - -class TestCPU(unittest.TestCase): - def boot_test(self, cpu_type, jobs, cpu_variant="standard"): - cmd = f'litex_sim --cpu-type={cpu_type} --cpu-variant={cpu_variant} --opt-level=O0 --jobs {jobs}' - litex_prompt = [b'\033\[[0-9;]+mlitex\033\[[0-9;]+m>'] - is_success = True - with open("/tmp/test_boot_log", "wb") as result_file: - p = pexpect.spawn(cmd, timeout=None, logfile=result_file) - try: - match_id = p.expect(litex_prompt, timeout=1200) - except pexpect.EOF: - print('\n*** Premature termination') - is_success = False - except pexpect.TIMEOUT: - print('\n*** Timeout ') - is_success = False - - if not is_success: - print(f'*** {cpu_type} Boot Failure') - with open("/tmp/test_boot_log", "r") as result_file: - print(result_file.read()) - else: - p.terminate(force=True) - print(f'*** {cpu_type} Boot Success') - - return is_success - - def test_cpu(self): - tested_cpus = [ - #"cv32e40p", # (riscv / softcore) - "femtorv", # (riscv / softcore) - "firev", # (riscv / softcore) - "marocchino", # (or1k / softcore) - "naxriscv", # (riscv / softcore) - "serv", # (riscv / softcore) - "vexriscv", # (riscv / softcore) - "vexriscv_smp", # (riscv / softcore) - #"microwatt", # (ppc64 / softcore) - "neorv32", # (riscv / softcore) - ] - untested_cpus = [ - "blackparrot", # (riscv / softcore) -> Broken install? - "cortex_m1", # (arm / softcore) -> Proprietary code. - "cortex_m3", # (arm / softcore) -> Proprieraty code. - "cv32e41p", # (riscv / softcore) -> Broken? - "cva5", # (riscv / softcore) -> Needs to be tested. - "cva6", # (riscv / softcore) -> Needs to be tested. - "eos_s3", # (arm / hardcore) -> Hardcore. - "gowin_emcu", # (arm / hardcore) -> Hardcore. - "ibex", # (riscv / softcore) -> Broken since 2022.11.12. - "lm32", # (lm32 / softcore) -> Requires LM32 toolchain. - "minerva", # (riscv / softcore) -> Broken install? (Amaranth?) - "mor1kx", # (or1k / softcore) -> Verilator compilation issue. - "picorv32", # (riscv / softcore) -> Verilator compilation issue. - "rocket", # (riscv / softcore) -> Not enough RAM in CI. - "zynq7000", # (arm / hardcore) -> Hardcore. - "zynqmp", # (aarch64 / hardcore) -> Hardcore. - ] - jobs = os.cpu_count() - for cpu in tested_cpus: - with self.subTest(target=cpu): - self.assertTrue(self.boot_test(cpu, jobs)) diff --git a/test/test_integration.py b/test/test_integration.py new file mode 100644 index 000000000..7a6ce2239 --- /dev/null +++ b/test/test_integration.py @@ -0,0 +1,128 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2021 Navaneeth Bhardwaj +# SPDX-License-Identifier: BSD-2-Clause + +import unittest +import pexpect +import os +import sys +import tempfile +import itertools + +class TestIntegration(unittest.TestCase): + def boot_test(self, cpu_type="vexriscv", cpu_variant="standard", args=""): + cmd = f'litex_sim --cpu-type={cpu_type} --cpu-variant={cpu_variant} {args} --opt-level=O0 --jobs {os.cpu_count()}' + litex_prompt = [r'\033\[[0-9;]+mlitex\033\[[0-9;]+m>'] + is_success = True + + with tempfile.TemporaryFile(mode='w', prefix="litex_test") as log_file: + log_file.writelines(f"Command: {cmd}") + log_file.flush() + + p = pexpect.spawn(cmd, timeout=None, encoding=sys.getdefaultencoding(), logfile=log_file) + try: + match_id = p.expect(litex_prompt, timeout=1200) + except pexpect.EOF: + print('\n*** Premature termination') + is_success = False + except pexpect.TIMEOUT: + print('\n*** Timeout ') + is_success = False + + if not is_success: + print(f'*** ({self.id()}) Boot Failure: {cmd}') + log_file.seek(0) + print(log_file.read()) + else: + p.terminate(force=True) + print(f'*** ({self.id()}) Boot Success: {cmd}') + + return is_success + + def test_cpu(self): + tested_cpus = [ + #"cv32e40p", # (riscv / softcore) + "femtorv", # (riscv / softcore) + "firev", # (riscv / softcore) + "marocchino", # (or1k / softcore) + "naxriscv", # (riscv / softcore) + "serv", # (riscv / softcore) + "vexriscv", # (riscv / softcore) + "vexriscv_smp", # (riscv / softcore) + #"microwatt", # (ppc64 / softcore) + "neorv32", # (riscv / softcore) + ] + untested_cpus = [ + "blackparrot", # (riscv / softcore) -> Broken install? + "cortex_m1", # (arm / softcore) -> Proprietary code. + "cortex_m3", # (arm / softcore) -> Proprieraty code. + "cv32e41p", # (riscv / softcore) -> Broken? + "cva5", # (riscv / softcore) -> Needs to be tested. + "cva6", # (riscv / softcore) -> Needs to be tested. + "eos_s3", # (arm / hardcore) -> Hardcore. + "gowin_emcu", # (arm / hardcore) -> Hardcore. + "ibex", # (riscv / softcore) -> Broken since 2022.11.12. + "lm32", # (lm32 / softcore) -> Requires LM32 toolchain. + "minerva", # (riscv / softcore) -> Broken install? (Amaranth?) + "mor1kx", # (or1k / softcore) -> Verilator compilation issue. + "picorv32", # (riscv / softcore) -> Verilator compilation issue. + "rocket", # (riscv / softcore) -> Not enough RAM in CI. + "zynq7000", # (arm / hardcore) -> Hardcore. + "zynqmp", # (aarch64 / hardcore) -> Hardcore. + ] + + for cpu in tested_cpus: + with self.subTest(target=cpu): + self.assertTrue(self.boot_test(cpu)) + + def test_buses(self): + options = [("--bus-standard", ["wishbone", "axi-lite", "axi"]), + ("--bus-data-width", [32, 64]), + ("--bus-address-width", [32, 64]), + ("--bus-interconnect", ["shared", "crossbar"])] + + # TODO: Investigate those failures + blacklists = [ + # AXI-Lite with 64-bit data width and crossbar + [ + ("--bus-standard", ["axi-lite"]), + ("--bus-data-width", [64]), + ("--bus-interconnect", ["crossbar"]) + ], + # AXI with 64-bit data width + [ + ("--bus-standard", ["axi"]), + ("--bus-data-width", [64]) + ] + ] + + def is_blacklisted(config): + for blacklist in blacklists: + matches = True + for opt, values in blacklist: + cfg_value = next(v for k,v in config if k == opt) + if cfg_value not in values: + matches = False + break + if matches: + return True + return False + + # Generate all combinations + keys = [k for k,_ in options] + values = [v for _,v in options] + + for combination in itertools.product(*values): + config = list(zip(keys, combination)) + + # Skip blacklisted combinations + if is_blacklisted(config): + continue + + # Build args string + args = " ".join(f"{k}={v}" for k,v in config) + + with self.subTest(args=args): + self.assertTrue(self.boot_test(args=args))