diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50f3ce11..7163c14e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,6 +29,7 @@ jobs: sw/include/regs/*.h .dir-locals.el utils/* + scripts/* lint-sv: runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index a0b13c0c..53124614 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ work/ /logs/ /working_dir/ +sw/tests/bare-metal/safed/*.h # Created by https://www.toptal.com/developers/gitignore/api/python # Edit at https://www.toptal.com/developers/gitignore?templates=python diff --git a/Bender.yml b/Bender.yml index eba4e7ee..dc46a08a 100644 --- a/Bender.yml +++ b/Bender.yml @@ -32,6 +32,9 @@ workspace: package_links: cheshire: cheshire spatz: spatz + safety_island: safety_island + opentitan: opentitan + pulp_cluster: pulp_cluster sources: # Source files grouped in levels. Files in level 0 have no dependencies on files in this @@ -52,6 +55,7 @@ sources: - target: test files: - tb/hyp_vip/s27ks0641.v + - tb/vip_carfield_soc.sv - tb/carfield_fix.sv - tb/carfield_tb.sv @@ -62,7 +66,7 @@ sources: - target: all(synthesis, not(fpga)) files: - target/synth/carfield_synth_wrap.sv - + - target: all(xilinx, fpga) files: - target/xilinx/src/carfield_top_xilinx.sv diff --git a/README.md b/README.md index 99cf9664..cd6e6a3b 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,7 @@ To handle project dependencies, you can use ## Carfield Initialization To initialize Carfield, do the following: - * Export the `RISCV` environment variable to the RISC-V toolchain. To work on IIS machines, - do `export RISCV=/usr/pack/riscv-1.0-kgf/riscv64-gcc-11.2.0`. - * Execute the command: +* Execute the command: ``` make car-init @@ -28,18 +26,25 @@ To initialize Carfield, do the following: It will take care of: - ** Clone all the Carfield dependencies; - ** Initialize the [Cheshire SoC](https://github.com/pulp-platform/cheshire). This can be + 1. Clone all the Carfield dependencies; + 2. Initialize the [Cheshire SoC](https://github.com/pulp-platform/cheshire). This can be done separately by running `make chs-init` - ** Downloads the Hyperram models from the iis-gitlab. If you don't have access to it, you + 3. Downloads the Hyperram models from the iis-gitlab. If you don't have access to it, you can also download the freely-available Hyperram models from [here](https://www.cypress.com/documentation/models/verilog/s27kl0641-s27ks0641-verilog) and unzip them according to the bender. +* Check that you have a RISCV toolchain for both RV64 and RV32 ISAs. For ETH, type: + ``` + source scripts/env-iis.sh + ``` + ## Simulation Follow these steps to launch a Carfield simulation: +### Compile HW and SW + * Generate the compile scripts for Questasim and compile Carfield. ``` @@ -55,9 +60,11 @@ Follow these steps to launch a Carfield simulation: make car-sw-build ``` -* Simulate a binary in RTL. The current supported bootmodes from Cheshire are: +### System bootmodes + +* The current supported bootmodes from Cheshire are: - | Bootmode | Preload mode | Action | + | `CHS_BOOTMODE` | `CHS_PRELMODE` | Action | | --- | --- | --- | | 0 | 0 | Passive bootmode, JTAG preload | | 0 | 1 | Passive bootmode, Serial Link preload | @@ -66,18 +73,33 @@ Follow these steps to launch a Carfield simulation: | 2 | - | Autonomous bootmode, SPI flash | | 3 | - | Autonomous bootmode, I2C EEPROM | - `Bootmode` indicates the available bootmodes in Cheshire, while `Preload mode` - indicates the type of preload, if any is needed. For RTL simulation, bootmodes - 0, 2 and 3 are supported. SPI SD card bootmode is supported on FPGA emulation. + `Bootmode` indicates the available bootmodes in Cheshire, while `Preload mode` indicates the type + of preload, if any is needed. For RTL simulation, bootmodes 0, 2 and 3 are supported. SPI SD card + bootmode is supported on FPGA emulation. - To launch an RTL simulation with the selected boot and preload modes, type: +* The current supported bootmodes ffrom the Safety Island are: - | Bootmode | Command | + | `SAFED_BOOTMODE` | Action | | --- | --- | - | 0 | `make car-hw-sim BOOTMODE= PRELMODE= CHS_BINARY=.car.elf SECD_BINARY= SAFED_BINARY=` | - | 1, 2, 3 | `make car-hw-sim BOOTMODE= PRELMODE= CHS_IMAGE=.car.memh` | + | 0 | Passive bootmode, JTAG preload | + | 1 | Passive bootmode, Serial Link preload | + +### Simulation + +To launch an RTL simulation with the selected boot/preload modes for the island of choice, type: + + +* For cheshire in passive bootmode (`CHS_BOOTMODE=0`), set `CHS_BINARY` for Cheshire + +``` +make car-hw-sim CHS_BOOTMODE= CHS_PRELMODE= CHS_BINARY=.car.elf PULPCL_BINARY= SPATZCL_BINARY= SECD_BINARY= SAFED_BOOTMODE= SAFED_BINARY= +``` + +* For cheshire in autonomous bootmode (`CHS_BOOTMODE` = {1,2,3}), set `CHS_IMAGE` for Cheshire - Default is passive bootmode with serial link preload. +``` +make car-hw-sim CHS_BOOTMODE= CHS_PRELMODE= CHS_IMAGE=.car.memh PULPCL_BINARY= SPATZCL_BINARY= SECD_BINARY= SAFED_BOOTMODE= SAFED_BINARY= +``` ## License diff --git a/bender-common.mk b/bender-common.mk index 08c817af..e1a1d44a 100644 --- a/bender-common.mk +++ b/bender-common.mk @@ -1,4 +1,4 @@ -# Copyright 2021 ETH Zurich and University of Bologna. +# Copyright 2023 ETH Zurich and University of Bologna. # Solderpad Hardware License, Version 0.51, see LICENSE for details. # SPDX-License-Identifier: SHL-0.51 # diff --git a/bender-safed.mk b/bender-safed.mk new file mode 100644 index 00000000..ba77202b --- /dev/null +++ b/bender-safed.mk @@ -0,0 +1,8 @@ +# Copyright 2023 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 +# +# Author: Alessandro Ottaviano + +# bender defines +safed_defs += -D TARGET_SIMULATION diff --git a/bender-synth.mk b/bender-synth.mk index d6fd4c40..e879770b 100644 --- a/bender-synth.mk +++ b/bender-synth.mk @@ -1,4 +1,4 @@ -# Copyright 2021 ETH Zurich and University of Bologna. +# Copyright 2023 ETH Zurich and University of Bologna. # Solderpad Hardware License, Version 0.51, see LICENSE for details. # SPDX-License-Identifier: SHL-0.51 # diff --git a/carfield.mk b/carfield.mk index f89351bb..d34a6f59 100644 --- a/carfield.mk +++ b/carfield.mk @@ -14,14 +14,12 @@ CAR_SW_DIR := $(CAR_ROOT)/sw CAR_XIL_DIR := $(CAR_ROOT)/target/xilinx CAR_HW_DIR := $(CAR_ROOT)/hw -# Bender BENDER ?= bender QUESTA ?= questa-2022.3 VIVADO ?= vitis-2020.2 vivado TBENCH ?= tb_carfield_soc -BOOTMODE ?= 0 # default passive bootmode -PRELMODE ?= 1 # default serial link preload VOPTARGS ?= + # Interrupt configuration in cheshire # CLINT interruptible harts CLINTCORES := 3 @@ -30,26 +28,47 @@ PLICCORES := 6 # PLIC number of input interrupts PLIC_NUM_INTRS := 89 +# Cheshire +CHS_ROOT ?= $(shell $(BENDER) path cheshire) # Include cheshire's makefrag only if the dependency was cloned -include $(CHS_ROOT)/cheshire.mk -# Spatz -SPATZ_ROOT ?= $(CAR_ROOT)/spatz -SPATZ_MAKEDIR := $(SPATZ_ROOT)/hw/system/spatz_cluster - -TESTNAME ?= helloworld -MEMTYPE ?= spm -CHS_BINARY ?= $(CAR_ROOT)/sw/tests/hostd/$(TESTNAME).car.$(MEMTYPE).elf -SECD_BINARY ?= # TODO: secd sw root -SAFED_BINARY ?= # TODo: safed sw root +CHS_BOOTMODE ?= 0 # default passive bootmode +CHS_PRELMODE ?= 1 # default serial link preload +CHS_BINARY ?= CHS_IMAGE ?= +# Safety Island +SAFED_ROOT ?= $(shell $(BENDER) path safety_island) +SAFED_SW_DIR := $(SAFED_ROOT)/sw +SAFED_BOOTMODE ?= 0 +SAFED_BINARY ?= + +# Security island +SECD_ROOT ?= $(shell $(BENDER) path opentitan) +SECD_BINARY ?= +SECD_BOOTMODE ?= + +# PULP cluster +PULPCL_ROOT ?= $(shell $(BENDER) path pulp_cluster) +PULPCL_BINARY ?= + +# Spatz cluster +SPATZCL_ROOT ?= $(shell $(BENDER) path spatz) +SPATZCL_MAKEDIR := $(SPATZCL_ROOT)/hw/system/spatz_cluster +SPATZCL_BINARY ?= + +# Default variable values for RTL simulation +TBENCH ?= tb_carfield_soc +OPTARGS ?= + # Include bender targets and defines for common usage and synth verification # (the following includes are mandatory) include $(CAR_ROOT)/bender-common.mk include $(CAR_ROOT)/bender-sim.mk include $(CAR_ROOT)/bender-synth.mk include $(CAR_ROOT)/bender-xilinx.mk +include $(CAR_ROOT)/bender-safed.mk # Setup Virtual Environment for python scripts (reggen) VENVDIR?=$(WORKDIR)/.venv @@ -69,7 +88,7 @@ endif ###################### CAR_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:carfield/carfield-nonfree.git -CAR_NONFREE_COMMIT ?= f09457c9aabc3b150ae36c854961e89b679360aa +CAR_NONFREE_COMMIT ?= 72bdf4836596be7c3a939e6bea71924811066e86 ## Clone the non-free verification IP for the Carfield TB car-nonfree-init: @@ -88,16 +107,16 @@ include $(CAR_SW_DIR)/sw.mk ############## # Simulation # ############## -.PHONY: hw/regs/carfield_regs.hjson -hw/regs/carfield_regs.hjson: hw/regs/carfield_regs.csv | venv +.PHONY: $(CAR_ROOT)/hw/regs/carfield_regs.hjson +$(CAR_ROOT)/hw/regs/carfield_regs.hjson: hw/regs/carfield_regs.csv | venv $(VENV)/python ./scripts/csv_to_json.py --input $< --output $@ -.PHONY: hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv -hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv: hw/regs/carfield_regs.hjson | venv +.PHONY: $(CAR_ROOT)/hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv +$(CAR_ROOT)/hw/regs/carfield_reg_pkg.sv $(CAR_ROOT)/hw/regs/carfield_reg_top.sv: $(CAR_ROOT)/hw/regs/carfield_regs.hjson | venv $(VENV)/python utils/reggen/regtool.py -r $< --outdir $(dir $@) -.PHONY: sw/include/regs/soc_ctrl.h -sw/include/regs/soc_ctrl.h: hw/regs/carfield_regs.hjson | venv +.PHONY: $(CAR_SW_DIR)/include/regs/soc_ctrl.h +$(CAR_SW_DIR)/include/regs/soc_ctrl.h: $(CAR_ROOT)/hw/regs/carfield_regs.hjson | venv $(VENV)/python utils/reggen/regtool.py -D $< > $@ ## @section Carfield SoC HW Generation @@ -106,7 +125,7 @@ sw/include/regs/soc_ctrl.h: hw/regs/carfield_regs.hjson | venv ## hw/regs/carfield_regs.csv. You don't have to run this target unless you changed the CSV file. The ## checked-in pregenerated register file RTL should be up-to-date. If you regenerate the regfile, do ## not forget to check in the generated RTL. -regenerate_soc_regs: hw/regs/carfield_reg_pkg.sv hw/regs/carfield_reg_top.sv +regenerate_soc_regs: $(CAR_ROOT)/hw/regs/carfield_reg_pkg.sv $(CAR_ROOT)/hw/regs/carfield_reg_top.sv $(CAR_SW_DIR)/include/regs/soc_ctrl.h ## @section Carfield CLINT and PLIC interruptible harts configuration @@ -134,7 +153,7 @@ $(CAR_ROOT)/tb/hyp_vip: .PHONY: scripts/carfield_compile.tcl scripts/carfield_compile.tcl: - $(BENDER) script vsim $(common_targs) $(sim_targs) $(common_defs) --vlog-arg="$(VLOG_ARGS)" --compilation-mode separate > $@ + $(BENDER) script vsim $(common_targs) $(sim_targs) $(common_defs) $(safed_defs) --vlog-arg="$(VLOG_ARGS)" --compilation-mode separate > $@ echo 'vlog "$(CHS_ROOT)/target/sim/src/elfloader.cpp" -ccflags "-std=c++11"' >> $@ .PHONY: car-sim-init @@ -155,7 +174,21 @@ car-hw-build: car-sim-init ## @param VOPTARGS="" Additional arguments to Questa's vopt command. ## @param TBENCH=tb_carfield_soc The toplevel testbench to use. Defaults to 'tb_carfield_soc'. car-hw-sim: - $(QUESTA) vsim $(VSIM_FLAG) -do "set BOOTMODE $(BOOTMODE); set PRELMODE $(PRELMODE); set CHS_BINARY $(CHS_BINARY); set SECD_BINARY $(SECD_BINARY); set SAFED_BINARY $(SAFED_BINARY); set VOPTARGS $(VOPTARGS); set CHS_IMAGE $(CHS_IMAGE); set TESTBENCH $(TBENCH); source scripts/start_carfield.tcl ; add log -r sim:/$(TBENCH)/*; $(RUN_AND_EXIT)" + $(QUESTA) vsim $(VSIM_FLAG) -do \ + "set CHS_BOOTMODE $(CHS_BOOTMODE); \ + set CHS_PRELMODE $(CHS_PRELMODE); \ + set CHS_BINARY $(CHS_BINARY); \ + set CHS_IMAGE $(CHS_IMAGE); \ + set SECD_BINARY $(SECD_BINARY); \ + set SAFED_BOOTMODE $(SAFED_BOOTMODE); \ + set SAFED_BINARY $(SAFED_BINARY); \ + set PULPCL_BINARY $(PULPCL_BINARY); \ + set SPATZCL_BINARY $(SPATZCL_BINARY); \ + set VOPTARGS $(VOPTARGS); \ + set TESTBENCH $(TBENCH); \ + source scripts/start_carfield.tcl ; \ + add log -r sim:/$(TBENCH)/*; \ + $(RUN_AND_EXIT)" .PHONY: car-hw-clean ## Remove all simulation build artifacts @@ -193,7 +226,7 @@ car-hw-init: spatz-hw-init chs-hw-init .PHONY: spatz-hw-init spatz-hw-init: - $(MAKE) -C $(SPATZ_MAKEDIR) -B SPATZ_CLUSTER_CFG=$(CAR_HW_DIR)/cfg/spatz_carfield.hjson bootrom + $(MAKE) -C $(SPATZCL_MAKEDIR) -B SPATZ_CLUSTER_CFG=$(CAR_HW_DIR)/cfg/spatz_carfield.hjson bootrom .PHONY: chs-hw-init ## This target has a prerequisite, i.e. the PLIC configuration must be chosen before generating the @@ -209,17 +242,28 @@ chs-sim-init: .PHONY: chs-sw-build ## Builds the SW libraries in cheshire and generates an archive (`libcheshire.a`) available for ## carfield as static library at link time. -chs-sw-build: - $(MAKE) chs-sw-all +chs-sw-build: chs-sw-all .PHONY: car-sw-build ## Builds carfield application SW and specific libraries. It links against `libcheshire.a`. -car-sw-build: chs-sw-build - $(MAKE) car-sw-all +car-sw-build: chs-sw-build car-sw-all .PHONY: car-init ## Shortcut to initialize carfield with all the targets described above. -car-init: car-checkout car-hw-init car-sim-init car-sw-build +car-init: car-checkout car-hw-init car-sim-init safed-sw-init + +# Initialize and build Safety Island SW +.PHONY: safed-sw-init +safed-sw-init: $(SAFED_ROOT) $(SAFED_SW_DIR)/pulp-runtime $(SAFED_SW_DIR)/pulp-freertos + +$(SAFED_SW_DIR)/pulp-runtime: $(SAFED_ROOT) + $(MAKE) -C $(SAFED_ROOT) pulp-runtime +$(SAFED_SW_DIR)/pulp-freertos: $(SAFED_ROOT) + $(MAKE) -C $(SAFED_ROOT) pulp-freertos + +# For independent boot of an island, we allow to compile the binary standalone. +.PHONY: safed-sw-build +safed-sw-build: safed-sw-init safed-sw-all ############ # RTL LINT # diff --git a/hw/carfield.sv b/hw/carfield.sv index 15f3c7f9..5fd85022 100644 --- a/hw/carfield.sv +++ b/hw/carfield.sv @@ -288,10 +288,10 @@ logic [CheshireNumIntHarts-1:0] safed_hostd_mbox_intr; // from safety island t localparam axi_in_t AxiIn = gen_axi_in(Cfg); localparam axi_out_t AxiOut = gen_axi_out(Cfg); -/*****************************/ -/* Wide Parameters: A48, D32 */ -/*****************************/ -localparam int unsigned AxiStrbWidth = Cfg.AxiDataWidth / 8; +/////////////////////////////// +// Wide Parameters: A48, D32 // +/////////////////////////////// + localparam int unsigned AxiSlvIdWidth = Cfg.AxiMstIdWidth + $clog2(AxiIn.num_in); // Wide AXI types diff --git a/hw/carfield_pkg.sv b/hw/carfield_pkg.sv index 1ad0d586..a05ad31c 100644 --- a/hw/carfield_pkg.sv +++ b/hw/carfield_pkg.sv @@ -374,9 +374,7 @@ localparam doub_bt L2Port2NonInterlBase = L2Port2Base + L2MemSize; /****************************/ localparam int unsigned LogDepth = 3; localparam int unsigned SafetyIslandMemOffset = 'h0000_0000; -localparam int unsigned SafetyIslandMemSize = 'h0020_0000; localparam int unsigned SafetyIslandPerOffset = 'h0020_0000; -localparam int unsigned SafetyIslandPerSize = 'h0010_0000; /******************************/ /* Integer Cluster Parameters */ diff --git a/requirements.txt b/requirements.txt index ba73c693..d722a3d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ hjson==3.1.0 Mako==1.1.6 PyYAML==6.0 pandas==1.0.1 +pyelftools==0.29 diff --git a/scripts/elf_to_header.py b/scripts/elf_to_header.py new file mode 100644 index 00000000..df3c9481 --- /dev/null +++ b/scripts/elf_to_header.py @@ -0,0 +1,615 @@ +#!/usr/bin/env python3 + +# +# Copyright (C) 2018 ETH Zurich, University of Bologna +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from elftools.elf.elffile import ELFFile +import os +import os.path +import struct +import argparse + +#c_header = """\ +#// Auto-generated code +##ifdef USE_HYPER +##include "hyperbus_test.h" +##endif +# +#extern int __cluster_code_start; +#extern int __cluster_code_end; +# +#""" +#c_function = """\ +# #ifdef CLUSTER_BIN +# uint32_t *p, *end, *p0; +# p = (uint32_t*)&__cluster_code_start; +# p0 = (uint32_t*)&__cluster_code_start; +# end = (uint32_t*)&__cluster_code_end; +# #ifdef USE_HYPER +# udma_hyper_setup(); +# set_pagebound_hyper(2048); +# udma_hyper_dread((end-p)*4,p-0x80000000, 0x1C000000, 128, 0); +# udma_hyper_wait(0); +# #else +# uint32_t * addr; +# while(p 0x%x]' % (start, start + size)) + self.areas.append([start, start+size]) + + + def __add_mem_word(self, base, size, data, width): + + aligned_base = base & ~(width - 1) + + shift = base - aligned_base + iter_size = width - shift + if iter_size > size: + iter_size = size + + value = self.mem.get(str(aligned_base)) + if value is None: + value = 0 + + value &= ~(((1< 0: + + iter_size = self.__add_mem_word(base, size, data, width) + + size -= iter_size + base += iter_size + data = data[iter_size:] + + + def __gen_stim_slm(self, filename, width): + + self.dump(' Generating to file: ' + filename) + + try: + os.makedirs(os.path.dirname(filename)) + except: + pass + + with open(filename, 'w') as file: + for key in sorted(self.mem.keys()): + file.write('%X_%0*X\n' % (int(key), width*2, self.mem.get(key))) + + def __gen_stim_header(self, filename, width): + + self.dump(' Generating to file: ' + filename) + + try: + os.makedirs(os.path.dirname(filename)) + except: + pass + + with open(filename, 'w') as file: + file.write(c_header) + file.write('int load_safed_payload() {\n' ) + file.write(c_function) + for key in sorted(self.mem.keys()): + file.write(' (*(volatile unsigned int *)(uint64_t)(0x%X)) = 0x%0*X ;\n' % (int(key), width*2, self.mem.get(key))) + #file.write('#endif\n') + file.write('return 0; \n }\n') + + + def __parse_binaries(self, width): + + self.mem = {} + + for binary in self.binaries: + + with open(binary, 'rb') as file: + elffile = ELFFile(file) + + for segment in elffile.iter_segments(): + + if segment['p_type'] == 'PT_LOAD': + + data = segment.data() + addr = segment['p_paddr'] + size = len(data) + + load = True + if len(self.areas) != 0: + load = False + for area in self.areas: + if addr >= area[0] and addr + size <= area[1]: + load = True + break + + if load: + + self.dump(' Handling section (base: 0x%x, size: 0x%x)' % (addr, size)) + + self.__add_mem(addr, size, data, width) + + if segment['p_filesz'] < segment['p_memsz']: + addr = segment['p_paddr'] + segment['p_filesz'] + size = segment['p_memsz'] - segment['p_filesz'] + self.dump(' Init section to 0 (base: 0x%x, size: 0x%x)' % (addr, size)) + self.__add_mem(addr, size, [0] * size, width) + + else: + + self.dump(' Bypassing section (base: 0x%x, size: 0x%x)' % (addr, size)) + + + + def gen_stim_header_32(self, stim_file): + + self.__parse_binaries(4) + + self.__gen_stim_header(stim_file, 4) + + def gen_stim_slm_64(self, stim_file): + + self.__parse_binaries(8) + + self.__gen_stim_slm(stim_file, 8) + + + def gen_stim_bin(self, stim_file): + + self.__parse_binaries(1) + + try: + os.makedirs(os.path.dirname(stim_file)) + except: + pass + + with open(stim_file, 'wb') as file: + prev_addr = None + for key in sorted(self.mem.keys()): + addr = int(key) + if prev_addr is not None: + while prev_addr != addr - 1: + file.write(struct.pack('B', 0)) + prev_addr += 1 + + prev_addr = addr + file.write(struct.pack('B', int(self.mem.get(key)))) + + + +class Efuse(object): + + def __init__(self, config, verbose=False): + self.config = config + self.verbose = verbose + + self.dump('Created efuse stimuli generator') + + + def dump(self, str): + if self.verbose: + print (str) + + def gen_stim_txt(self, filename): + + + user_efuses = {} + + efuses = self.config.get('**/efuse/values') + if efuses is None: + efuses = [] + else: + efuses = efuses.get_dict() + for efuse in efuses: + efuse_id, val = efuse.split(':') + efuse_id = int(efuse_id, 0) + val = int(val, 0) + user_efuses[efuse_id] = val + + nb_regs = self.config.get_child_int('**/efuse/nb_regs') + + pulp_chip = self.config.get_child_str('**/chip/name') + + pulp_chip_family = self.config.get_child_str('**/chip/pulp_chip_family') + + if pulp_chip_family == 'gap' or pulp_chip == 'vega' or pulp_chip == 'gap9': + + load_mode = self.config.get_child_str('**/runner/boot-mode') + encrypted = self.config.get_child_str('**/efuse/encrypted') + aes_key = self.config.get_child_str('**/efuse/aes_key') + aes_iv = self.config.get_child_str('**/efuse/aes_iv') + xtal_check = self.config.get_child_bool('**/efuse/xtal_check') + xtal_check_delta = self.config.get_child_bool('**/efuse/xtal_check_delta') + xtal_check_min = self.config.get_child_bool('**/efuse/xtal_check_min') + xtal_check_max = self.config.get_child_bool('**/efuse/xtal_check_max') + no_preload = self.config.get_child_str('**/efuse/no-preload') + + # In case we boot with the classic rom mode, don't init any efuse, the boot loader will boot with the default mode + load_mode_hex = None + + if pulp_chip == 'gap': + + if load_mode == 'rom': + load_mode_hex = 0x3A + elif load_mode == 'spi': + load_mode_hex = 0x0A + elif load_mode == 'jtag': + load_mode_hex = 0x12 + elif load_mode == 'rom_hyper': + load_mode_hex = 0x2A + elif load_mode == 'rom_spim_single': + load_mode_hex = 0x32 + elif load_mode == 'rom_spim': + load_mode_hex = 0x3A + elif load_mode == 'jtag_dev' or load_mode == 'spi_dev': + load_mode_hex = None + + if xtal_check: + if load_mode_hex == None: load_mode_hex = 0 + load_mode_hex |= 1<<7 + delta = int(xtal_check_delta*((1 << 15)-1)) + efuses.append('26:0x%x' % (delta & 0xff)) + efuses.append('27:0x%x' % ((delta >> 8) & 0xff)) + efuses.append('28:0x%x' % (xtal_check_min)) + efuses.append('29:0x%x' % (xtal_check_max)) + + if load_mode_hex != None: + if encrypted: + load_mode_hex |= 0x40 + for i in range(0, 16): + efuses.append('%d:0x%s' % (2+i, aes_key[30-i*2:32-i*2])) + for i in range(0, 8): + efuses.append('%d:0x%s' % (18+i, aes_iv[14-i*2:16-i*2])) + + efuses.append('0:%s' % load_mode_hex) + + elif pulp_chip == 'vega' or pulp_chip == 'gap9': + efuses = [0] * 128 + info2 = 0 + info3 = 0 + info4 = 0 + info5 = 0 + info6 = 0 + + clk_div = self.config.get_child_int('**/efuse/clkdiv') + fll_freq = self.config.get_child_int('**/efuse/fll/freq') + fll_assert_cycles = self.config.get_child_int('**/efuse/fll/assert_cycles') + fll_lock_tolerance = self.config.get_child_int('**/efuse/fll/lock_tolerance') + hyper_delay = self.config.get_child_int('**/efuse/hyper/delay') + hyper_latency = self.config.get_child_int('**/efuse/hyper/latency') + + if load_mode == 'rom': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + elif load_mode == 'rom_hyper': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # Hyperflash type + info3 = (1 << 0) + elif load_mode == 'rom_spim': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # SPI flash type + info3 = (0 << 0) + elif load_mode == 'rom_mram': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # MRAM type + info3 = (2 << 0) + # Activate MRAM TRIM CFG and fill it with dummy numbers until we get the real one. Also activate clock divider + info6 |= (1 << 6) | (1<<7) + info2 |= (2 << 3) + efuses[56] = 32*4 + for i in range(0, 32): + efuses [57+i] = i | ((i*4+1)<<8) | ((i*4+2)<<16) | ((i*4+3)<<24) + + if clk_div is not None: + info6 |= 1 << 7 + info2 = (info2 & ~(3<<3)) | (clk_div << 3) + + + if fll_freq is not None: + info2 |= (1 << 0) | (1 << 2) + efuses[31] = fll_freq + + if fll_lock_tolerance is not None or fll_assert_cycles is not None: + info2 |= (1<< 1) + efuses[32] = fll_lock_tolerance + efuses[33] = fll_assert_cycles + + if hyper_delay is not None: + info5 |= (1<<6) + efuses[30] = hyper_delay + + if hyper_latency is not None: + info5 |= (1<<7) + efuses[51] = hyper_latency + + + + if load_mode_hex != None: + if encrypted: + load_mode_hex |= 0x40 + info6 |= 1<<4 + for i in range(0, 16): + efuses[2+i] = aes_key[30-i*2:32-i*2] + for i in range(0, 8): + efuses[18+i] = aes_iv[14-i*2:16-i*2] + + efuses[0] = load_mode_hex + + efuses[1] = info2 + efuses[37] = info3 + efuses[38] = info4 + efuses[39] = info5 + efuses[40] = info6 + elif pulp_chip == 'gap_rev1': + info3 = 0 + info6 = 0 + if load_mode == 'rom': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + elif load_mode == 'rom_hyper': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # Hyperflash type + info3 = (1 << 0) + elif load_mode == 'rom_spim': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # SPI flash type + info3 = (0 << 0) + + if xtal_check: + if load_mode_hex == None: load_mode_hex = 0 + load_mode_hex |= 1<<7 + delta = int(xtal_check_delta*((1 << 15)-1)) + efuses.append('26:0x%x' % (delta & 0xff)) + efuses.append('27:0x%x' % ((delta >> 8) & 0xff)) + efuses.append('28:0x%x' % (xtal_check_min)) + efuses.append('29:0x%x' % (xtal_check_max)) + + if load_mode_hex != None: + if encrypted: + load_mode_hex |= 0x40 + info6 |= 1<<4 + for i in range(0, 16): + efuses.append('%d:0x%s' % (2+i, aes_key[30-i*2:32-i*2])) + for i in range(0, 8): + efuses.append('%d:0x%s' % (18+i, aes_iv[14-i*2:16-i*2])) + + efuses.append('0:%s' % load_mode_hex) + + efuses.append('1:%s' % 0) + efuses.append('37:%s' % (info3)) + efuses.append('38:%s' % 0) + efuses.append('39:%s' % 0) + efuses.append('40:%s' % (info6)) + + elif pulp_chip == 'gap8_revc': + + fll_freq = self.config.get_child_int('**/efuse/fll/freq') + ref_clk_wait = self.config.get_child_int('**/efuse/ref_clk_wait') + burst_size = self.config.get_child_int('**/efuse/burst_size') + flash_id = self.config.get_child_bool('**/efuse/flash_id') + fll_assert_cycles = self.config.get_child_int('**/efuse/fll/assert_cycles') + fll_lock_tolerance = self.config.get_child_int('**/efuse/fll/lock_tolerance') + hyper_delay = self.config.get_child_int('**/efuse/hyper/delay') + hyper_latency = self.config.get_child_int('**/efuse/hyper/latency') + + if hyper_delay is None: + hyper_delay = 3 + + efuses = [0] * 128 + info3 = 0 + info2 = 0 + info6 = 0 + info5 = 0 + + if self.config.get_child_str('**/vsim/model') == 'rtl': + info7 = 1 # Don't use UDMA MEMCPY as it makes RTL platform crash + else: + info7 = 0 + if load_mode == 'rom': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + elif load_mode == 'rom_hyper': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # Hyperflash type + info3 = (1 << 0) + info7 |= (1 << 2) # Partially reconfigure pads to overcome HW issue with rwds cg latch + elif load_mode == 'rom_spim': + # RTL platform | flash boot | no encryption | no wait xtal + load_mode_hex = 2 | (2 << 3) | (0 << 4) | (0 << 5) | (0 << 6) | (0 << 7) + # SPI flash type + info3 = (0 << 0) + + if burst_size is not None: + info6 |= (1 << 7) + efuses[61] = burst_size & 0xff + efuses[62] = (burst_size >> 8) & 0xff + + if flash_id: + info6 |= (1 << 5) + + if fll_freq is not None: + info2 |= (1 << 0) + efuses[57] = fll_freq + + if ref_clk_wait is not None: + info2 |= (1 << 6) + efuses[35] = ref_clk_wait & 0xff + efuses[36] = (ref_clk_wait >> 8) & 0xff + else: + info2 |= (1 << 6) + efuses[35] = 0 + efuses[36] = 0 + + if hyper_delay is not None: + info5 |= (1<<6) + efuses[32] |= hyper_delay + + if hyper_latency is not None: + info5 |= (1<<7) + efuses[51] |= hyper_latency + + + if fll_lock_tolerance is not None or fll_assert_cycles is not None: + info2 |= (1<< 1) + efuses[58] = fll_lock_tolerance + efuses[59] = fll_assert_cycles + + if xtal_check: + if load_mode_hex == None: load_mode_hex = 0 + load_mode_hex |= 1<<7 + delta = int(xtal_check_delta*((1 << 15)-1)) + efuses[26] = delta & 0xff + efuses[27] = (delta >> 8) & 0xff + efuses[28] = xtal_check_min & 0xff + efuses[29] = (xtal_check_min >> 8) & 0xff + efuses[30] |= xtal_check_max & 0xff + efuses[31] = (xtal_check_max >> 8) & 0xff + + if load_mode_hex != None: + if encrypted: + load_mode_hex |= 0x40 + info6 |= 1<<4 + for i in range(0, 16): + efuses[2+i] = int('0x%s' % aes_key[30-i*2:32-i*2], 0) + for i in range(0, 8): + efuses[18+i] = int('0x%s' % aes_iv[14-i*2:16-i*2], 0) + + efuses[0] = load_mode_hex + + efuses[1] = info2 + efuses[37] = info3 + efuses[38] = 0 + efuses[39] = info5 + efuses[40] = info6 + efuses[60] = info7 + + + # Efuse preloading file generation + if pulp_chip == 'vega' or pulp_chip == 'gap9': + + self.dump(' Generating to file: ' + filename) + + with open(filename, 'w') as file: + if no_preload is None or no_preload == False: + for efuseId in range (0, 128): + value = efuses[efuseId] + self.dump(' Writing register (index: %d, value: 0x%x)' % (efuseId, value)) + file.write('{0:032b}\n'.format(value)) + + elif pulp_chip == 'gap8_revc': + + values = [0] * nb_regs * 8 + for efuseId in range (0, nb_regs): + value = user_efuses.get(efuseId) + if value is None: + value = efuses[efuseId] + self.dump(' Writing register (index: %d, value: 0x%x)' % (efuseId, value)) + for index in range(0, 8): + if (value >> index) & 1 == 1: values[efuseId + index*128] = 1 + + self.dump(' Generating to file: ' + filename) + + with open(filename, 'w') as file: + for value in values: + file.write('%d ' % (value)) + + else: + + values = [0] * nb_regs * 8 + for efuse in efuses: + efuseId, value = efuse.split(':') + self.dump(' Writing register (index: %d, value: 0x%x)' % (int(efuseId, 0), int(value, 0))) + efuseId = int(efuseId, 0) + value = int(value, 0) + for index in range(0, 8): + if (value >> index) & 1 == 1: values[efuseId + index*128] = 1 + + self.dump(' Generating to file: ' + filename) + + with open(filename, 'w') as file: + for value in values: + file.write('%d ' % (value)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Generate stimuli') + + parser.add_argument("--binary", dest="binary", default=None, help="Specify input binary") + parser.add_argument("--vectors", dest="vectors", default=None, help="Specify output vectors file") + + args = parser.parse_args() + + if args.binary is None: + raise Exception('Specify the input binary with --binary=') + + if args.vectors is not None: + + stim_gen = stim(verbose=True) + + stim_gen.add_binary(args.binary) + + stim_gen.gen_stim_header_32(args.vectors) diff --git a/scripts/env-iis.sh b/scripts/env-iis.sh index 3e0c7ca2..6aee5197 100644 --- a/scripts/env-iis.sh +++ b/scripts/env-iis.sh @@ -5,6 +5,8 @@ # set up environment variables for rtl simulation ROOTD=$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd) -export PATH="/usr/pack/riscv-1.0-kgf/riscv64-gcc-11.2.0/bin:$PATH" -export RISCV=/usr/pack/riscv-1.0-kgf/riscv64-gcc-11.2.0 +export PATH="/usr/pack/riscv-1.0-kgf/riscv64-gcc-11.2.0/bin:$PATH" # RV64 GCC toolchain +export PATH="/usr/pack/riscv-1.0-kgf/pulp-gcc-2.6.0/bin:$PATH" # RV32 GCC toolchain export QUESTA=questa-2022.3 +[[ -d "$ROOTD/safety_island/sw/pulp-freertos" ]] && source "$ROOTD/safety_island/sw/pulp-freertos/env/safety-island.sh" #TODO add carfield target in freertos +[[ -d "$ROOTD/safety_island/sw/pulp-runtime" ]] && source "$ROOTD/safety_island/sw/pulp-runtime/configs/carfield.sh" diff --git a/scripts/start_carfield.tcl b/scripts/start_carfield.tcl index c91ff3b8..95672886 100644 --- a/scripts/start_carfield.tcl +++ b/scripts/start_carfield.tcl @@ -16,12 +16,13 @@ if {![info exists VOPTARGS]} { set flags "-permissive -suppress 3009 -suppress 8386 -error 7" set pargs "" -if {[info exists BOOTMODE]} { append pargs "+BOOTMODE=${BOOTMODE} " } -if {[info exists PRELMODE]} { append pargs "+PRELMODE=${PRELMODE} " } -if {[info exists CHS_BINARY]} { append pargs "+CHS_BINARY=${CHS_BINARY} " } -if {[info exists SECD_BINARY]} { append pargs "+SECD_BINARY=${SECD_BINARY} " } -if {[info exists SAFED_BINARY]} { append pargs "+SAFED_BINARY=${SAFED_BINARY} " } -if {[info exists CHS_IMAGE]} { append pargs "+CHS_IMAGE=${CHS_IMAGE} " } +if {[info exists CHS_BOOTMODE]} { append pargs "+CHS_BOOTMODE=${CHS_BOOTMODE} " } +if {[info exists CHS_PRELMODE]} { append pargs "+CHS_PRELMODE=${CHS_PRELMODE} " } +if {[info exists CHS_BINARY]} { append pargs "+CHS_BINARY=${CHS_BINARY} " } +if {[info exists SECD_BINARY]} { append pargs "+SECD_BINARY=${SECD_BINARY} " } +if {[info exists SAFED_BOOTMODE]} { append pargs "+SAFED_BOOTMODE=${SAFED_BOOTMODE} " } +if {[info exists SAFED_BINARY]} { append pargs "+SAFED_BINARY=${SAFED_BINARY} " } +if {[info exists CHS_IMAGE]} { append pargs "+CHS_IMAGE=${CHS_IMAGE} " } eval "vsim -c ${TESTBENCH} -t 1ps -vopt -voptargs=\"${VOPTARGS}\"" ${pargs} ${flags} diff --git a/sw/include/car_memory_map.h b/sw/include/car_memory_map.h index 3c3cbb75..cd7e53be 100644 --- a/sw/include/car_memory_map.h +++ b/sw/include/car_memory_map.h @@ -15,6 +15,8 @@ #ifndef __CAR_MEMORY_MAP_H #define __CAR_MEMORY_MAP_H +#include "regs/safety_soc_ctrl.h" + // Base addresses provided at link time extern void *__base_l2; @@ -33,8 +35,17 @@ extern void *__base_l2; #define CAR_L2_SPM_PORT1_CONTIGUOUS_END_ADDR 0x78400000 // Safety Island -#define CAR_SAFETY_ISLAND_SPM_BASE_ADDR 0x60000000 -#define CAR_SAFETY_ISLAND_SPM_END_ADDR 0x60020000 +#define CAR_SAFETY_ISLAND_SPM_BASE_ADDR 0x60000000 +#define CAR_SAFETY_ISLAND_SPM_END_ADDR 0x60020000 +#define CAR_SAFETY_ISLAND_PERIPHERALS_OFFSET 0x00200000 +#define CAR_SAFETY_ISLAND_SOC_CTRL_OFFSET 0x00000000 +#define CAR_SAFETY_ISLAND_ENTRY_POINT (CAR_SAFETY_ISLAND_SPM_BASE_ADDR + 0x00010080) +#define CAR_SAFETY_ISLAND_SOC_CTRL_ADDR (CAR_SAFETY_ISLAND_SPM_BASE_ADDR + CAR_SAFETY_ISLAND_PERIPHERALS_OFFSET + CAR_SAFETY_ISLAND_SOC_CTRL_OFFSET) + +#define CAR_SAFETY_ISLAND_BOOTADDR_ADDR (CAR_SAFETY_ISLAND_SOC_CTRL_ADDR + SAFETY_SOC_CTRL_BOOTADDR_REG_OFFSET) +#define CAR_SAFETY_ISLAND_FETCHEN_ADDR (CAR_SAFETY_ISLAND_SOC_CTRL_ADDR + SAFETY_SOC_CTRL_FETCHEN_REG_OFFSET) +#define CAR_SAFETY_ISLAND_BOOTMODE_ADDR (CAR_SAFETY_ISLAND_SOC_CTRL_ADDR + SAFETY_SOC_CTRL_BOOTMODE_REG_OFFSET) +#define CAR_SAFETY_ISLAND_CORESTATUS_ADDR (CAR_SAFETY_ISLAND_SOC_CTRL_ADDR + SAFETY_SOC_CTRL_CORESTATUS_REG_OFFSET) #define CAR_SAFETY_ISLAND_PERIPHS_BASE_ADDR 0x60200000 #define CAR_SAFETY_ISLAND_PERIPHS_END_ADDR 0x60300000 @@ -64,7 +75,7 @@ extern void *__base_l2; #define CAR_WATCHDOG_TIMER_OFFSET 0x7000 #define CAR_HYPERBUS_CFG_OFFSET 0x9000 #define CAR_PAD_CFG_OFFSET 0xa000 -#define CAR_SOC_CTRL_OFFSET 0x10000 +#define CAR_SOC_CTRL_OFFSET 0x10000 #define CAR_ETHERNET_BASE_ADDR (CAR_PERIPHS_BASE_ADDR + CAR_ETHERNET_OFFSET) #define CAR_CAN_BASE_ADDR (CAR_PERIPHS_BASE_ADDR + CAR_CAN_OFFSET) @@ -77,4 +88,10 @@ extern void *__base_l2; #define CAR_MBOX_BASE_ADDR 0x40000000 +// Error codes +#define EHOSTDEXEC 1 // Execution error host domain +#define ESAFEDEXEC 2 // Execution error safe domain +#define EINTCLEXEC 3 // Execution error integer cluster +#define EFPCLEXEC 4 // Execution error floating point cluster + #endif /* __CAR_MEMORY_MAP_H */ diff --git a/sw/include/car_util.h b/sw/include/car_util.h index 485dbe79..2edc4e5d 100644 --- a/sw/include/car_util.h +++ b/sw/include/car_util.h @@ -51,22 +51,22 @@ enum car_rst { #define X(NAME) \ static inline uint32_t car_get_##NAME##_offset(enum car_rst rst) \ { \ - switch (rst) { \ - case CAR_PERIPH_RST: \ - return CARFIELD_PERIPH_##NAME##_REG_OFFSET; \ - case CAR_SAFETY_RST: \ - return CARFIELD_SAFETY_ISLAND_##NAME##_REG_OFFSET; \ - case CAR_SECURITY_RST: \ - return CARFIELD_SECURITY_ISLAND_##NAME##_REG_OFFSET; \ - case CAR_PULP_RST: \ - return CARFIELD_PULP_CLUSTER_##NAME##_REG_OFFSET; \ - case CAR_SPATZ_RST: \ - return CARFIELD_SPATZ_CLUSTER_##NAME##_REG_OFFSET; \ - case CAR_L2_RST: \ - return CARFIELD_L2_##NAME##_REG_OFFSET; \ - default: \ - return -1; \ - } \ + switch (rst) { \ + case CAR_PERIPH_RST: \ + return CARFIELD_PERIPH_##NAME##_REG_OFFSET; \ + case CAR_SAFETY_RST: \ + return CARFIELD_SAFETY_ISLAND_##NAME##_REG_OFFSET; \ + case CAR_SECURITY_RST: \ + return CARFIELD_SECURITY_ISLAND_##NAME##_REG_OFFSET; \ + case CAR_PULP_RST: \ + return CARFIELD_PULP_CLUSTER_##NAME##_REG_OFFSET; \ + case CAR_SPATZ_RST: \ + return CARFIELD_SPATZ_CLUSTER_##NAME##_REG_OFFSET; \ + case CAR_L2_RST: \ + return CARFIELD_L2_##NAME##_REG_OFFSET; \ + default: \ + return -1; \ + } \ } X(RST); @@ -78,22 +78,22 @@ X(ISOLATE_STATUS); #define X(NAME) \ static inline uint32_t car_get_##NAME##_offset(enum car_clk clk) \ { \ - switch (clk) { \ - case CAR_HOST_CLK: \ - return CARFIELD_HOST_##NAME##_REG_OFFSET; \ - case CAR_PERIPH_CLK: \ - return CARFIELD_PERIPH_##NAME##_REG_OFFSET; \ - case CAR_SAFETY_CLK: \ - return CARFIELD_SAFETY_ISLAND_##NAME##_REG_OFFSET; \ - case CAR_SECURITY_CLK: \ - return CARFIELD_SECURITY_ISLAND_##NAME##_REG_OFFSET; \ - case CAR_SPATZ_CLK: \ - return CARFIELD_SPATZ_CLUSTER_##NAME##_REG_OFFSET; \ - case CAR_L2_CLK: \ - return CARFIELD_L2_##NAME##_REG_OFFSET; \ - default: \ - return -1; \ - } \ + switch (clk) { \ + case CAR_HOST_CLK: \ + return CARFIELD_HOST_##NAME##_REG_OFFSET; \ + case CAR_PERIPH_CLK: \ + return CARFIELD_PERIPH_##NAME##_REG_OFFSET; \ + case CAR_SAFETY_CLK: \ + return CARFIELD_SAFETY_ISLAND_##NAME##_REG_OFFSET; \ + case CAR_SECURITY_CLK: \ + return CARFIELD_SECURITY_ISLAND_##NAME##_REG_OFFSET; \ + case CAR_SPATZ_CLK: \ + return CARFIELD_SPATZ_CLUSTER_##NAME##_REG_OFFSET; \ + case CAR_L2_CLK: \ + return CARFIELD_L2_##NAME##_REG_OFFSET; \ + default: \ + return -1; \ + } \ } X(CLK_EN); @@ -105,17 +105,17 @@ static inline enum car_clk car_clkd_from_rstd(enum car_rst rst) { switch (rst) { case CAR_PERIPH_RST: - return CAR_PERIPH_CLK; + return CAR_PERIPH_CLK; case CAR_SAFETY_RST: - return CAR_SAFETY_CLK; + return CAR_SAFETY_CLK; case CAR_SECURITY_RST: - return CAR_SECURITY_CLK; + return CAR_SECURITY_CLK; case CAR_PULP_RST: - return CAR_PULP_CLK; + return CAR_PULP_CLK; case CAR_SPATZ_RST: - return CAR_SPATZ_CLK; + return CAR_SPATZ_CLK; case CAR_L2_RST: - return CAR_L2_CLK; + return CAR_L2_CLK; } } @@ -124,8 +124,8 @@ void car_set_isolate(enum car_rst rst, enum car_isolation_status status) writew(status, CAR_SOC_CTRL_BASE_ADDR + car_get_ISOLATE_offset(rst)); fence(); while (readw(CAR_SOC_CTRL_BASE_ADDR + car_get_ISOLATE_STATUS_offset(rst)) != - status) - ; + status) + ; } void car_enable_clk(enum car_clk clk) @@ -153,11 +153,63 @@ void car_reset_domain(enum car_rst rst) car_set_rst(rst, CAR_RST_ASSERT); for (volatile int i = 0; i < 16; i++) - ; + ; car_set_rst(rst, CAR_RST_RELEASE); car_enable_clk(car_clkd_from_rstd(rst)); car_set_isolate(rst, CAR_ISOLATE_DISABLE); } +// Safety Island offload +void prepare_safed_boot () { + + // Select bootmode + volatile uintptr_t *bootmode_addr = (uintptr_t*)CAR_SAFETY_ISLAND_BOOTMODE_ADDR; + writew(1, bootmode_addr); + + // Write entry point into boot address + volatile uintptr_t *bootaddr_addr = (uintptr_t*)CAR_SAFETY_ISLAND_BOOTADDR_ADDR; + writew(CAR_SAFETY_ISLAND_ENTRY_POINT, bootaddr_addr); + + // Assert fetch enable + volatile uintptr_t *fetchen_addr = (uintptr_t*)CAR_SAFETY_ISLAND_FETCHEN_ADDR; + writew(1, fetchen_addr); + +} + +uint32_t poll_safed_corestatus () { + + volatile uint32_t corestatus; + volatile uintptr_t *corestatus_addr = (uintptr_t*)CAR_SAFETY_ISLAND_CORESTATUS_ADDR; + // TODO: Add a timeut to not poll indefinitely + while (((uint32_t)readw(corestatus_addr) & 0x80000000) == 0) { + corestatus = (uint32_t) readw(corestatus_addr); + } + + corestatus = (uint32_t) readw(corestatus_addr); + + return corestatus; +} + +uint32_t safed_offloader_blocking () { + + uint32_t ret = 0; + + // Load binary payload + load_safed_payload(); + + // Select bootmode, write entry point, write launch signal + prepare_safed_boot(); + + // Poll status register + volatile uint32_t corestatus = poll_safed_corestatus(); + + // Check core status. Return safed exit code to signal an error in the execution. + if ((corestatus & 0x7FFFFFFF) != 0) { + ret = ESAFEDEXEC; + } + + return ret; +} + #endif diff --git a/sw/sw.mk b/sw/sw.mk index d60c1dbb..749f106f 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -7,6 +7,10 @@ # Paul Scheffler # Alessandro Ottaviano +############ +# Carfield # +############ + CAR_LD_DIR ?= $(CAR_SW_DIR)/link RISCV_LDFLAGS ?= $(CHS_SW_FLAGS) -nostartfiles -Wl,--gc-sections -Wl,) -L$(CHS_SW_LD_DIR) -L$(CAR_LD_DIR) @@ -16,11 +20,9 @@ car-sw-all: car-sw-libs car-sw-tests .PRECIOUS: %.elf %.dtb .PHONY: car-sw-all car-sw-libs car-sw-headers car-sw-tests -############# -# Libraries # -############# +# Libraries -CAR_SW_INCLUDES = -I$(CAR_SW_DIR)/include -I$(CHS_SW_DIR)/include $(CHS_SW_DEPS_INCS) +CAR_SW_INCLUDES = -I$(CAR_SW_DIR)/include -I$(CAR_SW_DIR)/tests/bare-metal/safed -I$(CHS_SW_DIR)/include $(CHS_SW_DEPS_INCS) CAR_SW_LIB_SRCS_S = $(wildcard $(CAR_SW_DIR)/lib/*.S $(CAR_SW_DIR)/lib/**/*.S) CAR_SW_LIB_SRCS_C = $(wildcard $(CAR_SW_DIR)/lib/*.c $(CAR_SW_DIR)/lib/**/*.c) CAR_SW_LIB_SRCS_O = $(CAR_SW_DEPS_SRCS:.c=.o) $(CAR_SW_LIB_SRCS_S:.S=.o) $(CAR_SW_LIB_SRCS_C:.c=.o) @@ -32,9 +34,7 @@ $(CAR_SW_DIR)/lib/libcarfield.a: $(CAR_SW_LIB_SRCS_O) car-sw-libs: $(CAR_SW_LIBS) -############### -# Compilation # -############### +# Compilation # All objects require up-to-date patches and headers %.car.o: %.c @@ -53,12 +53,13 @@ endef $(foreach link,$(patsubst $(CAR_LD_DIR)/%.ld,%,$(wildcard $(CAR_LD_DIR)/*.ld)),$(eval $(call car_ld_elf_rule,$(link)))) -######### -# Tests # -######### +# Tests + +CAR_ELFLOAD_BLOCKING_SAFED_SRC_C := $(CAR_SW_DIR)/tests/bare-metal/hostd/safed_offloader_blocking.c +CAR_ELFLOAD_BLOCKING_SAFED_PATH := $(basename $(CAR_ELFLOAD_BLOCKING_SAFED_SRC_C)) -CAR_SW_TEST_SRCS_S = $(wildcard $(CAR_SW_DIR)/tests/hostd/*.S) -CAR_SW_TEST_SRCS_C = $(wildcard $(CAR_SW_DIR)/tests/hostd/*.c) +CAR_SW_TEST_SRCS_S = $(wildcard $(CAR_SW_DIR)/tests/bare-metal/hostd/*.S) +CAR_SW_TEST_SRCS_C = $(filter-out $(CAR_ELFLOAD_BLOCKING_SAFED_SRC_C), $(wildcard $(CAR_SW_DIR)/tests/bare-metal/hostd/*.c)) CAR_SW_TEST_DRAM_DUMP = $(CAR_SW_TEST_SRCS_S:.S=.car.dram.dump) $(CAR_SW_TEST_SRCS_C:.c=.car.dram.dump) CAR_SW_TEST_SPM_DUMP = $(CAR_SW_TEST_SRCS_S:.S=.car.spm.dump) $(CAR_SW_TEST_SRCS_C:.c=.car.spm.dump) @@ -66,4 +67,24 @@ CAR_SW_TEST_L2_DUMP = $(CAR_SW_TEST_SRCS_S:.S=.car.l2.dump) $(CAR_SW_TEST_SRCS CAR_SW_TEST_SPM_ROMH = $(CAR_SW_TEST_SRCS_S:.S=.car.rom.memh) $(CAR_SW_TEST_SRCS_C:.c=.car.rom.memh) CAR_SW_TEST_SPM_GPTH = $(CAR_SW_TEST_SRCS_S:.S=.car.gpt.memh) $(CAR_SW_TEST_SRCS_C:.c=.car.gpt.memh) -car-sw-tests: $(CAR_SW_TEST_DRAM_DUMP) $(CAR_SW_TEST_SPM_DUMP) $(CAR_SW_TEST_L2_DUMP) $(CAR_SW_TEST_SPM_ROMH) $(CAR_SW_TEST_SPM_GPTH) +car-sw-tests: $(CAR_SW_TEST_DRAM_DUMP) $(CAR_SW_TEST_SPM_DUMP) $(CAR_SW_TEST_L2_DUMP) $(CAR_SW_TEST_SPM_ROMH) $(CAR_SW_TEST_SPM_GPTH) car-sw-offload-tests + +################# +# Safety Island # +################# + +include $(CAR_SW_DIR)/tests/bare-metal/safed/sw.mk + +# Generate ELFs for blocking offload from cheshire. We execute from L2 or dram. +# TODO: Make this generation nicer and using patterns. As of now, it is ugly and inefficient. +car-sw-offload-tests: safed-sw-all + $(foreach header,$(HEADER_TARGETS), \ + cp $(header) $(CAR_SW_DIR)/tests/bare-metal/safed/payload.h; \ + $(RISCV_CC) $(CAR_SW_INCLUDES) $(RISCV_CCFLAGS) -c $(CAR_ELFLOAD_BLOCKING_SAFED_SRC_C) -o $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.o; \ + $(RISCV_CC) $(CAR_SW_INCLUDES) -T$(CAR_LD_DIR)/l2.ld $(RISCV_LDFLAGS) -o $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.l2.elf $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.o $(CHS_SW_LIBS) $(CAR_SW_LIBS); \ + $(RISCV_OBJDUMP) -d -S $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.l2.elf > $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.l2.dump; \ + $(RISCV_CC) $(CAR_SW_INCLUDES) -T$(CHS_LD_DIR)/dram.ld $(RISCV_LDFLAGS) -o $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.dram.elf $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.o $(CHS_SW_LIBS) $(CAR_SW_LIBS); \ + $(RISCV_OBJDUMP) -d -S $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.dram.elf > $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.dram.dump; \ + $(RM) $(CAR_SW_DIR)/tests/bare-metal/safed/payload.h; \ + $(RM) $(CAR_ELFLOAD_BLOCKING_SAFED_PATH).$(basename $(notdir $(header))).car.o; \ + ) diff --git a/sw/tests/hostd/addressability_test.c b/sw/tests/bare-metal/hostd/addressability_test.c similarity index 100% rename from sw/tests/hostd/addressability_test.c rename to sw/tests/bare-metal/hostd/addressability_test.c diff --git a/sw/tests/hostd/helloworld.c b/sw/tests/bare-metal/hostd/helloworld.c similarity index 100% rename from sw/tests/hostd/helloworld.c rename to sw/tests/bare-metal/hostd/helloworld.c diff --git a/sw/tests/hostd/mbox_test.c b/sw/tests/bare-metal/hostd/mbox_test.c similarity index 97% rename from sw/tests/hostd/mbox_test.c rename to sw/tests/bare-metal/hostd/mbox_test.c index aaaf303e..e047b97a 100644 --- a/sw/tests/hostd/mbox_test.c +++ b/sw/tests/bare-metal/hostd/mbox_test.c @@ -1,6 +1,9 @@ // Copyright 2023 ETH Zurich and University of Bologna. // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +// +// Maicol Ciani +// #include "car_memory_map.h" #include "io.h" diff --git a/sw/tests/bare-metal/hostd/safed_offloader_blocking.c b/sw/tests/bare-metal/hostd/safed_offloader_blocking.c new file mode 100644 index 00000000..836aef05 --- /dev/null +++ b/sw/tests/bare-metal/hostd/safed_offloader_blocking.c @@ -0,0 +1,30 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Alessandro Ottaviano +// + +#include +#include + +#include "car_memory_map.h" +#include "io.h" +#include "dif/clint.h" +#include "dif/uart.h" +#include "params.h" +#include "regs/cheshire.h" +#include "util.h" +#include "payload.h" +#include "car_util.h" + +extern int load_safed_payload (); + +int main(void) +{ + // Here we assume that the offloader has to poll a status register to catch the end of + // computation of the Safety Island. Therefore, the offloading is blocking. + uint32_t ret = safed_offloader_blocking(); + + return ret; +} diff --git a/sw/tests/hostd/sw_rst_seq.c b/sw/tests/bare-metal/hostd/sw_rst_seq.c similarity index 100% rename from sw/tests/hostd/sw_rst_seq.c rename to sw/tests/bare-metal/hostd/sw_rst_seq.c diff --git a/sw/tests/hostd/system_timer_test.c b/sw/tests/bare-metal/hostd/system_timer_test.c similarity index 100% rename from sw/tests/hostd/system_timer_test.c rename to sw/tests/bare-metal/hostd/system_timer_test.c diff --git a/sw/tests/bare-metal/safed/sw.mk b/sw/tests/bare-metal/safed/sw.mk new file mode 100644 index 00000000..6eebed57 --- /dev/null +++ b/sw/tests/bare-metal/safed/sw.mk @@ -0,0 +1,41 @@ +# Copyright 2023 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Alessandro Ottaviano + +RISCV32_GCC_BINROOT ?= $(dir $(shell which riscv32-unknown-elf-gcc)) +RISCV32_CC ?= $(RISCV32_GCC_BINROOT)/riscv32-unknown-elf-gcc + +.PHONY: all clean + +# Make fragment for safety island bare-metal tests compiled with pulp-runtime. + +# List all the directories in the 'tests' folder +TEST_DIRS := $(wildcard $(SAFED_SW_DIR)/tests/*) +TEST_DIRS := $(filter-out $(SAFED_SW_DIR)/tests/runtime_shared,$(TEST_DIRS)) +TEST_DIRS := $(filter-out $(wildcard $(SAFED_SW_DIR)/tests/freertos*),$(TEST_DIRS)) + +# Generate the list of build targets based on the directories +BUILD_TARGETS := $(addsuffix /build,$(TEST_DIRS)) + +# We have a target per test. The target (1) compiles the binary and (2) generates the needed stimuli +# file format, if any is required. +$(SAFED_SW_DIR)/tests/%/build: safety_island | venv + # Compile + $(MAKE) -C $(SAFED_SW_DIR)/tests/$* all + +# Convert compiled binaries to header files +HEADER_TARGETS := $(patsubst $(SAFED_SW_DIR)/tests/%, $(CAR_SW_DIR)/tests/bare-metal/safed/%.h, $(TEST_DIRS)) + +$(CAR_SW_DIR)/tests/bare-metal/safed/%.h: $(SAFED_SW_DIR)/tests/%/build | venv + $(VENV)/python ./scripts/elf_to_header.py --binary $ $@ ) + +# Global targets +safed-sw-all: $(BUILD_TARGETS) $(HEADER_TARGETS) + +safed-sw-clean: + # Clean all the directories in 'tests' + $(foreach dir, $(TEST_DIRS), $(MAKE) -C $(dir) clean;) + $(RM) $(CAR_SW_DIR)/tests/bare-metal/safed/*.h diff --git a/sw/tests/secd/sw.mk b/sw/tests/secd/sw.mk deleted file mode 100644 index aeefabb6..00000000 --- a/sw/tests/secd/sw.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2023 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 - -# Currently empty file, TODO diff --git a/tb/carfield_fix.sv b/tb/carfield_fix.sv index d35c6569..7ec405d3 100644 --- a/tb/carfield_fix.sv +++ b/tb/carfield_fix.sv @@ -16,6 +16,7 @@ module carfield_soc_fixture; import cheshire_pkg::*; import carfield_pkg::*; + import safety_island_pkg::*; /////////// // DPI // @@ -31,12 +32,14 @@ module carfield_soc_fixture; ///////// localparam cheshire_cfg_t DutCfg = carfield_pkg::CarfieldCfgDefault; - `CHESHIRE_TYPEDEF_ALL(, DutCfg) - localparam int unsigned RstCycles = 5; - localparam real TAppl = 0.1; - localparam real TTest = 0.9; + localparam time ClkPeriodSys = 5ns; + localparam time ClkPeriodJtag = 20ns; + localparam time ClkPeriodRtc = 30518ns; + localparam int unsigned RstCycles = 5; + localparam real TAppl = 0.1; + localparam real TTest = 0.9; localparam int NumPhys = 2; localparam int NumChips = 2; @@ -47,6 +50,9 @@ module carfield_soc_fixture; logic [1:0] boot_mode; logic rtc; + logic exit_status_safed; + logic [1:0] boot_mode_safed; + logic jtag_tck; logic jtag_trst_n; logic jtag_tms; @@ -88,33 +94,25 @@ module carfield_soc_fixture; logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_i; logic [SlinkNumChan-1:0][SlinkNumLanes-1:0] slink_o; - logic [NumPhys-1:0][NumChips-1:0] hyper_cs_n_wire; - logic [NumPhys-1:0][NumChips-1:0] hyper_cs_pen_wire; - logic [NumPhys-1:0][NumChips-1:0] hyper_cs_pad_out; - logic [NumPhys-1:0] hyper_ck_wire; - logic [NumPhys-1:0] hyper_ck_out_wire; - logic [NumPhys-1:0] hyper_ck_pen_wire; - logic [NumPhys-1:0] hyper_ck_n_wire; - logic [NumPhys-1:0] hyper_ck_n_out_wire; - logic [NumPhys-1:0] hyper_ck_n_pen_wire; + logic [NumPhys-1:0][NumChips-1:0] hyper_cs_no; + logic [NumPhys-1:0] hyper_ck_i; + logic [NumPhys-1:0] hyper_ck_o; + logic [NumPhys-1:0] hyper_ck_ni; + logic [NumPhys-1:0] hyper_ck_no; logic [NumPhys-1:0] hyper_rwds_o; logic [NumPhys-1:0] hyper_rwds_i; - logic [NumPhys-1:0] hyper_rwds_oe; - logic [NumPhys-1:0] hyper_rwds_pen; + logic [NumPhys-1:0] hyper_rwds_oe_o; logic [NumPhys-1:0][7:0] hyper_dq_i; logic [NumPhys-1:0][7:0] hyper_dq_o; - logic [NumPhys-1:0][7:0] hyper_dq_pen; - logic [NumPhys-1:0] hyper_dq_oe; - logic [NumPhys-1:0] hyper_reset_n_wire; - logic [NumPhys-1:0] hyper_rst_n_out_wire; - logic [NumPhys-1:0] hyper_rst_n_pen_wire; - - wire [NumPhys-1:0][NumChips-1:0] pad_hyper_csn; - wire [NumPhys-1:0] pad_hyper_ck; - wire [NumPhys-1:0] pad_hyper_ckn; - wire [NumPhys-1:0] pad_hyper_rwds; - wire [NumPhys-1:0] pad_hyper_reset; - wire [NumPhys-1:0][7:0] pad_hyper_dq; + logic [NumPhys-1:0] hyper_dq_oe_o; + logic [NumPhys-1:0] hyper_reset_no; + + wire [NumPhys-1:0][NumChips-1:0] pad_hyper_csn; + wire [NumPhys-1:0] pad_hyper_ck; + wire [NumPhys-1:0] pad_hyper_ckn; + wire [NumPhys-1:0] pad_hyper_rwds; + wire [NumPhys-1:0] pad_hyper_reset; + wire [NumPhys-1:0][7:0] pad_hyper_dq; carfield #( .Cfg ( DutCfg ), @@ -143,12 +141,12 @@ module carfield_soc_fixture; .jtag_ot_tdo_o ( jtag_secd_tdo ), .jtag_ot_tdo_oe_o ( ), .jtag_safety_island_tck_i ( jtag_safed_tck ), - .jtag_safety_island_trst_ni ( jtag_trst_n ), // Temporary - .jtag_safety_island_tms_i ( '0 ), // Temporary - .jtag_safety_island_tdi_i ( '0 ), // Temporary + .jtag_safety_island_trst_ni ( jtag_safed_trst_n ), + .jtag_safety_island_tms_i ( jtag_safed_tms ), + .jtag_safety_island_tdi_i ( jtag_safed_tdi ), .jtag_safety_island_tdo_o ( jtag_safed_tdo ), - .bootmode_ot_i ( '0 ), // Temporary - .bootmode_safe_isln_i ( '0 ), // Temporary + .bootmode_ot_i ( '0 ), + .bootmode_safe_isln_i ( boot_mode_safed ), .uart_tx_o ( uart_tx ), .uart_rx_i ( uart_rx ), .uart_ot_tx_o ( ), @@ -193,16 +191,16 @@ module carfield_soc_fixture; .slink_rcv_clk_o ( slink_rcv_clk_o ), .slink_i ( slink_i ), .slink_o ( slink_o ), - .hyper_cs_no ( hyper_cs_n_wire ), - .hyper_ck_o ( hyper_ck_wire ), - .hyper_ck_no ( hyper_ck_n_wire ), + .hyper_cs_no ( hyper_cs_no ), + .hyper_ck_o ( hyper_ck_o ), + .hyper_ck_no ( hyper_ck_no ), .hyper_rwds_o ( hyper_rwds_o ), .hyper_rwds_i ( hyper_rwds_i ), - .hyper_rwds_oe_o ( hyper_rwds_oe ), + .hyper_rwds_oe_o ( hyper_rwds_oe_o ), .hyper_dq_i ( hyper_dq_i ), .hyper_dq_o ( hyper_dq_o ), - .hyper_dq_oe_o ( hyper_dq_oe ), - .hyper_reset_no ( hyper_reset_n_wire ), + .hyper_dq_oe_o ( hyper_dq_oe_o ), + .hyper_reset_no ( hyper_reset_no ), .ext_reg_async_slv_req_i ( '0 ), .ext_reg_async_slv_ack_o ( ), .ext_reg_async_slv_data_i ( '0 ), @@ -212,91 +210,48 @@ module carfield_soc_fixture; .debug_signals_o ( ) ); - ////////////// - // HyperRam // - ////////////// - - for (genvar i = 0 ; i + +// collects all existing verification ip (vip) for carfield SoC + +module vip_carfield_soc + import carfield_pkg::*; + import cheshire_pkg::*; +#( + // DUT + parameter cheshire_cfg_t DutCfg = carfield_pkg::CarfieldCfgDefault, + parameter type axi_slv_ext_req_t = logic, + parameter type axi_slv_ext_rsp_t = logic, + parameter int unsigned HypNumPhys = 2, + parameter int unsigned HypNumChips = 2, + // Timing + parameter time ClkPeriodSys = 5ns, + parameter time ClkPeriodJtag = 20ns, + parameter time ClkPeriodRtc = 30518ns, + parameter int unsigned RstCycles = 5, + parameter real TAppl = 0.1, + parameter real TTest = 0.9, + // External AXI ports + parameter int unsigned NumAxiExtSlvPorts = 4, + // Serial Link + parameter int unsigned SlinkMaxWaitAx = 100, + parameter int unsigned SlinkMaxWaitR = 5, + parameter int unsigned SlinkMaxWaitResp = 20, + parameter int unsigned SlinkBurstBytes = 1024, + parameter bit SlinkAxiDebug = 0, + // Derived Parameters; *do not override* + parameter int unsigned AxiStrbWidth = DutCfg.AxiDataWidth/8, + parameter int unsigned AxiStrbBits = $clog2(DutCfg.AxiDataWidth/8) +) ( + output logic clk_vip, + output logic rst_n_vip, + // Hyperbus interface + wire [HypNumPhys-1:0][HypNumChips-1:0] pad_hyper_csn, + wire [HypNumPhys-1:0] pad_hyper_ck, + wire [HypNumPhys-1:0] pad_hyper_ckn, + wire [HypNumPhys-1:0] pad_hyper_rwds, + wire [HypNumPhys-1:0] pad_hyper_reset, + wire [HypNumPhys-1:0][7:0] pad_hyper_dq, + // External virtual AXI ports + input axi_slv_ext_req_t [NumAxiExtSlvPorts-1:0] axi_slvs_req, + output axi_slv_ext_rsp_t [NumAxiExtSlvPorts-1:0] axi_slvs_rsp, + // Multiplexed virtual AXI ports + output axi_slv_ext_req_t axi_muxed_req, + input axi_slv_ext_rsp_t axi_muxed_rsp +); + + `include "cheshire/typedef.svh" + `include "axi/assign.svh" + + `CHESHIRE_TYPEDEF_ALL(, DutCfg) + + /////////////////////////////// + // SoC Clock, Reset, Modes // + /////////////////////////////// + + logic clk, rst_n; + assign clk_vip = clk; + assign rst_n_vip = rst_n; + + clk_rst_gen #( + .ClkPeriod ( ClkPeriodSys ), + .RstClkCycles ( RstCycles ) + ) i_clk_rst_sys ( + .clk_o ( clk ), + .rst_no ( rst_n ) + ); + + ////////////// + // Hyperbus // + ////////////// + + for (genvar i=0; i