diff --git a/dv/uvm/core_ibex/sim.py b/dv/uvm/core_ibex/sim.py index 47435de3..6d361bf5 100755 --- a/dv/uvm/core_ibex/sim.py +++ b/dv/uvm/core_ibex/sim.py @@ -363,7 +363,7 @@ def compare_test_run(test, idx, iss, output_dir, report): ''' test_name = test['test'] elf = os.path.join(output_dir, - 'instr_gen/asm_tests/{}.{}.o'.format(test_name, idx)) + 'instr_gen/asm_test/{}.{}.o'.format(test_name, idx)) logging.info("Comparing %s/DUT sim result : %s" % (iss, elf)) @@ -586,7 +586,7 @@ def main(): # Create the output directory output_dir = ("%s/rtl_sim" % args.o) - bin_dir = ("%s/instr_gen/asm_tests" % args.o) + bin_dir = ("%s/instr_gen/asm_test" % args.o) subprocess.run(["mkdir", "-p", output_dir]) steps = { diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 9cc9c027..c51538ee 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: 3da32bbf6080d3bf252a7f71c5e3a32ea4924e49 + rev: 0b625258549e733082c12e5dc749f05aefb07d5a } } diff --git a/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml b/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml new file mode 100644 index 00000000..2efccf95 --- /dev/null +++ b/vendor/google_riscv-dv/.github/workflows/metrics-regress.yml @@ -0,0 +1,26 @@ +# This is a basic workflow to help you get started with Actions + +name: metrics-regress + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the master branch +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +# If you fork this repository, you must create a new Metrics project for your fork +# and set the environment variable $METRICS_PROJECT_ID accordingly +jobs: + metrics-regression: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: ./scripts/metrics-regress.py $METRICS_REGRESSION_NAME $METRICS_PROJECT_ID + env: + METRICS_CI_TOKEN: ${{ secrets.METRICS_CI_TOKEN }} + METRICS_REGRESSION_NAME: riscv-dv_regression + METRICS_PROJECT_ID: ${{ secrets.METRICS_PROJECT_ID }} + shell: bash + diff --git a/vendor/google_riscv-dv/.metrics.json b/vendor/google_riscv-dv/.metrics.json new file mode 100644 index 00000000..7b688cb5 --- /dev/null +++ b/vendor/google_riscv-dv/.metrics.json @@ -0,0 +1,52 @@ +{ + "variables": { + "DSIM" : "${DSIM_HOME}/bin/dsim", + "DSIM_LIB_PATH" : "${DSIM_HOME}/uvm-1.2/src/dpi", + "RISCV_GCC" : "${RISCV_TOOLCHAIN}/bin/riscv-none-embed-gcc", + "RISCV_OBJCOPY" : "${RISCV_TOOLCHAIN}/bin/riscv-none-embed-objcopy", + "OVPSIM_PATH" : "/customer-tools/riscv-ovpsim/bin/Linux64" + }, + "builds": { + "list": [{ + "name": "rv32imc", + "image": "ibex-dsim-toolchain:latest", + "memory" : "1", + "cmd": "python3 run.py --test riscv_arithmetic_basic_test --simulator dsim --output out --verbose --co", + "wavesCmd": "python3 run.py --test riscv_arithmetic_basic_test --simulator dsim --output out --verbose --co" + }] + }, + "regressions": [{ + "name": "riscv-dv_sanity", + "description": "Basic test generated by Google riscv-dv instruction generator", + "tests": { + "builds": ["rv32imc"], + "resultsDir" : "/mux-flow/build/repo/out", + "memory" : "1", + "list": [ + { + "name": "riscv_arithmetic_basic_test", + "build": "rv32imc", + "iterations": 2, + "cmd": "cd /mux-flow/results; python3 /run.py --test riscv_arithmetic_basic_test --seed --simulator dsim --iss ovpsim --so --out /out --verbose; /scripts/check-status $?; rm -fr /out/dsim", + "wavesCmd": "python3 /run.py --test riscv_arithmetic_basic_test --seed --simulator dsim --iss ovpsim --so --out /out --verbose; /scripts/check-status $?; rm -rf out/dsim", + "logFile": "simulation.log", + "metricsFile": "metrics.db", + "isPass": "Test passed", + "seed": "random" + } + ] + } + }, + { + "name" : "riscv-dv_regression", + "description": "Tests generated by Google riscv-dv instruction generator", + "tests": { + "resultsDir": "/mux-flow/build/repo/out", + "builds": ["rv32imc"], + "memory": "1", + "listCmd": "/scripts/genMetricsList.py", + "listFile": "/regression_list.json" + } + } + ] +} diff --git a/vendor/google_riscv-dv/docs/source/getting_started.rst b/vendor/google_riscv-dv/docs/source/getting_started.rst index fec09527..7cf2b199 100644 --- a/vendor/google_riscv-dv/docs/source/getting_started.rst +++ b/vendor/google_riscv-dv/docs/source/getting_started.rst @@ -187,16 +187,16 @@ corner cases:: # Run a single/multiple assembly/C test - run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2/asm_test2.S - run --c_tests c_test_path1/c_test1.c,c_test_path2/c_test2.c + run --asm_test asm_test_path1/asm_test1.S,asm_test_path2/asm_test2.S + run --c_test c_test_path1/c_test1.c,c_test_path2/c_test2.c - # Run regression with all assembly tests(*.S)/ C tests(*.c) under a given directory - run --asm_tests asm_test_path1,asm_test_path2 - run --c_tests c_test_path1,c_test_path2 + # Run regression with all assembly test(*.S)/ C test(*.c) under a given directory + run --asm_test asm_test_path1,asm_test_path2 + run --c_test c_test_path1,c_test_path2 - # Run mix between the assembly/C test and assembly/C tests under a directory - run --asm_tests asm_test_path1/asm_test1.S,asm_test_path2 - run --c_tests c_test_path1/c_test1.c,c_test_path2 + # Run mix between the assembly/C test and assembly/C test under a directory + run --asm_test asm_test_path1/asm_test1.S,asm_test_path2 + run --c_test c_test_path1/c_test1.c,c_test_path2 You could also use this approach to integrate the assembly/C tests from other sources to riscv-dv flow. diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_amo_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_amo_instr.py new file mode 100644 index 00000000..db4a0324 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_amo_instr.py @@ -0,0 +1,71 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. +""" + +import sys +import logging +import vsc +from pygen_src.isa.riscv_instr import riscv_instr +from pygen_src.riscv_instr_pkg import pkg_ins, riscv_instr_name_t, riscv_instr_group_t + + +@vsc.randobj +class riscv_amo_instr(riscv_instr): + def __init__(self): + super().__init__() + self.aq = vsc.rand_bit_t(1) + self.rl = vsc.rand_bit_t(1) + + @vsc.constraint + def aq_rl_c(self): + self.aq & self.rl == 0 + + def get_instr_name(self): + get_instr_name = self.instr_name.name + if self.group == riscv_instr_group_t.RV32A: + get_instr_name = "{}.w".format(get_instr_name[:-2]) + if self.aq: + get_instr_name = "{}.aq".format(get_instr_name) + else: + if self.rl: + get_instr_name = "{}.rl".format(get_instr_name) + else: + get_instr_name = get_instr_name + elif self.group == riscv_instr_group_t.RV64A: + get_instr_name = "{}.d".format(get_instr_name[:-2]) + if self.aq: + get_instr_name = "{}.aq".format(get_instr_name) + else: + if self.rl: + get_instr_name = "{}.rl".format(get_instr_name) + else: + logging.critical("Unexpected amo instr group: {} / {}" + .format(self.group.name, self.instr_name.name)) + sys.exit(1) + return get_instr_name + + # Convert the instruction to assembly code + def convert2asm(self, prefix = ""): + asm_str = pkg_ins.format_string(self.get_instr_name(), pkg_ins.MAX_INSTR_STR_LEN) + if self.group in [riscv_instr_group_t.RV32A, riscv_instr_group_t.RV64A]: + if self.instr_name in [riscv_instr_name_t.LR_W, riscv_instr_name_t.LR_D]: + asm_str = "{} {}, ({})".format(asm_str, self.rd.name, self.rs1.name) + else: + asm_str = "{} {}, {}, ({})".format(asm_str, self.rd.name, self.rs2.name, + self.rs1.name) + else: + logging.critical("Unexpected amo instr group: {} / {}" + .format(self.group.name, self.instr_name.name)) + sys.exit(1) + if self.comment != "": + asm_str = "{} #{}".format(asm_str, self.comment) + return asm_str.lower() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_b_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_b_instr.py new file mode 100644 index 00000000..3db7f451 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_b_instr.py @@ -0,0 +1,178 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. + +""" + +import math +import logging +import vsc +from importlib import import_module +from pygen_src.isa.riscv_instr import riscv_instr +from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_category_t, riscv_reg_t, + riscv_instr_name_t, riscv_instr_group_t, + riscv_instr_format_t) +from pygen_src.riscv_instr_gen_config import cfg +rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") + + +@vsc.randobj +class riscv_b_instr(riscv_instr): + def __init__(self): + super().__init__() + self.rs3 = vsc.rand_enum_t(riscv_reg_t) + self.has_rs3 = vsc.bit_t(1) + + def set_rand_mode(self): + super().set_rand_mode() + self.has_rs3 = 0 + if self.format == riscv_instr_format_t.R_FORMAT: + if self.instr_name in [riscv_instr_name_t.CLZW, + riscv_instr_name_t.CTZW, riscv_instr_name_t.PCNTW, + riscv_instr_name_t.SEXT_B, riscv_instr_name_t.SEXT_H, + riscv_instr_name_t.CLZ, riscv_instr_name_t.CTZ, + riscv_instr_name_t.PCNT, riscv_instr_name_t.BMATFLIP, + riscv_instr_name_t.CRC32_B, riscv_instr_name_t.CRC32_H, + riscv_instr_name_t.CRC32_W, riscv_instr_name_t.CRC32C_B, + riscv_instr_name_t.CRC32C_H, riscv_instr_name_t.CRC32C_W, + riscv_instr_name_t.CRC32_D, riscv_instr_name_t.CRC32C_D]: + self.has_rs2 = 0 + elif self.format == riscv_instr_format_t.R4_FORMAT: + self.has_imm = 0 + self.has_rs3 = 1 + elif self.format == riscv_instr_format_t.I_FORMAT: + self.has_rs2 = 0 + if self.instr_name in [riscv_instr_name_t.FSRI, riscv_instr_name_t.FSRIW]: + self.has_rs3 = 1 + + def pre_randomize(self): + super().pre_randomize() + with vsc.raw_mode(): + self.rs3.rand_mode = bool(self.has_rs3) + + def set_imm_len(self): + if self.format == riscv_instr_format_t.I_FORMAT: + if self.category in [riscv_instr_category_t.SHIFT, riscv_instr_category_t.LOGICAL]: + if (self.group.name == riscv_instr_group_t.RV64B and + self.instr_name != riscv_instr_name_t.SLLIU_W): + self.imm_len = math.ceil(math.log2(rcs.XLEN)) - 1 + else: + self.imm_len = math.ceil(math.log2(rcs.XLEN)) + # ARITHMETIC RV32B + if self.instr_name in [riscv_instr_name_t.SHFLI, riscv_instr_name_t.UNSHFLI]: + self.imm_len = math.ceil(math.log2(rcs.XLEN)) - 1 + # ARITHMETIC RV64B + if self.instr_name == riscv_instr_name_t.ADDIWU: + self.imm_len = 12 + self.imm_mask = self.imm_mask << self.imm_len + + # Convert the instruction to assembly code + def convert2asm(self, prefix = " "): + asm_str_final = "" + asm_str = "" + asm_str = pkg_ins.format_string(self.get_instr_name(), pkg_ins.MAX_INSTR_STR_LEN) + if self.format == riscv_instr_format_t.I_FORMAT: + if self.instr_name in [riscv_instr_name_t.FSRI, + riscv_instr_name_t.FSRIW]: # instr rd, rs1, rs3, imm + asm_str_final = "{}{}, {}, {}, {}".format(asm_str, self.rd.name, self.rs1.name, + self.rs3.name, self.get_imm()) + elif self.format == riscv_instr_format_t.R_FORMAT: # instr rd, rs1 + if not self.has_rs2: + asm_str_final = "{}{}, {}".format(asm_str, self.rd.name, self.rs1.name) + + elif self.format == riscv_instr_format_t.R4_FORMAT: # instr rd, rs1, rs2, rs3 + asm_str_final = "{}{}, {}, {}, {}".format(asm_str, self.rd.name, self.rs1.name, + self.rs2.name, self.rs3.name) + else: + logging.info("Unsupported format {}".format(self.format)) + if asm_str_final == "": + return super().convert2asm(prefix) + + if self.comment != "": + asm_str_final = asm_str_final + " #" + self.comment + return asm_str_final.lower() + + def get_opcode(self): + # TODO + pass + + def get_func3(self): + # TODO + pass + + def get_func5(self): + # TODO + pass + + def get_func2(self): + # TODO + pass + + # Convert the instruction to assembly code + def convert2bin(self, prefix): + pass + + def is_supported(self, cfg): + return (cfg.enable_b_extension and + ("ZBB" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["CLZ", "CTZ", "CLZW", "CTZW", "PCNT", "PCNTW", + "SLO", "SLOI", "SLOW", "SLOIW", + "SRO", "SROI", "SROW", "SROIW", + "MIN", "MINU", "MAX", "MAXU", + "ADDWU", "ADDIWU", "SUBWU", + "ADDU_W", "SUBU_W", + "SLLIU_W", + "ANDN", "ORN", + "XNOR", "PACK", "PACKW", "PACKU", "PACKUW", "PACKH", + "ROL", "ROLW", "ROR", "RORW", "RORI", "RORIW" + ]) or + ("ZBS" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["SBSET", "SBSETW", "SBSETI", "SBSETIW", + "SBCLR", "SBCLRW", "SBCLRI", "SBCLRIW", + "SBINV", "SBINVW", "SBINVI", "SBINVIW", + "SBEXT", "SBEXTW", "SBEXTI" + ]) or + ("ZBP" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["GREV", "GREVW", "GREVI", "GREVIW", + "GORC", "GORCW", "GORCI", "GORCIW", + "SHFL", "SHFLW", "UNSHFL", "UNSHFLW", "SHFLI", "UNSHFLI" + ]) or + ("ZBE" in cfg.enable_bitmanip_groups and self.instr_name in + ["BEXT", "BEXTW", + "BDEP", "BDEPW" + ]) or + ("ZBF" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["BFP", "BFPW" + ]) or + ("ZBC" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["CLMUL", "CLMULW", "CLMULH", "CLMULHW", "CLMULR", "CLMULRW" + ]) or + ("ZBR" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["CRC32_B", "CRC32_H", "CRC32_W", "CRC32_D", + "CRC32C_B", "CRC32C_H", "CRC32C_W", "CRC32C_D" + ]) or + ("ZBM" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["BMATOR", "BMATXOR", "BMATFLIP" + ]) or + ("ZBT" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["CMOV", "CMIX", + "FSL", "FSLW", "FSR", "FSRW", "FSRI", "FSRIW" + ]) or + # TODO, spec 0.92 doesn't categorize these 2 instr, put them in ZB_TMP #572 + ("ZB_TMP" in cfg.enable_bitmanip_groups and self.instr_name.name in + ["SEXT_B", "SEXT_H" + ]) + ) + + # Coverage related functions + def update_src_regs(self, operands): + # TODO + pass diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py index 0140cf62..ff1639ad 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py @@ -139,9 +139,10 @@ class riscv_instr: if instr_name in [riscv_instr_name_t.FENCE, riscv_instr_name_t.FENCE_I, riscv_instr_name_t.SFENCE_VMA]: continue - if (instr_inst.group.name in rcs.supported_isa and + if (instr_inst.group in rcs.supported_isa and not(cfg.disable_compressed_instr and - instr_inst.group.name in ["RV32C", "RV64C", "RV32DC", "RV32FC", "RV128C"]) and + instr_inst.group.name in ["RV32C", "RV64C", "RV32DC", + "RV32FC", "RV128C"]) and not(not(cfg.enable_floating_point) and instr_inst.group.name in ["RV32F", "RV64F", "RV32D", "RV64D"])): cls.instr_category[instr_inst.category.name].append(instr_name) @@ -169,8 +170,9 @@ class riscv_instr: cls.instr_category["LOGICAL"] + cls.instr_category["COMPARE"]) if cfg.no_ebreak == 0: cls.basic_instr.append("EBREAK") - for items in rcs.supported_isa: - if("RV32C" in rcs.supported_isa and not(cfg.disable_compressed_instr)): + for _ in rcs.supported_isa: + if(riscv_instr_group_t.RV32C in rcs.supported_isa and + not(cfg.disable_compressed_instr)): cls.basic_instr.append("C_EBREAK") break if cfg.no_dret == 0: diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32a_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32a_instr.py new file mode 100644 index 00000000..b4dba6a2 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32a_instr.py @@ -0,0 +1,40 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. +""" + +from pygen_src.riscv_defines import DEFINE_AMO_INSTR +from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t, + riscv_instr_category_t, riscv_instr_group_t) + + +DEFINE_AMO_INSTR(riscv_instr_name_t.LR_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.SC_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.STORE, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOSWAP_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOADD_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOAND_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOOR_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOXOR_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMIN_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMAX_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMINU_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) +DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMAXU_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.AMO, riscv_instr_group_t.RV32A, g=globals()) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32b_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32b_instr.py new file mode 100644 index 00000000..47f35d42 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/rv32b_instr.py @@ -0,0 +1,135 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. + +""" + +from pygen_src.riscv_defines import DEFINE_B_INSTR +from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t, + riscv_instr_category_t, riscv_instr_group_t, imm_t) + + +DEFINE_B_INSTR(riscv_instr_name_t.SEXT_B, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SEXT_H, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.ANDN, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.ORN, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.XNOR, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.GORC, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.GORCI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CMIX, riscv_instr_format_t.R4_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CMOV, riscv_instr_format_t.R4_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.PACK, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.PACKU, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.PACKH, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32B, g=globals()) + +# SHIFH instructions +DEFINE_B_INSTR(riscv_instr_name_t.SLO, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SRO, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.ROL, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.ROR, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBCLR, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBSET, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBINV, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBEXT, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.GREV, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.GREVI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SLOI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SROI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.RORI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBCLRI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBSETI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBINVI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SBEXTI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.FSL, riscv_instr_format_t.R4_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.FSR, riscv_instr_format_t.R4_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.FSRI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32B, imm_t.UIMM, g=globals()) + +# ARITMETIC instructions +DEFINE_B_INSTR(riscv_instr_name_t.CLZ, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CTZ, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.PCNT, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32_B, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32_H, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32C_B, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32C_H, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CRC32C_W, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CLMUL, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CLMULR, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.CLMULH, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.MIN, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.MAX, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.MINU, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.MAXU, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SHFL, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.UNSHFL, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.BDEP, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.BEXT, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.BFP, riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.SHFLI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, imm_t.UIMM, + g=globals()) +DEFINE_B_INSTR(riscv_instr_name_t.UNSHFLI, riscv_instr_format_t.I_FORMAT, + riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32B, imm_t.UIMM, + g=globals()) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py new file mode 100644 index 00000000..f3f1b5ec --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py @@ -0,0 +1,193 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. +""" + +import vsc +import random +from importlib import import_module +from pygen_src.riscv_directed_instr_lib import riscv_mem_access_stream +from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t, + riscv_instr_name_t, riscv_instr_category_t, + riscv_instr_group_t) +from pygen_src.riscv_instr_gen_config import cfg +from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr +from pygen_src.isa.riscv_instr import riscv_instr +rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") + + +# Base class for AMO instruction stream +@vsc.randobj +class riscv_amo_base_instr_stream(riscv_mem_access_stream): + def __init__(self): + super().__init__() + self.num_amo = vsc.rand_uint32_t() + self.num_mixed_instr = vsc.rand_uint32_t() + self.offset = vsc.randsz_list_t(vsc.int32_t()) + self.rs1_reg = vsc.randsz_list_t(vsc.enum_t(riscv_reg_t)) + self.num_of_rs1_reg = vsc.rand_int32_t() + self.data_page_id = vsc.uint32_t() + self.max_offset = vsc.uint32_t() + self.XLEN = vsc.uint32_t(rcs.XLEN) + # User can specify a small group of available registers to generate various hazard condition + self.avail_regs = vsc.randsz_list_t(vsc.enum_t(riscv_reg_t)) + + @vsc.constraint + def num_of_rs1_reg_c(self): + self.num_of_rs1_reg == 1 + + @vsc.constraint + def rs1_c(self): + # TODO constraint size with num_of_rs1_reg + vsc.solve_order(self.num_of_rs1_reg, self.rs1_reg) + self.rs1_reg.size == 1 # self.num_of_rs1_reg + self.offset.size == 1 # self.num_of_rs1_reg + with vsc.foreach(self.rs1_reg, idx = True) as i: + self.rs1_reg[i].not_inside(vsc.rangelist(cfg.reserved_regs, + self.reserved_rd, riscv_reg_t.ZERO)) + vsc.unique(self.rs1_reg) + + @vsc.constraint + def addr_range_c(self): + with vsc.foreach(self.offset, idx = True) as i: + self.offset[i] in vsc.rangelist(vsc.rng(0, self.max_offset - 1)) + + @vsc.constraint + def aligned_amo_c(self): + + with vsc.foreach(self.offset, idx = True) as i: + with vsc.if_then(self.XLEN == 32): + self.offset[i] % 4 == 0 + with vsc.else_then(): + self.offset[i] % 8 == 0 + + def pre_randomize(self): + self.data_page = cfg.amo_region + max_data_page_id = len(self.data_page) + self.data_page_id = random.randrange(0, max_data_page_id - 1) + self.max_offset = self.data_page[self.data_page_id]['size_in_bytes'] + + # Use "la" instruction to initialize the offset regiseter + def init_offset_reg(self): + for i in range(len(self.rs1_reg)): + la_instr = riscv_pseudo_instr() + la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA + la_instr.rd = self.rs1_reg[i] + la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id]['name'], + self.offset[i]) + self.instr_list.insert(0, la_instr) + + def post_randomize(self): + self.gen_amo_instr() + self.reserved_rd.append(self.rs1_reg) + self.add_mixed_instr(self.num_mixed_instr) + self.init_offset_reg() + super().post_randomize() + + # AMO instruction generation + def gen_amo_instr(self): + pass + + +# A pair of LR/SC instruction +@vsc.randobj +class riscv_lr_sc_instr_stream (riscv_amo_base_instr_stream): + def __init__(self): + super().__init__() + self.lr_instr = vsc.attr(riscv_instr()) + self.sc_instr = vsc.attr(riscv_instr()) + + @vsc.constraint + def legal_c(self): + self.num_amo == 1 + self.num_mixed_instr in vsc.rangelist(vsc.rng(0, 15)) + + def gen_amo_instr(self): + allowed_lr_instr = [] + allowed_sc_instr = [] + if riscv_instr_group_t.RV32A in rcs.supported_isa: + allowed_lr_instr.append(riscv_instr_name_t.LR_W) + allowed_sc_instr.append(riscv_instr_name_t.SC_W) + if riscv_instr_group_t.RV64A in rcs.supported_isa: + allowed_lr_instr.append(riscv_instr_name_t.LR_D) + allowed_sc_instr.append(riscv_instr_name_t.SC_D) + self.lr_instr = riscv_instr.get_rand_instr(include_instr = allowed_lr_instr) + self.sc_instr = riscv_instr.get_rand_instr(include_instr = allowed_sc_instr) + with self.lr_instr.randomize_with(): + # self.lr_instr.rs1 == self.rs1_reg[0] # TODO Getting error + with vsc.if_then(self.reserved_rd.size > 0): + self.lr_instr.rd.not_inside(vsc.rangelist(self.reserved_rd)) + with vsc.if_then(cfg.reserved_regs.size > 0): + self.lr_instr.rd.not_inside(vsc.rangelist(cfg.reserved_regs)) + # self.lr_instr.rd != self.rs1_reg[0] # TODO + with self.sc_instr.randomize_with(): + # self.sc_instr.rs1 == self.rs1_reg[0] # TODO + with vsc.if_then(self.reserved_rd.size > 0): + self.sc_instr.rd.not_inside(vsc.rangelist(self.reserved_rd)) + with vsc.if_then(cfg.reserved_regs.size > 0): + self.sc_instr.rd.not_inside(vsc.rangelist(cfg.reserved_regs)) + # self.sc_instr.rd != self.rs1_reg[0] # TODO + self.instr_list.extend((self.lr_instr, self.sc_instr)) + + ''' + section 8.3 Eventual Success of Store-Conditional Instructions + An LR/SC sequence begins with an LR instruction and ends with an SC instruction. + The dynamic code executed between the LR and SC instructions can only contain + instructions from the base “I” instruction set, excluding loads, stores, backward + jumps, taken backward branches, JALR, FENCE, and SYSTEM instructions. If the “C” + extension is supported, then compressed forms of the aforementioned “I” instructions + are also permitted. + ''' + def add_mixed_instr(self, instr_cnt): + self.setup_allowed_instr(no_branch = 1, no_load_store = 1) + for i in range(instr_cnt): + instr = riscv_instr() + instr = self.randomize_instr(instr, include_group = [riscv_instr_group_t.RV32I, + riscv_instr_group_t.RV32C]) + if instr.category not in [riscv_instr_category_t.SYSTEM, riscv_instr_category_t.SYNCH]: + self.insert_instr(instr) + + +@vsc.randobj +class riscv_amo_instr_stream (riscv_amo_base_instr_stream): + def __init__(self): + super().__init__() + self.amo_instr = [] + + @vsc.constraint + def reasonable_c(self): + vsc.solve_order(self.num_amo, self.num_mixed_instr) + self.num_amo in vsc.rangelist(vsc.rng(1, 10)) + self.num_mixed_instr in vsc.rangelist(vsc.rng(0, self.num_amo)) + + @vsc.constraint + def num_of_rs1_reg_c(self): + vsc.solve_order(self.num_amo, self.num_of_rs1_reg) + self.num_of_rs1_reg in vsc.rangelist(vsc.rng(1, self.num_amo)) + self.num_of_rs1_reg < 5 + + def gen_amo_instr(self): + for i in range(self.num_amo): + self.amo_instr.append(riscv_instr.get_rand_instr( + include_category=[riscv_instr_category_t.AMO])) + with self.amo_instr[i].randomize_with(): + with vsc.if_then(self.reserved_rd.size > 0): + self.amo_instr[i].rd.not_inside(vsc.rangelist(self.reserved_rd)) + with vsc.if_then(cfg.reserved_regs.size > 0): + self.amo_instr[i].rd.not_inside(vsc.rangelist(cfg.reserved_regs)) + self.amo_instr[i].rs1.inside(vsc.rangelist(self.rs1_reg)) + self.amo_instr[i].rd.inside(vsc.rangelist(self.rs1_reg)) + self.instr_list.insert(0, self.amo_instr[i]) + + +class riscv_vector_amo_instr_stream(): + # TODO + pass diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py index 5ef606f0..abf8cd7e 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py @@ -17,12 +17,12 @@ import random import copy import sys import vsc -from bitstring import BitArray from importlib import import_module from pygen_src.riscv_instr_sequence import riscv_instr_sequence from pygen_src.riscv_instr_pkg import (pkg_ins, privileged_reg_t, privileged_mode_t, mtvec_mode_t, - misa_ext_t, riscv_instr_group_t) + misa_ext_t, riscv_instr_group_t, + satp_mode_t) from pygen_src.riscv_instr_gen_config import cfg from pygen_src.riscv_data_page_gen import riscv_data_page_gen from pygen_src.riscv_privileged_common_seq import riscv_privileged_common_seq @@ -60,7 +60,7 @@ class riscv_asm_program_gen: # Commenting out for now # sub_program_name = [] self.instr_stream.append(f"h{int(hart)}_start:") - if(not(cfg.bare_program_mode)): + if not cfg.bare_program_mode: self.setup_misa() # Create all page tables self.create_page_table(hart) @@ -95,7 +95,8 @@ class riscv_asm_program_gen: self.main_program[hart].label_name = label_name self.generate_directed_instr_stream(hart=hart, label=self.main_program[hart].label_name, - original_instr_cnt=self.main_program[hart].instr_cnt, + original_instr_cnt= + self.main_program[hart].instr_cnt, min_insert_cnt=1, instr_stream=self.main_program[hart].directed_instr) self.main_program[hart].gen_instr(is_main_program=1, no_branch=cfg.no_branch_jump) @@ -124,16 +125,16 @@ class riscv_asm_program_gen: self.gen_data_page_begin(hart) if not cfg.no_data_page: self.gen_data_page(hart) - - if((hart == 0) and ("RV32A" in rcs.supported_isa)): + if(hart == 0 and riscv_instr_group_t.RV32A + in rcs.supported_isa): self.gen_data_page(hart, amo = 1) self.gen_stack_section(hart) - if(not cfg.bare_program_mode): + if not cfg.bare_program_mode: self.gen_kernel_sections(hart) def gen_kernel_sections(self, hart): - if(rcs.SATP_MODE != "BARE"): + if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") @@ -166,7 +167,7 @@ class riscv_asm_program_gen: self.instr_stream.append(".include \"user_define.h\"") self.instr_stream.append(".globl _start") self.instr_stream.append(".section .text") - if(cfg.disable_compressed_instr): + if cfg.disable_compressed_instr: self.instr_stream.append(".option norvc;") string.append(".include \"user_init.s\"") string.append("csrr x5, mhartid") @@ -180,13 +181,13 @@ class riscv_asm_program_gen: self.instr_stream.append("{}: j h{}_start".format(hart, hart)) def gen_program_end(self, hart): - if(hart == 0): + if hart == 0: self.gen_section("write_tohost", ["sw gp, tohost, t5"]) self.gen_section("_exit", ["j write_tohost"]) def gen_data_page_begin(self, hart): self.instr_stream.append(".section .data") - if (hart == 0): + if hart == 0: self.instr_stream.append(".align 6; .global tohost; tohost: .dword 0;") self.instr_stream.append(".align 6; .global fromhost; fromhost: .dword 0;") @@ -197,13 +198,13 @@ class riscv_asm_program_gen: def gen_stack_section(self, hart): hart_prefix_string = pkg_ins.hart_prefix(hart) - if(cfg.use_push_data_section): + if cfg.use_push_data_section: self.instr_stream.append( ".pushsection .{}user_stack,\"aw\",@progbits;".format(hart_prefix_string)) else: self.instr_stream.append( ".section .{}user_stack,\"aw\",@progbits;".format(hart_prefix_string)) - if(rcs.SATP_MODE != "BARE"): + if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") @@ -214,18 +215,18 @@ class riscv_asm_program_gen: self.instr_stream.append(".endr") self.instr_stream.append(pkg_ins.get_label("user_stack_end:", hart)) self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) - if (cfg.use_push_data_section): + if cfg.use_push_data_section: self.instr_stream.push_back(".popsection;") def gen_kernel_stack_section(self, hart): hart_prefix_string = pkg_ins.hart_prefix(hart) - if(cfg.use_push_data_section): + if cfg.use_push_data_section: self.instr_stream.append( ".pushsection .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string)) else: self.instr_stream.append( ".section .{}kernel_stack,\"aw\",@progbits;".format(hart_prefix_string)) - if(rcs.SATP_MODE != "BARE"): + if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") @@ -236,24 +237,24 @@ class riscv_asm_program_gen: self.instr_stream.append(".endr") self.instr_stream.append(pkg_ins.get_label("kernel_stack_end:", hart)) self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) - if (cfg.use_push_data_section): + if cfg.use_push_data_section: self.instr_stream.push_back(".popsection;") def gen_init_section(self, hart): string = pkg_ins.format_string("init:", pkg_ins.LABEL_STR_LEN) self.instr_stream.append(string) - if (cfg.enable_floating_point): + if cfg.enable_floating_point: self.init_floating_point_gpr() self.init_gpr() # Init stack pointer to point to the end of the user stack string = "{}la x{}, {}user_stack_end".format( pkg_ins.indent, cfg.sp.value, pkg_ins.hart_prefix(hart)) self.instr_stream.append(string) - if (cfg.enable_vector_extension): + if cfg.enable_vector_extension: self.init_vector_engine() self.core_is_initialized() self.gen_dummy_csr_write() - if (rcs.support_pmp): + if rcs.support_pmp: string = pkg_ins.indent + "j main" self.instr_stream.append(string) @@ -268,46 +269,47 @@ class riscv_asm_program_gen: misa[rcs.XLEN - 1:rcs.XLEN - 2] = 3 if cfg.check_misa_init_val: self.instr_stream.append("{}csrr x15, {}".format(pkg_ins.indent, - hex(privileged_reg_t.MISA))) - for i in range(len(rcs.supported_isa)): - if rcs.supported_isa[i] in [riscv_instr_group_t.RV32C.name, - riscv_instr_group_t.RV64C.name, - riscv_instr_group_t.RV128C.name]: + hex(privileged_reg_t.MISA))) + for group in rcs.supported_isa: + if group in [riscv_instr_group_t.RV32C, + riscv_instr_group_t.RV64C, + riscv_instr_group_t.RV128C]: misa[misa_ext_t.MISA_EXT_C] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32I.name, - riscv_instr_group_t.RV64I.name, - riscv_instr_group_t.RV128I.name]: + elif group in [riscv_instr_group_t.RV32I, + riscv_instr_group_t.RV64I, + riscv_instr_group_t.RV128I]: misa[misa_ext_t.MISA_EXT_I] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32M.name, - riscv_instr_group_t.RV64M.name]: + elif group in [riscv_instr_group_t.RV32M, + riscv_instr_group_t.RV64M]: misa[misa_ext_t.MISA_EXT_M] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32A.name, - riscv_instr_group_t.RV64A.name]: + elif group in [riscv_instr_group_t.RV32A, + riscv_instr_group_t.RV64A]: misa[misa_ext_t.MISA_EXT_A] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32B.name, - riscv_instr_group_t.RV64B.name]: + elif group in [riscv_instr_group_t.RV32B, + riscv_instr_group_t.RV64B]: misa[misa_ext_t.MISA_EXT_B] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32F.name, - riscv_instr_group_t.RV64F.name, - riscv_instr_group_t.RV32FC.name]: + elif group in [riscv_instr_group_t.RV32F, + riscv_instr_group_t.RV64F, + riscv_instr_group_t.RV32FC]: misa[misa_ext_t.MISA_EXT_F] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32D.name, - riscv_instr_group_t.RV64D.name, - riscv_instr_group_t.RV32DC.name]: + elif group in [riscv_instr_group_t.RV32D, + riscv_instr_group_t.RV64D, + riscv_instr_group_t.RV32DC]: misa[misa_ext_t.MISA_EXT_D] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RVV.name]: + elif group in [riscv_instr_group_t.RVV]: misa[misa_ext_t.MISA_EXT_V] = 1 - elif rcs.supported_isa[i] in [riscv_instr_group_t.RV32X.name, - riscv_instr_group_t.RV64X.name]: + elif group in [riscv_instr_group_t.RV32X, + riscv_instr_group_t.RV64X]: misa[misa_ext_t.MISA_EXT_X] = 1 else: - logging.error("{} is not yet supported".format(rcs.supported_isa[i])) + logging.critical("{} is not yet supported".format(group.name)) + sys.exit(1) if privileged_mode_t.SUPERVISOR_MODE.name in rcs.supported_privileged_mode: misa[misa_ext_t.MISA_EXT_S] = 1 self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value, - hex(misa.get_val()))) - self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, - hex(privileged_reg_t.MISA), cfg.gpr[0].value)) + hex(misa.get_val()))) + self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, hex(privileged_reg_t.MISA), + cfg.gpr[0].value)) def core_is_initialized(self): pass @@ -316,35 +318,28 @@ class riscv_asm_program_gen: pass def init_gpr(self): - reg_val = BitArray(uint = 0, length = pkg_ins.DATA_WIDTH) - # TODO Map the function with PyVSC std::randomize() + reg_val = vsc.rand_bit_t(pkg_ins.DATA_WIDTH) for i in range(rcs.NUM_GPR): if i in [cfg.sp.value, cfg.tp.value]: continue - if i == 0: - reg_val = BitArray(hex='0x0') - elif i == 1: - reg_val = BitArray(hex='0x80000000') - elif i == 2: - temp = random.randrange(0x1, 0xf) - reg_val = BitArray(hex(temp), length=32) - elif i == 3: - temp = random.randrange(0x10, 0xefffffff) - reg_val = BitArray(hex(temp), length=32) - else: - temp = random.randrange(0xf0000000, 0xffffffff) - reg_val = BitArray(hex(temp), length=32) - init_string = "{}li x{}, {}".format(pkg_ins.indent, i, reg_val) + try: + with vsc.randomize_with(reg_val): + vsc.dist(reg_val, [vsc.weight(0, 1), vsc.weight(0x80000000, 1), + vsc.weight(vsc.rng(0x1, 0xf), 1), + vsc.weight(vsc.rng(0x10, 0xefffffff), 1), + vsc.weight(vsc.rng(0xf0000000, 0xffffffff), 1)]) + except Exception: + logging.critical("Cannot Randomize reg_val") + sys.exit(1) + init_string = "{}li x{}, {}".format(pkg_ins.indent, i, hex(reg_val.get_val())) self.instr_stream.append(init_string) def init_floating_point_gpr(self): for i in range(rcs.NUM_FLOAT_GPR): - # TODO randselect - ''' - vsc.randselect([(1, lambda:self.init_floating_point_gpr_with_spf(i)), - ('RV64D' in rcs.supported_isa, lambda:self.init_floating_point_gpr_with_dpf(i))]) - ''' - self.init_floating_point_gpr_with_spf(i) + vsc.randselect([ + (1, lambda: self.init_floating_point_gpr_with_spf(i)), + (riscv_instr_group_t.RV64D in rcs.supported_isa, + lambda: self.init_floating_point_gpr_with_dpf(i))]) # Initialize rounding mode of FCSR fsrmi_instr = "{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm) self.instr_stream.append(fsrmi_instr) @@ -353,7 +348,7 @@ class riscv_asm_program_gen: imm = self.get_rand_spf_value() li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value, hex(imm)) fmv_instr = "{}fmv.w.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr, - cfg.gpr[0].value) + cfg.gpr[0].value) self.instr_stream.extend((li_instr, fmv_instr)) def init_floating_point_gpr_with_dpf(self, int_floating_gpr): @@ -391,7 +386,7 @@ class riscv_asm_program_gen: self.instr_stream.append(string) self.instr_stream.append(pkg_ins.indent + "li gp, 1") - if(cfg.bare_program_mode): + if cfg.bare_program_mode: self.instr_stream.append(pkg_ins.indent + "j write_tohost") else: self.instr_stream.append(pkg_ins.indent + "ecall") @@ -404,7 +399,7 @@ class riscv_asm_program_gen: # Generate sw/sd instructions for i in range(32): - if (rcs.XLEN == 64): + if rcs.XLEN == 64: string = "{}sd x{}, {}(x{})".format( pkg_ins.indent, i, i * (rcs.XLEN / 8), cfg.gpr[0].value) else: @@ -424,7 +419,7 @@ class riscv_asm_program_gen: self.trap_vector_init(hart) self.setup_pmp(hart) - if(cfg.virtual_addr_translation_on): + if cfg.virtual_addr_translation_on: self.page_table_list.process_page_table(instr) self.gen_section(pkg_ins.get_label("process_pt", hart), instr) self.setup_epc(hart) @@ -435,7 +430,7 @@ class riscv_asm_program_gen: for i in range(len(rcs.supported_privileged_mode)): instr = [] csr_handshake = [] - if(rcs.supported_privileged_mode[i] != cfg.init_privileged_mode.name): + if rcs.supported_privileged_mode[i] != cfg.init_privileged_mode: continue logging.info("Generating privileged mode routing for {}" .format(rcs.supported_privileged_mode[i])) @@ -451,14 +446,14 @@ class riscv_asm_program_gen: def setup_epc(self, hart): instr = [] instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart))) - if(cfg.virtual_addr_translation_on): + if cfg.virtual_addr_translation_on: # For supervisor and user mode, use virtual address instead of physical address. # Virtual address starts from address 0x0, here only the lower 12 bits are kept # as virtual address offset. instr.append("slli x{}, x{}, {}".format(cfg.gpr[0].value, - cfg.gpr[0].value, rcs.XLEN - 12) + - "srli x{}, x{}, {}".format(cfg.gpr[0].value, - cfg.gpr[0].value, rcs.XLEN - 12)) + cfg.gpr[0].value, rcs.XLEN - 12) + + "srli x{}, x{}, {}".format(cfg.gpr[0].value, + cfg.gpr[0].value, rcs.XLEN - 12)) mode_name = cfg.init_privileged_mode.name instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0].value)) if not rcs.support_pmp: @@ -472,7 +467,7 @@ class riscv_asm_program_gen: self.gen_delegation_instr(hart, "MEDELEG", "MIDELEG", cfg.m_mode_exception_delegation, cfg.m_mode_interrupt_delegation) - if(rcs.support_umode_trap): + if rcs.support_umode_trap: self.gen_delegation_instr(hart, "SEDELEG", "SIDELEG", cfg.s_mode_exception_delegation, cfg.s_mode_interrupt_delegation) @@ -483,28 +478,28 @@ class riscv_asm_program_gen: def trap_vector_init(self, hart): instr = [] - for items in rcs.supported_privileged_mode: - if(items == "MACHINE_MODE"): + for mode in rcs.supported_privileged_mode: + if mode == privileged_mode_t.MACHINE_MODE: trap_vec_reg = privileged_reg_t.MTVEC - elif(items == "SUPERVISOR_MODE"): + elif mode == privileged_mode_t.SUPERVISOR_MODE: trap_vec_reg = privileged_reg_t.STVEC - elif(items == "USER_MODE"): + elif mode == privileged_mode_t.USER_MODE: trap_vec_reg = privileged_reg_t.UTVEC else: - logging.critical( - "[riscv_asm_program_gen] Unsupported privileged_mode {}".format(items)) + logging.critical("Unsupported privileged_mode {}".format(mode.name)) + sys.exit(1) - if(items == "USER_MODE" and not (rcs.support_umode_trap)): + if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)): continue - if(items < cfg.init_privileged_mode.name): + if mode < cfg.init_privileged_mode: continue tvec_name = trap_vec_reg.name tvec_name = tvec_name.lower() instr.append("la x{}, {}{}_handler".format( cfg.gpr[0].value, pkg_ins.hart_prefix(hart), tvec_name)) - if(rcs.SATP_MODE != "BARE" and items != "MACHINE_MODE"): + if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE): instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0].value, cfg.gpr[0].value, rcs.XLEN - 20) + "srli x{}, x{}, {}".format(cfg.gpr[0].value, @@ -518,7 +513,7 @@ class riscv_asm_program_gen: self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr) def gen_all_trap_handler(self, hart): - if(not rcs.support_pmp): + if not rcs.support_pmp: self.gen_trap_handlers(hart) self.gen_ecall_handler(hart) self.gen_instr_fault_handler(hart) @@ -537,7 +532,7 @@ class riscv_asm_program_gen: is_interrupt = 1 tvec_name = "" instr = [] - if (cfg.mtvec_mode == mtvec_mode_t.VECTORED): + if cfg.mtvec_mode == mtvec_mode_t.VECTORED: self.gen_interrupt_vector_table(hart, mode, status, cause, ie, ip, scratch, instr) else: # Push user mode GPR to kernel stack before executing exception handling, @@ -552,14 +547,17 @@ class riscv_asm_program_gen: instr.append("csrr x{}, {} # {}".format( cfg.gpr[0].value, hex(status.value), status.name)) instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0].value, hex(cause.value), - cause.name) + + cause.name) + "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0].value, - cfg.gpr[0].value, rcs.XLEN - 1) + "{}bne x{}, x0, {}{}mode_instr_handler" - .format(pkg_ins.indent, cfg.gpr[0].value, pkg_ins.hart_prefix(hart), mode)) + cfg.gpr[0].value, rcs.XLEN - 1) + + "{}bne x{}, x0, {}{}mode_instr_handler".format(pkg_ins.indent, + cfg.gpr[0].value, + pkg_ins.hart_prefix(hart), + mode)) # The trap handler will occupy one 4KB page, it will be allocated one entry in # the page table with a specific privileged mode. - if (rcs.SATP_MODE != "BARE"): + if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align {}".format(cfg.tvec_alignment)) @@ -614,46 +612,47 @@ class riscv_asm_program_gen: def gen_interrupt_handler_section(self, mode, hart): interrupt_handler_instr = [] - ls_unit = "w" if (rcs.XLEN == 32) else "d" - # TODO - # if(mode.value < cfg.init_privileged_mode): - # return - if(mode is privileged_mode_t.USER_MODE.name and not (rcs.support_umode_trap)): + ls_unit = "w" if rcs.XLEN == 32 else "d" + if mode < cfg.init_privileged_mode: return - if(mode == privileged_mode_t.MACHINE_MODE.name): + if(mode is privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)): + return + if mode == privileged_mode_t.MACHINE_MODE: mode_prefix = "m" status = privileged_reg_t.MSTATUS ip = privileged_reg_t.MIP ie = privileged_reg_t.MIE scratch = privileged_reg_t.MSCRATCH - elif(mode is privileged_mode_t.SUPERVISOR_MODE.name): + elif mode is privileged_mode_t.SUPERVISOR_MODE: mode_prefix = "s" status = privileged_reg_t.SSTATUS ip = privileged_reg_t.SIP ie = privileged_reg_t.SIE scratch = privileged_reg_t.SSCRATCH - elif(mode == privileged_mode_t.USER_MODE.name): + elif mode == privileged_mode_t.USER_MODE: mode_prefix = "u" status = privileged_reg_t.USTATUS ip = privileged_reg_t.UIP ie = privileged_reg_t.UIE scratch = privileged_reg_t.USCRATCH else: - logging.critical("Unsupported mode: %0s" % (mode)) + logging.critical("Unsupported mode: {}".format(mode.name)) + sys.exit(1) - if(cfg.enable_nested_interrupt): + if cfg.enable_nested_interrupt: interrupt_handler_instr.append("csrr x%0d, 0x%0x" % (cfg.gpr[0].value, scratch.value)) interrupt_handler_instr.append("bgtz x%0d, 1f" % (cfg.gpr[0].value)) interrupt_handler_instr.append("csrwi 0x%0x, 0x1" % (scratch.value)) - if(status == privileged_reg_t.MSTATUS): + if status == privileged_reg_t.MSTATUS: interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 8)) - elif(status == privileged_reg_t.SSTATUS): + elif status == privileged_reg_t.SSTATUS: interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 2)) - elif(status == privileged_reg_t.USTATUS): + elif status == privileged_reg_t.USTATUS: interrupt_handler_instr.append("csrsi 0x%0x, 0x%0x" % (status.value, 1)) else: - logging.critical("Unsupported status %0s" % (status.value)) + logging.critical("Unsupported status {}".format(status.name)) + sys.exit(1) interrupt_handler_instr.append("1: csrwi 0x%0x,0" % (scratch.value)) @@ -674,7 +673,7 @@ class riscv_asm_program_gen: cfg.sp, cfg.tp, interrupt_handler_instr) interrupt_handler_instr.append("%0sret;" % (mode_prefix)) - if(rcs.SATP_MODE != "BARE"): + if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") @@ -686,7 +685,7 @@ class riscv_asm_program_gen: pass def gen_section(self, label, instr): - if(label != ""): + if label != "": string = pkg_ins.format_string("{}:".format(label), pkg_ins.LABEL_STR_LEN) self.instr_stream.append(string) for items in instr: @@ -737,12 +736,12 @@ class riscv_asm_program_gen: min_insert_cnt = 0, kernel_mode = 0, instr_stream = []): instr_insert_cnt = 0 idx = 0 - if(cfg.no_directed_instr): + if cfg.no_directed_instr: return for instr_stream_name in self.directed_instr_stream_ratio: instr_insert_cnt = int(original_instr_cnt * self.directed_instr_stream_ratio[instr_stream_name] // 1000) - if(instr_insert_cnt <= min_insert_cnt): + if instr_insert_cnt <= min_insert_cnt: instr_insert_cnt = min_insert_cnt logging.info("Insert directed instr stream %0s %0d/%0d times", instr_stream_name, instr_insert_cnt, original_instr_cnt) @@ -750,11 +749,11 @@ class riscv_asm_program_gen: name = "{}_{}".format(instr_stream_name, i) object_h = factory(instr_stream_name) object_h.name = name - if(object_h is None): + if not object_h: logging.critical("Cannot create instr stream %0s", name) sys.exit(1) new_instr_stream = copy.deepcopy(object_h) - if(new_instr_stream): + if new_instr_stream: new_instr_stream.hart = hart new_instr_stream.label = "{}_{}".format(label, idx) new_instr_stream.kernel_mode = kernel_mode diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py index af074679..cbdbb262 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py @@ -9,18 +9,19 @@ 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. - """ from pygen_src.riscv_instr_pkg import imm_t from pygen_src.isa.riscv_instr import riscv_instr from pygen_src.isa.riscv_compressed_instr import riscv_compressed_instr from pygen_src.isa.riscv_floating_point_instr import riscv_floating_point_instr +from pygen_src.isa.riscv_b_instr import riscv_b_instr +from pygen_src.isa.riscv_amo_instr import riscv_amo_instr # Regular integer instruction def DEFINE_INSTR(instr_n, instr_format, instr_category, - instr_group, imm_tp=imm_t.IMM, g=globals()): + instr_group, imm_tp = imm_t.IMM, g = globals()): class_name = "riscv_{}_instr".format(instr_n.name) def __init__(self): @@ -42,7 +43,7 @@ def DEFINE_INSTR(instr_n, instr_format, instr_category, # Compressed instruction def DEFINE_C_INSTR(instr_n, instr_format, instr_category, - instr_group, imm_tp=imm_t.IMM, g=globals()): + instr_group, imm_tp = imm_t.IMM, g = globals()): class_name = "riscv_{}_instr".format(instr_n.name) def __init__(self): @@ -63,7 +64,7 @@ def DEFINE_C_INSTR(instr_n, instr_format, instr_category, # Floating point instruction def DEFINE_FP_INSTR(instr_n, instr_format, instr_category, - instr_group, imm_tp=imm_t.IMM, g=globals()): + instr_group, imm_tp = imm_t.IMM, g = globals()): class_name = "riscv_{}_instr".format(instr_n.name) def __init__(self): @@ -84,7 +85,7 @@ def DEFINE_FP_INSTR(instr_n, instr_format, instr_category, # Floating point compressed instruction def DEFINE_FC_INSTR(instr_n, instr_format, instr_category, - instr_group, imm_tp=imm_t.IMM, g=globals()): + instr_group, imm_tp = imm_t.IMM, g = globals()): class_name = "riscv_{}_instr".format(instr_n.name) def __init__(self): @@ -103,6 +104,48 @@ def DEFINE_FC_INSTR(instr_n, instr_format, instr_category, g[class_name] = NewClass +# B-extension instruction +def DEFINE_B_INSTR(instr_n, instr_format, instr_category, + instr_group, imm_tp = imm_t.IMM, g = globals()): + class_name = "riscv_{}_instr".format(instr_n.name) + + def __init__(self): + riscv_b_instr.__init__(self) + self.instr_name = instr_n + self.format = instr_format + self.category = instr_category + self.group = instr_group + self.imm_type = imm_tp + self.set_imm_len() + self.set_rand_mode() + NewClass = type(class_name, (riscv_b_instr,), { + "__init__": __init__, + "valid": riscv_b_instr.register(instr_n, instr_group) + }) + g[class_name] = NewClass + + +# A-extension instruction +def DEFINE_AMO_INSTR(instr_n, instr_format, instr_category, + instr_group, imm_tp = imm_t.IMM, g = globals()): + class_name = "riscv_{}_instr".format(instr_n.name) + + def __init__(self): + riscv_amo_instr.__init__(self) + self.instr_name = instr_n + self.format = instr_format + self.category = instr_category + self.group = instr_group + self.imm_type = imm_tp + self.set_imm_len() + self.set_rand_mode() + NewClass = type(class_name, (riscv_amo_instr,), { + "__init__": __init__, + "valid": riscv_amo_instr.register(instr_n, instr_group) + }) + g[class_name] = NewClass + + ''' TODO @vsc.constraint diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py index 396a8cb4..6029d91b 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py @@ -45,6 +45,45 @@ class riscv_directed_instr_stream(riscv_rand_instr_stream): self.instr_list[0].has_label = 1 +@vsc.randobj +class riscv_mem_access_stream(riscv_directed_instr_stream): + def __init__(self): + super().__init__() + self.max_data_page_id = vsc.int32_t() + self.load_store_shared_memory = 0 + self.data_page = {} + + def pre_randomize(self): + if self.load_store_shared_memory: + self.data_page = cfg.amo_region + elif self.kernel_mode: + self.data_page = cfg.s_mem_region + else: + self.data_page = cfg.mem_region + self.max_data_page_id = len(self.data_page) + + def add_rs1_init_la_instr(self, gpr, idx, base = 0): + la_instr = riscv_pseudo_instr() + la_instr.pseudo_instr_name = riscv_pseudo_instr_name_t.LA + la_instr.rd = gpr + if self.load_store_shared_memory: + la_instr.imm_str = "{}+{}".format(cfg.amo_region[idx]['name'], base) + elif self.kernel_mode: + la_instr.imm_str = "{}{}+{}".format(pkg_ins.hart_prefix(self.hart), + cfg.s_mem_region[idx]['name'], base) + else: + la_instr.imm_str = "{}{}+{}".format(pkg_ins.hart_prefix(self.hart), + cfg.mem_region[idx]['name'], base) + self.instr_list.insert(0, la_instr) + + def add_mixed_instr(self, instr_cnt): + self.setup_allowed_instr(1, 1) + for i in range(instr_cnt): + instr = riscv_instr() + instr = self.randomize_instr(instr) + self.insert_instr(instr) + + @vsc.randobj class riscv_jal_instr(riscv_rand_instr_stream): def __init__(self): @@ -73,7 +112,7 @@ class riscv_jal_instr(riscv_rand_instr_stream): jal.append(riscv_instr_name_t.C_J) if rcs.XLEN == 32: jal.append(riscv_instr_name_t.C_JAL) - self.jump_start = riscv_instr.get_instr(riscv_instr_name_t.JAL.name) + self.jump_start = riscv_instr.get_instr(riscv_instr_name_t.JAL) with self.jump_start.randomize_with() as it: self.jump_start.rd == RA self.jump_start.imm_str = "{}f".format(order[0]) @@ -83,7 +122,7 @@ class riscv_jal_instr(riscv_rand_instr_stream): self.jump_end = self.randomize_instr(self.jump_end) self.jump_end.label = "{}".format(self.num_of_jump_instr) for i in range(self.num_of_jump_instr): - self.jump[i] = riscv_instr.get_rand_instr(include_instr = [jal[0].name]) + self.jump[i] = riscv_instr.get_rand_instr(include_instr = [jal[0]]) with self.jump[i].randomize_with() as it: if self.jump[i].has_rd: vsc.dist(self.jump[i].rd, [vsc.weight(riscv_reg_t.RA, 5), vsc.weight( @@ -119,23 +158,24 @@ class int_numeric_e(IntEnum): class riscv_int_numeric_corner_stream(riscv_directed_instr_stream): def __init__(self): super().__init__() - self.num_of_avail_regs = 10 + self.num_of_avail_regs = vsc.uint32_t(10) self.num_of_instr = vsc.rand_uint8_t() - self.init_val = vsc.rand_list_t(vsc.rand_bit_t(rcs.XLEN - 1), sz = 10) - self.init_val_type = vsc.rand_list_t(vsc.enum_t(int_numeric_e), sz =10) + self.init_val = vsc.randsz_list_t(vsc.rand_bit_t(rcs.XLEN - 1)) + self.init_val_type = vsc.randsz_list_t(vsc.enum_t(int_numeric_e)) self.init_instr = [] @vsc.constraint def init_val_c(self): - # TO DO - # solve init_val_type before init_val; - self.init_val_type.size == self.num_of_avail_regs - self.init_val.size == self.num_of_avail_regs + # TODO + vsc.solve_order(self.init_val_type, self.init_val) + self.init_val_type.size == 10 # self.num_of_avail_regs + self.init_val.size == 10 # self.num_of_avail_regs self.num_of_instr in vsc.rangelist(vsc.rng(15, 30)) @vsc.constraint def avail_regs_c(self): - self.avail_regs.size == self.num_of_avail_regs + # TODO + self.avail_regs.size == 10 # self.num_of_avail_regs vsc.unique(self.avail_regs) with vsc.foreach(self.avail_regs, idx = True) as i: self.avail_regs[i].not_inside(cfg.reserved_regs) @@ -177,8 +217,8 @@ class riscv_push_stack_instr(riscv_rand_instr_stream): self.num_of_redundant_instr = 0 self.push_stack_instr = [] self.saved_regs = [] - self.branch_instr = riscv_instr() - self.enable_branch = vsc.rand_bit_t() + self.branch_instr = vsc.attr(riscv_instr()) + self.enable_branch = vsc.rand_bit_t(1) self.push_start_label = '' def init(self): @@ -203,7 +243,7 @@ class riscv_push_stack_instr(riscv_rand_instr_stream): with self.push_stack_instr[0].randomize_with() as it: self.push_stack_instr[0].rd == cfg.sp self.push_stack_instr[0].rs1 == cfg.sp - self.push_stack_instr[0].imm == (~cfg.stack_len) + 1 + self.push_stack_instr[0].imm == (~cfg.stack_len + 1) self.push_stack_instr[0].imm_str = '-{}'.format(self.stack_len) for i in range(len(self.saved_regs)): @@ -222,14 +262,15 @@ class riscv_push_stack_instr(riscv_rand_instr_stream): self.push_stack_instr[i + 1].process_load_store = 0 if allow_branch: - # TODO `DV_CHECK_STD_RANDOMIZE_FATAL(enable_branch) + # TODO + # vsc.randomize(self.enable_branch) pass else: self.enable_branch = 0 if self.enable_branch: self.branch_instr = \ riscv_instr.get_rand_instr(include_category=[riscv_instr_name_t.BRANCH.name]) - # `DV_CHECK_STD_RANDOMIZE_FATAL(branch_instr) + self.branch_instr.randomize() self.branch_instr.imm_str = self.push_start_label self.branch_instr.brach_assigned = 1 self.push_stack_instr[0].label = self.push_start_label @@ -250,7 +291,7 @@ class riscv_pop_stack_instr(riscv_rand_instr_stream): self.stack_len = 0 self.num_of_reg_to_save = 0 self.num_of_redundant_instr = 0 - self.pop_stack_instr = [] + self.pop_stack_instr = vsc.list_t(vsc.attr(riscv_instr())) self.saved_regs = [] def init(self): @@ -286,12 +327,14 @@ class riscv_pop_stack_instr(riscv_rand_instr_stream): self.imm == 8 * (i + 1) self.pop_stack_instr[i].process_load_store = 0 # addi sp,sp,imm - ''' TODO `DV_CHECK_RANDOMIZE_WITH_FATAL(pop_stack_instr[num_of_reg_to_save], - rd == cfg.sp; rs1 == cfg.sp; imm == stack_len;) ''' + with self.pop_stack_instr[self.num_of_reg_to_save].randomize_with() as it: + self.rd == cfg.sp + self.rs1 == cfg.sp + self.imm == self.stack_len self.pop_stack_instr[self.num_of_reg_to_save] = riscv_instr.get_instr( riscv_instr_name_t.ADDI.name) self.pop_stack_instr[self.num_of_reg_to_save].imm_str = pkg_ins.format_string( - '{}', self.stack_len) + '{}'.format(self.stack_len)) self.mix_instr_stream(self.pop_stack_instr) for i in range(len(self.instr_list)): self.instr_list[i].atomic = 1 diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py index aaf95f13..a2731798 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py @@ -19,19 +19,21 @@ import vsc from importlib import import_module from pygen_src.riscv_instr_pkg import (mtvec_mode_t, f_rounding_mode_t, riscv_reg_t, privileged_mode_t, - riscv_instr_group_t, data_pattern_t) + riscv_instr_group_t, data_pattern_t, + riscv_instr_category_t, satp_mode_t) @vsc.randobj class riscv_instr_gen_config: def __init__(self): - # TODO Support for command line argument - self.main_program_instr_cnt = 100 # count of main_prog + self.main_program_instr_cnt = vsc.rand_int32_t() # count of main_prog self.sub_program_instr_cnt = [] # count of sub_prog self.debug_program_instr_cnt = 0 # count of debug_rom self.debug_sub_program_instr_cnt = [] # count of debug sub_progrms self.max_directed_instr_stream_seq = 20 self.data_page_pattern = vsc.rand_enum_t(data_pattern_t) + + self.init_delegation() self.argv = self.parse_args() self.args_dict = vars(self.argv) @@ -65,13 +67,7 @@ class riscv_instr_gen_config: self.fcsr_rm = vsc.rand_enum_t(f_rounding_mode_t) self.enable_sfence = vsc.rand_bit_t(1) - self.gpr = [] - - # Helper fields for gpr - self.gpr0 = vsc.rand_enum_t(riscv_reg_t) - self.gpr1 = vsc.rand_enum_t(riscv_reg_t) - self.gpr2 = vsc.rand_enum_t(riscv_reg_t) - self.gpr3 = vsc.rand_enum_t(riscv_reg_t) + self.gpr = vsc.rand_list_t(vsc.enum_t(riscv_reg_t), sz=4) self.scratch_reg = vsc.rand_enum_t(riscv_reg_t) self.pmp_reg = vsc.rand_enum_t(riscv_reg_t) @@ -179,9 +175,15 @@ class riscv_instr_gen_config: self.march_isa = self.argv.march_isa if len(self.march_isa) != 0: - rcs.supported_isa = self.march_isa - if "RV32C" not in rcs.supported_isa: + rcs.supported_isa.append(self.march_isa) + if riscv_instr_group_t.RV32C not in rcs.supported_isa: self.disable_compressed_instr = 1 + self.setup_instr_distribution() + self.get_invalid_priv_lvl_csr() + + @vsc.constraint + def default_c(self): + self.main_program_instr_cnt in vsc.rangelist(vsc.rng(10, self.instr_cnt)) @vsc.constraint def sp_tp_c(self): @@ -189,21 +191,16 @@ class riscv_instr_gen_config: self.sp == riscv_reg_t.SP self.sp != self.tp self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP, - riscv_reg_t.RA, riscv_reg_t.ZERO)) + riscv_reg_t.RA, riscv_reg_t.ZERO)) self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP, - riscv_reg_t.RA, riscv_reg_t.ZERO)) + riscv_reg_t.RA, riscv_reg_t.ZERO)) @vsc.constraint def gpr_c(self): - self.gpr0.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg, - riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP)) - self.gpr1.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg, - riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP)) - self.gpr2.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg, - riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP)) - self.gpr3.not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg, - riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP)) - vsc.unique(self.gpr0, self.gpr1, self.gpr2, self.gpr3) + with vsc.foreach(self.gpr, idx = True) as i: + self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg, + riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP)) + vsc.unique(self.gpr) @vsc.constraint def ra_c(self): @@ -214,21 +211,21 @@ class riscv_instr_gen_config: @vsc.constraint def reserve_scratch_reg_c(self): self.scratch_reg.not_inside(vsc.rangelist(riscv_reg_t.ZERO, self.sp, - self.tp, self.ra, riscv_reg_t.GP)) + self.tp, self.ra, riscv_reg_t.GP)) @vsc.constraint def mtvec_c(self): self.mtvec_mode.inside(vsc.rangelist(mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED)) - if(self.mtvec_mode == mtvec_mode_t.DIRECT): + with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT): vsc.soft(self.tvec_alignment == 2) - else: - vsc.soft(self.tvec_alignment == (rcs.XLEN * 4) / 8) + with vsc.else_then(): + vsc.soft(self.tvec_alignment == (rcs.XLEN * 4) // 8) @vsc.constraint def floating_point_c(self): - if self.enable_floating_point: + with vsc.if_then(self.enable_floating_point): self.mstatus_fs == 1 - else: + with vsc.else_then(): self.mstatus_fs == 0 @vsc.constraint @@ -237,7 +234,7 @@ class riscv_instr_gen_config: self.mstatus_mprv == 1 else: self.mstatus_mprv == 0 - if rcs.SATP_MODE == "BARE": + if rcs.SATP_MODE == satp_mode_t.BARE: self.mstatus_mxr == 0 self.mstatus_sum == 0 self.mstatus_tvm == 0 @@ -247,15 +244,18 @@ class riscv_instr_gen_config: support_128b = 0 # check the valid isa support - for x in rcs.supported_isa: - if x in ["RV64I", "RV64M", "RV64A", "RV64F", "RV64D", "RV64C", "RV64B"]: + for group in rcs.supported_isa: + if group in [riscv_instr_group_t.RV64I, riscv_instr_group_t.RV64M, + riscv_instr_group_t.RV64A, riscv_instr_group_t.RV64F, + riscv_instr_group_t.RV64D, riscv_instr_group_t.RV64C, + riscv_instr_group_t.RV64B]: support_64b = 1 logging.info("support_64b = {}".format(support_64b)) - logging.debug("Supported ISA = {}".format(x)) - elif x in ["RV128I", "RV128C"]: + logging.debug("Supported ISA = {}".format(group.name)) + elif group in [riscv_instr_group_t.RV128I, riscv_instr_group_t.RV128C]: support_128b = 1 logging.info("support_128b = {}".format(support_128b)) - logging.debug("Supported ISA = {}".format(x)) + logging.debug("Supported ISA = {}".format(group.name)) if support_128b and rcs.XLEN != 128: logging.critical("XLEN should be set to 128 based on \ @@ -275,43 +275,41 @@ class riscv_instr_gen_config: logging.info("XLEN Value = {}".format(rcs.XLEN)) sys.exit("XLEN is not equal to 32, set it Accordingly!") - if not(support_128b or support_64b) and not(rcs.SATP_MODE in ['SV32', "BARE"]): - logging.critical("SATP mode {} is not supported for RV32G ISA".format(rcs.SATP_MODE)) + if not(support_128b or support_64b) and \ + not(rcs.SATP_MODE in [satp_mode_t.SV32, satp_mode_t.BARE]): + logging.critical("SATP mode {} is not supported for RV32G ISA" + .format(rcs.SATP_MODE.name)) sys.exit("Supported SATP mode is not provided") - # TODO def setup_instr_distribution(self): + if self.dist_control_mode: + category_iter = iter([x for x in riscv_instr_category_t.__members__]) + category = riscv_instr_category_t(0) + while True: + opts = "dist_{}".format(category.name) + opts = opts.lower() + if self.args_dict[opts]: + self.category_dist[category] = self.args_dict[opts] + else: + self.category_dist[category] = 10 + logging.info("Set dist[{}] = {}".format(category, self.category_dist[category])) + category = next(category_iter) + if category != riscv_instr_category_t(0): + break + + # TODO + def init_delegation(self): pass - def init_delegation(self): - for i in self.mode_exp_lst: - if i == self.mode_exp_lst[0]: - continue - self.m_mode_exception_delegation[i] = 0 - self.s_mode_exception_delegation[i] = 0 - - for j in self.mode_intrpt_lst: - if j == self.mode_intrpt_lst[0]: - continue - self.m_mode_interrupt_delegation[j] = 0 - self.s_mode_interrupt_delegation[j] = 0 - def pre_randomize(self): - # Clearing the contents of self.gpr after each randomization. - # As it is being extended in post_randomize function. - self.gpr.clear() - for x in rcs.supported_privileged_mode: - if x == privileged_mode_t.SUPERVISOR_MODE: + for mode in rcs.supported_privileged_mode: + if mode == privileged_mode_t.SUPERVISOR_MODE: self.support_supervisor_mode = 1 def get_non_reserved_gpr(self): pass def post_randomize(self): - self.reserved_regs = [] - # Temporary fix for gpr_c constraint. - self.gpr.extend((self.gpr0, self.gpr1, self.gpr2, self.gpr3)) - self.reserved_regs.append(self.tp) self.reserved_regs.append(self.sp) self.reserved_regs.append(self.scratch_reg) @@ -328,36 +326,26 @@ class riscv_instr_gen_config: invalid_lvl = [] # Debug CSRs are inaccessible from all but Debug Mode # and we cannot boot into Debug Mode. - invalid_lvl.append('D') - - # TODO Need to change the logic once the constraints are up. - for mode in self.init_privileged_mode: - if mode == privileged_mode_t.MACHINE_MODE: - continue - if mode == privileged_mode_t.SUPERVISOR_MODE: - invalid_lvl.append('M') - logging.info("supr_mode---") - logging.debug(invalid_lvl) - elif mode == privileged_mode_t.USER_MODE: - invalid_lvl.append('S') - invalid_lvl.append('M') - logging.info("usr_mode---") - logging.debug(invalid_lvl) - else: - logging.critical("Unsupported initialization privilege mode") + invalid_lvl.append("D") + if self.init_privileged_mode == privileged_mode_t.MACHINE_MODE: + pass + elif self.init_privileged_mode == privileged_mode_t.SUPERVISOR_MODE: + invalid_lvl.append("M") + logging.info("supr_mode---") + logging.debug(invalid_lvl) + elif self.init_privileged_mode == privileged_mode_t.USER_MODE: + invalid_lvl.append("S") + invalid_lvl.append("M") + logging.info("usr_mode---") + logging.debug(invalid_lvl) + else: + logging.critical("Unsupported initialization privilege mode") + sys.exit(1) # implemented_csr from riscv_core_setting.py - for x in rcs.implemented_csr: - if x[0] in invalid_lvl: - self.invalid_priv_mode_csrs.append(x) - - # This function calls all the above defined function which should - # be called in init function as per SV logic.This function as to be - # called after every instance of the gen_config handle - def func_call_init(self): - self.init_delegation() - # self.setup_instr_distribution() # TODO - self.get_invalid_priv_lvl_csr() + for csr in rcs.implemented_csr: + if csr in invalid_lvl: + self.invalid_priv_mode_csrs.append(csr) def parse_args(self): parse = argparse.ArgumentParser() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py index 44b9aac3..1649355b 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py @@ -1455,7 +1455,7 @@ class riscv_instr_pkg: indent = LABEL_STR_LEN * " " def hart_prefix(self, hart=0): - if (rcs.NUM_HARTS <= 1): + if rcs.NUM_HARTS <= 1: return "" else: return f"h{hart}_" @@ -1481,11 +1481,11 @@ class riscv_instr_pkg: def push_gpr_to_kernel_stack(self, status, scratch, mprv, sp, tp, instr): store_instr = '' - if(rcs.XLEN == 32): + if rcs.XLEN == 32: store_instr = "sw" else: store_instr = "sd" - if (scratch.name in rcs.implemented_csr): + if scratch in rcs.implemented_csr: # Use kernal stack for handling exceptions. Save the user mode stack # pointer to the scratch register instr.append(pkg_ins.format_string( @@ -1495,10 +1495,10 @@ class riscv_instr_pkg: # If MPRV is set and MPP is S/U mode, it means the address translation and # memory protection for load/store instruction is the same as the mode indicated # by MPP. In this case, we need to use the virtual address to access the kernel stack. - if((status.name == "MSTATUS") and (rcs.SATP_MODE != "BARE")): + if(status.name == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE): # We temporarily use tp to check mstatus to avoid changing other GPR. The value # of sp has been saved to xScratch and can be restored later. - if(mprv): + if mprv: instr.append(pkg_ins.format_string( "csrr x{}, 0x{} // MSTATUS".format(tp, status.value))) instr.append(pkg_ins.format_string( @@ -1526,7 +1526,7 @@ class riscv_instr_pkg: def pop_gpr_from_kernel_stack(self, status, scratch, mprv, sp, tp, instr): load_instr = '' - if(rcs.XLEN == 32): + if rcs.XLEN == 32: load_instr = "lw" else: load_instr = "ld" @@ -1537,7 +1537,7 @@ class riscv_instr_pkg: # Restore kernel stack pointer instr.append(pkg_ins.format_string( "addi x{}, x{}, {}".format(sp, sp, int(31 * (rcs.XLEN / 8))))) - if (scratch in rcs.implemented_csr): + if scratch in rcs.implemented_csr: # Move SP to TP instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(tp, sp))) # Restore user mode stack pointer diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py index 8288ecbf..109d269d 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py @@ -21,7 +21,7 @@ from collections import defaultdict from pygen_src.riscv_instr_stream import riscv_rand_instr_stream from pygen_src.riscv_instr_gen_config import cfg from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_name_t, riscv_reg_t, - riscv_instr_category_t) + riscv_instr_category_t) from pygen_src.riscv_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") @@ -35,7 +35,7 @@ class riscv_instr_sequence: self.is_debug_program = 0 self.label_name = "" self.instr_string_list = [] # Save the instruction list - self.program_stack_len = 0 # Stack space allocated for this program + self.program_stack_len = vsc.int32_t(0) # Stack space allocated for this program self.directed_instr = [] # List of all directed instruction stream self.illegal_instr_pct = 0 # Percentage of illegal instructions self.hint_instr_pct = 0 # Percentage of hint instructions @@ -54,9 +54,21 @@ class riscv_instr_sequence: self.gen_stack_enter_instr() self.gen_stack_exit_instr() - # TODO def gen_stack_enter_instr(self): - pass + allow_branch = 0 if (self.illegal_instr_pct > 0 or self.hint_instr_pct > 0) else 1 + allow_branch &= not cfg.no_branch_jump + try: + with vsc.randomize_with(self.program_stack_len): + self.program_stack_len in vsc.rangelist(vsc.rng(cfg.min_stack_len_per_program, + cfg.max_stack_len_per_program)) + self.program_stack_len % (rcs.XLEN // 8) == 0 + except Exception: + logging.critical("Cannot randomize program_stack_len") + sys.exit(1) + self.instr_stack_enter.push_start_label = self.label_name + "_stack_p" + self.instr_stack_enter.gen_push_stack_instr(self.program_stack_len, + allow_branch = allow_branch) + self.instr_stream.instr_list.extend((self.instr_stack_enter.instr_list)) # Recover the saved GPR from the stack # Advance the stack pointer(SP) to release the allocated stack space. @@ -151,7 +163,6 @@ class riscv_instr_sequence: logging.info("Processing branch instruction[%0d]:%0s # %0d -> %0d", j, self.instr_stream.instr_list[j].convert2asm(), self.instr_stream.instr_list[j].idx, branch_target_label) - logging.info("Branch", branch_target_label) self.instr_stream.instr_list[j].imm_str = "{}f".format(branch_target_label) self.instr_stream.instr_list[j].branch_assigned = 1 branch_target[branch_target_label] = 1 @@ -166,7 +177,20 @@ class riscv_instr_sequence: logging.info("Finished post-processing instructions") def insert_jump_instr(self): - pass # TODO + # TODO riscv_jump_instr class implementation + """ + jump_instr = riscv_jump_instr() + jump_instr.target_program_label = target_label + if(not self.is_main_program): + jump_instr.stack_exit_instr = self.instr_stack_exit.pop_stack_instr + jump_instr.label = self.label_name + jump_instr.idx = idx + jump_instr.use_jalr = self.is_main_program + jump_instr.randomize() + self.instr_stream.insert_instr_stream(jump_instr.instr_list) + logging.info("{} -> {}...done".format(jump_instr.jump.instr_name.name, target_label)) + """ + pass def generate_instr_stream(self, no_label = 0): prefix = '' @@ -201,9 +225,14 @@ class riscv_instr_sequence: string = '' jump_instr = [riscv_instr_name_t.JALR] rand_lsb = random.randrange(0, 1) - ra = vsc.enum_t(riscv_reg_t) - # TODO - # `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(ra,!(ra inside {cfg.reserved_regs}) ra != ZERO) + ra = vsc.rand_enum_t(riscv_reg_t) + try: + with vsc.randomize_with(ra): + ra.not_inside(vsc.rangelist(cfg.reserved_regs)) + ra != riscv_reg_t.ZERO + except Exception: + logging.critical("Cannot randomize ra") + sys.exit(1) string = (prefix + pkg_ins.format_string("{}addi x{} x{} {}".format(ra.name, cfg.ra.name, rand_lsb))) self.instr_string_list.append(string) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py index fb211c09..c0bf8a86 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py @@ -34,7 +34,7 @@ class riscv_instr_stream: self.instr_cnt = 0 self.label = "" # User can specify a small group of available registers to generate various hazard condition - self.avail_regs = vsc.rand_list_t(vsc.enum_t(riscv_reg_t), sz = 10) + self.avail_regs = vsc.randsz_list_t(vsc.enum_t(riscv_reg_t)) # Some additional reserved registers that should not be used as rd register # by this instruction stream self.reserved_rd = vsc.list_t(vsc.enum_t(riscv_reg_t)) @@ -165,6 +165,10 @@ class riscv_rand_instr_stream(riscv_instr_stream): self.allowed_instr = [] self.category_dist = [] + @vsc.constraint + def avail_reg_c(self): + self.avail_regs.size == 10 + def create_instr_instance(self): for i in range(self.instr_cnt): self.instr_list.append(None) @@ -181,9 +185,19 @@ class riscv_rand_instr_stream(riscv_instr_stream): riscv_instr.instr_category[riscv_instr_category_t.STORE.name]) self.setup_instruction_dist(no_branch, no_load_store) - # TODO def randomize_avail_regs(self): - pass + if self.avail_regs.size > 0: + try: + with vsc.randomize_with(self.avail_regs): + vsc.unique(self.avail_regs) + self.avail_regs[0].inside(vsc.rangelist(vsc.rng(riscv_reg_t.S0, + riscv_reg_t.A5))) + with vsc.foreach(self.avail_regs, idx = True) as i: + self.avail_regs[i].not_inside(vsc.rangelist(cfg.reserved_regs, + self.reserved_rd)) + except Exception: + logging.critical("Cannot randomize avail_regs") + sys.exit(1) def setup_instruction_dist(self, no_branch = 0, no_load_store = 1): if cfg.dist_control_mode: @@ -204,7 +218,7 @@ class riscv_rand_instr_stream(riscv_instr_stream): if len(self.instr_list) == 0: break - def randomize_instr(self, instr, is_in_debug = 0): + def randomize_instr(self, instr, is_in_debug = 0, disable_dist = 0, include_group = []): exclude_instr = [] is_SP_in_reserved_rd = riscv_reg_t.SP in self.reserved_rd is_SP_in_reserved_regs = riscv_reg_t.SP in cfg.reserved_regs @@ -225,27 +239,28 @@ class riscv_rand_instr_stream(riscv_instr_stream): exclude_instr.extend([riscv_instr_name_t.EBREAK.name, riscv_instr_name_t.C_EBREAK.name]) instr = riscv_instr.get_rand_instr( - include_instr = self.allowed_instr, exclude_instr = exclude_instr) + include_instr = self.allowed_instr, exclude_instr = exclude_instr, + include_group = include_group) instr = self.randomize_gpr(instr) return instr def randomize_gpr(self, instr): with instr.randomize_with() as it: - if self.avail_regs.size > 0: - if instr.has_rs1: + with vsc.if_then(self.avail_regs.size > 0): + with vsc.if_then(instr.has_rs1): instr.rs1.inside(vsc.rangelist(self.avail_regs)) - if instr.has_rs2: + with vsc.if_then(instr.has_rs2): instr.rs2.inside(vsc.rangelist(self.avail_regs)) - if instr.has_rd: + with vsc.if_then(instr.has_rd): instr.rd.inside(vsc.rangelist(self.avail_regs)) with vsc.foreach(self.reserved_rd, idx = True) as i: - if instr.has_rd == 1: + with vsc.if_then(instr.has_rd): instr.rd != self.reserved_rd[i] - if instr.format == riscv_instr_format_t.CB_FORMAT: + with vsc.if_then(instr.format == riscv_instr_format_t.CB_FORMAT): instr.rs1 != self.reserved_rd[i] with vsc.foreach(cfg.reserved_regs, idx = True) as i: - with vsc.if_then(instr.has_rd == 1): + with vsc.if_then(instr.has_rd): instr.rd != cfg.reserved_regs[i] with vsc.if_then(instr.format == riscv_instr_format_t.CB_FORMAT): instr.rs1 != cfg.reserved_regs[i] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py index 8915deaa..ce612a18 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py @@ -15,7 +15,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import logging import vsc from importlib import import_module -from pygen_src.riscv_instr_pkg import pkg_ins, privileged_reg_t +from pygen_src.riscv_instr_pkg import (pkg_ins, privileged_reg_t, + privileged_mode_t, satp_mode_t) from pygen_src.riscv_instr_gen_config import cfg from pygen_src.riscv_privil_reg import riscv_privil_reg rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") @@ -27,18 +28,22 @@ class riscv_privileged_common_seq(): self.hart = 0 self.mstatus = vsc.attr(riscv_privil_reg) self.mie = vsc.attr(riscv_privil_reg) + self.sstatus = vsc.attr(riscv_privil_reg) + self.sie = vsc.attr(riscv_privil_reg) + self.ustatus = vsc.attr(riscv_privil_reg) + self.uie = vsc.attr(riscv_privil_reg) def enter_privileged_mode(self, mode, instrs): label = pkg_ins.format_string("{}init_{}:" - .format(pkg_ins.hart_prefix(self.hart), mode), + .format(pkg_ins.hart_prefix(self.hart), mode.name), pkg_ins.LABEL_STR_LEN) ret_instr = ["mret"] regs = vsc.list_t(vsc.attr(riscv_privil_reg())) label = label.lower() self.setup_mmode_reg(mode, regs) - if mode == "SUPERVISOR_MODE": + if mode == privileged_mode_t.SUPERVISOR_MODE: self.setup_smode_reg(mode, regs) - if mode == "USER_MODE": + if mode == privileged_mode_t.USER_MODE: self.setup_umode_reg(mode, regs) if cfg.virtual_addr_translation_on: self.setup_satp(instrs) @@ -49,10 +54,58 @@ class riscv_privileged_common_seq(): instrs[i] = pkg_ins.indent + instrs[i] instrs.insert(0, label) - # TODO def setup_mmode_reg(self, mode, regs): self.mstatus = riscv_privil_reg() self.mstatus.init_reg(privileged_reg_t.MSTATUS) + self.mstatus_set_field(mode, regs) + self.mie_set_field(mode, regs) + + def setup_smode_reg(self, mode, regs): + self.sstatus = riscv_privil_reg() + self.sstatus.init_reg(privileged_reg_t.SSTATUS) + self.sstatus.randomize() + self.sstatus_set_field(mode, regs) + self.sie_set_field(mode, regs) + + def setup_umode_reg(self, mode, regs): + # For implementations that do not provide any U-mode CSRs, return immediately + if not rcs.support_umode_trap: + return + self.ustatus = riscv_privil_reg() + self.ustatus.init_reg(privileged_reg_t.USTATUS) + self.ustatus.randomize() + self.ustatus_set_field(mode, regs) + self.uie_set_field(mode, regs) + + def gen_csr_instr(self, regs, instrs): + for i in range(len(regs)): + instrs.append("li x{}, {}".format(cfg.gpr[0].value, hex(regs[i].get_val()))) + instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name.value), + cfg.gpr[0], regs[i].reg_name.name)) + + def setup_satp(self, instrs): + satp_ppn_mask = vsc.bit_t(rcs.XLEN) + if rcs.SATP_MODE == satp_mode_t.BARE: + return + satp = riscv_privil_reg() + satp.init_reg(privileged_reg_t.SATP) + satp.set_field("MODE", rcs.SATP_MODE) + li0_instr = "li x{}, {}".format(cfg.gpr[0], hex(satp.get_val())) + csrw_instr = "csrw {}, x{} // satp".format(hex(privileged_reg_t.SATP), cfg.gpr[0]) + fld_name = satp.get_field_by_name("PPN") + satp_ppn_mask = hex((2**rcs.XLEN) - 1) >> (rcs.XLEN - fld_name.bit_width) + # Load the root page table physical address + la_instr = "la x{}, page_table_0".format(cfg.gpr[0]) + # Right shift to get PPN at 4k granularity + srli_instr = "srli x{}, x{}, 12".format(cfg.gpr[0], cfg.gpr[0]) + li1_instr = "li x{}, {}".format(cfg.gpr[1], hex(satp_ppn_mask)) + and_instr = "and x{}, x{}, x{}".format(cfg.gpr[0], cfg.gpr[0], cfg.gpr[1]) + # Set the PPN field for SATP + csrs_instr = "csrs {}, x{} // satp".format(hex(privileged_reg_t.SATP), cfg.gpr[0]) + instrs.extend((li0_instr, csrw_instr, la_instr, srli_instr, + li1_instr, and_instr, csrs_instr)) + + def mstatus_set_field(self, mode, regs): if cfg.randomize_csr: self.mstatus.set_val(cfg.mstatus) self.mstatus.set_field("MPRV", cfg.mstatus_mprv) @@ -62,11 +115,12 @@ class riscv_privileged_common_seq(): self.mstatus.set_field("TW", cfg.set_mstatus_tw) self.mstatus.set_field("FS", cfg.mstatus_fs) self.mstatus.set_field("VS", cfg.mstatus_vs) - if (not("SUPERVISOR_MODE" in rcs.supported_privileged_mode) and (rcs.XLEN != 32)): + if (not(privileged_mode_t.SUPERVISOR_MODE in rcs.supported_privileged_mode) and + (rcs.XLEN != 32)): self.mstatus.set_field("SXL", 0) elif rcs.XLEN == 64: self.mstatus.set_field("SXL", 2) - if (not("USER_MODE" in rcs.supported_privileged_mode) and (rcs.XLEN != 32)): + if (not(privileged_mode_t.USER_MODE in rcs.supported_privileged_mode) and (rcs.XLEN != 32)): self.mstatus.set_field("UXL", 0) elif rcs.XLEN == 64: self.mstatus.set_field("UXL", 2) @@ -74,7 +128,7 @@ class riscv_privileged_common_seq(): self.mstatus.set_field("SD", 0) self.mstatus.set_field("UIE", 0) # Set the previous privileged mode as the target mode - self.mstatus.set_field("MPP", 3) # TODO pass mode value as parameter + self.mstatus.set_field("MPP", mode.value) self.mstatus.set_field("SPP", 0) # Enable Interrupt self.mstatus.set_field("MPIE", cfg.enable_interrupt) @@ -85,8 +139,33 @@ class riscv_privileged_common_seq(): self.mstatus.set_field("UIE", rcs.support_umode_trap) logging.info("self.mstatus_val: {}".format(hex(self.mstatus.get_val()))) regs.append(self.mstatus) + + def sstatus_set_field(self, mode, regs): + if cfg.randomize_csr: + self.sstatus.set_val(cfg.sstatus) + self.sstatus.set_field("SPIE", cfg.enable_interrupt) + self.sstatus.set_field("SIE", cfg.enable_interrupt) + self.sstatus.set_field("UPIE", cfg.enable_interrupt) + self.sstatus.set_field("UIE", rcs.support_umode_trap) + if rcs.XLEN == 64: + self.sstatus.set_field("UXL", 2) + self.sstatus.set_field("FS", cfg.mstatus_fs) + self.sstatus.set_field("XS", 0) + self.sstatus.set_field("SD", 0) + self.sstatus.set_field("UIE", 0) + self.sstatus.set_field("SPP", 0) + regs.append(self.sstatus) + + def ustatus_set_field(self, mode, regs): + if cfg.randomize_csr: + self.ustatus.set_val(cfg.ustatus) + self.ustatus.set_field("UIE", cfg.enable_interrupt) + self.ustatus.set_field("UPIE", cfg.enable_interrupt) + regs.append(self.ustatus) + + def mie_set_field(self, mode, regs): # Enable external and timer interrupt - if "MIE" in rcs.implemented_csr: + if privileged_reg_t.MIE in rcs.implemented_csr: self.mie = riscv_privil_reg() self.mie.init_reg(privileged_reg_t.MIE) if cfg.randomize_csr: @@ -102,20 +181,28 @@ class riscv_privileged_common_seq(): self.mie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq) regs.append(self.mie) - # TODO - def setup_smode_reg(self, mode, regs): - pass + def sie_set_field(self, mode, regs): + # Enable external and timer interrupt + if privileged_reg_t.SIE in rcs.implemeted_csr: + self.sie = riscv_privil_reg() + self.sie.init_reg(privileged_reg_t.SIE) + if cfg.randomize_csr: + self.sie.set_val(cfg.sie) + self.sie.set_field("UEIE", cfg.enable_interrupt) + self.sie.set_field("SEIE", cfg.enable_interrupt) + self.sie.set_field("USIE", cfg.enable_interrupt) + self.sie.set_field("SSIE", cfg.enable_interrupt) + self.sie.set_field("STIE", cfg.enable_interrupt & cfg.enable_timer_irq) + self.sie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq) + regs.append(self.sie) - # TODO - def setup_umode_reg(self, mode, regs): - pass - - # TODO - def setup_satp(self, instrs): - pass - - def gen_csr_instr(self, regs, instrs): - for i in range(len(regs)): - instrs.append("li x{}, {}".format(cfg.gpr[0].value, hex(regs[i].get_val()))) - instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name.value), - cfg.gpr[0], regs[i].reg_name.name)) + def uie_set_field(self, mode, regs): + if privileged_reg_t.UIE in rcs.implemented_csr: + self.uie = riscv_privil_reg() + self.uie.init_reg(privileged_reg_t.UIE) + if cfg.randomize_csr: + self.uie.set_val(cfg.uie) + self.uie.set_field("UEIE", cfg.enable_interrupt) + self.uie.set_field("USIE", cfg.enable_interrupt) + self.uie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq) + regs.append(self.uie) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py index f542924b..395b2d02 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py @@ -107,13 +107,14 @@ class riscv_reg: logging.critical("Cannot match found field {}".format(fld_name)) sys.exit(1) - # TODO def rand_field(self, fld_name): - pass + fld_hd = self.get_field_by_name(fld_name) + fld_hd.randomize() - # TODO def set_field_rand_mode(self, fld_name, rand_on): - pass + fld_hd = self.get_field_by_name(fld_name) + with vsc.raw_mode(): + fld_hd.rand_mode = bool(rand_on) def reset(self): for i in range((len(self.fld) - 1), -1, -1): diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py index 87e21e29..e38109b9 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py @@ -18,14 +18,18 @@ from tabulate import tabulate from pygen_src.riscv_instr_gen_config import cfg from pygen_src.riscv_directed_instr_lib import (riscv_directed_instr_stream, riscv_int_numeric_corner_stream, - riscv_jal_instr) + riscv_jal_instr, riscv_mem_access_stream) +from pygen_src.riscv_amo_instr_lib import (riscv_lr_sc_instr_stream, riscv_amo_instr_stream) def factory(obj_of): objs = { "riscv_directed_instr_stream": riscv_directed_instr_stream, "riscv_int_numeric_corner_stream": riscv_int_numeric_corner_stream, - "riscv_jal_instr": riscv_jal_instr + "riscv_jal_instr": riscv_jal_instr, + "riscv_mem_access_stream": riscv_mem_access_stream, + "riscv_lr_sc_instr_stream": riscv_lr_sc_instr_stream, + "riscv_amo_instr_stream": riscv_amo_instr_stream } try: diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py index dc75afb2..6563ec6c 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py @@ -10,18 +10,24 @@ 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. """ +from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, + riscv_instr_group_t, privileged_mode_t) + XLEN = 32 -implemented_csr = ['MVENDORID', 'MARCHID', 'MIMPID', 'MHARTID', 'MSTATUS', 'MISA', 'MIE', - 'MTVEC', 'MCOUNTEREN', 'MSCRATCH', 'MEPC', 'MCAUSE', 'MTVAL', 'MIP'] +implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, privileged_reg_t.MIMPID, + privileged_reg_t.MHARTID, privileged_reg_t.MSTATUS, + privileged_reg_t.MISA, privileged_reg_t.MIE, + privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH, + privileged_reg_t.MEPC, privileged_reg_t.MCAUSE, + privileged_reg_t.MTVAL, privileged_reg_t.MIP] -SATP_MODE = 'BARE' +SATP_MODE = satp_mode_t.BARE -supported_isa = ['RV32I'] - -supported_privileged_mode = ['MACHINE_MODE'] +supported_isa = [riscv_instr_group_t.RV32I] +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] NUM_HARTS = 1 support_pmp = 0 diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imfdc/riscvOVPsim.ic b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscvOVPsim.ic similarity index 100% rename from vendor/google_riscv-dv/pygen/pygen_src/target/rv32imfdc/riscvOVPsim.ic rename to vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscvOVPsim.ic diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py new file mode 100644 index 00000000..ae183322 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py @@ -0,0 +1,80 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. +""" +from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t, + exception_cause_t, satp_mode_t, + riscv_instr_group_t, privileged_mode_t, + mtvec_mode_t) + + +XLEN = 32 + +implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, + privileged_reg_t.MIMPID, privileged_reg_t.MHARTID, + privileged_reg_t.MSTATUS, privileged_reg_t.MISA, privileged_reg_t.MIE, + privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH, + privileged_reg_t.MEPC, privileged_reg_t.MCAUSE, + privileged_reg_t.MTVAL, privileged_reg_t.MIP] + +SATP_MODE = satp_mode_t.BARE + +supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, + riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32F, + riscv_instr_group_t.RV32FC, riscv_instr_group_t.RV32D, + riscv_instr_group_t.RV32DC, riscv_instr_group_t.RV32A] + +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] + +max_interrupt_vector_num = 16 + +support_debug_mode = 0 + +NUM_HARTS = 1 + +support_pmp = 0 + +unsupported_instr = [] + +support_umode_trap = 0 + +support_sfence = 0 + +support_unaligned_load_store = 1 + +NUM_FLOAT_GPR = 32 + +NUM_GPR = 32 + +NUM_VEC_GPR = 32 + +VECTOR_EXTENSION_ENABLE = 0 + +VLEN = 512 + +ELEN = 32 + +SELEN = 0 + +MAX_MUL = 8 + +implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, + interrupt_cause_t.M_TIMER_INTR, + interrupt_cause_t.M_EXTERNAL_INTR] + +implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT, + exception_cause_t.ILLEGAL_INSTRUCTION, + exception_cause_t.BREAKPOINT, + exception_cause_t.LOAD_ADDRESS_MISALIGNED, + exception_cause_t.LOAD_ACCESS_FAULT, + exception_cause_t.ECALL_MMODE] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py index 38a608dd..7f464765 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py @@ -10,19 +10,29 @@ 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. """ +from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t, + exception_cause_t, satp_mode_t, + riscv_instr_group_t, privileged_mode_t, + mtvec_mode_t) + XLEN = 32 -implemented_csr = ['MVENDORID', 'MARCHID', 'MIMPID', 'MHARTID', 'MSTATUS', 'MISA', 'MIE', - 'MTVEC', 'MCOUNTEREN', 'MSCRATCH', 'MEPC', 'MCAUSE', 'MTVAL', 'MIP'] +implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, privileged_reg_t.MIMPID, + privileged_reg_t.MHARTID, privileged_reg_t.MSTATUS, + privileged_reg_t.MISA, privileged_reg_t.MIE, + privileged_reg_t.MTVEC, privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH, + privileged_reg_t.MEPC, privileged_reg_t.MCAUSE, + privileged_reg_t.MTVAL, privileged_reg_t.MIP] -SATP_MODE = 'BARE' +SATP_MODE = satp_mode_t.BARE -supported_isa = ['RV32I', 'RV32M', 'RV32C'] +supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, + riscv_instr_group_t.RV32C] -supported_privileged_mode = ['MACHINE_MODE'] +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] -supported_interrupt_mode = ['DIRECT', 'VECTORED'] +supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] max_interrupt_vector_num = 16 @@ -55,8 +65,12 @@ SELEN = 0 MAX_MUL = 8 -implemented_interrupt = ['M_SOFTWARE_INTR', 'M_TIMER_INTR', 'M_EXTERNAL_INTR'] +implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, + interrupt_cause_t.M_TIMER_INTR, + interrupt_cause_t.M_EXTERNAL_INTR] -implemented_exception = ['INSTRUCTION_ACCESS_FAULT', 'ILLEGAL_INSTRUCTION', - 'BREAKPOINT', 'LOAD_ADDRESS_MISALIGNED', 'LOAD_ACCESS_FAULT', - 'ECALL_MMODE'] +implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT, + exception_cause_t.ILLEGAL_INSTRUCTION, + exception_cause_t.BREAKPOINT, exception_cause_t.LOAD_ADDRESS_MISALIGNED, + exception_cause_t.LOAD_ACCESS_FAULT, + exception_cause_t.ECALL_MMODE] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscvOVPsim.ic b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscvOVPsim.ic new file mode 100644 index 00000000..cc637583 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscvOVPsim.ic @@ -0,0 +1,22 @@ +# riscOVPsim configuration file converted from YAML +--variant RV32I +--override riscvOVPsim/cpu/add_Extensions=MCB +--override riscvOVPsim/cpu/misa_MXL=1 +--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 +--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 +--override riscvOVPsim/cpu/unaligned=T +--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 +--override riscvOVPsim/cpu/user_version=2.3 +--override riscvOVPsim/cpu/priv_version=1.11 +--override riscvOVPsim/cpu/mvendorid=0 +--override riscvOVPsim/cpu/marchid=0 +--override riscvOVPsim/cpu/mimpid=0 +--override riscvOVPsim/cpu/mhartid=0 +--override riscvOVPsim/cpu/cycle_undefined=F +--override riscvOVPsim/cpu/instret_undefined=F +--override riscvOVPsim/cpu/time_undefined=T +--override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/simulateexceptions=T +--override riscvOVPsim/cpu/defaultsemihost=F +--override riscvOVPsim/cpu/wfi_is_nop=T +--exitonsymbol _exit diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py new file mode 100644 index 00000000..8a11e93c --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py @@ -0,0 +1,78 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. + +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. +""" +from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t, + exception_cause_t, satp_mode_t, + riscv_instr_group_t, privileged_mode_t, + mtvec_mode_t) + + +XLEN = 32 + +implemented_csr = [privileged_reg_t.MVENDORID, privileged_reg_t.MARCHID, + privileged_reg_t.MIMPID, privileged_reg_t.MHARTID, + privileged_reg_t.MSTATUS, privileged_reg_t.MISA, + privileged_reg_t.MIE, privileged_reg_t.MTVEC, + privileged_reg_t.MCOUNTEREN, privileged_reg_t.MSCRATCH, + privileged_reg_t.MEPC, privileged_reg_t.MCAUSE, + privileged_reg_t.MTVAL, privileged_reg_t.MIP] + +SATP_MODE = satp_mode_t.BARE + +supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, + riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32B] + +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] + +max_interrupt_vector_num = 16 + +support_debug_mode = 0 + +NUM_HARTS = 1 + +support_pmp = 0 + +unsupported_instr = [] + +support_umode_trap = 0 + +support_sfence = 0 + +support_unaligned_load_store = 1 + +# GPR Setting +NUM_FLOAT_GPR = 32 +NUM_GPR = 32 +NUM_VEC_GPR = 32 + +VECTOR_EXTENSION_ENABLE = 0 + +VLEN = 512 + +ELEN = 32 + +SELEN = 8 + +MAX_LMUL = 8 + +implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, + interrupt_cause_t.M_TIMER_INTR, + interrupt_cause_t.M_EXTERNAL_INTR] + +implemented_exception = [exception_cause_t.INSTRUCTION_ACCESS_FAULT, + exception_cause_t.ILLEGAL_INSTRUCTION, + exception_cause_t.BREAKPOINT, + exception_cause_t.LOAD_ADDRESS_MISALIGNED, + exception_cause_t.LOAD_ACCESS_FAULT, + exception_cause_t.ECALL_MMODE] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imfdc/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imfdc/riscv_core_setting.py deleted file mode 100644 index d1a19597..00000000 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imfdc/riscv_core_setting.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Copyright 2020 Google LLC -Copyright 2020 PerfectVIPs Inc. - -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. -""" - -XLEN = 32 - -implemented_csr = ['MVENDORID', 'MARCHID', 'MIMPID', 'MHARTID', 'MSTATUS', 'MISA', 'MIE', - 'MTVEC', 'MCOUNTEREN', 'MSCRATCH', 'MEPC', 'MCAUSE', 'MTVAL', 'MIP'] - -SATP_MODE = 'BARE' - -supported_isa = ['RV32I', 'RV32M', 'RV32C', 'RV32F', 'RV32FC', 'RV32D', 'RV32DC'] - -supported_privileged_mode = ['MACHINE_MODE'] - -supported_interrupt_mode = ['DIRECT', 'VECTORED'] - -max_interrupt_vector_num = 16 - -support_debug_mode = 0 - -NUM_HARTS = 1 - -support_pmp = 0 - -unsupported_instr = [] - -support_umode_trap = 0 - -support_sfence = 0 - -support_unaligned_load_store = 1 - -NUM_FLOAT_GPR = 32 - -NUM_GPR = 32 - -NUM_VEC_GPR = 32 - -VECTOR_EXTENSION_ENABLE = 0 - -VLEN = 512 - -ELEN = 32 - -SELEN = 0 - -MAX_MUL = 8 - -implemented_interrupt = ['M_SOFTWARE_INTR', 'M_TIMER_INTR', 'M_EXTERNAL_INTR'] - -implemented_exception = ['INSTRUCTION_ACCESS_FAULT', 'ILLEGAL_INSTRUCTION', - 'BREAKPOINT', 'LOAD_ADDRESS_MISALIGNED', - 'LOAD_ACCESS_FAULT', 'ECALL_MMODE'] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py index 94428a36..bc6a1077 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - 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 @@ -12,11 +11,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ import sys +import logging sys.path.append("pygen/") from pygen_src.riscv_instr_pkg import * from pygen_src.riscv_instr_gen_config import cfg # NOQA for isa in rcs.supported_isa: - import_module("pygen_src.isa." + isa.lower() + "_instr") + import_module("pygen_src.isa." + isa.name.lower() + "_instr") from pygen_src.isa.riscv_instr import riscv_instr # NOQA from pygen_src.riscv_asm_program_gen import riscv_asm_program_gen # NOQA from pygen_src.riscv_utils import gen_config_table @@ -26,22 +26,27 @@ class riscv_instr_base_test: def __init__(self): self.start_idx = cfg.argv.start_idx self.asm_file_name = cfg.argv.asm_file_name + self.asm = "" def run_phase(self): for _ in range(cfg.num_of_tests): - cfg.randomize() - gen_config_table() - asm = riscv_asm_program_gen() + self.randomize_cfg() + self.asm = riscv_asm_program_gen() riscv_instr.create_instr_list(cfg) if cfg.asm_test_suffix != "": self.asm_file_name = "{}.{}".format(self.asm_file_name, cfg.asm_test_suffix) test_name = "{}_{}.S".format(self.asm_file_name, _ + self.start_idx) - asm.get_directed_instr_stream() - asm.gen_program() - asm.gen_test_file(test_name) + self.asm.get_directed_instr_stream() + self.asm.gen_program() + self.asm.gen_test_file(test_name) + + def randomize_cfg(self): + cfg.randomize() + logging.info("riscv_instr_gen_config is randomized") + gen_config_table() -riscv_instr_base_test = riscv_instr_base_test() -riscv_instr_base_test.run_phase() +riscv_base_test_ins = riscv_instr_base_test() +riscv_base_test_ins.run_phase() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py new file mode 100644 index 00000000..6fc084b2 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py @@ -0,0 +1,42 @@ +""" +Copyright 2020 Google LLC +Copyright 2020 PerfectVIPs Inc. +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. +""" + +import sys +import logging +sys.path.append("pygen/") +from pygen_src.test.riscv_instr_base_test import riscv_instr_base_test +from pygen_src.riscv_instr_gen_config import cfg +from pygen_src.riscv_utils import gen_config_table + + +class riscv_rand_instr_test(riscv_instr_base_test): + def __init__(self): + super().__init__() + + def randomize_cfg(self): + cfg.instr_cnt = 10000 + cfg.num_of_sub_program = 5 + cfg.randomize() + logging.info("riscv_instr_gen_config is randomized") + gen_config_table() + + def apply_directed_instr(self): + self.asm.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 4) + self.asm.add_directed_instr_stream("riscv_loop_instr", 3) + self.asm.add_directed_instr_stream("riscv_jal_instr", 4) + self.asm.add_directed_instr_stream("riscv_hazard_instr_stream", 4) + self.asm.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 4) + self.asm.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 4) + self.asm.add_directed_instr_stream("riscv_mem_region_stress_test", 4) + + +riscv_rand_test_ins = riscv_rand_instr_test() diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index b26772d2..a3895263 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -228,7 +228,7 @@ def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd, (" --xlen {}".format( re.search(r"(?P[0-9]+)", isa).group("xlen"))) + \ (" --iterations {}".format(iterations)) + \ - (" --out {}/asm_tests".format(output_dir)) + \ + (" --out {}/asm_test".format(output_dir)) + \ (" --end_signature_addr {}".format(end_signature_addr)) if lsf_cmd: cmd_list.append(cmd) @@ -297,7 +297,7 @@ def do_simulate(sim_cmd, simulator, test_list, cwd, sim_opts, seed_gen, cmd = lsf_cmd + " " + sim_cmd.rstrip() + \ (" --num_of_tests={}".format(test_cnt)) + \ (" --start_idx={}".format(i * batch_size)) + \ - (" --asm_file_name={}/asm_tests/{}".format( + (" --asm_file_name={}/asm_test/{}".format( output_dir, test['test'])) + \ (" --log_file_name={}/sim_{}_{}{}.log ".format( output_dir, @@ -308,7 +308,7 @@ def do_simulate(sim_cmd, simulator, test_list, cwd, sim_opts, seed_gen, (" +UVM_TESTNAME={} ".format(test['gen_test'])) + \ (" +num_of_tests={} ".format(test_cnt)) + \ (" +start_idx={} ".format(i * batch_size)) + \ - (" +asm_file_name={}/asm_tests/{} ".format( + (" +asm_file_name={}/asm_test/{} ".format( output_dir, test['test'])) + \ (" -l {}/sim_{}_{}{}.log ".format( output_dir, test['test'], i, log_suffix)) @@ -403,7 +403,7 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts, debug_cmd): for i in range(0, test['iterations']): if 'no_gcc' in test and test['no_gcc'] == 1: continue - prefix = ("{}/asm_tests/{}_{}".format(output_dir, test['test'], i)) + prefix = ("{}/asm_test/{}_{}".format(output_dir, test['test'], i)) asm = prefix + ".S" elf = prefix + ".o" binary = prefix + ".bin" @@ -463,11 +463,11 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, report = ("{}/iss_regr.log".format(output_dir)).rstrip() asm = re.sub(r"^.*\/", "", asm_test) asm = re.sub(r"\.S$", "", asm) - prefix = ("{}/directed_asm_tests/{}".format(output_dir, asm)) + prefix = ("{}/directed_asm_test/{}".format(output_dir, asm)) elf = prefix + ".o" binary = prefix + ".bin" iss_list = iss_opts.split(",") - run_cmd("mkdir -p {}/directed_asm_tests".format(output_dir)) + run_cmd("mkdir -p {}/directed_asm_test".format(output_dir)) logging.info("Compiling assembly test : {}".format(asm_test)) # gcc compilation @@ -556,11 +556,11 @@ def run_c(c_test, iss_yaml, isa, mabi, gcc_opts, iss_opts, output_dir, report = ("{}/iss_regr.log".format(output_dir)).rstrip() c = re.sub(r"^.*\/", "", c_test) c = re.sub(r"\.c$", "", c) - prefix = ("{}/directed_c_tests/{}".format(output_dir, c)) + prefix = ("{}/directed_c_test/{}".format(output_dir, c)) elf = prefix + ".o" binary = prefix + ".bin" iss_list = iss_opts.split(",") - run_cmd("mkdir -p {}/directed_c_tests".format(output_dir)) + run_cmd("mkdir -p {}/directed_c_test".format(output_dir)) logging.info("Compiling c test : {}".format(c_test)) # gcc compilation @@ -647,7 +647,7 @@ def iss_sim(test_list, output_dir, iss_list, iss_yaml, iss_opts, continue else: for i in range(0, test['iterations']): - prefix = ("{}/asm_tests/{}_{}".format( + prefix = ("{}/asm_test/{}_{}".format( output_dir, test['test'], i)) elf = prefix + ".o" log = ("{}/{}.{}.log".format(log_dir, test['test'], i)) @@ -683,7 +683,7 @@ def iss_cmp(test_list, iss, output_dir, stop_on_first_error, exp, debug_cmd): run_cmd("rm -rf {}".format(report)) for test in test_list: for i in range(0, test['iterations']): - elf = ("{}/asm_tests/{}_{}.o".format(output_dir, test['test'], i)) + elf = ("{}/asm_test/{}_{}.o".format(output_dir, test['test'], i)) logging.info("Comparing ISS sim result {}/{} : {}".format( iss_list[0], iss_list[1], elf)) log_list = [] @@ -756,7 +756,7 @@ def parse_args(cwd): parser.add_argument("--target", type=str, default="rv32imc", help="Run the generator with pre-defined targets: \ - rv32imc, rv32i, rv32imfdc, rv64imc, rv64gc") + rv32imc, rv32i, rv32imafdc, rv64imc, rv64gc") parser.add_argument("-o", "--output", type=str, help="Output directory name", dest="o") parser.add_argument("-tl", "--testlist", type=str, default="", @@ -817,9 +817,9 @@ def parse_args(cwd): help="Path for the riscv_core_setting.sv") parser.add_argument("-ext", "--user_extension_dir", type=str, default="", help="Path for the user extension directory") - parser.add_argument("--asm_tests", type=str, default="", + parser.add_argument("--asm_test", type=str, default="", help="Directed assembly tests") - parser.add_argument("--c_tests", type=str, default="", + parser.add_argument("--c_test", type=str, default="", help="Directed c tests") parser.add_argument("--log_suffix", type=str, default="", help="Simulation log name suffix") @@ -918,9 +918,9 @@ def load_config(args, cwd): if args.target == "rv32imc": args.mabi = "ilp32" args.isa = "rv32imc" - elif args.target == "rv32imfdc": + elif args.target == "rv32imafdc": args.mabi = "ilp32" - args.isa = "rv32imfdc" + args.isa = "rv32imafdc" elif args.target == "rv32imc_sv32": args.mabi = "ilp32" args.isa = "rv32imc" @@ -979,9 +979,9 @@ def main(): if style_err: logging.info( "Found style error: \nERROR: " + style_err) - # Run any handcoded/directed assembly tests specified by args.asm_tests - if args.asm_tests != "": - asm_test = args.asm_tests.split(',') + # Run any handcoded/directed assembly tests specified by args.asm_test + if args.asm_test != "": + asm_test = args.asm_test.split(',') for path_asm_test in asm_test: full_path = os.path.expanduser(path_asm_test) # path_asm_test is a directory @@ -1001,9 +1001,9 @@ def main(): sys.exit(RET_FAIL) return - # Run any handcoded/directed c tests specified by args.c_tests - if args.c_tests != "": - c_test = args.c_tests.split(',') + # Run any handcoded/directed c tests specified by args.c_test + if args.c_test != "": + c_test = args.c_test.split(',') for path_c_test in c_test: full_path = os.path.expanduser(path_c_test) # path_c_test is a directory @@ -1023,7 +1023,7 @@ def main(): sys.exit(RET_FAIL) return - run_cmd_output(["mkdir", "-p", ("{}/asm_tests".format(output_dir))]) + run_cmd_output(["mkdir", "-p", ("{}/asm_test".format(output_dir))]) # Process regression test list matched_list = [] # Any tests in the YAML test list that specify a directed assembly test @@ -1035,21 +1035,21 @@ def main(): process_regression_list(args.testlist, args.test, args.iterations, matched_list, cwd) for t in list(matched_list): - # Check mutual exclusive between gen_test, asm_tests, and c_tests - if 'asm_tests' in t: - if 'gen_test' in t or 'c_tests' in t: + # Check mutual exclusive between gen_test, asm_test, and c_test + if 'asm_test' in t: + if 'gen_test' in t or 'c_test' in t: logging.error( - 'asm_tests must not be defined in the testlist ' - 'together with the gen_test or c_tests field') + 'asm_test must not be defined in the testlist ' + 'together with the gen_test or c_test field') sys.exit(RET_FATAL) asm_directed_list.append(t) matched_list.remove(t) - if 'c_tests' in t: - if 'gen_test' in t or 'asm_tests' in t: + if 'c_test' in t: + if 'gen_test' in t or 'asm_test' in t: logging.error( - 'c_tests must not be defined in the testlist ' - 'together with the gen_test or asm_tests field') + 'c_test must not be defined in the testlist ' + 'together with the gen_test or asm_test field') sys.exit(RET_FATAL) c_directed_list.append(t) matched_list.remove(t) @@ -1066,7 +1066,7 @@ def main(): gcc_opts = args.gcc_opts gcc_opts += test_entry.get('gcc_opts', '') path_asm_test = os.path.expanduser( - test_entry.get('asm_tests')) + test_entry.get('asm_test')) if path_asm_test: # path_asm_test is a directory if os.path.isdir(path_asm_test): @@ -1093,7 +1093,7 @@ def main(): for test_entry in c_directed_list: gcc_opts = args.gcc_opts gcc_opts += test_entry.get('gcc_opts', '') - path_c_test = os.path.expanduser(test_entry.get('c_tests')) + path_c_test = os.path.expanduser(test_entry.get('c_test')) if path_c_test: # path_c_test is a directory if os.path.isdir(path_c_test): diff --git a/vendor/google_riscv-dv/scripts/check-status b/vendor/google_riscv-dv/scripts/check-status new file mode 100755 index 00000000..ec76d7e3 --- /dev/null +++ b/vendor/google_riscv-dv/scripts/check-status @@ -0,0 +1,10 @@ +#!/bin/bash + +# Check the return code of run.py in order to give a pass/fail indication to Metrics +echo "run.py return code:" $1 + +if [ $1 == 0 ]; then + echo "Test passed"; +else + echo "Test failed"; +fi diff --git a/vendor/google_riscv-dv/scripts/genMetricsList.py b/vendor/google_riscv-dv/scripts/genMetricsList.py new file mode 100755 index 00000000..58f4794c --- /dev/null +++ b/vendor/google_riscv-dv/scripts/genMetricsList.py @@ -0,0 +1,65 @@ +#!/usr/bin/python3 + +## Summary: +## This Python script will create regression_list.json file which was referred by by .metrics.json +## Limitation: +## Only generate tests targeted for build "rv32imc" +## +## Note: Currently available testlists +## /yaml/base_testlist.yaml +## /yaml/cov_testlist.yaml +## /target/rv64gcv/testlist.yaml +## /target/rv64gc/testlist.yaml +## /target/rv32imcb/testlist.yaml +## /target/multi_harts/testlist.yaml +## /target/rv64imc/testlist.yaml +## /target/rv32imc/testlist.yaml +## /target/rv64imcb/testlist.yaml +## /target/ml/testlist.yaml +## /target/rv32i/testlist.yaml + +import json + +runCmdBase = "cd /mux-flow/results; python3 /run.py --test TESTNAME --simulator dsim --iss ovpsim --seed --so --out /out --verbose; /scripts/check-status $?; rm -fr /out/dsim" + +## Based on testlist located in /yaml/base_testlist.yaml +base_testList = ["riscv_arithmetic_basic_test", + "riscv_rand_instr_test", + "riscv_jump_stress_test", + "riscv_loop_test", + "riscv_rand_jump_test", + "riscv_mmu_stress_test", + "riscv_no_fence_test", + "riscv_illegal_instr_test", + "riscv_ebreak_test", + "riscv_ebreak_debug_mode_test", + "riscv_full_interrupt_test", + ## remove, will cause incomplete sim, need customized RTL + ##"riscv_csr_test", + "riscv_unaligned_load_store_test"] + +## Based on testlist located in /target/rv32imc/testlist.yaml +rv32imc_testList = [ + "riscv_non_compressed_instr_test", + "riscv_hint_instr_test", + "riscv_pmp_test" + ] + +metricsList = [] + +## Note: Build is targeting rv32imc only. +for testName in base_testList + rv32imc_testList: + test = {} + test["name"] = testName + test["build"] = "rv32imc" + test["cmd"] = runCmdBase.replace("TESTNAME", testName) + test["wavesCmd"] = test["cmd"] + test["logFile"] = "simulation.log" + test["isPass"] = "Test passed" + test["metricsFile"] = "metrics.db" + test["seed"] = "random" + + metricsList.append(test) + +with open("regression_list.json", "w") as f: + json.dump(metricsList, f) diff --git a/vendor/google_riscv-dv/scripts/gen_csr_test.py b/vendor/google_riscv-dv/scripts/gen_csr_test.py index 9a51a1a9..76c6bd19 100644 --- a/vendor/google_riscv-dv/scripts/gen_csr_test.py +++ b/vendor/google_riscv-dv/scripts/gen_csr_test.py @@ -214,6 +214,7 @@ def gen_setup(test_file): test_file.write(".section .text.init\n") test_file.write(".globl _start\n") test_file.write(".option norvc\n") + test_file.write(".org 0x80\n") test_file.write("_start:\n") diff --git a/vendor/google_riscv-dv/scripts/metrics-regress.py b/vendor/google_riscv-dv/scripts/metrics-regress.py new file mode 100755 index 00000000..303fa9e6 --- /dev/null +++ b/vendor/google_riscv-dv/scripts/metrics-regress.py @@ -0,0 +1,116 @@ +#!/usr/bin/python3 + +import json +import http.client +import argparse +import os +import time +import math + +def make_http_request( req_type, endpoint, params=None ): + headers = { 'Content-Type': 'application/json', + 'Private-Token': str(os.environ['METRICS_CI_TOKEN']) + } + + conn = http.client.HTTPSConnection(server) + conn.request(req_type, endpoint, params, headers) + response = conn.getresponse() + data = response.read() + regressionData = json.loads(data.decode('utf-8')) + conn.close() + + return response, regressionData + + +## Parse arguments to get regression name and project ID +parser = argparse.ArgumentParser(prog='metrics-regress', + description='Launch a regression on the Metrics platform and query results') +parser.add_argument('regressionName', help='The name of the regression to run') +parser.add_argument('projectId', help='The ID of the Metrics project') +args = parser.parse_args() + +## Server +server = 'chipsalliance.metrics.ca:443' + +## API Endpoints +postRegression = '/api/v1/projects/'+args.projectId+'/regressionRuns' +getRegressionRunInfo = '/api/v1/projects/'+args.projectId+'/regressionRuns/' + +## Start regression +reqParams = {} +reqParams['regressionName'] = args.regressionName +reqParams['branch'] = str(os.environ['GITHUB_REF']) +params = json.dumps(reqParams) + +response, regressionData = make_http_request('POST', postRegression, params) + +## Check response +if response.status is not 201: + print('Error, regression was not started. Response: ' + str(response.status) + ':' \ + + str(response.reason)) + print('Exit with code 1') + exit(1) +else: + print('Regression started. Id = ' + regressionData['id']) + +## Start polling regression status +regressionRunId = regressionData['id'] + +while True: + time.sleep(10) + response, regressionData = make_http_request('GET', getRegressionRunInfo+regressionRunId) + if response.status is 200: + if 'complete' in regressionData['status']: + print('Regression complete') + break + if 'buildFailed' in regressionData['status']: + print('A build has failed. No tests will be run') + print('Debug at: https://chipsalliance.metrics.ca/' + args.projectId + \ + '/results/regressionRuns/' + regressionRunId) + exit(1) + +## Print test status +print('\n') +print('Regression results') +print('==================') +print('Total number of tests: ' + str(regressionData['testRuns']['total'])) +print('Passed tests: ' + str(regressionData['testRuns']['passed'])) +print('Failed tests: ' + str(regressionData['testRuns']['failed'])) +print('Incomplete tests: ' + str(regressionData['testRuns']['incomplete'])) +print('\n') + +## Poll for coverage data +#while True: +# time.sleep(10) +# response, regressionData = make_http_request('GET', getRegressionRunInfo+regressionRunId) +# if response.status is 200: +# if regressionData['functionalCoverage'] is not None : +# break + +## Print functional coverage +#print('Coverage results') +#print('================') +#print('Functional: ' + str(math.trunc(regressionData['functionalCoverage']*100)/100)) +#if regressionData['assertionCoverage'] is not None: +# print('Assertion: ' + str(math.trunc(regressionData['assertionCoverage']*100) /100)) +#if regressionData['lineCoverage'] is not None: +# print('Code (block): ' + str(math.trunc(regressionData['lineCoverage']*100) /100)) +#print('\n') + +print('Full results at: https://chipsalliance.metrics.ca/' + args.projectId + \ + '/results/regressionRuns/' + regressionRunId) + +## Set the exit code to be used by github action +if regressionData['testRuns']['failed'] > 0 or \ + regressionData['testRuns']['incomplete'] > 0: + print('One or more tests has failed/is incomplete. Exit with code 1.') + exit(1) +else: + print('All tests have passed. Exit with code 0.') + exit(0) + + + + + + diff --git a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py index f643a8d7..2272cc31 100644 --- a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py @@ -27,10 +27,10 @@ sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) from riscv_trace_csv import * from lib import * -RD_RE = re.compile(r"(?P\d) 0x(?P[a-f0-9]+?) " \ +RD_RE = re.compile(r"(core\s+\d+:\s+)?(?P\d) 0x(?P[a-f0-9]+?) " \ "\((?P.*?)\) (?P[xf]\s*\d*?) 0x(?P[a-f0-9]+)") CORE_RE = re.compile( - r"core.*0x(?P[a-f0-9]+?) \(0x(?P.*?)\) (?P.*?)$") + r"core\s+\d+:\s+0x(?P[a-f0-9]+?) \(0x(?P.*?)\) (?P.*?)$") ADDR_RE = re.compile( r"(?P[a-z0-9]+?),(?P[\-0-9]+?)\((?P[a-z0-9]+)\)") ILLE_RE = re.compile(r"trap_illegal_instruction") diff --git a/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv index bcfcf985..66390900 100644 --- a/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv @@ -20,6 +20,8 @@ class riscv_floating_point_instr extends riscv_instr; rand riscv_fpr_t fs2; rand riscv_fpr_t fs3; rand riscv_fpr_t fd; + rand f_rounding_mode_t rm; + rand bit use_rounding_mode_from_instr; bit has_fs1 = 1'b1; bit has_fs2 = 1'b1; bit has_fs3 = 1'b0; @@ -67,6 +69,13 @@ class riscv_floating_point_instr extends riscv_instr; default: `uvm_fatal(`gfn, $sformatf("Unsupported floating point format: %0s", format.name())) endcase + if ((category == ARITHMETIC) && use_rounding_mode_from_instr && + !(instr_name inside {FMIN_S, FMAX_S, FMIN_D, FMAX_D, FMV_W_X, FMV_X_W, + FMV_D_X, FMV_X_D, FCLASS_S, FCLASS_D, + FCVT_D_S, FCVT_D_W, FCVT_D_WU, + FSGNJ_S, FSGNJN_S, FSGNJX_S, FSGNJ_D, FSGNJN_D, FSGNJX_D})) begin + asm_str = {asm_str, ", ", rm.name()}; + end if(comment != "") asm_str = {asm_str, " #",comment}; return asm_str.tolower(); @@ -174,9 +183,9 @@ class riscv_floating_point_instr extends riscv_instr; // FSW rs2 is fp fs2 = get_fpr(operands[0]); fs2_value = get_gpr_state(operands[0]); - rs1 = get_gpr(operands[2]); - rs1_value = get_gpr_state(operands[2]); - get_val(operands[1], imm); + rs1 = get_gpr(operands[1]); + rs1_value = get_gpr_state(operands[1]); + get_val(operands[2], imm); end R_FORMAT: begin // convert Pseudoinstructions for ovpsim diff --git a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv index 4dc3f2c1..91693c06 100644 --- a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv +++ b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv @@ -196,7 +196,7 @@ class riscv_privileged_common_seq extends uvm_sequence; satp.init_reg(SATP); satp.set_field("MODE", SATP_MODE); instrs.push_back($sformatf("li x%0d, 0x%0x", cfg.gpr[0], satp.get_val())); - instrs.push_back($sformatf("csrw 0x%0x, x%0d // satp", SATP, cfg.gpr[0])); + instrs.push_back($sformatf("csrw 0x%0x, x%0d # satp", SATP, cfg.gpr[0])); satp_ppn_mask = '1 >> (XLEN - satp.get_field_by_name("PPN").bit_width); // Load the root page table physical address instrs.push_back($sformatf("la x%0d, page_table_0", cfg.gpr[0])); @@ -205,7 +205,7 @@ class riscv_privileged_common_seq extends uvm_sequence; instrs.push_back($sformatf("li x%0d, 0x%0x", cfg.gpr[1], satp_ppn_mask)); instrs.push_back($sformatf("and x%0d, x%0d, x%0d", cfg.gpr[0], cfg.gpr[0], cfg.gpr[1])); // Set the PPN field for SATP - instrs.push_back($sformatf("csrs 0x%0x, x%0d // satp", SATP, cfg.gpr[0])); + instrs.push_back($sformatf("csrs 0x%0x, x%0d # satp", SATP, cfg.gpr[0])); endfunction endclass diff --git a/vendor/google_riscv-dv/target/rv32imfdc/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv32imafdc/riscv_core_setting.sv similarity index 96% rename from vendor/google_riscv-dv/target/rv32imfdc/riscv_core_setting.sv rename to vendor/google_riscv-dv/target/rv32imafdc/riscv_core_setting.sv index 2ac5da2c..41e1d7ce 100644 --- a/vendor/google_riscv-dv/target/rv32imfdc/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/target/rv32imafdc/riscv_core_setting.sv @@ -30,7 +30,7 @@ privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE}; riscv_instr_name_t unsupported_instr[]; // ISA supported by the processor -riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32F, RV32FC}; +riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32F, RV32FC, RV32D, RV32DC, RV32A}; // Interrupt mode support mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED}; @@ -96,8 +96,8 @@ parameter int NUM_HARTS = 1; privileged_reg_t implemented_csr[] = { `else const privileged_reg_t implemented_csr[] = { -`endif // - Machine mode mode CSR +`endif + // Machine mode mode CSR MVENDORID, // Vendor ID MARCHID, // Architecture ID MIMPID, // Implementation ID @@ -119,8 +119,8 @@ bit[11:0] custom_csr[] = { }; // ---------------------------------------------------------------------------- -// Supported interrupt / exception setting, used for functional coverage // ----------------------------------------------------------------------------- +// Supported interrupt / exception setting, used for functional coverage +// ---------------------------------------------------------------------------- `ifdef DSIM interrupt_cause_t implemented_interrupt[] = { diff --git a/vendor/google_riscv-dv/target/rv32imfdc/testlist.yaml b/vendor/google_riscv-dv/target/rv32imafdc/testlist.yaml similarity index 61% rename from vendor/google_riscv-dv/target/rv32imfdc/testlist.yaml rename to vendor/google_riscv-dv/target/rv32imafdc/testlist.yaml index bc562f64..c625c0bb 100644 --- a/vendor/google_riscv-dv/target/rv32imfdc/testlist.yaml +++ b/vendor/google_riscv-dv/target/rv32imafdc/testlist.yaml @@ -33,6 +33,74 @@ - import: /target/rv32imc/testlist.yaml +- test: riscv_machine_mode_rand_test + description: > + Machine mode random instruction test + iterations: 2 + gen_test: riscv_instr_base_test + gen_opts: > + +instr_cnt=10000 + +num_of_sub_program=5 + +boot_mode=m + rtl_test: core_base_test + +- test: riscv_privileged_mode_rand_test + description: > + Random previliged mode test + iterations: 2 + gen_test: riscv_instr_base_test + gen_opts: > + +instr_cnt=10000 + +num_of_sub_program=5 + rtl_test: core_base_test + +# TODO: Only enable booting into U-mode for now, as OVPsim doesn't support some debug CSRs +- test: riscv_invalid_csr_test + description: > + Boot core into random privileged mode and generate csr accesses to invalid CSRs (at a higher priv mode) + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=6000 + +num_of_sub_program=0 + +enable_access_invalid_csr_level=1 + +boot_mode=u + rtl_test: core_invalid_csr_test + sim_opts: > + +require_signature_addr=1 +# TODO: Re-enable this test after all the data/instruction page organization changes are done +- test: riscv_page_table_exception_test + description: > + Test random page table exception handling. An exception handling routine is + designed to fix the page table error and resume execution. + iterations: 0 + gen_test: riscv_rand_instr_test + gen_opts: > + +enable_page_table_exception=1 + rtl_test: core_base_test + +- test: riscv_sfence_exception_test + description: > + Random instruction test with S.FENCE exceptions + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +allow_sfence_exception=1 + rtl_test: core_base_test + + +- test: riscv_amo_test + description: > + RISC-V atomic instruction extension test + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=5000 + +num_of_sub_program=5 + # +directed_instr_0=riscv_lr_sc_instr_stream,10 + +directed_instr_1=riscv_amo_instr_stream,10 + rtl_test: core_base_test + - test: riscv_floating_point_arithmetic_test description: > Enable floating point instructions diff --git a/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv b/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv index cdb7fc0c..009e7568 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_cov_test.sv @@ -7,10 +7,11 @@ class riscv_instr_cov_test extends uvm_test; riscv_instr_cover_group instr_cg; string trace_csv[$]; string trace[string]; + bit report_illegal_instr; int unsigned entry_cnt; int unsigned total_entry_cnt; int unsigned skipped_cnt; - int unsigned unexpected_illegal_instr_cnt; + int unsigned illegal_instr_cnt; `uvm_component_utils(riscv_instr_cov_test) `uvm_component_new @@ -23,6 +24,7 @@ class riscv_instr_cov_test extends uvm_test; string header[$]; string entry[$]; int fd; + void'($value$plusargs("report_illegal_instr=%0d", report_illegal_instr)); while(1) begin args = {$sformatf("trace_csv_%0d", i), "=%s"}; if ($value$plusargs(args, csv)) begin @@ -42,9 +44,6 @@ class riscv_instr_cov_test extends uvm_test; bit expect_illegal_instr; entry_cnt = 0; instr_cg.reset(); - if (uvm_is_match("*illegal*", trace_csv[i]) || uvm_is_match("*unknown*", trace_csv[i]) ) begin - expect_illegal_instr = 1; - end `uvm_info(`gfn, $sformatf("Processing CSV trace[%0d]: %s", i, trace_csv[i]), UVM_LOW) fd = $fopen(trace_csv[i], "r"); if (fd) begin @@ -79,11 +78,11 @@ class riscv_instr_cov_test extends uvm_test; continue; end if (!sample()) begin - if (!expect_illegal_instr) begin + if (report_illegal_instr) begin `uvm_error(`gfn, $sformatf("Found unexpected illegal instr: %0s [%0s]", trace["instr"], line)) - unexpected_illegal_instr_cnt++; end + illegal_instr_cnt++; end end entry_cnt += 1; @@ -97,9 +96,9 @@ class riscv_instr_cov_test extends uvm_test; end `uvm_info(`gfn, $sformatf("Finished processing %0d trace CSV, %0d instructions", trace_csv.size(), total_entry_cnt), UVM_LOW) - if ((skipped_cnt > 0) || (unexpected_illegal_instr_cnt > 0)) begin + if ((skipped_cnt > 0) || ((illegal_instr_cnt > 0) && report_illegal_instr)) begin `uvm_error(`gfn, $sformatf("%0d instructions skipped, %0d illegal instruction", - skipped_cnt, unexpected_illegal_instr_cnt)) + skipped_cnt, illegal_instr_cnt)) end else begin `uvm_info(`gfn, "TEST PASSED", UVM_NONE);