diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 05b4fefb2..e6da1174c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,6 +128,32 @@ jobs: run: | make SIM_DIR=./runs/simple annotate -j + ############################################## + # Simulate SW on Snitch Cluster w/ GVSOC # + ############################################## + + sw-snitch-cluster-gvsoc: + name: Simulate SW on Snitch Cluster w/ GVSOC + runs-on: ubuntu-22.04 + needs: build-docker + if: > + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name != github.repository + container: + image: ghcr.io/pulp-platform/snitch_cluster:${{ github.ref_name }} + steps: + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + - name: Build Software + working-directory: target/snitch_cluster + run: | + make CFG_OVERRIDE=cfg/github-ci.hjson OPENOCD_SEMIHOSTING=ON sw + - name: Run Tests + working-directory: target/snitch_cluster + run: | + GVSOC_TARGET=pulp.snitch.snitch_cluster_single && ./util/run.py sw/run.yaml --simulator gvsoc -j + # ######################################### # # Build SW on Snitch Cluster w/ Banshee # # ######################################### diff --git a/target/common/common.mk b/target/common/common.mk index 77d0e79d3..48995aa61 100644 --- a/target/common/common.mk +++ b/target/common/common.mk @@ -54,6 +54,8 @@ SED_SRCS := sed -e ${MATCH_END} -e ${MATCH_BGN} -e ${MATCH_DEF} COMMON_BENDER_FLAGS += -t rtl +GVSOC_BUILDDIR ?= work-gvsoc + VSIM_BENDER += $(COMMON_BENDER_FLAGS) -t test -t simulation -t vsim VSIM_SOURCES = $(shell ${BENDER} script flist-plus ${VSIM_BENDER} | ${SED_SRCS}) VSIM_BUILDDIR ?= work-vsim diff --git a/target/common/gvsoc.mk b/target/common/gvsoc.mk new file mode 100644 index 000000000..4c3e743d7 --- /dev/null +++ b/target/common/gvsoc.mk @@ -0,0 +1,21 @@ +# Copyright 2024 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +$(BIN_DIR)/$(TARGET).gvsoc: + @echo "#!/bin/bash" > $@ + @echo 'binary=$$(realpath $$1)' >> $@ + @echo 'echo $$binary > .rtlbinary' >> $@ + @echo 'path="$$(dirname "$$(dirname "$$(readlink -f "$${BASH_SOURCE[0]}")")")"' >> $@ + @echo 'if [ -z "$$GVSOC_TARGET" ]; then' >> $@ + @echo ' GVSOC_TARGET=snitch' >> $@ + @echo 'fi' >> $@ + @echo 'gvsoc --target=$${GVSOC_TARGET} --binary $$binary \ + --control-script=$${path}/${GVSOC_BUILDDIR}/pulp/pulp/snitch/utils/gvcontrol.py $$2 run' >> $@ + @chmod +x $@ + +.PHONY: clean-gvsoc +clean-gvsoc: + rm -rf $(BIN_DIR)/$(TARGET).gvsoc $(GVSOC_BUILDDIR) + +clean: clean-gvsoc diff --git a/target/snitch_cluster/Makefile b/target/snitch_cluster/Makefile index 1a5ab2388..ff01611a4 100644 --- a/target/snitch_cluster/Makefile +++ b/target/snitch_cluster/Makefile @@ -215,6 +215,12 @@ $(BIN_DIR)/$(TARGET).vcs: ${VCS_SOURCES} ${TB_SRCS} $(TB_CC_SOURCES) $(RTL_CC_SO -assert disable_cover -override_timescale=1ns/1ps -full64 tb_bin $(TB_CC_SOURCES) $(RTL_CC_SOURCES) \ -CFLAGS "$(TB_CC_FLAGS)" -LDFLAGS "-L${FESVR}/lib" -lfesvr +######### +# GVSOC # +######### + +include $(ROOT)/target/common/gvsoc.mk + ######## # Util # ######## diff --git a/target/snitch_cluster/sw/run.yaml b/target/snitch_cluster/sw/run.yaml index 65a2f8067..c9cf3e22c 100644 --- a/target/snitch_cluster/sw/run.yaml +++ b/target/snitch_cluster/sw/run.yaml @@ -6,7 +6,7 @@ runs: - elf: tests/build/alias.elf simulators: [vsim, vcs, verilator] # banshee does not model alias regions - elf: tests/build/atomics.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x4 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x4 - elf: tests/build/barrier.elf - elf: tests/build/data_mover.elf - elf: tests/build/dma_empty_transfer.elf @@ -14,45 +14,45 @@ runs: - elf: tests/build/event_unit.elf - elf: tests/build/fence_i.elf - elf: tests/build/fp8_comparison_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with segfault + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with segfault - elf: tests/build/fp8_comparison_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with segfault + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with segfault - elf: tests/build/fp8_computation_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with JIT issue + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with JIT issue - elf: tests/build/fp8_computation_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x6 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x6 - elf: tests/build/fp8alt_comparison_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with segfault + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with segfault - elf: tests/build/fp8alt_comparison_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x10 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x10 - elf: tests/build/fp8alt_computation_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with JIT issue + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with JIT issue - elf: tests/build/fp8alt_computation_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x12 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x12 - elf: tests/build/fp16_comparison_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x10 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x10 - elf: tests/build/fp16_comparison_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x10 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x10 - elf: tests/build/fp16_computation_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with JIT issue + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with JIT issue - elf: tests/build/fp16_computation_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x6 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x6 - elf: tests/build/fp16alt_comparison_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x10 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x10 - elf: tests/build/fp16alt_comparison_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x10 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x10 - elf: tests/build/fp16alt_computation_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with JIT issue + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with JIT issue - elf: tests/build/fp16alt_computation_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x16 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x16 - elf: tests/build/fp32_comparison_scalar.elf - elf: tests/build/fp32_comparison_vector.elf - elf: tests/build/fp32_computation_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x2 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x2 - elf: tests/build/fp32_computation_vector.elf - simulators: [vsim, vcs, verilator] # banshee fails with exit code 0x2 + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with exit code 0x2 - elf: tests/build/fp32_conversions_scalar.elf - simulators: [vsim, vcs, verilator] # banshee fails with illegal instruction + simulators: [vsim, vcs, verilator, gvsoc] # banshee fails with illegal instruction # - elf: tests/build/fp64_conversions_scalar.elf # simulators: [vsim, vcs, verilator] - elf: tests/build/interrupt_local.elf @@ -72,6 +72,7 @@ runs: - elf: tests/build/non_null_exitcode.elf retcode: 56 - elf: tests/build/caq.elf + simulators: [vsim, vcs, verilator, banshee] # GVSOC does not model caq - elf: tests/build/caq_frep.elf simulators: [vsim, vcs, verilator] # banshee does not model FREP timing - elf: apps/blas/axpy/build/axpy.elf diff --git a/target/snitch_cluster/util/run.py b/target/snitch_cluster/util/run.py index 12cb67188..5c95701ff 100755 --- a/target/snitch_cluster/util/run.py +++ b/target/snitch_cluster/util/run.py @@ -15,7 +15,7 @@ sys.path.append(str(Path(__file__).parent / '../../../util/sim')) import sim_utils # noqa: E402 -from Simulator import QuestaSimulator, VCSSimulator, VerilatorSimulator, \ +from Simulator import QuestaSimulator, VCSSimulator, VerilatorSimulator, GvsocSimulator, \ BansheeSimulator # noqa: E402 @@ -23,7 +23,8 @@ 'vsim': QuestaSimulator(Path(__file__).parent.resolve() / '../bin/snitch_cluster.vsim'), 'vcs': VCSSimulator(Path(__file__).parent.resolve() / '../bin/snitch_cluster.vcs'), 'verilator': VerilatorSimulator(Path(__file__).parent.resolve() / '../bin/snitch_cluster.vlt'), - 'banshee': BansheeSimulator(Path(__file__).parent.resolve() / '../src/banshee.yaml') + 'banshee': BansheeSimulator(Path(__file__).parent.resolve() / '../src/banshee.yaml'), + 'gvsoc': GvsocSimulator(Path(__file__).parent.resolve() / '../bin/snitch_cluster.gvsoc') } diff --git a/util/sim/Simulation.py b/util/sim/Simulation.py index 5dd98ee35..caa98e0e6 100644 --- a/util/sim/Simulation.py +++ b/util/sim/Simulation.py @@ -267,6 +267,36 @@ def get_cpu_time(self): return hours*3600 + minutes*60 + seconds +class GvsocSimulation(Simulation): + """A functional simulation running on GVSOC.""" + + def __init__(self, sim_bin=None, cmd=None, **kwargs): + super().__init__(**kwargs) + + if cmd is None: + self.cmd = ['gvsoc', '--target', os.environ.get('GVSOC_TARGET'), '--binary', + str(self.elf), 'run'] + else: + self.dynamic_args = { + 'sim_bin': str(sim_bin), + 'elf': str(self.elf), + 'run_dir': str(self.run_dir) + } + self.cmd = [Template(arg).render(**self.dynamic_args) for arg in cmd] + self.cmd.append('--simulator=gvsoc') + + def successful(self): + """Return whether the simulation was successful.""" + # On GVSOC, OpenOCD semi-hosting is used which can just report 0 or 1 + actual_retcode = self.get_retcode() + if actual_retcode is not None: + if self.expected_retcode != 0: + return int(actual_retcode) != 0 + else: + return int(actual_retcode) == 0 + else: + return False + class VCSSimulation(QuestaVCSSimulation): """An RTL simulation running on VCS.""" diff --git a/util/sim/Simulator.py b/util/sim/Simulator.py index a5d7e1909..3cdccf5dd 100644 --- a/util/sim/Simulator.py +++ b/util/sim/Simulator.py @@ -4,7 +4,7 @@ # # Luca Colagrande -from Simulation import QuestaSimulation, VCSSimulation, VerilatorSimulation, BansheeSimulation +from Simulation import QuestaSimulation, VCSSimulation, VerilatorSimulation, BansheeSimulation, GvsocSimulation class Simulator(object): @@ -96,6 +96,23 @@ def get_simulation(self, test): cmd=cmd ) +class GvsocSimulator(RTLSimulator): + """Gvsoc simulator + + An [RTL simulator][Simulator.RTLSimulator], identified by the name + `vsim`, tailored to the creation of + [Gvsoc simulations][Simulation.GvsocSimulation]. + """ + + def __init__(self, binary): + """Constructor for the GvsocSimulator class. + + Arguments: + binary: The Gvsoc simulation binary. + """ + super().__init__(binary, name='gvsoc', simulation_cls=GvsocSimulation) + + class VCSSimulator(RTLSimulator): """VCS simulator diff --git a/util/sim/SnitchSim.py b/util/sim/SnitchSim.py index d98c1ec14..4eddd8b43 100755 --- a/util/sim/SnitchSim.py +++ b/util/sim/SnitchSim.py @@ -25,11 +25,12 @@ class SnitchSim: - def __init__(self, sim_bin: str, snitch_bin: str, log: str = None): + def __init__(self, sim_bin: str, snitch_bin: str, simulator: str = None, log: str = None): self.sim_bin = sim_bin self.snitch_bin = snitch_bin self.sim = None self.tmpdir = None + self.simulator = simulator self.log = open(log, 'w+') if log else log def start(self): @@ -40,10 +41,15 @@ def start(self): rx_fd = os.path.join(self.tmpdir.name, 'rx') os.mkfifo(rx_fd) # Start simulator process - ipc_arg = f'--ipc,{tx_fd},{rx_fd}' + if self.simulator == 'gvsoc': + ipc_arg = f'--ipc {tx_fd},{rx_fd}' + else: + ipc_arg = f'--ipc,{tx_fd},{rx_fd}' + self.sim = subprocess.Popen([self.sim_bin, self.snitch_bin, ipc_arg], stdout=self.log) # Open FIFOs self.tx = open(tx_fd, 'wb', buffering=0) # Unbuffered + self.rx = open(rx_fd, 'rb') # Create thread to monitor simulation self.stop_sim_monitor = threading.Event() diff --git a/util/sim/verif_utils.py b/util/sim/verif_utils.py index ef0caf8c7..0e257c821 100644 --- a/util/sim/verif_utils.py +++ b/util/sim/verif_utils.py @@ -97,6 +97,9 @@ def parser(self): parser.add_argument( '--log', help='Redirect simulation output to this log file') + parser.add_argument( + '--simulator', + help='Specifies simulator') parser.add_argument( '--dump-results', action='store_true', @@ -144,7 +147,8 @@ def simulate(self): elf = Elf(self.args.snitch_bin) # Start simulation - sim = SnitchSim(self.args.sim_bin, self.args.snitch_bin, log=self.args.log) + sim = SnitchSim(self.args.sim_bin, self.args.snitch_bin, simulator=self.args.simulator, + log=self.args.log) sim.start() # Wait for kernel execution to be over