diff --git a/.github/workflows/build-spike.yml b/.github/workflows/build-spike.yml index 442e825e..59fbfffb 100644 --- a/.github/workflows/build-spike.yml +++ b/.github/workflows/build-spike.yml @@ -36,7 +36,7 @@ jobs: key: ${{ env.cache_name }}_${{ env.cache_date }} restore-keys: ${{ env.cache_name }}_ - - name: Install prerequisities + - name: Install prerequisites if: ${{ steps.cache.outputs.cache-hit != 'true' }} run: | sudo apt -qqy update && sudo apt -qqy --no-install-recommends install \ diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index dd93d0cf..7858a706 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -22,12 +22,14 @@ jobs: name: Prepare test types run: | python3 -m pip install pyyaml - echo "tests=$(python3 .github/scripts/parse_testlist.py $RISCV_TARGET)" | tee -a $GITHUB_OUTPUT + python3 .github/scripts/parse_testlist.py $RISCV_TARGET > tests.list + echo "tests=$(cat tests.list)" | tee -a $GITHUB_OUTPUT - id: hash name: Prepare files' hash run: | - echo "files-hash=$(sha256sum **/*.sv **/*.py **/*.yml **/*.yaml | cut -d\ -f1 | sha256sum | cut -d\ -f1)" | tee -a $GITHUB_OUTPUT - + sha256sum **/*.sv **/*.py **/*.yaml > file.hash + echo "files-hash=$(cat file.hash | cut -d\ -f1 | sha256sum | cut -d\ -f1)" | tee -a $GITHUB_OUTPUT + generate-code: runs-on: [ self-hosted, Linux, X64, gcp-custom-runners ] @@ -39,7 +41,7 @@ jobs: test: ${{ fromJSON(needs.generate-config.outputs.test-types) }} version: [ uvm ] include: - - test: riscv_arithmetic_basic_test + - test: riscv_arithmetic_basic_test version: pyflow env: GHA_EXTERNAL_DISK: additional-tools @@ -89,9 +91,10 @@ jobs: --isa $RISCV_TARGET --mabi ilp32 --steps gen -v -o test 2>&1 | tee test/generate.log - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: + name: generate_code_${{ matrix.test }}_${{ matrix.version }} path: | test/asm_test/*.S @@ -116,7 +119,14 @@ jobs: - uses: actions/checkout@v4 - name: Install dependencies - run: sudo apt-get -qqy update && sudo apt-get -qqy install gcc-riscv64-unknown-elf device-tree-compiler + run: sudo apt-get -qqy update && sudo apt-get -qqy install device-tree-compiler + + - name: Install cross-compiler + shell: bash + run: | + echo "deb http://archive.ubuntu.com/ubuntu/ noble main universe" | sudo tee -a /etc/apt/sources.list > /dev/null + sudo apt -qqy update && sudo apt -qqy --no-install-recommends install gcc-riscv64-unknown-elf + riscv64-unknown-elf-gcc --version - name: Setup python # python dependencies cannot be properly downloaded with new versions of python @@ -174,9 +184,10 @@ jobs: --isa $RISCV_TARGET --mabi ilp32 --steps gcc_compile,iss_sim -v -o test 2>&1 | tee -a test/generate.log - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() with: + name: run_tests_log_${{ matrix.test }}_${{ matrix.version }} path: | - test/asm_test/*.log test/*.log + test/**/${{ matrix.test }}*.log diff --git a/run.py b/run.py index ac323177..4097c9f6 100644 --- a/run.py +++ b/run.py @@ -124,13 +124,14 @@ def get_generator_cmd(simulator, simulator_yaml, cov, exp, debug_cmd): sys.exit(RET_FAIL) -def parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd): +def parse_iss_yaml(iss, iss_yaml, isa, priv, setting_dir, debug_cmd): """Parse ISS YAML to get the simulation command Args: iss : target ISS used to look up in ISS YAML iss_yaml : ISS configuration file in YAML format isa : ISA variant passed to the ISS + priv: : privilege modes setting_dir : Generator setting directory debug_cmd : Produce the debug cmd log without running @@ -169,6 +170,7 @@ def parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd): cmd = re.sub("\", variant, cmd) else: cmd = re.sub("\", isa, cmd) + cmd = re.sub("\", priv, cmd) cmd = re.sub("\", scripts_dir, cmd) cmd = re.sub("\", yaml_dir, cmd) return cmd @@ -446,7 +448,12 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts, debug_cmd): if 'gen_opts' in test: # Disable compressed instruction if re.search('disable_compressed_instr', test['gen_opts']): - test_isa = re.sub("c", "", test_isa) + # Note that this substitution assumes the cannonical order + # of extensions, i.e. that extensions with preceding + # underscores will be provided after all letter extensions. + # This assumption should hold true, as this is a + # requirement enforced by e.g. gcc + test_isa = re.sub(r"(rv.+?)c", r"\1", test_isa) # If march/mabi is not defined in the test gcc_opts, use the default # setting from the command line. if not re.search('march', cmd): @@ -645,7 +652,7 @@ def run_c_from_dir(c_test_dir, iss_yaml, isa, mabi, gcc_opts, iss, def iss_sim(test_list, output_dir, iss_list, iss_yaml, iss_opts, - isa, setting_dir, timeout_s, debug_cmd): + isa, priv, setting_dir, timeout_s, debug_cmd): """Run ISS simulation with the generated test program Args: @@ -655,13 +662,15 @@ def iss_sim(test_list, output_dir, iss_list, iss_yaml, iss_opts, iss_yaml : ISS configuration file in YAML format iss_opts : ISS command line options isa : ISA variant passed to the ISS + priv : privilege modes setting_dir : Generator setting directory timeout_s : Timeout limit in seconds debug_cmd : Produce the debug cmd log without running """ for iss in iss_list.split(","): log_dir = ("{}/{}_sim".format(output_dir, iss)) - base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd) + base_cmd = parse_iss_yaml(iss, iss_yaml, isa, priv, setting_dir, debug_cmd) + base_cmd += iss_opts logging.info("{} sim log dir: {}".format(iss, log_dir)) run_cmd_output(["mkdir", "-p", log_dir]) for test in test_list: @@ -818,6 +827,8 @@ def parse_args(cwd): command is not specified") parser.add_argument("--isa", type=str, default="", help="RISC-V ISA subset") + parser.add_argument("--priv", type=str, default="m", + help="RISC-V privilege modes enabled in simulation [su]") parser.add_argument("-m", "--mabi", type=str, default="", help="mabi used for compilation", dest="mabi") parser.add_argument("--gen_timeout", type=int, default=360, @@ -940,40 +951,40 @@ def load_config(args, cwd): args.core_setting_dir = cwd + "/target/" + args.target if args.target == "rv32imc": args.mabi = "ilp32" - args.isa = "rv32imc" + args.isa = "rv32imc_zicsr_zifencei" elif args.target == "rv32imafdc": args.mabi = "ilp32" - args.isa = "rv32imafdc" + args.isa = "rv32imafdc_zicsr_zifencei" elif args.target == "rv32imc_sv32": args.mabi = "ilp32" - args.isa = "rv32imc" + args.isa = "rv32imc_zicsr_zifencei" elif args.target == "multi_harts": args.mabi = "ilp32" - args.isa = "rv32gc" + args.isa = "rv32gc_zicsr_zifencei" elif args.target == "rv32imcb": args.mabi = "ilp32" - args.isa = "rv32imcb" + args.isa = "rv32imcb_zicsr_zifencei" elif args.target == "rv32i": args.mabi = "ilp32" - args.isa = "rv32i" + args.isa = "rv32i_zicsr_zifencei" elif args.target == "rv64imc": args.mabi = "lp64" - args.isa = "rv64imc" + args.isa = "rv64imc_zicsr_zifencei" elif args.target == "rv64imcb": args.mabi = "lp64" - args.isa = "rv64imcb" + args.isa = "rv64imcb_zicsr_zifencei" elif args.target == "rv64gc": args.mabi = "lp64" - args.isa = "rv64gc" + args.isa = "rv64gc_zicsr_zifencei" elif args.target == "rv64gcv": args.mabi = "lp64" - args.isa = "rv64gcv" + args.isa = "rv64gcv_zicsr_zifencei" elif args.target == "ml": args.mabi = "lp64" - args.isa = "rv64imc" + args.isa = "rv64imc_zicsr_zifencei" elif args.target == "rv64imafdc": args.mabi = "lp64" - args.isa = "rv64imafdc" + args.isa = "rv64imafdc_zicsr_zifencei" else: sys.exit("Unsupported pre-defined target: {}".format(args.target)) else: @@ -1151,7 +1162,7 @@ def main(): if args.steps == "all" or re.match(".*iss_sim.*", args.steps): iss_sim(matched_list, output_dir, args.iss, args.iss_yaml, args.iss_opts, - args.isa, args.core_setting_dir, args.iss_timeout, + args.isa, args.priv, args.core_setting_dir, args.iss_timeout, args.debug) # Compare ISS simulation result diff --git a/scripts/instr_trace_compare.py b/scripts/instr_trace_compare.py index b0fd3e88..61566538 100644 --- a/scripts/instr_trace_compare.py +++ b/scripts/instr_trace_compare.py @@ -125,6 +125,8 @@ def compare_trace_csv(csv1, csv2, name1, name2, log, instr_trace_2[trace_2_index].gpr, gpr_val_2) if gpr_state_change_2 == 1: + fd.write("Mismatch[{}]:\n[{}] {} : {}\n".format( + mismatch_cnt, trace_1_index, name1,trace.get_trace_string())) fd.write("{} instructions left in trace {}\n".format( len(instr_trace_2) - trace_2_index, name2)) mismatch_cnt += len(instr_trace_2) - trace_2_index diff --git a/scripts/lib.py b/scripts/lib.py index ef9744da..a12cbc08 100644 --- a/scripts/lib.py +++ b/scripts/lib.py @@ -88,7 +88,7 @@ def get_env_var(var, debug_cmd=None): return val -def run_cmd(cmd, timeout_s=999, exit_on_error=1, check_return_code=True, +def run_cmd(cmd, timeout_s=3600, exit_on_error=1, check_return_code=True, debug_cmd=None): """Run a command and return output diff --git a/scripts/renode_wrapper.py b/scripts/renode_wrapper.py index 4f56d582..16c097f4 100644 --- a/scripts/renode_wrapper.py +++ b/scripts/renode_wrapper.py @@ -10,11 +10,12 @@ memory: Memory.MappedMemory @ sysbus 0x80000000 size: {mem} -cpu: CPU.RiscV32 @ sysbus +cpu: CPU.{cpu_type} @ sysbus cpuType: "{isa}" timeProvider: clint hartId: 0 - allowUnalignedAccesses: true + {priv_levels} + {additional_cpu_parameters} clint: IRQControllers.CoreLevelInterruptor @ sysbus 0x02000000 [0,1] -> cpu@[3,7] @@ -77,6 +78,26 @@ def main(): default="0x100000", help="Memory size", ) + parser.add_argument( + "--cpu-type", + type=str, + default="Riscv32", + help="Renode CPU type", + ) + parser.add_argument( + "--priv", + type=str, + default="", + help="Supported privilege levels", + ) + # Some CPUs might not expose these parameters as configurable + # allow the testing software to ignore/override them if needed + parser.add_argument( + "--additional-cpu-parameters", + type=str, + default="allowUnalignedAccesses: true", + help="Additional CPU parameters", + ) args = parser.parse_args() @@ -85,6 +106,16 @@ def main(): repl = os.path.join(tmpdir, "riscv.repl") resc = os.path.join(tmpdir, "riscv.resc") + priv_levels = "" + if args.priv: + priv_levels += "privilegeLevels: PrivilegeLevels." + if "m" in args.priv: + priv_levels += "Machine" + if "s" in args.priv: + priv_levels += "Supervisor" + if "u" in args.priv: + priv_levels += "User" + params = { "renode": args.renode, "isa": args.isa, @@ -93,6 +124,9 @@ def main(): "resc": resc, "log": args.log, "mem": args.mem_size, + "cpu_type": args.cpu_type, + "priv_levels": priv_levels, + "additional_cpu_parameters": args.additional_cpu_parameters, } # Render REPL template diff --git a/yaml/iss.yaml b/yaml/iss.yaml index ecf3224a..1167d7fd 100644 --- a/yaml/iss.yaml +++ b/yaml/iss.yaml @@ -15,7 +15,7 @@ - iss: spike path_var: SPIKE_PATH cmd: > - /spike --log-commits --isa= --misaligned -l + /spike --log-commits --isa= --priv= --misaligned -l - iss: ovpsim path_var: OVPSIM_PATH @@ -35,9 +35,9 @@ - iss: whisper path_var: WHISPER_ISS cmd: > - --log --xlen --isa --configfile /whisper.json --iccmrw + --log --xlen --isa --configfile /whisper.json --iccmrw - iss: renode path_var: RENODE_PATH cmd: > - python3 /renode_wrapper.py --renode "" --elf --isa --mem-size 0x80000000 + python3 /renode_wrapper.py --renode "" --elf --isa --priv= --mem-size 0x80000000