mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-23 05:17:12 -04:00
Update google_riscv-dv to google/riscv-dv@0b62525
Update code from upstream repository https://github.com/google/riscv- dv to revision 0b625258549e733082c12e5dc749f05aefb07d5a * Add a knob to use rounding mode from the instruction (google/riscv- dv#767) (taoliug) * Add rounding mode support for floating point arithmetic instructions (google/riscv-dv#766) (taoliug) * Fix syntax issue (google/riscv-dv#765) (taoliug) * Add riscv_amo_instr (aneels3) * convert string to enum type (ishita71) * Remove unintended errors in the coverage flow (google/riscv-dv#757) (taoliug) * Fix c_test handling in the YAML testlist (google/riscv-dv#756) (taoliug) * Add support for new Spike trace format (google/riscv-dv#755) (Daniel Bates) * Fix google/riscv-dv#751 for floating point coverage (Weicai Yang) * Fix issues with implemented TODO's (aneels3) * fix randomize_gpr (aneels3) * Add file riscv_b_instr.py (ishita71) * add std_randomize todo (pvipsyash) * Add todo for floating_point test (ShraddhaDevaiya) * Add scripts to integrate with Metrics regression platform (Aimee Sutton) Includes a fix to dv/uvm/core_ibex/sim.py to use `asm_test` rather than `asm_tests` due to changes in RISCV-DV Signed-off-by: Greg Chadwick <gac@lowrisc.org>
This commit is contained in:
parent
860b085e25
commit
0cb2afffa9
41 changed files with 1800 additions and 442 deletions
|
@ -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 = {
|
||||
|
|
2
vendor/google_riscv-dv.lock.hjson
vendored
2
vendor/google_riscv-dv.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/google/riscv-dv
|
||||
rev: 3da32bbf6080d3bf252a7f71c5e3a32ea4924e49
|
||||
rev: 0b625258549e733082c12e5dc749f05aefb07d5a
|
||||
}
|
||||
}
|
||||
|
|
26
vendor/google_riscv-dv/.github/workflows/metrics-regress.yml
vendored
Normal file
26
vendor/google_riscv-dv/.github/workflows/metrics-regress.yml
vendored
Normal file
|
@ -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
|
||||
|
52
vendor/google_riscv-dv/.metrics.json
vendored
Normal file
52
vendor/google_riscv-dv/.metrics.json
vendored
Normal file
|
@ -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 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss ovpsim --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim",
|
||||
"wavesCmd": "python3 <rootDir>/run.py --test riscv_arithmetic_basic_test --seed <seed> --simulator dsim --iss ovpsim --so --out <rootDir>/out --verbose; <rootDir>/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": "<rootDir>/scripts/genMetricsList.py",
|
||||
"listFile": "<rootDir>/regression_list.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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.
|
||||
|
|
71
vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_amo_instr.py
vendored
Normal file
71
vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_amo_instr.py
vendored
Normal file
|
@ -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()
|
178
vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_b_instr.py
vendored
Normal file
178
vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_b_instr.py
vendored
Normal file
|
@ -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
|
|
@ -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:
|
||||
|
|
40
vendor/google_riscv-dv/pygen/pygen_src/isa/rv32a_instr.py
vendored
Normal file
40
vendor/google_riscv-dv/pygen/pygen_src/isa/rv32a_instr.py
vendored
Normal file
|
@ -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())
|
135
vendor/google_riscv-dv/pygen/pygen_src/isa/rv32b_instr.py
vendored
Normal file
135
vendor/google_riscv-dv/pygen/pygen_src/isa/rv32b_instr.py
vendored
Normal file
|
@ -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())
|
193
vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
vendored
Normal file
193
vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py
vendored
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
80
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
vendored
Normal file
80
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py
vendored
Normal file
|
@ -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]
|
|
@ -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]
|
||||
|
|
22
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscvOVPsim.ic
vendored
Normal file
22
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscvOVPsim.ic
vendored
Normal file
|
@ -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
|
78
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
vendored
Normal file
78
vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py
vendored
Normal file
|
@ -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]
|
|
@ -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']
|
|
@ -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()
|
||||
|
|
42
vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
vendored
Normal file
42
vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py
vendored
Normal file
|
@ -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()
|
66
vendor/google_riscv-dv/run.py
vendored
66
vendor/google_riscv-dv/run.py
vendored
|
@ -228,7 +228,7 @@ def run_csr_test(cmd_list, cwd, csr_file, isa, iterations, lsf_cmd,
|
|||
(" --xlen {}".format(
|
||||
re.search(r"(?P<xlen>[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):
|
||||
|
|
10
vendor/google_riscv-dv/scripts/check-status
vendored
Executable file
10
vendor/google_riscv-dv/scripts/check-status
vendored
Executable file
|
@ -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
|
65
vendor/google_riscv-dv/scripts/genMetricsList.py
vendored
Executable file
65
vendor/google_riscv-dv/scripts/genMetricsList.py
vendored
Executable file
|
@ -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
|
||||
## <rootDir>/yaml/base_testlist.yaml
|
||||
## <rootDir>/yaml/cov_testlist.yaml
|
||||
## <rootDir>/target/rv64gcv/testlist.yaml
|
||||
## <rootDir>/target/rv64gc/testlist.yaml
|
||||
## <rootDir>/target/rv32imcb/testlist.yaml
|
||||
## <rootDir>/target/multi_harts/testlist.yaml
|
||||
## <rootDir>/target/rv64imc/testlist.yaml
|
||||
## <rootDir>/target/rv32imc/testlist.yaml
|
||||
## <rootDir>/target/rv64imcb/testlist.yaml
|
||||
## <rootDir>/target/ml/testlist.yaml
|
||||
## <rootDir>/target/rv32i/testlist.yaml
|
||||
|
||||
import json
|
||||
|
||||
runCmdBase = "cd /mux-flow/results; python3 <rootDir>/run.py --test TESTNAME --simulator dsim --iss ovpsim --seed <seed> --so --out <rootDir>/out --verbose; <rootDir>/scripts/check-status $?; rm -fr <rootDir>/out/dsim"
|
||||
|
||||
## Based on testlist located in <rootDir>/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 <rootDir>/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)
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
116
vendor/google_riscv-dv/scripts/metrics-regress.py
vendored
Executable file
116
vendor/google_riscv-dv/scripts/metrics-regress.py
vendored
Executable file
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
|
||||
RD_RE = re.compile(r"(core\s+\d+:\s+)?(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
|
||||
"\((?P<bin>.*?)\) (?P<reg>[xf]\s*\d*?) 0x(?P<val>[a-f0-9]+)")
|
||||
CORE_RE = re.compile(
|
||||
r"core.*0x(?P<addr>[a-f0-9]+?) \(0x(?P<bin>.*?)\) (?P<instr>.*?)$")
|
||||
r"core\s+\d+:\s+0x(?P<addr>[a-f0-9]+?) \(0x(?P<bin>.*?)\) (?P<instr>.*?)$")
|
||||
ADDR_RE = re.compile(
|
||||
r"(?P<rd>[a-z0-9]+?),(?P<imm>[\-0-9]+?)\((?P<rs1>[a-z0-9]+)\)")
|
||||
ILLE_RE = re.compile(r"trap_illegal_instruction")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[] = {
|
|
@ -33,6 +33,74 @@
|
|||
- import: <riscv_dv_root>/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
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue