diff --git a/.gitignore b/.gitignore index db20a918..4c8e9b87 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,16 @@ target/sim/vsim/transcript target/sim/vsim/vsim.wlf target/sim/vsim/work/ +# VCS generated files +target/sim/vcs/compile.*.sh +target/sim/vcs/*.log +target/sim/vcs/AN.DB +target/sim/vcs/simv* +target/sim/vcs/csrc +target/sim/vcs/ucli.key +target/sim/vcs/work* +target/sim/vcs/vc_hdrs.h + # Xilinx generated files target/xilinx/build target/xilinx/out diff --git a/Bender.lock b/Bender.lock index 7a4b7adf..5697c987 100644 --- a/Bender.lock +++ b/Bender.lock @@ -15,8 +15,8 @@ packages: - apb - register_interface axi: - revision: ac5deb3ff086aa34b168f392c051e92603d6c0e2 - version: 0.39.2 + revision: 39f5f2d51c5e524f6fc5cf8b6e901f7dcc5622d7 + version: 0.39.6 source: Git: https://github.com/pulp-platform/axi.git dependencies: diff --git a/Bender.yml b/Bender.yml index 909f3092..30817f2c 100644 --- a/Bender.yml +++ b/Bender.yml @@ -13,7 +13,7 @@ package: dependencies: apb_uart: { git: "https://github.com/pulp-platform/apb_uart.git", version: 0.2.1 } - axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.39.2 } + axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.39.6 } axi_llc: { git: "https://github.com/pulp-platform/axi_llc.git", version: 0.2.1 } axi_riscv_atomics: { git: "https://github.com/pulp-platform/axi_riscv_atomics.git", version: 0.8.2 } axi_rt: { git: "https://github.com/pulp-platform/axi_rt.git", version: 0.0.0-alpha.9 } diff --git a/cheshire.mk b/cheshire.mk index 43340922..c5cc4157 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -7,11 +7,13 @@ # Paul Scheffler BENDER ?= bender +VLOGAN ?= vlogan # Caution: Questasim requires this to point to the *actual* compiler install path CXX_PATH := $(shell which $(CXX)) -VLOG_ARGS ?= -suppress 2583 -suppress 13314 -timescale 1ns/1ps +VLOG_ARGS ?= -suppress 2583 -suppress 13314 -timescale 1ns/1ps +VLOGAN_ARGS ?= -kdb -nc -assert svaext +v2k -timescale=1ns/1ps # Common Bender flags for Cheshire RTL CHS_BENDER_RTL_FLAGS ?= -t rtl -t cva6 -t cv64a6_imafdcsclic_sv39 @@ -61,7 +63,7 @@ chs-clean-deps: ###################### CHS_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/cheshire-nonfree.git -CHS_NONFREE_COMMIT ?= fd3526f +CHS_NONFREE_COMMIT ?= f465b29 CHS_PHONY += chs-nonfree-init chs-nonfree-init: @@ -149,6 +151,10 @@ $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl: $(CHS_ROOT)/Bender.yml $(BENDER) script vsim -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOG_ARGS)" > $@ echo 'vlog "$(realpath $(CHS_ROOT))/target/sim/src/elfloader.cpp" -ccflags "-std=c++11" -cpppath "$(CXX_PATH)"' >> $@ +$(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh: $(CHS_ROOT)/Bender.yml + $(BENDER) script vcs -t sim -t test $(CHS_BENDER_RTL_FLAGS) --vlog-arg="$(VLOGAN_ARGS)" --vlogan-bin="$(VLOGAN)" > $@ + chmod +x $@ + .PRECIOUS: $(CHS_ROOT)/target/sim/models $(CHS_ROOT)/target/sim/models: mkdir -p $@ @@ -167,6 +173,7 @@ $(CHS_ROOT)/target/sim/models/24FC1025.v: $(CHS_ROOT)/Bender.yml | $(CHS_ROOT)/t CHS_SIM_ALL += $(CHS_ROOT)/target/sim/models/s25fs512s.v CHS_SIM_ALL += $(CHS_ROOT)/target/sim/models/24FC1025.v CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vsim/compile.cheshire_soc.tcl +CHS_SIM_ALL += $(CHS_ROOT)/target/sim/vcs/compile.cheshire_soc.sh ########### # DRAMSys # diff --git a/docs/tg/sim.md b/docs/tg/sim.md index c51bd9f3..3cf9d285 100644 --- a/docs/tg/sim.md +++ b/docs/tg/sim.md @@ -5,6 +5,7 @@ This page describes how to simulate Cheshire to *execute baremetal programs*. Pl We currently provide working setups for: - Questa Advanced Simulator (QuestaSim) `>= 2022.3` +- VCS `>= 2024.09` We plan on supporting more simulators in the future. If your situation requires it, simulating Cheshire on other setups should be straightforward. @@ -21,7 +22,7 @@ We provide a SystemVerilog testbench for `cheshire_soc` running baremetal progra Preloading boot modes expect an ELF executable to be passed through `BINARY`, while autonomous boot modes expect a disk image (GPT formatted or raw code) to be passed through `IMAGE`. For more information on how to build software for Cheshire and its boot process, see [Software Stack](../um/sw.md). -The `SELCFG` environment variable selects the Cheshire configuration used in simulations. Possible configurations are specified in the `tb_cheshire_pkg` package. If not set or set to `0`, the default configuration is selected. +The `SELCFG` variable selects the Cheshire configuration used in simulations. Possible configurations are specified in the `tb_cheshire_pkg` package. If not set or set to `0`, the default configuration is selected. | `SELCFG` | Configuration in (`tb_cheshire_pkg`) | | -------- | ----------------------------------------- | @@ -29,13 +30,13 @@ The `SELCFG` environment variable selects the Cheshire configuration used in sim | 1 | AXI-RT-enabled configuration | | 2 | CLIC-enabled configuration | -The `USE_DRAMSYS` environment variable controls whether simulations are linked against and use DRAMSys for DRAM simulation. Note that before starting a simulation using DRAMSys, it must be built with `make chs-dramsys-all` first. +The `USE_DRAMSYS` variable controls whether simulations are linked against and use DRAMSys for DRAM simulation. Note that before starting a simulation using DRAMSys, it must be built with `make chs-dramsys-all` first. For simulation of Cheshire in other designs, we provide the module `cheshire_vip` encapsulating all verification IPs and their interfaces. For details, see [Verifying Cheshire In-System](integr.md#verifying-cheshire-in-system). ## QuestaSim -After building Cheshire, start QuestaSim in `target/sim/vsim` and run: +Variables are read from QuestaSim's Tcl environment. After building Cheshire, start QuestaSim in `target/sim/vsim` and run: ```tcl # Preload `helloworld.spm.elf` through serial link @@ -52,3 +53,22 @@ run -all ``` The design needs to be recompiled only when hardware is changed. The simulation can be restarted by re-sourcing `start.cheshire_soc.tcl`, allowing binary (or image) and load method changes beforehand. + +## VCS + +Variables are read from your shell environment. After building Cheshire, start a POSIX-compliant shell in `target/sim/vcs` and run: + +```sh +# Preload `helloworld.spm.elf` through serial link +export BINARY="../../../sw/tests/helloworld.spm.elf" +export BOOTMODE=0 +export PRELMODE=1 + +# Compile design +./compile.cheshire_soc.sh + +# Start and run simulation +./start.cheshire_soc.sh +``` + +The design needs to be recompiled only when hardware is changed. The simulation can be run repeatedly using `start.cheshire_soc.sh`, allowing binary (or image) and load method changes beforehand. diff --git a/hw/cheshire_pkg.sv b/hw/cheshire_pkg.sv index cd06a2e4..4e31078b 100644 --- a/hw/cheshire_pkg.sv +++ b/hw/cheshire_pkg.sv @@ -463,7 +463,7 @@ package cheshire_pkg; // Choose static colocation of IDs based on how heavily used and/or critical they are function automatic cva6_id_map_t gen_cva6_id_map(cheshire_cfg_t cfg); - localparam int unsigned DefaultMapEntry[2] = '{0, 0}; + int unsigned DefaultMapEntry[2] = '{0, 0}; case (cfg.AxiMstIdWidth) // Provide exclusive ID to I-cache to prevent fetch blocking 1: return '{'{Cva6IdBypMmu, 0}, '{Cva6IdBypLoad, 0}, '{Cva6IdBypAccel, 0}, '{Cva6IdBypStore, 0}, diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index cead6f27..57b143d4 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -228,7 +228,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( assign jtag.tdo = jtag_tdo; initial begin - @(negedge rst_n); + wait (!rst_n); jtag_dbg.reset_master(); end @@ -469,6 +469,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( initial begin static byte_bt uart_read_buf [$]; byte_bt bite; + string line; wait_for_reset(); forever begin uart_read_byte(bite); @@ -477,7 +478,8 @@ module vip_cheshire_soc import cheshire_pkg::*; #( uart_boot_ena = 0; end else if (bite == "\n") begin if (uart_read_buf.size() > 0) begin - $display("[UART] %s", {>>8{uart_read_buf}}); + line = {>>8{uart_read_buf}}; + $display("[UART] %s", line); uart_read_buf.delete(); end else begin $display("[UART]"); @@ -648,7 +650,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( .AXI_DATA_WIDTH ( DutCfg.AxiDataWidth ), .AXI_ID_WIDTH ( DutCfg.AxiMstIdWidth ), .AXI_USER_WIDTH ( DutCfg.AxiUserWidth ) - ) slink_mst_ext(), slink_mst_vip(), slink_mst(); + ) slink_mst_ext(), slink_mst_vip(), slink_mst(), slink_slv_mux[1:0](); AXI_BUS #( .AXI_ADDR_WIDTH ( DutCfg.AddrWidth ), @@ -666,6 +668,9 @@ module vip_cheshire_soc import cheshire_pkg::*; #( .clk_i ( clk ) ); + `AXI_ASSIGN (slink_slv_mux[0], slink_mst_ext) + `AXI_ASSIGN (slink_slv_mux[1], slink_mst_vip) + // Multiplex internal and external AXI requests axi_mux_intf #( .SLV_AXI_ID_WIDTH ( DutCfg.AxiMstIdWidth ), @@ -678,8 +683,8 @@ module vip_cheshire_soc import cheshire_pkg::*; #( .clk_i ( clk ), .rst_ni ( rst_n ), .test_i ( test_mode ), - .slv ( '{slink_mst_vip, slink_mst_ext} ), - .mst ( slink_mst_mux ) + .slv ( slink_slv_mux ), + .mst ( slink_mst_mux ) ); // Serialize away added AXI index bits @@ -785,7 +790,7 @@ module vip_cheshire_soc import cheshire_pkg::*; #( slink_axi_driver_t slink_axi_driver = new (slink_mst_vip_dv); initial begin - @(negedge rst_n); + wait (!rst_n); slink_axi_driver.reset_master(); end @@ -951,20 +956,20 @@ endmodule module vip_cheshire_soc_tristate import cheshire_pkg::*; ( // I2C pad IO - output logic i2c_sda_i, - input logic i2c_sda_o, - input logic i2c_sda_en, - output logic i2c_scl_i, - input logic i2c_scl_o, - input logic i2c_scl_en, + output wire i2c_sda_i, + input wire i2c_sda_o, + input wire i2c_sda_en, + output wire i2c_scl_i, + input wire i2c_scl_o, + input wire i2c_scl_en, // SPI host pad IO - input logic spih_sck_o, - input logic spih_sck_en, - input logic [SpihNumCs-1:0] spih_csb_o, - input logic [SpihNumCs-1:0] spih_csb_en, - output logic [ 3:0] spih_sd_i, - input logic [ 3:0] spih_sd_o, - input logic [ 3:0] spih_sd_en, + input wire spih_sck_o, + input wire spih_sck_en, + input wire [SpihNumCs-1:0] spih_csb_o, + input wire [SpihNumCs-1:0] spih_csb_en, + output wire [ 3:0] spih_sd_i, + input wire [ 3:0] spih_sd_o, + input wire [ 3:0] spih_sd_en, // I2C wires inout wire i2c_sda, inout wire i2c_scl, diff --git a/target/sim/vcs/start.cheshire_soc.sh b/target/sim/vcs/start.cheshire_soc.sh new file mode 100755 index 00000000..6352c520 --- /dev/null +++ b/target/sim/vcs/start.cheshire_soc.sh @@ -0,0 +1,57 @@ +# #!/usr/bin/env bash +# Copyright 2022 ETH Zurich and University of Bologna. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +# +# Cyril Koenig + +TESTBENCH=tb_cheshire_soc + +# Set full path to c++ compiler. +if [ -z "${CXX_PATH}" ]; then + if [ -z "${CXX}" ]; then + CXX="g++" + fi + CXX_PATH=`which ${CXX}` +fi + +# Set default VCS binary +[[ -z "${VERDI_VERSION}" ]] && VERDI_VERSION="" +[[ -z "${VCS_VERSION}" ]] && VCS_VERSION="" +[[ -z "${VCS_BIN}" ]] && VCS_BIN="${VCS_VERSION} vcs" + +flags="-full64 -kdb " +# Set default to fast simulation flags. +if [ -z "${VCSARGS}" ]; then + # Use -debug_access+all for waveform debugging + flags+="-O2 -debug_access=r -debug_region=1,${TESTBENCH} " +fi + +flags+="-cpp ${CXX_PATH} " +[[ -n "${SELCFG}" ]] && flags+="-pvalue+SelectedCfg=${SELCFG} " + +pargs="" +[[ -n "${BOOTMODE}" ]] && pargs+="+BOOTMODE=${BOOTMODE} " +[[ -n "${PRELMODE}" ]] && pargs+="+PRELMODE=${PRELMODE} " +[[ -n "${BINARY}" ]] && pargs+="+BINARY=${BINARY} " +[[ -n "${IMAGE}" ]] && pargs+="+IMAGE=${IMAGE} " + +# DRAMSys +if [ -n "${USE_DRAMSYS}" ]; then + flags+="-pvalue UseDramSys=${USE_DRAMSYS} " + if [[ "${USE_DRAMSYS}" == 1 ]]; then + DRAMSYS_ROOT="../dramsys" + DRAMSYS_LIB="${DRAMSYS_ROOT}/build/lib" + pargs+="+DRAMSYS_RES=${DRAMSYS_ROOT}/configs " + pargs+="-sv_lib ${DRAMSYS_LIB}/libDRAMSys_Simulator " + fi +fi + +COLOR_NC='\e[0m' +COLOR_BLUE='\e[0;34m' + +${VCS_BIN} ${flags} ../src/elfloader.cpp ${TESTBENCH} | tee elaborate.log + +# Start simulation +printf ${COLOR_BLUE}"${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs}"${COLOR_NC}"\n" +${VCS_VERSION} ${VERDI_VERSION} ./simv ${pargs} | tee simulate.log