diff --git a/dv/uvm/core_ibex/Makefile b/dv/uvm/core_ibex/Makefile index 1c9d8c6864..f31ee49a95 100644 --- a/dv/uvm/core_ibex/Makefile +++ b/dv/uvm/core_ibex/Makefile @@ -51,7 +51,14 @@ ISS := spike # ISS runtime options ISS_OPTS := # ISA -ISA := rv32imcb +# Both an updated compiler and ISS are required to verify the bitmanip v.1.00 +# and draft v.0.93 extensions. For now, disable the bitmanip tests and verify +# RV32IMC only. +# For details, refer to https://github.com/lowRISC/ibex/issues/1470 +#ISA := rv32imcb +#ISA_ISS := rv32imc_Zba_Zbb_Zbc_Zbs_Xbitmanip +ISA := rv32imc +ISA_ISS := rv32imc # Test name (default: full regression) TEST := all TESTLIST := riscv_dv_extension/testlist.yaml @@ -125,7 +132,6 @@ CSR_OPTS=--csr_yaml=${CSR_FILE} \ --end_signature_addr=${SIGNATURE_ADDR} RISCV_DV_OPTS=--custom_target=riscv_dv_extension \ - --isa="${ISA}" \ --mabi=ilp32 \ # To avoid cluttering the output directory with stamp files, we place them in @@ -244,7 +250,7 @@ tests-and-seeds := \ # # To do this variable tracking, we dump each of the variables to a Makefile # fragment and try to load it up the next time around. -gen-var-deps := GEN_OPTS SIMULATOR RISCV_DV_OPTS CSR_OPTS \ +gen-var-deps := GEN_OPTS SIMULATOR RISCV_DV_OPTS ISA CSR_OPTS \ SIGNATURE_ADDR PMP_REGIONS PMP_GRANULARITY TEST_OPTS # Load up the generation stage's saved variable values. If this fails, that's @@ -281,6 +287,7 @@ $(metadata)/instr_gen.gen.stamp: \ --lsf_cmd="${LSF_CMD}" \ --simulator="${SIMULATOR}" \ ${RISCV_DV_OPTS} \ + --isa=${ISA} \ ${TEST_OPTS} \ ${CSR_OPTS} \ --sim_opts="+uvm_set_inst_override=riscv_asm_program_gen,ibex_asm_program_gen,"uvm_test_top.asm_gen" \ @@ -304,7 +311,8 @@ $(metadata)/instr_gen.compile.stamp: \ --steps=gcc_compile \ ${TEST_OPTS} \ --gcc_opts=-mno-strict-align \ - ${RISCV_DV_OPTS} && \ + ${RISCV_DV_OPTS} \ + --isa=${ISA} && \ touch $@ .PHONY: gcc_compile @@ -329,7 +337,7 @@ $(metadata)/instr_gen.iss.stamp: \ ${TEST_OPTS} \ --iss="${ISS}" \ --iss_opts="${ISS_OPTS}" \ - --isa="${ISA}" \ + --isa="${ISA_ISS}" \ ${RISCV_DV_OPTS} $(call dump-vars,$(metadata)/iss-vars.mk,iss,$(iss-var-deps)) @touch $@ diff --git a/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv b/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv index 5cba70cf2c..9d5df5dce6 100644 --- a/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv +++ b/dv/uvm/core_ibex/riscv_dv_extension/riscv_core_setting.sv @@ -52,7 +52,8 @@ riscv_instr_name_t unsupported_instr[] = {FENCE_I}; bit support_unaligned_load_store = 1'b1; // ISA supported by the processor -riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32B}; +riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, + RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS, RV32B}; // Interrupt mode support mtvec_mode_t supported_interrupt_mode[$] = {VECTORED}; diff --git a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml index c861072ba4..d543d957aa 100644 --- a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml +++ b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml @@ -715,28 +715,41 @@ # Disable cosim for bitmanip tests for now as Ibex implements a different # version of the spec compared to the Spike version used for the cosim. -- test: riscv_bitmanip_full_test - desc: > - Random instruction test with supported B extension instructions in full configuration - iterations: 10 - gen_test: riscv_rand_instr_test - gen_opts: > - +enable_b_extension=1 - +enable_bitmanip_groups=zbb,zb_tmp,zbt,zbs,zbp,zbf,zbe,zbc,zbr - +disable_cosim=1 - rtl_test: core_ibex_base_test - rtl_params: - RV32B: "ibex_pkg::RV32BFull" -- test: riscv_bitmanip_balanced_test - desc: > - Random instruction test with supported B extension instructions in balanced configuration - iterations: 10 - gen_test: riscv_rand_instr_test - gen_opts: > - +enable_b_extension=1 - +enable_bitmanip_groups=zbb,zb_tmp,zbt,zbs,zbf - +disable_cosim=1 - rtl_test: core_ibex_base_test - rtl_params: - RV32B: ["ibex_pkg::RV32BFull", "ibex_pkg::RV32BBalanced"] +# Both an updated compiler and ISS are required to verify the bitmanip v.1.00 +# and draft v.0.93 extensions. For now, disable the bitmanip tests. +# For details, refer to https://github.com/lowRISC/ibex/issues/1470 +#ISA := rv32imcb +#ISA_ISS := rv32imc_Zba_Zbb_Zbc_Zbs_Xbitmanip +#- test: riscv_bitmanip_full_test +# desc: > +# Random instruction test with supported B extension instructions in full configuration +# iterations: 10 +# gen_test: riscv_rand_instr_test +# gen_opts: > +# +enable_zba_extension=1 +# +enable_zbb_extension=1 +# +enable_zbc_extension=1 +# +enable_zbs_extension=1 +# +enable_b_extension=1 +# +enable_bitmanip_groups=zbe,zbf,zbp,zbr,zbt +# +disable_cosim=1 +# rtl_test: core_ibex_base_test +# rtl_params: +# RV32B: "ibex_pkg::RV32BFull" +# +#- test: riscv_bitmanip_balanced_test +# desc: > +# Random instruction test with supported B extension instructions in balanced configuration +# iterations: 10 +# gen_test: riscv_rand_instr_test +# gen_opts: > +# +enable_zba_extension=1 +# +enable_zbb_extension=1 +# +enable_zbs_extension=1 +# +enable_b_extension=1 +# +enable_bitmanip_groups=zbf,zbt +# +disable_cosim=1 +# rtl_test: core_ibex_base_test +# rtl_params: +# RV32B: ["ibex_pkg::RV32BFull", "ibex_pkg::RV32BBalanced"] diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 66c71851ee..596e877095 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: 59dcd8c813484eb6dcca67e7e36089fe772b9cc8 + rev: ea8dd25140178eed13c3e0f3d3a97a0c07ab44a0 } } diff --git a/vendor/google_riscv-dv/pygen/pygen_src/README.md b/vendor/google_riscv-dv/pygen/pygen_src/README.md new file mode 100644 index 0000000000..09c9dc8d69 --- /dev/null +++ b/vendor/google_riscv-dv/pygen/pygen_src/README.md @@ -0,0 +1,99 @@ +## Overview + +RISCV-DV-PyFlow is a purely Python based open-source instruction generator for RISC-V processor +verification. It uses [PyVSC](https://github.com/fvutils/pyvsc) as the main library for +randomization and coverage collection. It currently supports the following features: + +- Supported instruction set: RV32IMAFDC +- Supported privileged modes: For now only machine mode is supported. +- Illegal instruction and HINT instruction generation +- Random forward/backward branch instructions +- Supports mixing directed instructions with random instruction stream +- Support for direct & vectored interrupt table. +- Multi-hart support +- Functional coverage framework (reports GUI as well as text, currently + supports RV32IMFDC extensions) +- Supported ISS : Spike, OVPsim + +## Supported tests + +- riscv_arithmetic_basic_test +- riscv_amo_test +- riscv_floating_point_arithmetic_test +- riscv_floating_point_rand_test +- riscv_floating_point_mmu_stress_test +- riscv_b_ext_test +- riscv_rand_instr_test +- riscv_jump_stress_test +- riscv_rand_jump_test +- riscv_mmu_stress_test +- riscv_illegal_instr_test +- riscv_unaligned_load_store_test +- riscv_single_hart_test +- riscv_non_compressed_instr_test +- riscv_loop_test + + +## Getting Started + +### Prerequisites + +To be able to run the generator, you need to have RISCV-GCC compiler toolchain and ISS +(Instruction Set Simulator) installed (Spike is preferred). + + +### Install RISCV-DV-PyFlow + +Getting the source +```bash +git clone https://github.com/google/riscv-dv.git +``` + +```bash +pip3 install -r requirements.txt # install dependencies (only once) +python3 run.py --help +``` + +## Running the Generator + +Command to run a single test: +```bash +python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow +``` +--simulator=pyflow will invoke the Python generator. + +Run a single test 10 times +```bash +python3 run.py --test=riscv_arithmetic_basic_test --iterations=10 --simulator=pyflow +``` +Run the generator only, do not compile and simluation with ISS +```bash +python3 run.py --test=riscv_arithmetic_basic_test --simulator=pyflow --steps gen +``` +## Coverage Model +The coverage model of PyFlow is developed using PyVSC library. + +Command to generate the coverage report. +#### Process spike simulation log and collect functional coverage +```bash +python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization +``` +--enable_visualization helps enabling coverage report visualization for pyflow. +#### Get the command reference +```bash +cov --help +``` +#### Run the coverage flow with predefined targets +```bash +python3 cov.py --dir out/spike_sim/ --simulator=pyflow --enable_visualization --target rv32imc +``` +The coverage reports can be viewed using two ways: +1) Text format: By opening the CoverageReport.txt file. +2) GUI format: By opening the cov_db.xml using pyucis-viewer. +The GUI format could be enabled using "--enable_visualization" command option. +```bash +pyucis-viewer cov_db.xml +``` +## Note +Currently, time to generate a single program with larger than 10k instructions is around +12 minutes. We are working on improving the overall performance. diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py index 9ed8f85c16..8b89abd9cf 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_compressed_instr.py @@ -223,6 +223,6 @@ def conver2bin(self, prefix=""): def get_c_opcode(self): pass - # TOD0 + # TODO def get_func3(self): pass diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py index a5e75c4f0b..a8cff5af7b 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_cov_instr.py @@ -19,11 +19,11 @@ import logging from importlib import import_module from enum import Enum, IntEnum, auto -from bitstring import BitArray from pygen_src.riscv_instr_pkg import * from pygen_src.riscv_instr_gen_config import cfg rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") + class operand_sign_e(IntEnum): POSITIVE = 0 NEGATIVE = auto() @@ -35,6 +35,11 @@ class div_result_e(IntEnum): DIV_OVERFLOW = auto() +class div_result_ex_overflow_e(IntEnum): + DIV_NORMAL = 0 + DIV_BY_ZERO = auto() + + class compare_result_e(IntEnum): EQUAL = 0 LARGER = auto() @@ -142,7 +147,7 @@ def set_imm_len(self): if self.imm_type.name == "UIMM": self.imm_len = 5 else: - self.imm_len = 11 + self.imm_len = 12 def set_mode(self): # mode setting for Instruction Format @@ -320,10 +325,11 @@ def check_hazard_condition(self, pre_instr): the result of the check_hazard_condition won't be accurate. Need to explicitly extract the destination register from the operands ''' if pre_instr.has_rd: - if ((self.has_rs1 and self.rs1 == pre_instr.rd) or - (self.has_rs2 and self.rs1 == pre_instr.rd)): + if ((self.has_rs1 and (self.rs1 == pre_instr.rd)) or + (self.has_rs2 and (self.rs1 == pre_instr.rd))): + logging.info("pre_instr {}".format(pre_instr.instr.name)) self.gpr_hazard = hazard_e["RAW_HAZARD"] - elif self.has_rd and self.rd == pre_instr.rd: + elif self.has_rd and (self.rd == pre_instr.rd): self.gpr_hazard = hazard_e["WAW_HAZARD"] elif (self.has_rd and ((pre_instr.has_rs1 and (pre_instr.rs1 == self.rd)) or @@ -333,16 +339,16 @@ def check_hazard_condition(self, pre_instr): self.gpr_hazard = hazard_e["NO_HAZARD"] if self.category == riscv_instr_category_t.LOAD: if (pre_instr.category == riscv_instr_category_t.STORE and - pre_instr.mem_addr.get_val() == self.mem_addr.get_val()): + (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())): self.lsu_hazard = hazard_e["RAW_HAZARD"] else: self.lsu_hazard = hazard_e["NO_HAZARD"] if self.category == riscv_instr_category_t.STORE: if (pre_instr.category == riscv_instr_category_t.STORE and - pre_instr.mem_addr.get_val() == self.mem_addr.get_val()): + (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())): self.lsu_hazard = hazard_e["WAW_HAZARD"] elif (pre_instr.category == riscv_instr_category_t.LOAD and - pre_instr.mem_addr.get_val() == self.mem_addr.get_val()): + (pre_instr.mem_addr.get_val() == self.mem_addr.get_val())): self.lsu_hazard = hazard_e["WAR_HAZARD"] else: self.lsu_hazard = hazard_e["NO_HAZARD"] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py index 4d4dcba55d..3169c5ba1a 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_floating_point_instr.py @@ -116,7 +116,7 @@ def set_rand_mode(self): self.has_fs1 = 0 self.has_fd = 0 else: - logging.info("Unsupported format %0s", self.format.name) + logging.info("Unsupported format {}".format(self.format.name)) def pre_randomize(self): super().pre_randomize() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py index 74d922c65c..b592511e28 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/isa/riscv_instr.py @@ -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 @@ -9,7 +8,6 @@ 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 logging @@ -110,12 +108,32 @@ def imm_c(self): with vsc.if_then(self.XLEN != 32): self.imm[11:6] == 0 + @vsc.constraint + def csr_c(self): + # TODO + pass + @classmethod def register(cls, instr_name, instr_group): logging.info("Registering {}".format(instr_name.name)) cls.instr_registry[instr_name] = instr_group return 1 + def __deepcopy__(self, memo): + cls = self.__class__ # Extract the class of the object. + # Create a new instance of the object based on extracted class. + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k in ["_ro_int", "tname", "__field_info"]: + continue # Skip the fields which are not required. + else: + # Copy over attributes by copying directly. + setattr(result, k, copy.deepcopy(v, memo)) + return result + + # Create the list of instructions based on the supported ISA extensions and configuration + # of the generator @classmethod def create_instr_list(cls, cfg): cls.instr_names.clear() @@ -129,6 +147,7 @@ def create_instr_list(cls, cfg): if not instr_inst.is_supported(cfg): continue + # C_JAL is RV32C only instruction if ((rcs.XLEN != 32) and (instr_name == riscv_instr_name_t.C_JAL)): continue if ((riscv_reg_t.SP in cfg.reserved_regs) and @@ -310,7 +329,7 @@ def set_imm_len(self): if self.imm_type.name == "UIMM": self.imm_len = 5 else: - self.imm_len = 11 + self.imm_len = 12 self.imm_mask = (self.imm_mask << self.imm_len) & self.shift_t def extend_imm(self): diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py index f3f1b5ece7..46f8a21e73 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_amo_instr_lib.py @@ -14,13 +14,13 @@ import vsc import random from importlib import import_module +from pygen_src.riscv_instr_gen_config import cfg +from pygen_src.isa.riscv_instr import riscv_instr +from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr 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") @@ -62,7 +62,6 @@ def addr_range_c(self): @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 @@ -73,7 +72,7 @@ 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'] + 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): @@ -81,7 +80,7 @@ def init_offset_reg(self): 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'], + la_instr.imm_str = "{}+{}".format(cfg.amo_region[self.data_page_id].name, self.offset[i]) self.instr_list.insert(0, la_instr) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py index cf751b35a2..4d8c180a64 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_asm_program_gen.py @@ -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 @@ -9,7 +8,6 @@ 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 logging @@ -31,35 +29,43 @@ from pygen_src.riscv_utils import factory rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") -''' - RISC-V assembly program generator - This is the main class to generate a complete RISC-V program, including the init routine, - instruction section, data section, stack section, page table, interrupt and exception - handling etc. Check gen_program() function to see how the program is generated. -''' +# ---------------------------------------------------------------------------------- +# RISC-V assembly program generator + +# This is the main class to generate a complete RISC-V program, including the init routine, +# instruction section, data section, stack section, page table, interrupt and exception +# handling etc. Check gen_program() function to see how the program is generated. +# ---------------------------------------------------------------------------------- +@vsc.randobj class riscv_asm_program_gen: def __init__(self): self.instr_stream = [] + # Directed instruction ratio, occurance per 1000 instructions self.directed_instr_stream_ratio = {} self.hart = 0 self.page_table_list = [] self.main_program = [] self.sub_program = [] self.data_page_gen = None + self.spf_val = vsc.rand_bit_t(32) + self.dpf_val = vsc.rand_bit_t(64) + # ---------------------------------------------------------------------------------- # Main function to generate the whole program + # ---------------------------------------------------------------------------------- # This is the main function to generate all sections of the program. def gen_program(self): - # Generate program header self.instr_stream.clear() + # Generate program header self.gen_program_header() for hart in range(cfg.num_of_harts): # Commenting out for now + # TODO support for sub_program # sub_program_name = [] self.instr_stream.append(f"h{int(hart)}_start:") if not cfg.bare_program_mode: @@ -70,7 +76,6 @@ def gen_program(self): self.pre_enter_privileged_mode(hart) # Init section self.gen_init_section(hart) - # To DO ''' If PMP is supported, we want to generate the associated trap handlers and the test_done section at the start of the program so we can allow access through the pmpcfg0 CSR @@ -87,7 +92,8 @@ def gen_program(self): self.gen_store_fault_handler(hart) if hart == 0: self.gen_test_done() - + # Generate sub program + # TODO gen_sub_program() # Generate main program gt_lbl_str = pkg_ins.get_label("main", hart) label_name = gt_lbl_str @@ -103,8 +109,10 @@ def gen_program(self): 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) - + # Setup jump instruction among main program and sub programs + # TODO gen_callstack() self.main_program[hart].post_process_instr() + logging.info("Post-processing main program...done") self.main_program[hart].generate_instr_stream() logging.info("Generating main program instruction stream...done") self.instr_stream.extend(self.main_program[hart].instr_string_list) @@ -113,14 +121,14 @@ def gen_program(self): to test_done section at the end of main_program, as the test_done will have moved to the beginning of the program """ - self.instr_stream.append("{}j test_done".format(pkg_ins.indent)) - ''' - Test done section - If PMP isn't supported, generate this in the normal location - ''' + self.instr_stream.extend(("{}la x{}, test_done".format(pkg_ins.indent, cfg.scratch_reg), + "{}jalr x0, x{}, 0".format(pkg_ins.indent, cfg.scratch_reg))) + # Test done section + # If PMP isn't supported, generate this in the normal location if(hart == 0 and not(rcs.support_pmp)): self.gen_test_done() - + # Shuffle the sub programs and insert to the instruction stream + # TODO inser_sub_program() logging.info("Main/sub program generation...done") # program end self.gen_program_end(hart) @@ -138,6 +146,7 @@ def gen_program(self): # AMO memory region if(hart == 0 and riscv_instr_group_t.RV32A in rcs.supported_isa): self.gen_data_page(hart, amo = 1) + # Stack section self.gen_stack_section(hart) if not cfg.bare_program_mode: # Generate kernel program/data/stack section @@ -145,6 +154,10 @@ def gen_program(self): # Page table self.gen_page_table_section(hart) + # ---------------------------------------------------------------------------------- + # Generate kernel program/data/stack sections + # ---------------------------------------------------------------------------------- + def gen_kernel_sections(self, hart): if rcs.SATP_MODE != satp_mode_t.BARE: self.instr_stream.append(".align 12") @@ -152,56 +165,84 @@ def gen_kernel_sections(self, hart): self.instr_stream.append(".align 2") self.instr_stream.append(pkg_ins.get_label("kernel_instr_start:", hart)) self.instr_stream.append(".text") + # Kernel programs + # TODO + # All trap/interrupt handling is in the kernel region + # Trap/interrupt delegation to user mode is not supported now + # Trap handler self.gen_all_trap_handler(hart) + # Interrupt handling subroutine for mode in rcs.supported_privileged_mode: self.gen_interrupt_handler_section(mode, hart) self.instr_stream.append(pkg_ins.get_label("kernel_instr_end: nop", hart)) + # User stack and data pages may not be accessible when executing trap handling programs in + # machine/supervisor mode. Generate separate kernel data/stack sections to solve it. + if not cfg.virtual_addr_translation_on: + if rcs.SATP_MODE != satp_mode_t.BARE: + self.instr_stream.append(".align 12") + else: + self.instr_stream.append(".align 2") + # Kernel data pages + self.instr_stream.append(pkg_ins.get_label("kernel_data_start:", hart)) + if not cfg.no_data_page: + # Data section + self.gen_data_page(hart, 1) + # Kernel stack section self.gen_kernel_stack_section(hart) def gen_kernel_program(self, hart, seq): + # TODO pass + # ---------------------------------------------------------------------------------- + # Generate any subprograms and set up the callstack + # ---------------------------------------------------------------------------------- + def gen_sub_program(self, hart, sub_program, sub_program_name, num_sub_program, is_debug = 0, prefix = "sub"): + # TODO pass def gen_callstack(self, main_program, sub_program, sub_program_name, num_sub_program): + # TODO pass def insert_sub_program(self, sub_program, instr_list): + # TODO pass + # ---------------------------------------------------------------------------------- + # Major sections - init, stack, data, test_done etc. + # ---------------------------------------------------------------------------------- def gen_program_header(self): - string = [] - self.instr_stream.append(".include \"user_define.h\"") - self.instr_stream.append(".globl _start") - self.instr_stream.append(".section .text") + header_string = [] + self.instr_stream.extend((".include \"user_define.h\"", ".globl _start", ".section .text")) if cfg.disable_compressed_instr: self.instr_stream.append(".option norvc;") - string.append(".include \"user_init.s\"") - string.append("csrr x5, mhartid") - + header_string.extend((".include \"user_init.s\"", + "csrr x5, {}".format(hex(privileged_reg_t.MHARTID)))) for hart in range(cfg.num_of_harts): - string.append("li x6, {}\n{}beq x5, x6, {}f".format(hart, pkg_ins.indent, hart)) - - self.gen_section("_start", string) - + header_string.extend(("li x6, {}".format(hart), + "beq x5, x6, {}f".format(hart))) + self.gen_section("_start", header_string) for hart in range(cfg.num_of_harts): - self.instr_stream.append("{}: j h{}_start".format(hart, hart)) + self.instr_stream.extend(("{}: la x{}, h{}_start".format(hart, cfg.scratch_reg, hart), + "jalr x0, x{}, 0".format(cfg.scratch_reg))) def gen_program_end(self, hart): if hart == 0: + # Use write_tohost to terminate spike simulation 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: - self.instr_stream.append(".align 6; .global tohost; tohost: .dword 0;") - self.instr_stream.append(".align 6; .global fromhost; fromhost: .dword 0;") + self.instr_stream.extend((".align 6; .global tohost; tohost: .dword 0;", + ".align 6; .global fromhost; fromhost: .dword 0;")) def gen_data_page(self, hart, is_kernel = 0, amo = 0): self.data_page_gen = riscv_data_page_gen() @@ -221,15 +262,15 @@ def gen_stack_section(self, hart): else: self.instr_stream.append(".align 2") - self.instr_stream.append(pkg_ins.get_label("user_stack_start:", hart)) - self.instr_stream.append(".rept {}".format(cfg.stack_len - 1)) - self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) - 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)) + self.instr_stream.extend((pkg_ins.get_label("user_stack_start:", hart), + ".rept {}".format(cfg.stack_len - 1), + ".{}byte 0x0".format(rcs.XLEN // 8), ".endr", + pkg_ins.get_label("user_stack_end:", hart), + ".{}byte 0x0".format(rcs.XLEN // 8))) if cfg.use_push_data_section: - self.instr_stream.push_back(".popsection;") + self.instr_stream.append(".popsection;") + # The kernal stack is used to save user program context before executing exception handling def gen_kernel_stack_section(self, hart): hart_prefix_string = pkg_ins.hart_prefix(hart) if cfg.use_push_data_section: @@ -242,33 +283,31 @@ def gen_kernel_stack_section(self, hart): self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") - - self.instr_stream.append(pkg_ins.get_label("kernel_stack_start:", hart)) - self.instr_stream.append(".rept {}".format(cfg.kernel_stack_len - 1)) - self.instr_stream.append(".{}byte 0x0".format(rcs.XLEN // 8)) - 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)) + self.instr_stream.extend((pkg_ins.get_label("kernel_stack_start:", hart), + ".rept {}".format(cfg.stack_len - 1), + ".{}byte 0x0".format(rcs.XLEN // 8), ".endr", + pkg_ins.get_label("kernel_stack_end:", hart), + ".{}byte 0x0".format(rcs.XLEN // 8))) if cfg.use_push_data_section: - self.instr_stream.push_back(".popsection;") + self.instr_stream.append(".popsection;") def gen_init_section(self, hart): - string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN) - self.instr_stream.append(string) + init_string = pkg_ins.format_string(pkg_ins.get_label("init:", hart), pkg_ins.LABEL_STR_LEN) + self.instr_stream.append(init_string) 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( + init_string = "{}la x{}, {}user_stack_end".format( pkg_ins.indent, cfg.sp, pkg_ins.hart_prefix(hart)) - self.instr_stream.append(string) + self.instr_stream.append(init_string) if cfg.enable_vector_extension: - self.init_vector_engine() + self.randomize_vec_gpr_and_csr() self.core_is_initialized() self.gen_dummy_csr_write() if rcs.support_pmp: - string = pkg_ins.indent + "j main" - self.instr_stream.append(string) + init_string = pkg_ins.indent + "j main" + self.instr_stream.append(init_string) # Setup MISA based on supported extensions def setup_misa(self): @@ -316,21 +355,37 @@ def setup_misa(self): else: logging.critical("{} is not yet supported".format(group.name)) sys.exit(1) - if privileged_mode_t.SUPERVISOR_MODE.name in rcs.supported_privileged_mode: + if privileged_mode_t.SUPERVISOR_MODE 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], - hex(misa.get_val()))) - self.instr_stream.append("{}csrw {}, x{}".format(pkg_ins.indent, hex(privileged_reg_t.MISA), - cfg.gpr[0])) + self.instr_stream.extend(("{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0], + hex(misa.get_val())), + "{}csrw {}, x{}".format(pkg_ins.indent, + hex(privileged_reg_t.MISA), cfg.gpr[0]))) + # Write to the signature_addr with values to indicate to the core testbench + # that is safe to start sending interrupt and debug stimulus def core_is_initialized(self): - pass + instr = [] + if cfg.require_signature_addr: + if cfg.signature_addr != 0xdeadbeef: + self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, + core_status_t.INITIALIZED) + self.format_section(instr) + self.instr_stream.append(instr) + else: + logging.critical("The signature_addr is not properly configured!") + sys.exit(1) + # Generate some dummy writes to xSTATUS/xIE at the beginning of the test to check + # repeated writes to these CSRs. def gen_dummy_csr_write(self): + # TODO pass + # Initialize general purpose registers with random value def init_gpr(self): reg_val = vsc.rand_bit_t(pkg_ins.DATA_WIDTH) + # Init general purpose registers with random values for i in range(rcs.NUM_GPR): if i in [cfg.sp.value, cfg.tp.value]: continue @@ -343,19 +398,25 @@ def init_gpr(self): 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) + self.instr_stream.append("{}li x{}, {}".format(pkg_ins.indent, i, + hex(reg_val.get_val()))) + + # Initialize vector general purpose registers + def init_vec_gpr(self): + # TODO + pass + # Initialize floating point general purpose registers def init_floating_point_gpr(self): for i in range(rcs.NUM_FLOAT_GPR): 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) + # Initialize rounding mode of FCSR and append to the instr_stream + self.instr_stream.append("{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm)) + # get instructions initialize floating_point_gpr with single precision floating value def init_floating_point_gpr_with_spf(self, int_floating_gpr): imm = self.get_rand_spf_value() li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0], hex(imm)) @@ -363,6 +424,7 @@ def init_floating_point_gpr_with_spf(self, int_floating_gpr): cfg.gpr[0]) self.instr_stream.extend((li_instr, fmv_instr)) + # get instructions initialize floating_point_gpr with double precision floating value def init_floating_point_gpr_with_dpf(self, int_floating_gpr): imm = vsc.bit_t(64) imm = self.get_rand_dpf_value() @@ -378,114 +440,205 @@ def init_floating_point_gpr_with_dpf(self, int_floating_gpr): fmv_instr = "{}fmv.d.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr, int_gpr2) self.instr_stream.extend((li_instr0, slli_instr, li_instr1, or_instr, fmv_instr)) - # Get a random single precision floating value + def get_randselect(self, addr_range1, addr_range2, flag): + if flag: + # Get a random double precision floating value + with vsc.raw_mode(): + with vsc.randomize_with(self.dpf_val): + self.dpf_val in vsc.rangelist(addr_range1, addr_range2) + else: + # Get a random single precision floating value + with vsc.raw_mode(): + with vsc.randomize_with(self.spf_val): + self.spf_val in vsc.rangelist(addr_range1, addr_range2) + + def get_rng(self, val0, val1, spf_dpf, flag): + if flag == 0 and spf_dpf == 32: + with vsc.raw_mode(): + with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] > 0 + elif flag == 0 and spf_dpf == 64: + with vsc.raw_mode(): + with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] > 0 + elif flag == 1 and spf_dpf == 32: + with vsc.raw_mode(): + with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] == 0 + else: + with vsc.raw_mode(): + with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] == 0 + def get_rand_spf_value(self): - # TODO randcase - value = random.randrange(0, 2**32 - 1) - return value + vsc.randselect([ + # Infinity + (1, lambda: self.get_randselect(0x7f80_0000, 0xff80_0000, 0)), + # Largest + (1, lambda: self.get_randselect(0x7f7f_ffff, 0xff7f_ffff, 0)), + # Zero + (1, lambda: self.get_randselect(0x0000_0000, 0x8000_0000, 0)), + # NaN + (1, lambda: self.get_randselect(0x7f80_0001, 0x7fc0_0000, 0)), + # Normal + (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 0)), + # Subnormal + (1, lambda: self.get_rng(30, pkg_ins.SINGLE_PRECISION_FRACTION_BITS, 32, 1))]) + return self.spf_val - # Get a random double precision floating value def get_rand_dpf_value(self): - value = vsc.bit_t(64) - # TODO randcase - return value - - def init_vector_engine(self): - pass + vsc.randselect([ + # Infinity + (1, lambda: self.get_randselect(0x7ff0_0000_0000_0000, 0xfff0_0000_0000_0000, 1)), + # largest + (1, lambda: self.get_randselect(0x7fef_ffff_ffff_ffff, 0xffef_ffff_ffff_ffff, 1)), + # Zero + (1, lambda: self.get_randselect(0x0000_0000_0000_0000, 0x8000_0000_0000_0000, 1)), + # NaN + (1, lambda: self.get_randselect(0x7ff0_0000_0000_0001, 0x7ff8_0000_0000_0000, 1)), + # Normal + (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64 , 0)), + # Subnormal + (1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64, 1))]) + return self.dpf_val + + # Generate "test_done" section, test is finished by an ECALL instruction + # The ECALL trap handler will handle the clean up procedure before finishing the test. def gen_test_done(self): - string = pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN) - self.instr_stream.append(string) - self.instr_stream.append(pkg_ins.indent + "li gp, 1") - + self.instr_stream.extend((pkg_ins.format_string("test_done:", pkg_ins.LABEL_STR_LEN), + pkg_ins.indent + "li gp, 1")) if cfg.bare_program_mode: self.instr_stream.append(pkg_ins.indent + "j write_tohost") else: self.instr_stream.append(pkg_ins.indent + "ecall") - def gen_register_dump(self): - string = "" + # Dump all GPR to the starting point of the program + # TB can check the GPR value for this memory location to compare with expected value generated + # by the ISA simulator. If the processor doesn't have a good tracer unit, it might not be + # possible to compare the GPR value after each instruction execution. + def gen_register_dump(self, instr): # load base address - string = "{}la x{}, _start".format(pkg_ins.indent, cfg.gpr[0]) - self.instr_stream.append(string) - + instr.append("la x{}, _start".format(cfg.gpr[0])) # Generate sw/sd instructions for i in range(32): if rcs.XLEN == 64: - string = "{}sd x{}, {}(x{})".format( - pkg_ins.indent, i, i * (rcs.XLEN / 8), cfg.gpr[0]) + dump_str = "sd x{}, {}(x{})".format(i, i * (rcs.XLEN // 8), cfg.gpr[0]) else: - string = "{}sw x{}, {}(x{})".format( - pkg_ins.indent, i, int(i * (rcs.XLEN / 8)), cfg.gpr[0]) - self.instr_stream.append(string) + dump_str = "sw x{}, {}(x{})".format(i, i * (rcs.XLEN // 8), cfg.gpr[0]) + instr.append(dump_str) + + # ---------------------------------------------------------------------------------- + # Privileged mode entering routine + # ---------------------------------------------------------------------------------- def pre_enter_privileged_mode(self, hart): instr = [] - string = [] - - string.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart))) - self.gen_section(pkg_ins.get_label("kernel_sp", hart), string) - + privil_str = [] + # Setup kernel stack pointer + privil_str.append("la x{}, {}kernel_stack_end".format(cfg.tp, pkg_ins.hart_prefix(hart))) + self.gen_section(pkg_ins.get_label("kernel_sp", hart), privil_str) + # Setup interrupt and exception delegation if not cfg.no_delegation and (cfg.init_privileged_mode != privileged_mode_t.MACHINE_MODE): self.gen_delegation(hart) + # Setup trap vector register self.trap_vector_init(hart) + # Setup PMP CSRs self.setup_pmp(hart) - + # Generate PMPADDR write test sequence + self.gen_pmp_csr_write(hart) + # Initialize PTE (link page table based on their real physical address) if cfg.virtual_addr_translation_on: - self.page_table_list.process_page_table(instr) + # TODO + # self.page_table_list.process_page_table(instr) self.gen_section(pkg_ins.get_label("process_pt", hart), instr) + # Setup mepc register, jump to init entry self.setup_epc(hart) + # Initialization of any implementation-specific custom CSRs + self.setup_custom_csrs(hart) + # Setup initial privilege mode self.gen_privileged_mode_switch_routine(hart) def gen_privileged_mode_switch_routine(self, hart): privil_seq = riscv_privileged_common_seq() - for i in range(len(rcs.supported_privileged_mode)): + for privil_mode in rcs.supported_privileged_mode: instr = [] # csr_handshake = [] - if rcs.supported_privileged_mode[i] != cfg.init_privileged_mode: + if privil_mode != cfg.init_privileged_mode: continue logging.info("Generating privileged mode routing for {}" - .format(rcs.supported_privileged_mode[i])) + .format(privil_mode.name)) # Enter Privileged mode privil_seq.hart = hart privil_seq.randomize() - privil_seq.enter_privileged_mode(rcs.supported_privileged_mode[i], instr) - # TODO + privil_seq.enter_privileged_mode(privil_mode, instr) if cfg.require_signature_addr: + # TODO pass self.instr_stream.extend(instr) + # Setup EPC before entering target privileged mode def setup_epc(self, hart): instr = [] instr.append("la x{}, {}init".format(cfg.gpr[0], pkg_ins.hart_prefix(hart))) + 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], cfg.gpr[0], rcs.XLEN - 12) + - "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12)) - mode_name = cfg.init_privileged_mode.name + instr.extend(("slli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12), + "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 12))) instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0])) - if not rcs.support_pmp: - instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower())) self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr) + # Setup PMP CSR configuration def setup_pmp(self, hart): + # TODO + pass + # Generates a directed stream of instructions to write random values to all supported + # pmpaddr CSRs to test write accessibility. + # The original CSR values are restored afterwards. + + def gen_pmp_csr_write(self, hart): + # TODO + pass + + # Handles creation of a subroutine to initialize any custom CSRs + def setup_custom_csrs(self, hart): + # TODO + pass + + # This function should be overridden in the riscv_asm_program_gen extended class + # corresponding to the RTL implementation if it has any custom CSRs defined. + + # All that needs to be done in the overridden function is to manually create + # the instruction strings to set up any custom CSRs and then to push those strings + # into the instr queue. + def init_custom_csr(self, instr): + # TODO pass + # --------------------------------------------------------------------------------------- + # Privileged CSR setup for interrupt and exception handling and delegation + # --------------------------------------------------------------------------------------- + + # Interrupt and exception delegation setting. + # The lower level exception and interrupt can be delegated to higher level handler. def gen_delegation(self, hart): - self.gen_delegation_instr(hart, "MEDELEG", "MIDELEG", + self.gen_delegation_instr(hart, + privileged_reg_t.MEDELEG, + privileged_reg_t.MIDELEG, cfg.m_mode_exception_delegation, cfg.m_mode_interrupt_delegation) if rcs.support_umode_trap: - self.gen_delegation_instr(hart, "SEDELEG", "SIDELEG", + self.gen_delegation_instr(hart, + privileged_reg_t.SEDELEG, + privileged_reg_t.SIDELEG, cfg.s_mode_exception_delegation, cfg.s_mode_interrupt_delegation) def gen_delegation_instr(self, hart, edeleg, ideleg, edeleg_enable, ideleg_enable): + # TODO pass + # Setup trap vector - MTVEC, STVEC, UTVEC def trap_vector_init(self, hart): instr = [] for mode in rcs.supported_privileged_mode: @@ -498,43 +651,73 @@ def trap_vector_init(self, hart): else: logging.critical("Unsupported privileged_mode {}".format(mode.name)) sys.exit(1) - + # Skip utvec init if trap delegation to u_mode is not supported if(mode == privileged_mode_t.USER_MODE and not (rcs.support_umode_trap)): continue - 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], pkg_ins.hart_prefix(hart), tvec_name)) if(rcs.SATP_MODE != satp_mode_t.BARE and mode != privileged_mode_t.MACHINE_MODE): + # For supervisor and user mode, use virtual address instead of physical address. + # Virtual address starts from address 0x0, here only the lower 20 bits are kept + # as virtual address offset. instr.append("slli x{}, x{}, {}\n".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20) + "srli x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], rcs.XLEN - 20)) - instr.append("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode)) - instr.append("csrw {}, x{} # {}".format( - hex(trap_vec_reg), cfg.gpr[0], trap_vec_reg.name)) - + instr.extend(("ori x{}, x{}, {}".format(cfg.gpr[0], cfg.gpr[0], cfg.mtvec_mode), + "csrw {}, x{} # {}".format(hex(trap_vec_reg), cfg.gpr[0], + trap_vec_reg.name))) self.gen_section(pkg_ins.get_label("trap_vec_init", hart), instr) + # --------------------------------------------------------------------------------------- + # Exception handling routine + # --------------------------------------------------------------------------------------- + + # Trap handling routine def gen_all_trap_handler(self, hart): + instr = [] + # If PMP isn't supported, generate the relevant trap handler sections as per usual if not rcs.support_pmp: self.gen_trap_handlers(hart) + # Ecall handler self.gen_ecall_handler(hart) + # Instruction fault handler self.gen_instr_fault_handler(hart) + # Load fault handler self.gen_load_fault_handler(hart) + # Store fault handler self.gen_store_fault_handler(hart) + # Ebreak handler + self.gen_ebreak_handler(hart) + # Illegal instruction handler self.gen_illegal_instr_handler(hart) + # Generate page table fault handling routine + # Page table fault is always handled in machine mode, as virtual address translation may be + # broken when page fault happens. + self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, + core_status_t.HANDLING_EXCEPTION) + if not self.page_table_list: + # TODO + # self.page_table_list.gen_page_fault_handling_routine(instr) + pass + else: + instr.append("nop") + self.gen_section(pkg_ins.get_label("pt_fault_handler", hart), instr) def gen_trap_handlers(self, hart): + # TODO self.gen_trap_handler_section(hart, "m", privileged_reg_t.MCAUSE, privileged_reg_t.MTVEC, privileged_reg_t.MTVAL, privileged_reg_t.MEPC, privileged_reg_t.MSCRATCH, privileged_reg_t.MSTATUS, privileged_reg_t.MIE, privileged_reg_t.MIP) + # Generate the interrupt and trap handler for different privileged mode. + # The trap handler checks the xCAUSE to determine the type of the exception and jumps to + # corresponding exeception handling routine. def gen_trap_handler_section(self, hart, mode, cause, tvec, tval, epc, scratch, status, ie, ip): # is_interrupt = 1 @@ -546,7 +729,6 @@ def gen_trap_handler_section(self, hart, mode, cause, tvec, # Push user mode GPR to kernel stack before executing exception handling, # this is to avoid exception handling routine modify user program state # unexpectedly - # TODO pkg_ins.push_gpr_to_kernel_stack( status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) # Checking xStatus can be optional if ISS (like spike) has different implementation of @@ -554,6 +736,9 @@ def gen_trap_handler_section(self, hart, mode, cause, tvec, if cfg.check_xstatus: instr.append("csrr x{}, {} # {}".format( cfg.gpr[0], hex(status), status.name)) + # Use scratch CSR to save a GPR value + # Check if the exception is caused by an interrupt, if yes, jump to interrupt + # handler Interrupt is indicated by xCause[XLEN-1] instr.append("csrr x{}, {} # {}\n".format(cfg.gpr[0], hex(cause), cause.name) + "{}srli x{}, x{}, {}\n".format(pkg_ins.indent, cfg.gpr[0], @@ -564,26 +749,29 @@ def gen_trap_handler_section(self, hart, mode, cause, tvec, 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 != satp_mode_t.BARE: self.instr_stream.append(".align 12") else: self.instr_stream.append(".align {}".format(cfg.tvec_alignment)) - tvec_name = tvec.name self.gen_section(pkg_ins.get_label("{}_handler".format(tvec_name.lower()), hart), instr) - # TODO Exception handlers + + # Exception handler instr = [] if cfg.mtvec_mode == mtvec_mode_t.VECTORED: - pkg_ins.push_gpr_to_kernel_stack(status, scratch, - cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) + pkg_ins.push_gpr_to_kernel_stack( + status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr) self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, core_status_t.HANDLING_EXCEPTION) - # The trap is caused by an exception, read back xCAUSE, xEPC to see if these - # CSR values are set properly. The checking is done by comparing against the log - # generated by ISA simulator (spike). - instr.extend(("csrr x{}, 0x{} # {}".format(cfg.gpr[0], epc, epc.name), - "csrr x{}, 0x{} # {}".format(cfg.gpr[0], cause, cause.name), + # TODO + instr.extend(("csrr x{}, {} # {}".format(cfg.gpr[0], hex(epc), epc.name), + "csrr x{}, {} # {}".format(cfg.gpr[0], hex(cause), cause.name), + # Check if it's an ECALL exception. Jump to ECALL exception handler + # TODO ECALL_SMODE, ECALL_UMODE + "li x{}, {} # ECALL_MMODE".format(cfg.gpr[1], + hex(exception_cause_t.ECALL_MMODE)), + "beq x{}, x{}, {}ecall_handler".format( + cfg.gpr[0], cfg.gpr[1], pkg_ins.hart_prefix(hart)), # Illegal instruction exception "li x{}, {} # ILLEGAL_INSTRUCTION".format( cfg.gpr[1], hex(exception_cause_t.ILLEGAL_INSTRUCTION)), @@ -596,6 +784,7 @@ def gen_trap_handler_section(self, hart, mode, cause, tvec, "jalr x1, x{}, 0".format(cfg.scratch_reg))) self.gen_section(pkg_ins.get_label("{}mode_exception_handler".format(mode), hart), instr) + # Generate for interrupt vector table def gen_interrupt_vector_table(self, hart, mode, status, cause, ie, ip, scratch, instr): '''In vector mode, the BASE address is shared between interrupt 0 and exception handling. @@ -634,21 +823,37 @@ def gen_interrupt_vector_table(self, hart, mode, status, cause, ie, "jalr x0, x{}, 0".format(cfg.scratch_reg))) self.gen_section(pkg_ins.get_label( "{}mode_intr_vector_{}".format(mode, i), hart), intr_handler) + # ECALL trap handler + # It does some clean up like dump GPRs before communicating with host to terminate the test. + # User can extend this function if some custom clean up routine is needed. def gen_ecall_handler(self, hart): - string = "" - string = pkg_ins.format_string(pkg_ins.get_label( - "ecall_handler:", hart), pkg_ins.LABEL_STR_LEN) - self.instr_stream.append(string) - self.dump_perf_stats() - self.gen_register_dump() - string = pkg_ins.format_string(" ", pkg_ins.LABEL_STR_LEN) - string = string + "j write_tohost" - self.instr_stream.append(string) - + instr = [] + self.dump_perf_stats(instr) + self.gen_register_dump(instr) + instr.extend(("la x{}, write_tohost".format(cfg.scratch_reg), + "jalr x0, x{}, 0".format(cfg.scratch_reg))) + self.gen_section(pkg_ins.get_label("ecall_handler", hart), instr) + + # Ebreak trap handler + # When breakpoint exception happens, epc will be written with ebreak instruction + # itself. Add epc by 4 and resume execution. + # Note the breakpoint could be triggered by a C.EBREAK instruction, the generated program + # guarantees that epc + 4 is a valid instruction boundary + # TODO: Support random operations in debug mode + # TODO: Support ebreak exception delegation + # TODO: handshake the correct Xcause CSR based on delegation privil. mode def gen_ebreak_handler(self, hart): + # TODO pass + # Illegal instruction handler + # Note: Save the illegal instruction to MTVAL is optional in the spec, and mepc could be + # a virtual address that cannot be used in machine mode handler. As a result, there's no way to + # know the illegal instruction is compressed or not. This hanlder just simply adds the PC by + # 4 and resumes execution. The way that the illegal instruction is injected guarantees that + # PC + 4 is a valid instruction boundary. + # TODO: handshake the corret Xcause CSR based on delegation setup def gen_illegal_instr_handler(self, hart): instr = [] self.gen_signature_handshake(instr, signature_type_t.CORE_STATUS, @@ -662,24 +867,47 @@ def gen_illegal_instr_handler(self, hart): instr.append("mret") self.gen_section(pkg_ins.get_label("illegal_instr_handler", hart), instr) + # TODO: handshake correct csr based on delegation def gen_instr_fault_handler(self, hart): + # TODO pass + # TODO: handshake correct csr based on delegation def gen_load_fault_handler(self, hart): + # TODO pass + # TODO: handshake correct csr based on delegation def gen_store_fault_handler(self, hart): + # TODO pass + # --------------------------------------------------------------------------------------- + # Page table setup + # --------------------------------------------------------------------------------------- + + # Create page table if virtual address translation is supported. + # The page is created based on the address translation mode - SV32, SV39, SV48 + # Right now only the lowest level 4KB page table is configured as leaf page table entry (PTE), + # all the other super pages are link PTE. def create_page_table(self, hart): + # TODO pass + # Generate the page table section of the program + # The page table is generated as a group of continuous 4KB data sections. def gen_page_table_section(self, hart): + # TODO pass + # Only extend this function if the core utilizes a PLIC for handling interrupts + # In this case, the core will write to a specific location as the response to the interrupt, and + # external PLIC unit can detect this response and process the interrupt clean up accordingly. def gen_plic_section(self, interrupt_handler_instr): + # TODO pass + # Interrupt handler routine def gen_interrupt_handler_section(self, mode, hart): interrupt_handler_instr = [] # ls_unit = "w" if rcs.XLEN == 32 else "d" @@ -708,11 +936,12 @@ def gen_interrupt_handler_section(self, mode, hart): else: logging.critical("Unsupported mode: {}".format(mode.name)) sys.exit(1) - + # If nested interrupts are enabled, set xSTATUS.xIE in the interrupt handler + # to re-enable interrupt handling capabilities if cfg.enable_nested_interrupt: - interrupt_handler_instr.append("csrr x{}, {}".format(cfg.gpr[0], hex(scratch))) - interrupt_handler_instr.append("bgtz x{}, 1f".format(cfg.gpr[0])) - interrupt_handler_instr.append("csrwi {}, 0x1".format(hex(scratch))) + interrupt_handler_instr.extend(("csrr x{}, {}".format(cfg.gpr[0], hex(scratch)), + "bgtz x{}, 1f".format(cfg.gpr[0]), + "csrwi {}, 0x1".format(hex(scratch)))) if status == privileged_reg_t.MSTATUS: interrupt_handler_instr.append("csrsi {}, {}".format(hex(status), hex(8))) @@ -725,7 +954,8 @@ def gen_interrupt_handler_section(self, mode, hart): sys.exit(1) interrupt_handler_instr.append("1: csrwi {},0".format(hex(scratch))) - + # Read back interrupt related privileged CSR + # The value of these CSR are checked by comparing with spike simulation result. to_extend_interrupt_hanlder_instr = ["csrr x{}, {} # {};".format(cfg.gpr[0], hex(status), status.name), @@ -739,21 +969,30 @@ def gen_interrupt_handler_section(self, mode, hart): ip.name)] interrupt_handler_instr.extend(to_extend_interrupt_hanlder_instr) self.gen_plic_section(interrupt_handler_instr) + # Restore user mode GPR value from kernel stack before return pkg_ins.pop_gpr_from_kernel_stack(status, scratch, cfg.mstatus_mprv, cfg.sp, cfg.tp, interrupt_handler_instr) interrupt_handler_instr.append("{}ret;".format(mode_prefix)) if rcs.SATP_MODE != satp_mode_t.BARE: + # The interrupt handler will use one 4KB page self.instr_stream.append(".align 12") else: self.instr_stream.append(".align 2") - self.gen_section(pkg_ins.get_label("%0smode_intr_handler" % - (mode_prefix), hart), interrupt_handler_instr) + self.gen_section(pkg_ins.get_label("{}mode_intr_handler".format(mode_prefix), hart), + interrupt_handler_instr) + + # --------------------------------------------------------------------------------------- + # Helper functions + # --------------------------------------------------------------------------------------- + # Format a code section, without generating it def format_section(self, instr): + # TODO pass + # Generate a code section def gen_section(self, label, instr): if label != "": string = pkg_ins.format_string("{}:".format(label), pkg_ins.LABEL_STR_LEN) @@ -763,9 +1002,12 @@ def gen_section(self, label, instr): self.instr_stream.append(string) self.instr_stream.append("") - def dump_perf_stats(self): + # Dump performance CSRs if applicable + def dump_perf_stats(self, instr): + # TODO pass + # Write the generated program to a file def gen_test_file(self, test_name): file = open(test_name, "w+") for items in self.instr_stream: @@ -774,6 +1016,8 @@ def gen_test_file(self, test_name): file.close() logging.info("{} is generated".format(test_name)) + # Helper function to generate the proper sequence of handshake instructions + # to signal the testbench (see riscv_signature_pkg.sv) def gen_signature_handshake(self, instr, signature_type, core_status=core_status_t.INITIALIZED, test_result=test_result_t.TEST_FAIL, @@ -828,6 +1072,10 @@ def gen_signature_handshake(self, instr, signature_type, logging.critical("signature_type is not defined") sys.exit(1) + # --------------------------------------------------------------------------------------- + # Inject directed instruction stream + # --------------------------------------------------------------------------------------- + def add_directed_instr_stream(self, name, ratio): self.directed_instr_stream_ratio[name] = ratio logging.info("Adding directed instruction stream:%0s ratio:%0d/1000", name, ratio) @@ -852,6 +1100,7 @@ def get_directed_instr_stream(self): stream_freq = cfg.args_dict[stream_freq_opts] self.add_directed_instr_stream(stream_name, stream_freq) + # Generate directed instruction stream based on the ratio setting def generate_directed_instr_stream(self, hart = 0, label = "", original_instr_cnt = 0, min_insert_cnt = 0, kernel_mode = 0, instr_stream = []): instr_insert_cnt = 0 @@ -885,5 +1134,18 @@ def generate_directed_instr_stream(self, hart = 0, label = "", original_instr_cn idx += 1 random.shuffle(instr_stream) + # ---------------------------------------------------------------------------------- + # Generate the debug ROM, and any related programs + # ---------------------------------------------------------------------------------- + def gen_debug_rom(self, hart): + # TODO + pass + + # ---------------------------------------------------------------------------------- + # Vector extension generation + # ---------------------------------------------------------------------------------- + + def randomize_vec_gpr_and_csr(self): + # TODO pass diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py index 03a4499f02..ac8e91f3a9 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_data_page_gen.py @@ -14,16 +14,23 @@ import vsc import random from collections import defaultdict -from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t from pygen_src.riscv_instr_gen_config import cfg +from pygen_src.riscv_instr_pkg import pkg_ins, data_pattern_t +# ----------------------------------------------------------------------------------------- +# RISC-V assmebly program data section generator +# There can be user mode and supervisor(kernel) mode data pages +# ----------------------------------------------------------------------------------------- + @vsc.randobj class riscv_data_page_gen: def __init__(self): self.data_page_str = [] self.mem_region_setting = defaultdict(list) + # The data section can be initialized with different data pattern: + # - Random value, incremental value, all zeros @staticmethod def gen_data(idx, pattern, num_of_bytes, data): temp_data = 0 @@ -36,10 +43,9 @@ def gen_data(idx, pattern, num_of_bytes, data): data[i] = (idx + i) % 256 return data + # Generate data pages for all memory regions def gen_data_page(self, hart_id, pattern, is_kernel=0, amo=0): - tmp_str = "" temp_data = [] - page_size = 0 self.data_page_str.clear() if is_kernel: self.mem_region_setting = cfg.s_mem_region @@ -47,8 +53,6 @@ def gen_data_page(self, hart_id, pattern, is_kernel=0, amo=0): self.mem_region_setting = cfg.amo_region else: self.mem_region_setting = cfg.mem_region - for i in range(len(self.mem_region_setting)): - logging.info("mem_region_setting {}".format(self.mem_region_setting[i])) for i in range(len(self.mem_region_setting)): logging.info("Generate data section: {} size:0x{} xwr:0x{}".format( self.mem_region_setting[i].name, diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py index cbdbb262d4..3b545f3064 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_defines.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py index 0d6784b7a4..91e4823fea 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_directed_instr_lib.py @@ -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 @@ -20,14 +19,13 @@ from pygen_src.riscv_instr_stream import riscv_rand_instr_stream from pygen_src.isa.riscv_instr import riscv_instr from pygen_src.riscv_instr_gen_config import cfg -from pygen_src.riscv_instr_pkg import (riscv_reg_t, - riscv_pseudo_instr_name_t, - riscv_instr_name_t, pkg_ins, - mem_region_t) +from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_pseudo_instr_name_t, + riscv_instr_name_t, mem_region_t, pkg_ins) from pygen_src.riscv_pseudo_instr import riscv_pseudo_instr rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") +# Base class for directed instruction stream class riscv_directed_instr_stream(riscv_rand_instr_stream): label = "" @@ -47,6 +45,7 @@ def post_randomize(self): self.instr_list[0].has_label = 1 +# Base class for memory access stream @vsc.randobj class riscv_mem_access_stream(riscv_directed_instr_stream): def __init__(self): @@ -65,6 +64,7 @@ def pre_randomize(self): self.data_page.extend(cfg.mem_region) self.max_data_page_id = len(self.data_page) + # Use "la" instruction to initialize the base regiseter 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 @@ -79,6 +79,7 @@ def add_rs1_init_la_instr(self, gpr, idx, base = 0): cfg.mem_region[idx].name, base) self.instr_list.insert(0, la_instr) + # Insert some other instructions to mix with mem_access instruction def add_mixed_instr(self, instr_cnt): self.setup_allowed_instr(1, 1) for i in range(instr_cnt): @@ -87,6 +88,7 @@ def add_mixed_instr(self, instr_cnt): self.insert_instr(instr) +# Stress back to back jump instruction @vsc.randobj class riscv_jal_instr(riscv_rand_instr_stream): def __init__(self): @@ -96,6 +98,7 @@ def __init__(self): self.jump_start = riscv_instr() self.jump_end = riscv_instr() self.num_of_jump_instr = vsc.rand_int_t() + self.jal = [] @vsc.constraint def instr_c(self): @@ -115,6 +118,8 @@ def post_randomize(self): jal.append(riscv_instr_name_t.C_J) if rcs.XLEN == 32: jal.append(riscv_instr_name_t.C_JAL) + + # First instruction 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 @@ -157,6 +162,7 @@ class int_numeric_e(IntEnum): NegativeMax = auto() +# Strees the numeric corner cases of integer arithmetic operations @vsc.randobj class riscv_int_numeric_corner_stream(riscv_directed_instr_stream): def __init__(self): @@ -185,6 +191,7 @@ def avail_regs_c(self): self.avail_regs[i] != riscv_reg_t.ZERO def pre_randomize(self): + # TODO pass def post_randomize(self): @@ -212,7 +219,6 @@ def post_randomize(self): # Push Stack Instructions class riscv_push_stack_instr(riscv_rand_instr_stream): - def __init__(self): super().__init__() self.stack_len = 0 @@ -225,12 +231,13 @@ def __init__(self): self.push_start_label = '' def init(self): + # Save RA, T0 self.reserved_rd = [cfg.ra] self.saved_regs = [cfg.ra] self.num_of_reg_to_save = len(self.saved_regs) if self.num_of_reg_to_save * (rcs.XLEN / 8) > self.stack_len: - logging.error('stack len [%0d] is not enough to store %d regs', - self.stack_len, self.num_of_reg_to_save) + logging.error('stack len [{}] is not enough to store {} regs' + .format(self.stack_len, self.num_of_reg_to_save)) sys.exit(1) self.num_of_redundant_instr = random.randrange(3, 10) self.initialize_instr_list(self.num_of_redundant_instr) @@ -288,7 +295,6 @@ def gen_push_stack_instr(self, stack_len, allow_branch=1): # Pop stack instruction stream class riscv_pop_stack_instr(riscv_rand_instr_stream): - def __init__(self): super().__init__() self.stack_len = 0 @@ -301,8 +307,8 @@ def init(self): self.reserved_rd = [cfg.ra] self.num_of_reg_to_save = len(self.saved_regs) if self.num_of_reg_to_save * 4 > self.stack_len: - logging.error('stack len [%0d] is not enough to store %d regs', - self.stack_len, self.num_of_reg_to_save) + logging.error('stack len [{}] is not enough to store {} regs' + .format(self.stack_len, self.num_of_reg_to_save)) sys.exit(1) self.num_of_redundant_instr = random.randrange(3, 10) self.initialize_instr_list(self.num_of_redundant_instr) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py index 3f534a44f6..4be43bce17 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_illegal_instr.py @@ -162,8 +162,8 @@ def compressed_instr_op_c(self): @vsc.constraint def b_extension_c(self): if riscv_instr_group_t.RV32B in rcs.supported_isa: - with vsc.if_then(self.exception in [illegal_instr_type_e.kIllegalFunc3, - illegal_instr_type_e.kIllegalFunc7]): + with vsc.if_then(self.exception.inside(vsc.rangelist(illegal_instr_type_e.kIllegalFunc3, + illegal_instr_type_e.kIllegalFunc7))): self.opcode.inside(vsc.rangelist([51, 19, 59])) @vsc.constraint @@ -338,7 +338,7 @@ def illegal_func7_c(self): def initialize(self): if (riscv_instr_group_t.RV32F in rcs.supported_isa) or \ (riscv_instr_group_t.RV32D in rcs.supported_isa): - self.legal_opcode.extend(7, 39, 67, 71, 75, 79, 83) + self.legal_opcode.extend((7, 39, 67, 71, 75, 79, 83)) if riscv_instr_group_t.RV64I in rcs.supported_isa: self.legal_opcode.append(27) if riscv_instr_group_t.RV32A in rcs.supported_isa: @@ -347,8 +347,8 @@ def initialize(self): (riscv_instr_group_t.RV64M in rcs.supported_isa): self.legal_opcode.append(59) if riscv_instr_group_t.RV64I in rcs.supported_isa: - self.legal_c00_opcode.extend(3, 7) - self.legal_c10_opcode.extend(3, 7) + self.legal_c00_opcode.extend((3, 7)) + self.legal_c10_opcode.extend((3, 7)) # TODO csr def get_bin_str(self): diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py index b020e3d932..4912face34 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_cover_group.py @@ -13,6 +13,7 @@ limitations under the License. """ +import traceback from pygen_src.isa.riscv_cov_instr import * @@ -1381,6 +1382,195 @@ def __init__(self): self.cp_align = vsc.cross([self.cp_imm_align, self.cp_rs1_align]) self.cp_ras = vsc.cross([self.cp_rs1_link, self.cp_rd_link]) + '''MUL instructions''' + @vsc.covergroup + class mul_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + @vsc.covergroup + class mulh_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + @vsc.covergroup + class mulhsu_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + @vsc.covergroup + class mulhu_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + @vsc.covergroup + class div_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result, + cp_t=vsc.enum_t(div_result_e)) + + @vsc.covergroup + class divu_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result, + cp_t=vsc.enum_t(div_result_ex_overflow_e)) + + @vsc.covergroup + class rem_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result, + cp_t=vsc.enum_t(div_result_e)) + + @vsc.covergroup + class remu_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_t)) + self.cp_rs1_sign = vsc.coverpoint(lambda: self.instr.rs1_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_rd_sign = vsc.coverpoint(lambda: self.instr.rd_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_sign_cross = vsc.cross([self.cp_rs1_sign, self.cp_rs2_sign, + self.cp_rd_sign]) + self.cp_div_result = vsc.coverpoint(lambda: self.instr.div_result, + cp_t=vsc.enum_t(div_result_ex_overflow_e)) + '''CSR instructions''' @vsc.covergroup @@ -1402,7 +1592,7 @@ def __init__(self): super().__init__() self.instr = None - self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[7:2], + self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[6:2], bins={ "a": vsc.bin_array([], [0, 31]) } @@ -1430,11 +1620,430 @@ def __init__(self): } ) + @vsc.covergroup + class hint_cg(object): + def __init__(self): + super().__init__() + self.instr = None + self.cp_hint0 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(addi=vsc.wildcard_bin_array([], + "0b0000_1xxx_x000_0001", + "0b0000_x1xx_x000_0001", + "0b0000_xx1x_x000_0001", + "0b0000_xxx1_x000_0001", + "0b0000_xxxx_1000_0001"))) + self.cp_hint1 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(li=vsc.wildcard_bin( + "0b010x_0000_0xxx_xx01"))) + self.cp_hint2 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(lui=vsc.wildcard_bin( + "0b011x_0000_0xxx_xx01"))) + self.cp_hint3 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(srli64=vsc.wildcard_bin( + "0b1000_00xx_x000_0001"))) + self.cp_hint4 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(srai64=vsc.wildcard_bin( + "0b1000_01xx_x000_0001"))) + self.cp_hint5 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(slli=vsc.wildcard_bin( + "0b000x_0000_0xxx_xx10"))) + self.cp_hint6 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(slli64=vsc.wildcard_bin( + "0b0000_xxxx_x000_0010"))) + self.cp_hint7 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(mv=vsc.wildcard_bin_array([], + "0b1000_0000_01xx_xx10", + "0b1000_0000_0x1x_xx10", + "0b1000_0000_0xx1_xx10", + "0b1000_0000_0xxx_1x10", + "0b1000_0000_0xxx_x110"))) + self.cp_hint8 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins=dict(add=vsc.wildcard_bin_array([], + "0b1001_0000_01xx_xx10", + "0b1001_0000_0x1x_xx10", + "0b1001_0000_0xx1_xx10", + "0b1001_0000_0xxx_1x10", + "0b1001_0000_0xxx_x110" + ))) + + @vsc.covergroup + class illegal_compressed_instr_cg(object): + def __init__(self): + super().__init__() + self.instr = None + self.cp_point0 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_illegal=vsc.wildcard_bin( + "0b0000_0000_0000_0000"))) + self.cp_point1 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_addi4spn=vsc.wildcard_bin_array([], + "0b0000_0000_000x_x100", + "0b0000_0000_000x_1x00", + "0b0000_0000_0001_xx00"))) + self.cp_point2 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_addiw=vsc.wildcard_bin( + "0b001x_0000_0xxx_xx01"))) + self.cp_point3 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_addi16sp=vsc.wildcard_bin( + "0b0110_0001_0000_0001"))) + self.cp_point4 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_lui=vsc.wildcard_bin_array([], + "0b0110_xxxx_1000_0001", + "0b0110_xx1x_x000_0001", + "0b0110_x1xx_x000_0001", + "0b0110_1xxx_x000_0001"))) + self.cp_point5 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_reserv_0=vsc.wildcard_bin( + "0b1001_11xx_x10x_xx01"))) + self.cp_point6 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_reserv_1=vsc.wildcard_bin( + "0b1001_11xx_x11x_xx01"))) + self.cp_point7 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_jr=vsc.wildcard_bin( + "0b1000_0000_0000_0010"))) + self.cp_point8 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_lwsp=vsc.wildcard_bin( + "0b010x_0000_0xxx_xx10"))) + self.cp_point9 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_lqsp=vsc.wildcard_bin( + "0b001x_0000_0xxx_xx10"))) + self.cp_point10 = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins = dict(c_ldsp=vsc.wildcard_bin( + "0b011x_0000_0xxx_xx10"))) + + '''Compressed instructions''' + + @vsc.covergroup + class compressed_opcode_cg(object): + # TODO issue with iff parameter + def __init__(self): + super().__init__() + self.instr = None + '''self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[15:0], + bins={ + "a": vsc.bin_array([], [0, 31]) + } + )''' + + @vsc.covergroup + class c_lw_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + + @vsc.covergroup + class c_lwsp_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + + @vsc.covergroup + class c_sw_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard, + cp_t=vsc.enum_t(store_lsu_hazard_e)) + + @vsc.covergroup + class c_swsp_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + + @vsc.covergroup + class c_addi4spn_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(store_lsu_hazard_e)) + + @vsc.covergroup + class c_addi_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(store_lsu_hazard_e)) + + @vsc.covergroup + class c_addi16sp_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(store_lsu_hazard_e)) + + @vsc.covergroup + class c_li_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(store_lsu_hazard_e)) + + @vsc.covergroup + class c_lui_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_sp_t)) + + @vsc.covergroup + class c_sub_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_add_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_mv_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign, + cp_t=vsc.enum_t(operand_sign_e)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_andi_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + + @vsc.covergroup + class c_xor_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_or_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_and_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(hazard_e)) + + @vsc.covergroup + class c_beqz_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + + @vsc.covergroup + class c_bnez_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + + @vsc.covergroup + class c_srli_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + + @vsc.covergroup + class c_srai_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(compressed_gpr)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + + @vsc.covergroup + class c_slli_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rd = vsc.coverpoint(lambda: self.instr.rd, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard, + cp_t=vsc.enum_t(branch_hazard_e)) + + @vsc.covergroup + class c_j_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + + @vsc.covergroup + class c_jal_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign, + cp_t=vsc.enum_t(operand_sign_e)) + + @vsc.covergroup + class c_jr_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0], + bins={ + "Zero" : vsc.bin(0), + "One" : vsc.bin(1), + "Two" : vsc.bin(2), + "Three": vsc.bin(3) + }) + + @vsc.covergroup + class c_jalr_cg(object): + def __init__(self): + super().__init__() + + self.instr = None + self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1, + cp_t=vsc.enum_t(riscv_reg_ex_zero_t)) + self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0], + bins={ + "Zero" : vsc.bin(0), + "One" : vsc.bin(1), + "Two" : vsc.bin(2), + "Three": vsc.bin(3) + }) + self.cp_rd_align = vsc.coverpoint(lambda: self.instr.rd_value[1], + bins={ + "Aligned" : vsc.bin(1), + "Not-aligned": vsc.bin(0) + }) + def cg_instantiation(self): self.opcode_cg_i = self.opcode_cg() self.csrrw_cg_i = self.csrrw_cg() self.rv32i_misc_cg_i = self.rv32i_misc_cg() self.mepc_alignment_cg_i = self.mepc_alignment_cg() + # self.compressed_opcode_cg_i = self.compressed_opcode_cg() self.beq_cg_i = self.beq_cg() self.jal_cg_i = self.jal_cg() self.lui_cg_i = self.lui_cg() @@ -1458,13 +2067,56 @@ def cg_instantiation(self): self.srai_cg_i = self.srai_cg() self.slt_cg_i = self.slt_cg() self.slli_cg_i = self.slli_cg() + self.mul_cg_i = self.mul_cg() + self.mulh_cg_i = self.mulh_cg() + self.mulhsu_cg_i = self.mulhsu_cg() + self.mulhu_cg_i = self.mulhu_cg() + self.div_cg_i = self.div_cg() + self.divu_cg_i = self.divu_cg() + self.rem_cg_i = self.rem_cg() + self.remu_cg_i = self.remu_cg() + self.c_lw_cg_i = self.c_lw_cg() + self.c_lwsp_cg_i = self.c_lwsp_cg() + self.c_sw_cg_i = self.c_sw_cg() + self.c_swsp_cg_i = self.c_swsp_cg() + self.c_addi4spn_cg_i = self.c_addi4spn_cg() + self.c_addi_cg_i = self.c_addi_cg() + self.c_addi16sp_cg_i = self.c_addi16sp_cg() + self.c_li_cg_i = self.c_li_cg() + self.c_lui_cg_i = self.c_lui_cg() + self.c_sub_cg_i = self.c_sub_cg() + self.c_add_cg_i = self.c_add_cg() + self.c_mv_cg_i = self.c_mv_cg() + self.c_andi_cg_i = self.c_andi_cg() + self.c_xor_cg_i = self.c_xor_cg() + self.c_or_cg_i = self.c_or_cg() + self.c_and_cg_i = self.c_and_cg() + self.c_beqz_cg_i = self.c_beqz_cg() + self.c_bnez_cg_i = self.c_bnez_cg() + self.c_srli_cg_i = self.c_srli_cg() + self.c_srai_cg_i = self.c_srai_cg() + self.c_slli_cg_i = self.c_slli_cg() + self.c_j_cg_i = self.c_j_cg() + self.c_jal_cg_i = self.c_jal_cg() + self.c_jr_cg_i = self.c_jr_cg() + self.c_jalr_cg_i = self.c_jalr_cg() + self.hint_cg_i = self.hint_cg() + self.illegal_compressed_instr_cg_i = self.illegal_compressed_instr_cg() def sample(self, instr): self.instr_cnt += 1 if self.instr_cnt > 1: instr.check_hazard_condition(self.pre_instr) - # TODO: sampling for hint, compressed, and illegal_compressed insts - if instr.binary[2:0] == 3: + # TODO: sampling for compressed_instr_cg + if ((instr.binary[1:0] != 3) and (riscv_instr_group_t.RV32C in rcs.supported_isa)): + # self.compressed_opcode_cg_i.instr = instr + # self.compressed_opcode_cg_i.sample() + self.hint_cg_i.instr = instr + self.hint_cg_i.sample() + self.illegal_compressed_instr_cg_i.instr = instr + self.illegal_compressed_instr_cg_i.sample() + + if instr.binary[1:0] == 3: self.opcode_cg_i.instr = instr self.opcode_cg_i.sample() try: @@ -1474,6 +2126,9 @@ def sample(self, instr): except Exception: logging.info("Covergroup for instr {} is not supported yet".format( instr.instr.name)) + # Trace the error if there is an Exception + logging.info("Traceback error log: {}".format(traceback.format_exc())) + if instr.group.name == "RV32I": self.rv32i_misc_cg_i.instr = instr self.rv32i_misc_cg_i.sample() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py index 0de86af6cb..f99fd4b10d 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_gen_config.py @@ -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 @@ -9,7 +8,6 @@ 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 @@ -22,19 +20,48 @@ riscv_reg_t, privileged_mode_t, riscv_instr_group_t, data_pattern_t, riscv_instr_category_t, satp_mode_t, - mem_region_t) + mem_region_t, vreg_init_method_t) + +# ---------------------------------------------------------------------------- +# RISC-V assembly program generator configuration class +# ---------------------------------------------------------------------------- @vsc.randobj class riscv_instr_gen_config: + def __init__(self): - 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 + # --------------------------------------------------------------------------- + # Random instruction generation settings + # --------------------------------------------------------------------------- + + # Instruction count of the main program + self.main_program_instr_cnt = vsc.rand_int32_t() + + # Instruction count of each sub-program + self.sub_program_instr_cnt = [] + + # Instruction count of the debug rom + self.debug_program_instr_cnt = 0 + + # Instruction count of debug sub-programs + self.debug_sub_program_instr_cnt = [] + + # Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL self.data_page_pattern = vsc.rand_enum_t(data_pattern_t) + # Initialization of the vregs + # SAME_VALUES_ALL_ELEMS - Using vmv.v.x to fill all the elements of the vreg with + # the same value as the one in the GPR selected + # RANDOM_VALUES_VMV - Using vmv.v.x + vslide1up.vx to randomize the contents + # of each vector element + # RANDOM_VALUES_LOAD - Using vle.v, same approach as RANDOM_VALUES_VMV but more + # efficient for big VLEN + self.vreg_init_method = vreg_init_method_t.RANDOM_VALUES_VMV + + # Maximum directed instruction stream sequence count + self.max_directed_instr_stream_seq = 20 + self.init_delegation() self.argv = self.parse_args() self.args_dict = vars(self.argv) @@ -42,12 +69,16 @@ def __init__(self): global rcs rcs = import_module("pygen_src.target." + self.argv.target + ".riscv_core_setting") + # Dict for delegation configuration for each exception and interrupt + # When the bit is 1, the corresponding delegation is enabled. + # TODO self.m_mode_exception_delegation = {} self.s_mode_exception_delegation = {} self.m_mode_interrupt_delegation = {} self.s_mode_interrupt_delegation = {} # init_privileged_mode default to MACHINE_MODE + # TODO: remove defult machine_mode once all modes get supported self.init_privileged_mode = privileged_mode_t.MACHINE_MODE self.mstatus = vsc.rand_bit_t(rcs.XLEN - 1) @@ -57,6 +88,8 @@ def __init__(self): self.ustatus = vsc.rand_bit_t(rcs.XLEN - 1) self.uie = vsc.rand_bit_t(rcs.XLEN - 1) + # Key fields in xSTATUS + # Memory protection bits self.mstatus_mprv = vsc.rand_bit_t(1) self.mstatus_mxr = vsc.rand_bit_t(1) self.mstatus_sum = vsc.rand_bit_t(1) @@ -65,25 +98,55 @@ def __init__(self): self.mstatus_vs = vsc.rand_bit_t(2) self.mtvec_mode = vsc.rand_enum_t(mtvec_mode_t) - self.tvec_alignment = vsc.rand_uint8_t(self.argv.tvec_alignment) + # TVEC alignment + # This value is the log_2 of the byte-alignment of TVEC.BASE field + # As per RISC-V privileged spec, default will be set to 2 (4-byte aligned) + self.tvec_alignment = vsc.rand_uint32_t(self.argv.tvec_alignment) + # Floating point rounding mode self.fcsr_rm = vsc.rand_enum_t(f_rounding_mode_t) + + # Enable sfence.vma instruction self.enable_sfence = vsc.rand_bit_t(1) + + # Reserved register + # Reserved for various hardcoded routines self.gpr = vsc.rand_list_t(vsc.enum_t(riscv_reg_t), sz=4) + # Used by any DCSR operations inside of the debug rom. + # Also used by the PMP generation. self.scratch_reg = vsc.rand_enum_t(riscv_reg_t) + + # Reg used exclusively by the PMP exception handling routine. + # Can overlap with the other GPRs used in the random generation, + # as PMP exception handler is hardcoded and does not include any + # random instructions. self.pmp_reg = vsc.rand_enum_t(riscv_reg_t) + + # Use a random register for stack pointer/thread pointer self.sp = vsc.rand_enum_t(riscv_reg_t) self.tp = vsc.rand_enum_t(riscv_reg_t) self.ra = vsc.rand_enum_t(riscv_reg_t) + + # Options for privileged mode CSR checking + # Below checking can be made optional as the ISS implementation + # could be different with the processor. self.check_misa_init_val = 0 self.check_xstatus = 1 - self.virtual_addr_translation_on = 0 + + # Virtual address translation is on for this test + self.virtual_addr_translation_on = vsc.rand_bit_t(1) # Commenting out for now - # vector_cfg = riscv_vector_cfg # TODO + # vector_cfg = riscv_vector_cfg # TODO # pmp_cfg = riscv_pmp_cfg # TODO + # Stack section word length + self.stack_len = 5000 + + # ----------------------------------------------------------------------------- + # User space memory region and stack setting + # ----------------------------------------------------------------------------- self.mem_region = vsc.list_t(mem_region_t()) self.amo_region = vsc.list_t(mem_region_t()) self.s_mem_region = vsc.list_t(mem_region_t()) @@ -92,37 +155,52 @@ def __init__(self): self.amo_region.extend([mem_region_t(name = "amo_0", size_in_bytes = 64, xwr = 8)]) self.s_mem_region.extend([mem_region_t(name = "s_region_0", size_in_bytes = 4096, xwr = 8), mem_region_t(name = "s_region_1", size_in_bytes = 4096, xwr = 8)]) - - self.stack_len = 5000 + # Kernel Stack section word length self.kernel_stack_len = 4000 + + # Number of instructions for each kernel program self.kernel_program_instr_cnt = 400 - # list of main implemented CSRs + + # List of all the main implemented CSRs that the boot privilege mode cannot access + # e.g. these CSRs are in higher privilege modes - access should raise an exception self.invalid_priv_mode_csrs = [] + + # ----------------------------------------------------------------------------- + # Command line options or control knobs + # ----------------------------------------------------------------------------- + # Main options for RISC-V assembly program generation + # Number of sub-programs per test self.num_of_sub_program = self.argv.num_of_sub_program self.instr_cnt = self.argv.instr_cnt self.num_of_tests = self.argv.num_of_tests + # For tests doesn't involve load/store, the data section generation could be skipped self.no_data_page = self.argv.no_data_page - self.no_branch_jump = self.argv.no_branch_jump - self.no_load_store = self.argv.no_load_store - self.no_csr_instr = self.argv.no_csr_instr - self.no_ebreak = self.argv.no_ebreak - self.no_dret = self.argv.no_dret - self.no_fence = self.argv.no_fence - self.no_wfi = self.argv.no_wfi + # Options to turn off some specific types of instructions + self.no_branch_jump = self.argv.no_branch_jump # No branch/jump instruction + self.no_load_store = self.argv.no_load_store # No load/store instruction + self.no_csr_instr = self.argv.no_csr_instr # No csr instruction + self.no_ebreak = self.argv.no_ebreak # No ebreak instruction + self.no_dret = self.argv.no_dret # No dret instruction + self.no_fence = self.argv.no_fence # No fence instruction + self.no_wfi = self.argv.no_wfi # No WFI instruction self.enable_unaligned_load_store = self.argv.enable_unaligned_load_store self.illegal_instr_ratio = self.argv.illegal_instr_ratio self.hint_instr_ratio = self.argv.hint_instr_ratio + # Number of harts to be simulated, must be <= NUM_HARTS if self.argv.num_of_harts is None: self.num_of_harts = rcs.NUM_HARTS else: self.num_of_harts = self.argv.num_of_harts + # Use SP as stack pointer + self.fix_sp = vsc.bit_t(1) self.fix_sp = self.argv.fix_sp + # Use push/pop section for data pages self.use_push_data_section = self.argv.use_push_data_section + # Directed boot privileged mode, u, m, s self.boot_mode_opts = self.argv.boot_mode # self.isa = self.argv.isa - if self.boot_mode_opts: - logging.info("Got boot mode option - %0s", self.boot_mode_opts) + logging.info("Got boot mode option - {}".format(self.boot_mode_opts)) if self.boot_mode_opts == "m": self.init_privileged_mode = privileged_mode_t.MACHINE_MODE elif self.boot_mode_opts == "s": @@ -130,50 +208,89 @@ def __init__(self): elif self.boot_mode_opts == "u": self.init_privileged_mode = privileged_mode_t.USER_MODE else: - logging.error("Illegal boot mode option - %0s", self.boot_mode_opts) - + logging.error("Illegal boot mode option - {}".format(self.boot_mode_opts)) self.enable_page_table_exception = self.argv.enable_page_table_exception self.no_directed_instr = self.argv.no_directed_instr self.asm_test_suffix = self.argv.asm_test_suffix + # Enable interrupt bit in MSTATUS (MIE, SIE, UIE) self.enable_interrupt = self.argv.enable_interrupt self.enable_nested_interrupt = self.argv.enable_nested_interrupt + # We need a separate control knob for enabling timer interrupts, as Spike + # throws an exception if xIE.xTIE is enabled self.enable_timer_irq = self.argv.enable_timer_irq + # Generate a bare program without any init/exit/error handling/page table routines + # The generated program can be integrated with a larger program. + # Note that the bare mode program is not expected to run in standalone mode self.bare_program_mode = self.argv.bare_program_mode + # Enable accessing illegal CSR instruction + # - Accessing non-existence CSR + # - Accessing CSR with wrong privileged mode self.enable_illegal_csr_instruction = self.argv.enable_illegal_csr_instruction + # Enable accessing CSRs at an invalid privilege level self.enable_access_invalid_csr_level = self.argv.enable_access_invalid_csr_level + # Enable misaligned instruction (caused by JALR instruction) self.enable_misaligned_instr = self.argv.enable_misaligned_instr + # Enable some dummy writes to main system CSRs (xSTATUS/xIE) at beginning of test + # to check repeated writes self.enable_dummy_csr_write = self.argv.enable_dummy_csr_write self.randomize_csr = self.argv.randomize_csr + # sfence support self.allow_sfence_exception = self.argv.allow_sfence_exception + # Interrupt/Exception Delegation self.no_delegation = self.argv.no_delegation self.force_m_delegation = self.argv.force_m_delegation self.force_s_delegation = self.argv.force_s_delegation - self.support_supervisor_mode = 0 + self.support_supervisor_mode = 0 # TODO self.disable_compressed_instr = self.argv.disable_compressed_instr self.require_signature_addr = self.argv.require_signature_addr - if self.require_signature_addr: self.signature_addr = int(self.argv.signature_addr, 16) else: self.signature_addr = 0xdeadbeef - + # Enable a full or empty debug_rom section. + # Full debug_rom will contain random instruction streams. + # Empty debug_rom will contain just dret instruction and will return immediately. + # Will be empty by default. self.gen_debug_section = self.argv.gen_debug_section + # Enable generation of a directed sequence of instructions containing + # ebreak inside the debug_rom. + # Disabled by default. self.enable_ebreak_in_debug_rom = self.argv.enable_ebreak_in_debug_rom + # Enable setting dcsr.ebreak(m/s/u) self.set_dcsr_ebreak = self.argv.set_dcsr_ebreak + # Number of sub programs in the debug rom self.num_debug_sub_program = self.argv.num_debug_sub_program + # Enable debug single stepping self.enable_debug_single_step = self.argv.enable_debug_single_step - self.single_step_iterations = 0 + # Number of single stepping iterations + self.single_step_iterations = vsc.rand_uint32_t() + # Enable mstatus.tw bit - causes u-mode WFI to raise illegal instruction exceptions self.set_mstatus_tw = self.argv.set_mstatus_tw + # Enable users to set mstatus.mprv to enable privilege checks on memory accesses. self.set_mstatus_mprv = vsc.bit_t(1) self.set_mstatus_mprv = self.argv.set_mstatus_mprv - self.min_stack_len_per_program = 10 * (rcs.XLEN / 8) - self.max_stack_len_per_program = 16 * (rcs.XLEN / 8) + # Stack space allocated to each program, need to be enough to store necessary context + # Example: RA, SP, T0 + self.min_stack_len_per_program = 10 * (rcs.XLEN // 8) + self.max_stack_len_per_program = 16 * (rcs.XLEN // 8) + # Maximum branch distance, avoid skipping large portion of the code self.max_branch_step = 20 + # Reserved registers self.reserved_regs = vsc.list_t(vsc.enum_t(riscv_reg_t)) + # Floating point support + self.enable_floating_point = vsc.bit_t(1) self.enable_floating_point = self.argv.enable_floating_point + # Vector extension support self.enable_vector_extension = self.argv.enable_vector_extension + # Only generate vector instructions + self. vector_instr_only = vsc.bit_t(1) + # Bit manipulation extension support self.enable_b_extension = self.argv.enable_b_extension self.enable_bitmanip_groups = self.argv.enable_bitmanip_groups + + # ----------------------------------------------------------------------------- + # Command line options for instruction distribution control + # ----------------------------------------------------------------------------- self.dist_control_mode = 0 self.category_dist = {} self.march_isa = self.argv.march_isa @@ -198,11 +315,72 @@ def __init__(self): @vsc.constraint def default_c(self): + # TODO Add constraint related to sub_program self.main_program_instr_cnt in vsc.rangelist(vsc.rng(10, self.instr_cnt)) + @vsc.constraint + def debug_mode_c(self): + # TODO + pass + + # Keep the number of single step iterations relatively small + @vsc.constraint + def debug_single_step_c(self): + # TODO + pass + + # Boot privileged mode distribution + @vsc.constraint + def boot_privileged_mode_dist_c(self): + # Boot to higher privileged mode more often + # TODO + pass + + @vsc.constraint + def mtvec_c(self): + self.mtvec_mode.inside(vsc.rangelist(self.supported_interrupt_mode)) + with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT): + vsc.soft(self.tvec_alignment == 2) + with vsc.else_then(): + # Setting MODE = Vectored may impose an additional alignmentconstraint on BASE, + # requiring up to 4×XLEN-byte alignment + vsc.soft(self.tvec_alignment == self.tvec_ceil) + + @vsc.constraint + def mstatus_c(self): + with vsc.if_then(self.set_mstatus_mprv == 1): + self.mstatus_mprv == 1 + with vsc.else_then(): + self.mstatus_mprv == 0 + with vsc.if_then(self.SATP_MODE == satp_mode_t.BARE): + self.mstatus_mxr == 0 + self.mstatus_sum == 0 + self.mstatus_tvm == 0 + + # Exception delegation setting + @vsc.constraint + def exception_delegation_c(self): + # Do not delegate instruction page fault to supervisor/user mode because this may introduce + # dead loop. All the subsequent instruction fetches may fail and program cannot recover. + # TODO + pass + + # Spike only supports a subset of exception and interrupt delegation + # You can modify this constraint if your ISS support different set of delegations + @vsc.constraint + def delegation_c(self): + # TODO + pass + + @vsc.constraint + def ra_c(self): + self.ra != riscv_reg_t.SP + self.ra != riscv_reg_t.TP + self.ra != riscv_reg_t.ZERO + @vsc.constraint def sp_tp_c(self): - if self.fix_sp: + with vsc.if_then(self.fix_sp == 1): self.sp == riscv_reg_t.SP self.sp != self.tp self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP, @@ -210,6 +388,20 @@ def sp_tp_c(self): self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP, riscv_reg_t.RA, riscv_reg_t.ZERO)) + # This reg is used in various places throughout the generator, + # so need more conservative constraints on it. + @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)) + + # This reg is only used inside PMP exception routine, + # so we can be a bit looser with constraints. + @vsc.constraint + def reserved_pmp_reg_c(self): + # TODO + pass + @vsc.constraint def gpr_c(self): with vsc.foreach(self.gpr, idx = True) as i: @@ -218,41 +410,70 @@ def gpr_c(self): vsc.unique(self.gpr) @vsc.constraint - def ra_c(self): - self.ra != riscv_reg_t.SP - self.ra != riscv_reg_t.TP - self.ra != riscv_reg_t.ZERO - - @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)) + def addr_translation_rnd_order_c(self): + # TODO + pass @vsc.constraint - def mtvec_c(self): - self.mtvec_mode.inside(vsc.rangelist(self.supported_interrupt_mode)) - with vsc.if_then(self.mtvec_mode == mtvec_mode_t.DIRECT): - vsc.soft(self.tvec_alignment == 2) + def addr_translation_c(self): + with vsc.if_then((self.init_privil_mode != privileged_mode_t.MACHINE_MODE) & + (self.SATP_MODE != satp_mode_t.BARE)): + self.virtual_addr_translation_on == 1 with vsc.else_then(): - vsc.soft(self.tvec_alignment == self.tvec_ceil) + self.virtual_addr_translation_on == 0 @vsc.constraint def floating_point_c(self): - with vsc.if_then(self.enable_floating_point): + with vsc.if_then(self.enable_floating_point == 1): self.mstatus_fs == 1 with vsc.else_then(): self.mstatus_fs == 0 @vsc.constraint - def mstatus_c(self): - with vsc.if_then(self.set_mstatus_mprv == 1): - self.mstatus_mprv == 1 - with vsc.else_then(): - self.mstatus_mprv == 0 - with vsc.if_then(self.SATP_MODE == satp_mode_t.BARE): - self.mstatus_mxr == 0 - self.mstatus_sum == 0 - self.mstatus_tvm == 0 + def mstatus_vs_c(self): + # TODO + pass + + 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 # Default ratio + logging.info("Set dist[{}] = {}".format(category, self.category_dist[category])) + category = next(category_iter) + if category != riscv_instr_category_t(0): + break + + # Initialize the exception/interrupt delegation associate array, set all delegation default to 0 + def init_delegation(self): + # TODO + pass + + def pre_randomize(self): + 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): + # Setup the list all reserved registers + self.reserved_regs.extend((self.tp, self.sp, self.scratch_reg)) + # Need to save all loop registers, and RA/T0 + self.min_stack_len_per_program = 2 * (rcs.XLEN // 8) + logging.info("min_stack_len_per_program value = {}" + .format(self.min_stack_len_per_program)) + self.check_setting() # check if the setting is legal + # WFI is not supported in umode + if self.init_privileged_mode == privileged_mode_t.USER_MODE: + self.no_wfi = 1 def check_setting(self): support_64b = 0 @@ -296,47 +517,8 @@ def check_setting(self): .format(rcs.SATP_MODE.name)) sys.exit("Supported SATP mode is not provided") - 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 pre_randomize(self): - 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.append(self.tp) - self.reserved_regs.append(self.sp) - self.reserved_regs.append(self.scratch_reg) - self.min_stack_len_per_program = 2 * (rcs.XLEN / 8) - logging.info("min_stack_len_per_program value = {}" - .format(self.min_stack_len_per_program)) - self.check_setting() # check if the setting is legal - - if self.init_privileged_mode == privileged_mode_t.USER_MODE: - logging.info("mode = USER_MODE") - self.no_wfi = 1 - + # Populate invalid_priv_mode_csrs with the main implemented CSRs for each supported privilege + # mode def get_invalid_priv_lvl_csr(self): invalid_lvl = [] # Debug CSRs are inaccessible from all but Debug Mode @@ -416,7 +598,7 @@ def parse_args(self): help = 'illegal_instr_ratio', type = int, default = 0) parse.add_argument('--hint_instr_ratio', help = 'hint_instr_ratio', type = int, default = 0) parse.add_argument('--num_of_harts', help = 'num_of_harts', - type = int, default = 1) + type = int) parse.add_argument('--enable_unaligned_load_store', help = 'enable_unaligned_load_store', choices = [0, 1], type = int, default = 0) @@ -486,7 +668,6 @@ def parse_args(self): if ($value$plusargs("tvec_alignment=%0d", tvec_alignment)) begin tvec_alignment.rand_mode(0); end - vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg"); pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg"); pmp_cfg.rand_mode(pmp_cfg.pmp_randomize); @@ -495,7 +676,6 @@ def parse_args(self): get_invalid_priv_lvl_csr(); ''' args = parse.parse_args() - return args diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py index 41f4ba3d35..5808a4ff65 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_pkg.py @@ -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 @@ -9,7 +8,6 @@ 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 logging @@ -26,6 +24,14 @@ def __init__(self, name = "", size_in_bytes=0, xwr=0): self.size_in_bytes = vsc.uint32_t(i=size_in_bytes) self.xwr = vsc.uint8_t(i=xwr) +# Initialization of the vregs + + +class vreg_init_method_t(IntEnum): + SAME_VALUES_ALL_ELEMS = 0 + RANDOM_VALUES_VMV = auto() + RANDOM_VALUES_LOAD = auto() + class satp_mode_t(IntEnum): BARE = 0b0000 @@ -50,12 +56,13 @@ class mtvec_mode_t(IntEnum): class imm_t(IntEnum): - IMM = 0 - UIMM = auto() - NZUIMM = auto() - NZIMM = auto() + IMM = 0 # Signed immediate + UIMM = auto() # Unsigned immediate + NZUIMM = auto() # Non-zero unsigned immediate + NZIMM = auto() # Non-zero signed immediate +# Privileged mode class privileged_mode_t(IntEnum): USER_MODE = 0b00 SUPERVISOR_MODE = 0b01 @@ -90,6 +97,7 @@ class riscv_instr_group_t(IntEnum): class riscv_instr_name_t(IntEnum): + # RV32I instructions LUI = 0 AUIPC = auto() JAL = auto() @@ -138,6 +146,7 @@ class riscv_instr_name_t(IntEnum): CSRRWI = auto() CSRRSI = auto() CSRRCI = auto() + # RV32B instructions ANDN = auto() ORN = auto() XNOR = auto() @@ -195,6 +204,7 @@ class riscv_instr_name_t(IntEnum): BFP = auto() SHFLI = auto() UNSHFLI = auto() + # RV64B instructions ADDIWU = auto() SLLIU_W = auto() ADDWU = auto() @@ -238,6 +248,7 @@ class riscv_instr_name_t(IntEnum): PACKW = auto() PACKUW = auto() BFPW = auto() + # RV32M instructions MUL = auto() MULH = auto() MULHSU = auto() @@ -246,11 +257,13 @@ class riscv_instr_name_t(IntEnum): DIVU = auto() REM = auto() REMU = auto() + # RV64M instructions MULW = auto() DIVW = auto() DIVUW = auto() REMW = auto() REMUW = auto() + # RV32F instructions FLW = auto() FSW = auto() FMADD_S = auto() @@ -277,10 +290,12 @@ class riscv_instr_name_t(IntEnum): FCVT_S_W = auto() FCVT_S_WU = auto() FMV_W_X = auto() + # RV64F instructions FCVT_L_S = auto() FCVT_LU_S = auto() FCVT_S_L = auto() FCVT_S_LU = auto() + # RV32D instructions FLD = auto() FSD = auto() FMADD_D = auto() @@ -307,12 +322,14 @@ class riscv_instr_name_t(IntEnum): FCVT_WU_D = auto() FCVT_D_W = auto() FCVT_D_WU = auto() + # RV64D instructions FCVT_L_D = auto() FCVT_LU_D = auto() FMV_X_D = auto() FCVT_D_L = auto() FCVT_D_LU = auto() FMV_D_X = auto() + # RV64I instructions LWU = auto() LD = auto() SD = auto() @@ -325,6 +342,7 @@ class riscv_instr_name_t(IntEnum): SLLW = auto() SRLW = auto() SRAW = auto() + # RV32C instructions C_LW = auto() C_SW = auto() C_LWSP = auto() @@ -352,6 +370,7 @@ class riscv_instr_name_t(IntEnum): C_JAL = auto() C_JR = auto() C_JALR = auto() + # RV64C instructions C_ADDIW = auto() C_SUBW = auto() C_ADDW = auto() @@ -359,6 +378,7 @@ class riscv_instr_name_t(IntEnum): C_SD = auto() C_LDSP = auto() C_SDSP = auto() + # RV128C instructions C_SRLI64 = auto() C_SRAI64 = auto() C_SLLI64 = auto() @@ -366,14 +386,17 @@ class riscv_instr_name_t(IntEnum): C_SQ = auto() C_LQSP = auto() C_SQSP = auto() + # RV32FC instructions C_FLW = auto() C_FSW = auto() C_FLWSP = auto() C_FSWSP = auto() + # RV32DC instructions C_FLD = auto() C_FSD = auto() C_FLDSP = auto() C_FSDSP = auto() + # RV32A instructions LR_W = auto() SC_W = auto() AMOSWAP_W = auto() @@ -385,6 +408,7 @@ class riscv_instr_name_t(IntEnum): AMOMAX_W = auto() AMOMINU_W = auto() AMOMAXU_W = auto() + # RV64A instructions LR_D = auto() SC_D = auto() AMOSWAP_D = auto() @@ -396,6 +420,7 @@ class riscv_instr_name_t(IntEnum): AMOMAX_D = auto() AMOMINU_D = auto() AMOMAXU_D = auto() + # Vector instructions VSETVL = auto() VSETVLI = auto() VADD = auto() @@ -448,6 +473,10 @@ class riscv_instr_name_t(IntEnum): VWMACC = auto() VWMACCSU = auto() VWMACCUS = auto() + # VQMACCU = auto() + # VQMACC = auto() + # VQMACCSU = auto() + # VQMACCUS = auto() VMERGE = auto() VMV = auto() VSADDU = auto() @@ -462,6 +491,7 @@ class riscv_instr_name_t(IntEnum): VSSRA = auto() VNCLIPU = auto() VNCLIP = auto() + # 14. Vector Floating-Point instructions VFADD = auto() VFSUB = auto() VFRSUB = auto() @@ -511,6 +541,7 @@ class riscv_instr_name_t(IntEnum): VFNCVT_F_X_W = auto() VFNCVT_F_F_W = auto() VFNCVT_ROD_F_F_W = auto() + # 15. Vector reduction instructions VREDSUM_VS = auto() VREDMAXU_VS = auto() VREDMAX_VS = auto() @@ -526,6 +557,7 @@ class riscv_instr_name_t(IntEnum): VFREDMAX_VS = auto() VFWREDOSUM_VS = auto() VFWREDSUM_VS = auto() + # Vector mask instructions VMAND_MM = auto() VMNAND_MM = auto() VMANDNOT_MM = auto() @@ -541,6 +573,7 @@ class riscv_instr_name_t(IntEnum): VMSOF_M = auto() VIOTA_M = auto() VID_V = auto() + # Vector permutation instructions VMV_X_S = auto() VMV_S_X = auto() VFMV_F_S = auto() @@ -555,12 +588,45 @@ class riscv_instr_name_t(IntEnum): VMV2R_V = auto() VMV4R_V = auto() VMV8R_V = auto() + # Vector load/store instructions + VLE_V = auto() + VSE_V = auto() + VLSE_V = auto() + VSSE_V = auto() + VLXEI_V = auto() + VSXEI_V = auto() + VSUXEI_V = auto() + VLEFF_V = auto() + # Segmented load/store instruction + VLSEGE_V = auto() + VSSEGE_V = auto() + VLSEGEFF_V = auto() + VLSSEGE_V = auto() + VSSSEGE_V = auto() + VLXSEGEI_V = auto() + VSXSEGEI_V = auto() + VSUXSEGEI_V = auto() + # Vector AMO instruction + # EEW vector AMOs + VAMOSWAPE_V = auto() + VAMOADDE_V = auto() + VAMOXORE_V = auto() + VAMOANDE_V = auto() + VAMOORE_V = auto() + VAMOMINE_V = auto() + VAMOMAXE_V = auto() + VAMOMINUE_V = auto() + VAMOMAXUE_V = auto() + # Supervisor instruction DRET = auto() MRET = auto() URET = auto() SRET = auto() WFI = auto() SFENCE_VMA = auto() + # Custom instructions + # TODO add a way to import custom instructions here from isa/custom/riscv_custom_instr_enum.py + # You can add other instructions here INVALID_INSTR = auto() @@ -677,6 +743,7 @@ class riscv_instr_format_t(IntEnum): R_FORMAT = auto() S_FORMAT = auto() R4_FORMAT = auto() + # Compressed instruction format CI_FORMAT = auto() CB_FORMAT = auto() CJ_FORMAT = auto() @@ -686,13 +753,15 @@ class riscv_instr_format_t(IntEnum): CS_FORMAT = auto() CSS_FORMAT = auto() CIW_FORMAT = auto() + # Vector instruction format VSET_FORMAT = auto() VA_FORMAT = auto() - VS2_FORMAT = auto() + VS2_FORMAT = auto() # op vd,vs2 VL_FORMAT = auto() VS_FORMAT = auto() +# Vector arithmetic instruction variant class va_variant_t(IntEnum): VV = 0 VI = auto() @@ -725,269 +794,277 @@ class riscv_instr_category_t(IntEnum): CHANGELEVEL = auto() TRAP = auto() INTERRUPT = auto() - AMO = auto() - - -# typedef bit[11:0] riscv_csr_t; + # TODO import vector_category + AMO = auto() # (last one) class privileged_reg_t(IntEnum): - USTATUS = 0x000 - UIE = 0x004 - UTVEC = 0x005 - USCRATCH = 0x040 - UEPC = 0x041 - UCAUSE = 0x042 - UTVAL = 0x043 - UIP = 0x044 - FFLAGS = 0x001 - FRM = 0x002 - FCSR = 0x003 - CYCLE = 0xC00 - TIME = 0xC01 - INSTRET = 0xC02 - HPMCOUNTER3 = 0xC03 - HPMCOUNTER4 = 0xC04 - HPMCOUNTER5 = 0xC05 - HPMCOUNTER6 = 0xC06 - HPMCOUNTER7 = 0xC07 - HPMCOUNTER8 = 0xC08 - HPMCOUNTER9 = 0xC09 - HPMCOUNTER10 = 0xC0A - HPMCOUNTER11 = 0xC0B - HPMCOUNTER12 = 0xC0C - HPMCOUNTER13 = 0xC0D - HPMCOUNTER14 = 0xC0E - HPMCOUNTER15 = 0xC0F - HPMCOUNTER16 = 0xC10 - HPMCOUNTER17 = 0xC11 - HPMCOUNTER18 = 0xC12 - HPMCOUNTER19 = 0xC13 - HPMCOUNTER20 = 0xC14 - HPMCOUNTER21 = 0xC15 - HPMCOUNTER22 = 0xC16 - HPMCOUNTER23 = 0xC17 - HPMCOUNTER24 = 0xC18 - HPMCOUNTER25 = 0xC19 - HPMCOUNTER26 = 0xC1A - HPMCOUNTER27 = 0xC1B - HPMCOUNTER28 = 0xC1C - HPMCOUNTER29 = 0xC1D - HPMCOUNTER30 = 0xC1E - HPMCOUNTER31 = 0xC1F - CYCLEH = 0xC80 - TIMEH = 0xC81 - INSTRETH = 0xC82 - HPMCOUNTER3H = 0xC83 - HPMCOUNTER4H = 0xC84 - HPMCOUNTER5H = 0xC85 - HPMCOUNTER6H = 0xC86 - HPMCOUNTER7H = 0xC87 - HPMCOUNTER8H = 0xC88 - HPMCOUNTER9H = 0xC89 - HPMCOUNTER10H = 0xC8A - HPMCOUNTER11H = 0xC8B - HPMCOUNTER12H = 0xC8C - HPMCOUNTER13H = 0xC8D - HPMCOUNTER14H = 0xC8E - HPMCOUNTER15H = 0xC8F - HPMCOUNTER16H = 0xC90 - HPMCOUNTER17H = 0xC91 - HPMCOUNTER18H = 0xC92 - HPMCOUNTER19H = 0xC93 - HPMCOUNTER20H = 0xC94 - HPMCOUNTER21H = 0xC95 - HPMCOUNTER22H = 0xC96 - HPMCOUNTER23H = 0xC97 - HPMCOUNTER24H = 0xC98 - HPMCOUNTER25H = 0xC99 - HPMCOUNTER26H = 0xC9A - HPMCOUNTER27H = 0xC9B - HPMCOUNTER28H = 0xC9C - HPMCOUNTER29H = 0xC9D - HPMCOUNTER30H = 0xC9E - HPMCOUNTER31H = 0xC9F - SSTATUS = 0x100 - SEDELEG = 0x102 - SIDELEG = 0x103 - SIE = 0x104 - STVEC = 0x105 - SCOUNTEREN = 0x106 - SSCRATCH = 0x140 - SEPC = 0x141 - SCAUSE = 0x142 - STVAL = 0x143 - SIP = 0x144 - SATP = 0x180 - MVENDORID = 0xF11 - MARCHID = 0xF12 - MIMPID = 0xF13 - MHARTID = 0xF14 - MSTATUS = 0x300 - MISA = 0x301 - MEDELEG = 0x302 - MIDELEG = 0x303 - MIE = 0x304 - MTVEC = 0x305 - MCOUNTEREN = 0x306 - MSCRATCH = 0x340 - MEPC = 0x341 - MCAUSE = 0x342 - MTVAL = 0x343 - MIP = 0x344 - PMPCFG0 = 0x3A0 - PMPCFG1 = 0x3A1 - PMPCFG2 = 0x3A2 - PMPCFG3 = 0x3A3 - PMPADDR0 = 0x3B0 - PMPADDR1 = 0x3B1 - PMPADDR2 = 0x3B2 - PMPADDR3 = 0x3B3 - PMPADDR4 = 0x3B4 - PMPADDR5 = 0x3B5 - PMPADDR6 = 0x3B6 - PMPADDR7 = 0x3B7 - PMPADDR8 = 0x3B8 - PMPADDR9 = 0x3B9 - PMPADDR10 = 0x3BA - PMPADDR11 = 0x3BB - PMPADDR12 = 0x3BC - PMPADDR13 = 0x3BD - PMPADDR14 = 0x3BE - PMPADDR15 = 0x3BF - MCYCLE = 0xB00 - MINSTRET = 0xB02 - MHPMCOUNTER3 = 0xB03 - MHPMCOUNTER4 = 0xB04 - MHPMCOUNTER5 = 0xB05 - MHPMCOUNTER6 = 0xB06 - MHPMCOUNTER7 = 0xB07 - MHPMCOUNTER8 = 0xB08 - MHPMCOUNTER9 = 0xB09 - MHPMCOUNTER10 = 0xB0A - MHPMCOUNTER11 = 0xB0B - MHPMCOUNTER12 = 0xB0C - MHPMCOUNTER13 = 0xB0D - MHPMCOUNTER14 = 0xB0E - MHPMCOUNTER15 = 0xB0F - MHPMCOUNTER16 = 0xB10 - MHPMCOUNTER17 = 0xB11 - MHPMCOUNTER18 = 0xB12 - MHPMCOUNTER19 = 0xB13 - MHPMCOUNTER20 = 0xB14 - MHPMCOUNTER21 = 0xB15 - MHPMCOUNTER22 = 0xB16 - MHPMCOUNTER23 = 0xB17 - MHPMCOUNTER24 = 0xB18 - MHPMCOUNTER25 = 0xB19 - MHPMCOUNTER26 = 0xB1A - MHPMCOUNTER27 = 0xB1B - MHPMCOUNTER28 = 0xB1C - MHPMCOUNTER29 = 0xB1D - MHPMCOUNTER30 = 0xB1E - MHPMCOUNTER31 = 0xB1F - MCYCLEH = 0xB80 - MINSTRETH = 0xB82 - MHPMCOUNTER3H = 0xB83 - MHPMCOUNTER4H = 0xB84 - MHPMCOUNTER5H = 0xB85 - MHPMCOUNTER6H = 0xB86 - MHPMCOUNTER7H = 0xB87 - MHPMCOUNTER8H = 0xB88 - MHPMCOUNTER9H = 0xB89 - MHPMCOUNTER10H = 0xB8A - MHPMCOUNTER11H = 0xB8B - MHPMCOUNTER12H = 0xB8C - MHPMCOUNTER13H = 0xB8D - MHPMCOUNTER14H = 0xB8E - MHPMCOUNTER15H = 0xB8F - MHPMCOUNTER17H = 0xB90 - MHPMCOUNTER18H = 0xB91 - MHPMCOUNTER19H = 0xB92 - MHPMCOUNTER20H = 0xB93 - MHPMCOUNTER21H = 0xB94 - MHPMCOUNTER22H = 0xB95 - MHPMCOUNTER23H = 0xB96 - MHPMCOUNTER24H = 0xB97 - MHPMCOUNTER25H = 0xB98 - MHPMCOUNTER26H = 0xB99 - MHPMCOUNTER27H = 0xB9A - MHPMCOUNTER28H = 0xB9B - MHPMCOUNTER29H = 0xB9C - MHPMCOUNTER30H = 0xB9D - MHPMCOUNTER31H = 0xB9E - MCOUNTINHIBIT = 0x320F - MHPMEVENT3 = 0x323 - MHPMEVENT4 = 0x324 - MHPMEVENT5 = 0x325 - MHPMEVENT6 = 0x326 - MHPMEVENT7 = 0x327 - MHPMEVENT8 = 0x328 - MHPMEVENT9 = 0x329 - MHPMEVENT10 = 0x32A - MHPMEVENT11 = 0x32B - MHPMEVENT12 = 0x32C - MHPMEVENT13 = 0x32D - MHPMEVENT14 = 0x32E - MHPMEVENT15 = 0x32F - MHPMEVENT16 = 0x330 - MHPMEVENT17 = 0x331 - MHPMEVENT18 = 0x332 - MHPMEVENT19 = 0x333 - MHPMEVENT20 = 0x334 - MHPMEVENT21 = 0x335 - MHPMEVENT22 = 0x336 - MHPMEVENT23 = 0x337 - MHPMEVENT24 = 0x338 - MHPMEVENT25 = 0x339 - MHPMEVENT26 = 0x33A - MHPMEVENT27 = 0x33B - MHPMEVENT28 = 0x33C - MHPMEVENT29 = 0x33D - MHPMEVENT30 = 0x33E - MHPMEVENT31 = 0x33F - TSELECT = 0x7A0 - TDATA1 = 0x7A1 - TDATA2 = 0x7A2 - TDATA3 = 0x7A3 - DCSR = 0x7B0 - DPC = 0x7B1 - DSCRATCH0 = 0x7B2 - DSCRATCH1 = 0x7B3 - VSTART = 0x008 - VXSTAT = 0x009 - VXRM = 0x00A - VL = 0xC20 - VTYPE = 0xC21 - VLENB = 0xC22 + # User mode register + USTATUS = 0x000 # User status + UIE = 0x004 # User interrupt-enable register + UTVEC = 0x005 # User trap-handler base address + USCRATCH = 0x040 # Scratch register for user trap handlers + UEPC = 0x041 # User exception program counter + UCAUSE = 0x042 # User trap cause + UTVAL = 0x043 # User bad address or instruction + UIP = 0x044 # User interrupt pending + FFLAGS = 0x001 # Floating-Point Accrued Exceptions + FRM = 0x002 # Floating-Point Dynamic Rounding Mode + FCSR = 0x003 # Floating-Point Control/Status Register (FRM + FFLAGS) + CYCLE = 0xC00 # Cycle counter for RDCYCLE instruction + TIME = 0xC01 # Timer for RDTIME instruction + INSTRET = 0xC02 # Instructions-retired counter for RDINSTRET instruction + HPMCOUNTER3 = 0xC03 # Performance-monitoring counter + HPMCOUNTER4 = 0xC04 # Performance-monitoring counter + HPMCOUNTER5 = 0xC05 # Performance-monitoring counter + HPMCOUNTER6 = 0xC06 # Performance-monitoring counter + HPMCOUNTER7 = 0xC07 # Performance-monitoring counter + HPMCOUNTER8 = 0xC08 # Performance-monitoring counter + HPMCOUNTER9 = 0xC09 # Performance-monitoring counter + HPMCOUNTER10 = 0xC0A # Performance-monitoring counter + HPMCOUNTER11 = 0xC0B # Performance-monitoring counter + HPMCOUNTER12 = 0xC0C # Performance-monitoring counter + HPMCOUNTER13 = 0xC0D # Performance-monitoring counter + HPMCOUNTER14 = 0xC0E # Performance-monitoring counter + HPMCOUNTER15 = 0xC0F # Performance-monitoring counter + HPMCOUNTER16 = 0xC10 # Performance-monitoring counter + HPMCOUNTER17 = 0xC11 # Performance-monitoring counter + HPMCOUNTER18 = 0xC12 # Performance-monitoring counter + HPMCOUNTER19 = 0xC13 # Performance-monitoring counter + HPMCOUNTER20 = 0xC14 # Performance-monitoring counter + HPMCOUNTER21 = 0xC15 # Performance-monitoring counter + HPMCOUNTER22 = 0xC16 # Performance-monitoring counter + HPMCOUNTER23 = 0xC17 # Performance-monitoring counter + HPMCOUNTER24 = 0xC18 # Performance-monitoring counter + HPMCOUNTER25 = 0xC19 # Performance-monitoring counter + HPMCOUNTER26 = 0xC1A # Performance-monitoring counter + HPMCOUNTER27 = 0xC1B # Performance-monitoring counter + HPMCOUNTER28 = 0xC1C # Performance-monitoring counter + HPMCOUNTER29 = 0xC1D # Performance-monitoring counter + HPMCOUNTER30 = 0xC1E # Performance-monitoring counter + HPMCOUNTER31 = 0xC1F # Performance-monitoring counter + CYCLEH = 0xC80 # Upper 32 bits of CYCLE, RV32I only + TIMEH = 0xC81 # Upper 32 bits of TIME, RV32I only + INSTRETH = 0xC82 # Upper 32 bits of INSTRET, RV32I only + HPMCOUNTER3H = 0xC83 # Upper 32 bits of HPMCOUNTER3, RV32I only + HPMCOUNTER4H = 0xC84 # Upper 32 bits of HPMCOUNTER4, RV32I only + HPMCOUNTER5H = 0xC85 # Upper 32 bits of HPMCOUNTER5, RV32I only + HPMCOUNTER6H = 0xC86 # Upper 32 bits of HPMCOUNTER6, RV32I only + HPMCOUNTER7H = 0xC87 # Upper 32 bits of HPMCOUNTER7, RV32I only + HPMCOUNTER8H = 0xC88 # Upper 32 bits of HPMCOUNTER8, RV32I only + HPMCOUNTER9H = 0xC89 # Upper 32 bits of HPMCOUNTER9, RV32I only + HPMCOUNTER10H = 0xC8A # Upper 32 bits of HPMCOUNTER10, RV32I only + HPMCOUNTER11H = 0xC8B # Upper 32 bits of HPMCOUNTER11, RV32I only + HPMCOUNTER12H = 0xC8C # Upper 32 bits of HPMCOUNTER12, RV32I only + HPMCOUNTER13H = 0xC8D # Upper 32 bits of HPMCOUNTER13, RV32I only + HPMCOUNTER14H = 0xC8E # Upper 32 bits of HPMCOUNTER14, RV32I only + HPMCOUNTER15H = 0xC8F # Upper 32 bits of HPMCOUNTER15, RV32I only + HPMCOUNTER16H = 0xC90 # Upper 32 bits of HPMCOUNTER16, RV32I only + HPMCOUNTER17H = 0xC91 # Upper 32 bits of HPMCOUNTER17, RV32I only + HPMCOUNTER18H = 0xC92 # Upper 32 bits of HPMCOUNTER18, RV32I only + HPMCOUNTER19H = 0xC93 # Upper 32 bits of HPMCOUNTER19, RV32I only + HPMCOUNTER20H = 0xC94 # Upper 32 bits of HPMCOUNTER20, RV32I only + HPMCOUNTER21H = 0xC95 # Upper 32 bits of HPMCOUNTER21, RV32I only + HPMCOUNTER22H = 0xC96 # Upper 32 bits of HPMCOUNTER22, RV32I only + HPMCOUNTER23H = 0xC97 # Upper 32 bits of HPMCOUNTER23, RV32I only + HPMCOUNTER24H = 0xC98 # Upper 32 bits of HPMCOUNTER24, RV32I only + HPMCOUNTER25H = 0xC99 # Upper 32 bits of HPMCOUNTER25, RV32I only + HPMCOUNTER26H = 0xC9A # Upper 32 bits of HPMCOUNTER26, RV32I only + HPMCOUNTER27H = 0xC9B # Upper 32 bits of HPMCOUNTER27, RV32I only + HPMCOUNTER28H = 0xC9C # Upper 32 bits of HPMCOUNTER28, RV32I only + HPMCOUNTER29H = 0xC9D # Upper 32 bits of HPMCOUNTER29, RV32I only + HPMCOUNTER30H = 0xC9E # Upper 32 bits of HPMCOUNTER30, RV32I only + HPMCOUNTER31H = 0xC9F # Upper 32 bits of HPMCOUNTER31, RV32I only + # Supervisor mode register + SSTATUS = 0x100 # Supervisor status + SEDELEG = 0x102 # Supervisor exception delegation register + SIDELEG = 0x103 # Supervisor interrupt delegation register + SIE = 0x104 # Supervisor interrupt-enable register + STVEC = 0x105 # Supervisor trap-handler base address + SCOUNTEREN = 0x106 # Supervisor counter enable + SSCRATCH = 0x140 # Scratch register for supervisor trap handlers + SEPC = 0x141 # Supervisor exception program counter + SCAUSE = 0x142 # Supervisor trap cause + STVAL = 0x143 # Supervisor bad address or instruction + SIP = 0x144 # Supervisor interrupt pending + SATP = 0x180 # Supervisor address translation and protection + # Machine mode register + MVENDORID = 0xF11 # Vendor ID + MARCHID = 0xF12 # Architecture ID + MIMPID = 0xF13 # Implementation ID + MHARTID = 0xF14 # Hardware thread ID + MSTATUS = 0x300 # Machine status + MISA = 0x301 # ISA and extensions + MEDELEG = 0x302 # Machine exception delegation register + MIDELEG = 0x303 # Machine interrupt delegation register + MIE = 0x304 # Machine interrupt-enable register + MTVEC = 0x305 # Machine trap-handler base address + MCOUNTEREN = 0x306 # Machine counter enable + MSCRATCH = 0x340 # Scratch register for machine trap handlers + MEPC = 0x341 # Machine exception program counter + MCAUSE = 0x342 # Machine trap cause + MTVAL = 0x343 # Machine bad address or instruction + MIP = 0x344 # Machine interrupt pending + PMPCFG0 = 0x3A0 # Physical memory protection configuration + PMPCFG1 = 0x3A1 # Physical memory protection configuration, RV32 only + PMPCFG2 = 0x3A2 # Physical memory protection configuration + PMPCFG3 = 0x3A3 # Physical memory protection configuration, RV32 only + PMPADDR0 = 0x3B0 # Physical memory protection address register + PMPADDR1 = 0x3B1 # Physical memory protection address register + PMPADDR2 = 0x3B2 # Physical memory protection address register + PMPADDR3 = 0x3B3 # Physical memory protection address register + PMPADDR4 = 0x3B4 # Physical memory protection address register + PMPADDR5 = 0x3B5 # Physical memory protection address register + PMPADDR6 = 0x3B6 # Physical memory protection address register + PMPADDR7 = 0x3B7 # Physical memory protection address register + PMPADDR8 = 0x3B8 # Physical memory protection address register + PMPADDR9 = 0x3B9 # Physical memory protection address register + PMPADDR10 = 0x3BA # Physical memory protection address register + PMPADDR11 = 0x3BB # Physical memory protection address register + PMPADDR12 = 0x3BC # Physical memory protection address register + PMPADDR13 = 0x3BD # Physical memory protection address register + PMPADDR14 = 0x3BE # Physical memory protection address register + PMPADDR15 = 0x3BF # Physical memory protection address register + MCYCLE = 0xB00 # Machine cycle counter + MINSTRET = 0xB02 # Machine instructions-retired counter + MHPMCOUNTER3 = 0xB03 # Machine performance-monitoring counter + MHPMCOUNTER4 = 0xB04 # Machine performance-monitoring counter + MHPMCOUNTER5 = 0xB05 # Machine performance-monitoring counter + MHPMCOUNTER6 = 0xB06 # Machine performance-monitoring counter + MHPMCOUNTER7 = 0xB07 # Machine performance-monitoring counter + MHPMCOUNTER8 = 0xB08 # Machine performance-monitoring counter + MHPMCOUNTER9 = 0xB09 # Machine performance-monitoring counter + MHPMCOUNTER10 = 0xB0A # Machine performance-monitoring counter + MHPMCOUNTER11 = 0xB0B # Machine performance-monitoring counter + MHPMCOUNTER12 = 0xB0C # Machine performance-monitoring counter + MHPMCOUNTER13 = 0xB0D # Machine performance-monitoring counter + MHPMCOUNTER14 = 0xB0E # Machine performance-monitoring counter + MHPMCOUNTER15 = 0xB0F # Machine performance-monitoring counter + MHPMCOUNTER16 = 0xB10 # Machine performance-monitoring counter + MHPMCOUNTER17 = 0xB11 # Machine performance-monitoring counter + MHPMCOUNTER18 = 0xB12 # Machine performance-monitoring counter + MHPMCOUNTER19 = 0xB13 # Machine performance-monitoring counter + MHPMCOUNTER20 = 0xB14 # Machine performance-monitoring counter + MHPMCOUNTER21 = 0xB15 # Machine performance-monitoring counter + MHPMCOUNTER22 = 0xB16 # Machine performance-monitoring counter + MHPMCOUNTER23 = 0xB17 # Machine performance-monitoring counter + MHPMCOUNTER24 = 0xB18 # Machine performance-monitoring counter + MHPMCOUNTER25 = 0xB19 # Machine performance-monitoring counter + MHPMCOUNTER26 = 0xB1A # Machine performance-monitoring counter + MHPMCOUNTER27 = 0xB1B # Machine performance-monitoring counter + MHPMCOUNTER28 = 0xB1C # Machine performance-monitoring counter + MHPMCOUNTER29 = 0xB1D # Machine performance-monitoring counter + MHPMCOUNTER30 = 0xB1E # Machine performance-monitoring counter + MHPMCOUNTER31 = 0xB1F # Machine performance-monitoring counter + MCYCLEH = 0xB80 # Upper 32 bits of MCYCLE, RV32I only + MINSTRETH = 0xB82 # Upper 32 bits of MINSTRET, RV32I only + MHPMCOUNTER3H = 0xB83 # Upper 32 bits of HPMCOUNTER3, RV32I only + MHPMCOUNTER4H = 0xB84 # Upper 32 bits of HPMCOUNTER4, RV32I only + MHPMCOUNTER5H = 0xB85 # Upper 32 bits of HPMCOUNTER5, RV32I only + MHPMCOUNTER6H = 0xB86 # Upper 32 bits of HPMCOUNTER6, RV32I only + MHPMCOUNTER7H = 0xB87 # Upper 32 bits of HPMCOUNTER7, RV32I only + MHPMCOUNTER8H = 0xB88 # Upper 32 bits of HPMCOUNTER8, RV32I only + MHPMCOUNTER9H = 0xB89 # Upper 32 bits of HPMCOUNTER9, RV32I only + MHPMCOUNTER10H = 0xB8A # Upper 32 bits of HPMCOUNTER10, RV32I only + MHPMCOUNTER11H = 0xB8B # Upper 32 bits of HPMCOUNTER11, RV32I only + MHPMCOUNTER12H = 0xB8C # Upper 32 bits of HPMCOUNTER12, RV32I only + MHPMCOUNTER13H = 0xB8D # Upper 32 bits of HPMCOUNTER13, RV32I only + MHPMCOUNTER14H = 0xB8E # Upper 32 bits of HPMCOUNTER14, RV32I only + MHPMCOUNTER15H = 0xB8F # Upper 32 bits of HPMCOUNTER15, RV32I only + MHPMCOUNTER16H = 0xB8F # Upper 32 bits of HPMCOUNTER16, RV32I only + MHPMCOUNTER17H = 0xB90 # Upper 32 bits of HPMCOUNTER17, RV32I only + MHPMCOUNTER18H = 0xB91 # Upper 32 bits of HPMCOUNTER18, RV32I only + MHPMCOUNTER19H = 0xB92 # Upper 32 bits of HPMCOUNTER19, RV32I only + MHPMCOUNTER20H = 0xB93 # Upper 32 bits of HPMCOUNTER20, RV32I only + MHPMCOUNTER21H = 0xB94 # Upper 32 bits of HPMCOUNTER21, RV32I only + MHPMCOUNTER22H = 0xB95 # Upper 32 bits of HPMCOUNTER22, RV32I only + MHPMCOUNTER23H = 0xB96 # Upper 32 bits of HPMCOUNTER23, RV32I only + MHPMCOUNTER24H = 0xB97 # Upper 32 bits of HPMCOUNTER24, RV32I only + MHPMCOUNTER25H = 0xB98 # Upper 32 bits of HPMCOUNTER25, RV32I only + MHPMCOUNTER26H = 0xB99 # Upper 32 bits of HPMCOUNTER26, RV32I only + MHPMCOUNTER27H = 0xB9A # Upper 32 bits of HPMCOUNTER27, RV32I only + MHPMCOUNTER28H = 0xB9B # Upper 32 bits of HPMCOUNTER28, RV32I only + MHPMCOUNTER29H = 0xB9C # Upper 32 bits of HPMCOUNTER29, RV32I only + MHPMCOUNTER30H = 0xB9D # Upper 32 bits of HPMCOUNTER30, RV32I only + MHPMCOUNTER31H = 0xB9E # Upper 32 bits of HPMCOUNTER31, RV32I only + MCOUNTINHIBIT = 0x320F # Machine counter-inhibit register + MHPMEVENT3 = 0x323 # Machine performance-monitoring event selector + MHPMEVENT4 = 0x324 # Machine performance-monitoring event selector + MHPMEVENT5 = 0x325 # Machine performance-monitoring event selector + MHPMEVENT6 = 0x326 # Machine performance-monitoring event selector + MHPMEVENT7 = 0x327 # Machine performance-monitoring event selector + MHPMEVENT8 = 0x328 # Machine performance-monitoring event selector + MHPMEVENT9 = 0x329 # Machine performance-monitoring event selector + MHPMEVENT10 = 0x32A # Machine performance-monitoring event selector + MHPMEVENT11 = 0x32B # Machine performance-monitoring event selector + MHPMEVENT12 = 0x32C # Machine performance-monitoring event selector + MHPMEVENT13 = 0x32D # Machine performance-monitoring event selector + MHPMEVENT14 = 0x32E # Machine performance-monitoring event selector + MHPMEVENT15 = 0x32F # Machine performance-monitoring event selector + MHPMEVENT16 = 0x330 # Machine performance-monitoring event selector + MHPMEVENT17 = 0x331 # Machine performance-monitoring event selector + MHPMEVENT18 = 0x332 # Machine performance-monitoring event selector + MHPMEVENT19 = 0x333 # Machine performance-monitoring event selector + MHPMEVENT20 = 0x334 # Machine performance-monitoring event selector + MHPMEVENT21 = 0x335 # Machine performance-monitoring event selector + MHPMEVENT22 = 0x336 # Machine performance-monitoring event selector + MHPMEVENT23 = 0x337 # Machine performance-monitoring event selector + MHPMEVENT24 = 0x338 # Machine performance-monitoring event selector + MHPMEVENT25 = 0x339 # Machine performance-monitoring event selector + MHPMEVENT26 = 0x33A # Machine performance-monitoring event selector + MHPMEVENT27 = 0x33B # Machine performance-monitoring event selector + MHPMEVENT28 = 0x33C # Machine performance-monitoring event selector + MHPMEVENT29 = 0x33D # Machine performance-monitoring event selector + MHPMEVENT30 = 0x33E # Machine performance-monitoring event selector + MHPMEVENT31 = 0x33F # Machine performance-monitoring event selector + TSELECT = 0x7A0 # Debug/Trace trigger register select + TDATA1 = 0x7A1 # First Debug/Trace trigger data register + TDATA2 = 0x7A2 # Second Debug/Trace trigger data register + TDATA3 = 0x7A3 # Third Debug/Trace trigger data register + TINFO = 0x7A4 # Debug trigger info register + TCONTROL = 0x7A5 # Debug trigger control register + MCONTEXT = 0x7A8 # Machine mode trigger context register + SCONTEXT = 0x7AA # Supervisor mode trigger context register + DCSR = 0x7B0 # Debug control and status register + DPC = 0x7B1 # Debug PC + DSCRATCH0 = 0x7B2 # Debug scratch register + DSCRATCH1 = 0x7B3 # Debug scratch register (last one) + VSTART = 0x008 # Vector start position + VXSTAT = 0x009 # Fixed point saturate flag + VXRM = 0x00A # Fixed point rounding mode + VL = 0xC20 # Vector length + VTYPE = 0xC21 # Vector data type register + VLENB = 0xC22 # VLEN/8 (vector register length in bytes) class privileged_reg_fld_t(IntEnum): - RSVD = 0 - MXL = auto() - EXTENSION = auto() - MODE = auto() - ASID = auto() - PPN = auto() + RSVD = 0 # Reserved field + MXL = auto() # mis.mxl + EXTENSION = auto() # mis.extension + MODE = auto() # satp.mode + ASID = auto() # satp.asid + PPN = auto() # satp.ppn class privileged_level_t(IntEnum): - M_LEVEL = 0b11 - S_LEVEL = 0b01 - U_LEVEL = 0b00 + M_LEVEL = 0b11 # Machine mode + S_LEVEL = 0b01 # Supervisor mode + U_LEVEL = 0b00 # User mode class reg_field_access_t(IntEnum): - WPRI = 0 - WLRL = auto() - WARL = auto() + WPRI = 0 # Reserved Writes Preserve Values, Reads Ignore Value + WLRL = auto() # Write/Read Only Legal Values + WARL = auto() # Write Any Values, Reads Legal Values +# Pseudo instructions class riscv_pseudo_instr_name_t(IntEnum): LI = 0 LA = auto() +# Data pattern of the memory model class data_pattern_t(IntEnum): RAND_DATA = 0 ALL_ZERO = auto() @@ -995,12 +1072,12 @@ class data_pattern_t(IntEnum): class pte_permission_t(IntEnum): - NEXT_LEVEL_PAGE = 0b000 - READ_ONLY_PAGE = 0b001 - READ_WRITE_PAGE = 0b011 - EXECUTE_ONLY_PAGE = 0b100 - READ_EXECUTE_PAGE = 0b101 - R_W_EXECUTE_PAGE = 0b111 + NEXT_LEVEL_PAGE = 0b000 # Pointer to next level of page table. + READ_ONLY_PAGE = 0b001 # Read-only page. + READ_WRITE_PAGE = 0b011 # Read-write page. + EXECUTE_ONLY_PAGE = 0b100 # Execute-only page. + READ_EXECUTE_PAGE = 0b101 # Read-execute page. + R_W_EXECUTE_PAGE = 0b111 # Read-write-execute page class interrupt_cause_t(IntEnum): @@ -1098,42 +1175,7 @@ class jalr_riscv_reg_t(IntEnum): RA = 0 T1 = auto() - -# Ignore ZERO as src1 of load instructions -class riscv_reg_ex_zero_t(IntEnum): - RA = 0 - SP = auto() - GP = auto() - TP = auto() - T0 = auto() - T1 = auto() - T2 = auto() - S0 = auto() - S1 = auto() - A0 = auto() - A1 = auto() - A2 = auto() - A3 = auto() - A4 = auto() - A5 = auto() - A6 = auto() - A7 = auto() - S2 = auto() - S3 = auto() - S4 = auto() - S5 = auto() - S6 = auto() - S7 = auto() - S8 = auto() - S9 = auto() - S10 = auto() - S11 = auto() - T3 = auto() - T4 = auto() - T5 = auto() - T6 = auto() - - +# PMP address matching mode class pmp_addr_mode_t(Enum): OFF = 0b00 TOR = 0b01 @@ -1166,7 +1208,7 @@ class b_ext_group_t(Enum): ZBR = auto() ZBM = auto() ZBT = auto() - ZB_TMP = auto() + ZB_TMP = auto() # for uncategorized instructions class all_gpr(Enum): @@ -1204,8 +1246,8 @@ class all_gpr(Enum): T6 = auto() -class compressed_gpr(Enum): - S0 = 0 +class compressed_gpr(IntEnum): + S0 = 8 S1 = auto() A0 = auto() A1 = auto() @@ -1215,7 +1257,7 @@ class compressed_gpr(Enum): A5 = auto() -class all_categories(Enum): +class all_categories(IntEnum): LOAD = 0 STORE = auto() SHIFT = auto() @@ -1233,6 +1275,75 @@ class all_categories(Enum): INTERRUPT = auto() AMO = auto() +# Ignore ZERO and SP +class riscv_reg_ex_zero_sp_t(IntEnum): + RA = 1 + GP = 3 + TP = auto() + T0 = auto() + T1 = auto() + T2 = auto() + S0 = auto() + S1 = auto() + A0 = auto() + A1 = auto() + A2 = auto() + A3 = auto() + A4 = auto() + A5 = auto() + A6 = auto() + A7 = auto() + S2 = auto() + S3 = auto() + S4 = auto() + S5 = auto() + S6 = auto() + S7 = auto() + S8 = auto() + S9 = auto() + S10 = auto() + S11 = auto() + T3 = auto() + T4 = auto() + T5 = auto() + T6 = auto() + +# Ignore ZERO only +class riscv_reg_ex_zero_t(IntEnum): + RA = 1 + SP = auto() + GP = auto() + TP = auto() + T0 = auto() + T1 = auto() + T2 = auto() + S0 = auto() + S1 = auto() + A0 = auto() + A1 = auto() + A2 = auto() + A3 = auto() + A4 = auto() + A5 = auto() + A6 = auto() + A7 = auto() + S2 = auto() + S3 = auto() + S4 = auto() + S5 = auto() + S6 = auto() + S7 = auto() + S8 = auto() + S9 = auto() + S10 = auto() + S11 = auto() + T3 = auto() + T4 = auto() + T5 = auto() + T6 = auto() + +# Currently PyVSC doesn't supports ignore bins +# TODO riscv_reg_ex_zero_sp_t and riscv_reg_ex_zero_t is added as a WA and it can be removed later. def get_val(in_string, hexa=0): if len(in_string) > 2: @@ -1422,6 +1533,113 @@ def get_attr_list(instr_name): riscv_instr_name_t.CSRRCI: [riscv_instr_format_t.I_FORMAT, riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM], + #RV32M + riscv_instr_name_t.MUL: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.MULH: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.MULHU: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.MULHSU: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.DIV: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.DIVU: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.REM: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + riscv_instr_name_t.REMU: [riscv_instr_format_t.R_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32M], + # RV32C + riscv_instr_name_t.C_LW: [riscv_instr_format_t.CL_FORMAT, + riscv_instr_category_t.LOAD, + riscv_instr_group_t.RV32C, imm_t.UIMM], + riscv_instr_name_t.C_SW: [riscv_instr_format_t.CS_FORMAT, + riscv_instr_category_t.STORE, + riscv_instr_group_t.RV32C, imm_t.UIMM], + riscv_instr_name_t.C_LWSP: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.LOAD, + riscv_instr_group_t.RV32C, imm_t.UIMM], + riscv_instr_name_t.C_SWSP: [riscv_instr_format_t.CSS_FORMAT, + riscv_instr_category_t.STORE, + riscv_instr_group_t.RV32C, imm_t.UIMM], + riscv_instr_name_t.C_ADDI4SPN: [riscv_instr_format_t.CIW_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C, imm_t.NZUIMM], + riscv_instr_name_t.C_ADDI: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C, imm_t.NZIMM], + riscv_instr_name_t.C_ADDI16SP: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C, imm_t.NZIMM], + riscv_instr_name_t.C_LI: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_LUI: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C, imm_t.NZIMM], + riscv_instr_name_t.C_SUB: [riscv_instr_format_t.CA_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_ADD: [riscv_instr_format_t.CR_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_NOP: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_MV: [riscv_instr_format_t.CR_FORMAT, + riscv_instr_category_t.ARITHMETIC, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_ANDI: [riscv_instr_format_t.CB_FORMAT, + riscv_instr_category_t.LOGICAL, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_XOR: [riscv_instr_format_t.CA_FORMAT, + riscv_instr_category_t.LOGICAL, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_OR: [riscv_instr_format_t.CA_FORMAT, + riscv_instr_category_t.LOGICAL, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_AND: [riscv_instr_format_t.CA_FORMAT, + riscv_instr_category_t.LOGICAL, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_BEQZ: [riscv_instr_format_t.CB_FORMAT, + riscv_instr_category_t.BRANCH, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_BNEZ: [riscv_instr_format_t.CB_FORMAT, + riscv_instr_category_t.BRANCH, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_SRLI: [riscv_instr_format_t.CB_FORMAT, + riscv_instr_category_t.SHIFT, + riscv_instr_group_t.RV32C, imm_t.NZUIMM], + riscv_instr_name_t.C_SRAI: [riscv_instr_format_t.CB_FORMAT, + riscv_instr_category_t.SHIFT, + riscv_instr_group_t.RV32C, imm_t.NZUIMM], + riscv_instr_name_t.C_SLLI: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.SHIFT, + riscv_instr_group_t.RV32C, imm_t.NZUIMM], + riscv_instr_name_t.C_J: [riscv_instr_format_t.CJ_FORMAT, + riscv_instr_category_t.JUMP, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_JAL: [riscv_instr_format_t.CJ_FORMAT, + riscv_instr_category_t.JUMP, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_JR: [riscv_instr_format_t.CR_FORMAT, + riscv_instr_category_t.JUMP, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_JALR: [riscv_instr_format_t.CR_FORMAT, + riscv_instr_category_t.JUMP, + riscv_instr_group_t.RV32C], + riscv_instr_name_t.C_EBREAK: [riscv_instr_format_t.CI_FORMAT, + riscv_instr_category_t.SYSTEM, + riscv_instr_group_t.RV32C], } # if instruction is not present in the dictionary,second argument well # be assigned as default value of passed argument @@ -1442,9 +1660,11 @@ class riscv_instr_pkg: from pygen_src.riscv_instr_gen_config import cfg rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") + # xSTATUS bit mask MPRV_BIT_MASK = BitArray(uint=0x1 << 0x17, length=rcs.XLEN) SUM_BIT_MASK = BitArray(uint=0x1 << 0x18, length=rcs.XLEN) MPP_BIT_MASK = BitArray(uint=0x3 << 0x11, length=rcs.XLEN) + MAX_USED_VADDR_BITS = 30 IMM25_WIDTH = 25 IMM12_WIDTH = 12 @@ -1456,6 +1676,8 @@ class riscv_instr_pkg: MAX_SUB_PROGRAM_CNT = 20 MAX_CALL_PER_FUNC = 5 indent = LABEL_STR_LEN * " " + SINGLE_PRECISION_FRACTION_BITS = 23 + DOUBLE_PRECISION_FRACTION_BITS = 52 def hart_prefix(self, hart=0): if rcs.NUM_HARTS <= 1: @@ -1466,13 +1688,16 @@ def hart_prefix(self, hart=0): def get_label(self, label, hart=0): return (self.hart_prefix(hart) + label) + # Format the string to a fixed length def format_string(self, string, length=10): formatted_str = length * " " - if (int(length) < len(string)): + if int(length) < len(string): return string formatted_str = string + formatted_str[0: (int(length) - len(string))] return formatted_str + # Print the data in the following format + # 0xabcd, 0x1234, 0x3334 ... def format_data(self, data, byte_per_group=4): string = "0x" for i in range(len(data)): @@ -1482,70 +1707,55 @@ def format_data(self, data, byte_per_group=4): string = string + "{:02x}".format(data[i]) return string + # Push general purpose register to stack, this is needed before trap handling def push_gpr_to_kernel_stack(self, status, scratch, mprv, sp, tp, instr): - store_instr = '' - if rcs.XLEN == 32: - store_instr = "sw" - else: - store_instr = "sd" + store_instr = "sw" if rcs.XLEN == 32 else "sd" 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( - "csrrw x{}, {}, x{}".format(sp, hex(scratch.value), sp))) - # Move TP to SP - instr.append(pkg_ins.format_string("add x{}, x{}, zero".format(sp, tp))) + instr.extend(("csrrw x{}, {}, x{}".format(sp, hex(scratch), sp), + # Move TP to SP + "add x{}, x{}, zero".format(sp, tp))) # 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 == privileged_reg_t.MSTATUS and rcs.SATP_MODE != satp_mode_t.BARE): + if(status == 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: - instr.append(pkg_ins.format_string( - "csrr x{}, 0x{} // MSTATUS".format(tp, status.value))) - instr.append(pkg_ins.format_string( - "srli x{}, x{}, 11".format(tp, tp))) # Move MPP to bit 0 - instr.append(pkg_ins.format_string( - "andi x{}, x{}, 0x3".format(tp, tp))) # keep the MPP bits - # Check if MPP equals to M-mode('b11) - instr.append(pkg_ins.format_string("xori x{}, x{}, 0x3".format(tp, tp))) - # Use physical address for kernel SP - instr.append(pkg_ins.format_string("bnez x{}, 1f".format(tp))) - # Use virtual address for stack pointer - instr.append(pkg_ins.format_string( - "slli x{}, x{}, {}".format(sp, sp, - rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS))) - instr.append(pkg_ins.format_string( - "srli x{}, x{}, {}".format(sp, sp, - rcs.XLEN - riscv_instr_pkg.MAX_USED_VADDR_BITS))) + instr.extend(("csrr x{}, {} // MSTATUS".format(tp, hex(status)), + "srli x{}, x{}, 11".format(tp, tp), # Move MPP to bit 0 + "andi x{}, x{}, 0x3".format(tp, tp), # keep the MPP bits + # Check if MPP equals to M-mode('b11) + "xori x{}, x{}, 0x3".format(tp, tp), + # Use physical address for kernel SP + "bnez x{}, 1f".format(tp), + # Use virtual address for stack pointer + "slli x{}, x{}, {}".format(sp, sp, + rcs.XLEN - self.MAX_USED_VADDR_BITS), + "srli x{}, x{}, {}".format(sp, sp, + rcs.XLEN - self.MAX_USED_VADDR_BITS))) # Reserve space from kernel stack to save all 32 GPR except for x0 - instr.append(pkg_ins.format_string( - "1: addi x{}, x{}, -{}".format(sp, sp, int(31 * (rcs.XLEN / 8))))) + instr.append("1: addi x{}, x{}, -{}".format(sp, sp, 31 * (rcs.XLEN // 8))) # Push all GPRs to kernel stack for i in range(1, 32): - instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format( - store_instr, i, int(i * (rcs.XLEN / 8)), sp))) + instr.append("{} x{}, {}(x{})".format( + store_instr, i, i * (rcs.XLEN // 8), sp)) + # Pop general purpose register from stack, this is needed before returning to user program def pop_gpr_from_kernel_stack(self, status, scratch, mprv, sp, tp, instr): - load_instr = '' - if rcs.XLEN == 32: - load_instr = "lw" - else: - load_instr = "ld" + load_instr = "lw" if rcs.XLEN == 32 else "ld" # Pop user mode GPRs from kernel stack for i in range(1, 32): - instr.append(pkg_ins.format_string("{} x{}, {}(x{})".format( - load_instr, i, int(i * (rcs.XLEN / 8)), sp))) + instr.append("{} x{}, {}(x{})".format( + load_instr, i, i * (rcs.XLEN // 8), sp)) # Restore kernel stack pointer - instr.append(pkg_ins.format_string( - "addi x{}, x{}, {}".format(sp, sp, int(31 * (rcs.XLEN / 8))))) + instr.append("addi x{}, x{}, {}".format(sp, sp, 31 * (rcs.XLEN // 8))) 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 - instr.append(pkg_ins.format_string( - "csrrw x{}, 0x{}, x{}".format(sp, scratch.value, sp))) + instr.extend(("add x{}, x{}, zero".format(tp, sp), + # Restore user mode stack pointer + "csrrw x{}, {}, x{}".format(sp, hex(scratch), sp))) pkg_ins = riscv_instr_pkg() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py index 5c1a1f0e9d..6227302e29 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_sequence.py @@ -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 @@ -9,53 +8,83 @@ 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 re -import logging -import random import sys +import random +import logging import vsc from importlib import import_module from collections import defaultdict +from pygen_src.riscv_instr_gen_config import cfg from pygen_src.riscv_instr_stream import riscv_rand_instr_stream from pygen_src.riscv_illegal_instr import riscv_illegal_instr, illegal_instr_type_e -from pygen_src.riscv_instr_gen_config import cfg +from pygen_src.riscv_directed_instr_lib import riscv_pop_stack_instr, riscv_push_stack_instr from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_instr_name_t, riscv_reg_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") +# ----------------------------------------------------------------------------------------- +# RISC-V instruction sequence + +# This class is used to generate a single instruction sequence for a RISC-V assembly program. +# It's used by riscv_asm_program_gen to generate the main program and all sub-programs. The +# flow is explained below: +# For main program: +# - Generate instruction sequence body. +# - Post-process the load/store/branch instructions. +# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen). +# For sub program: +# - Generate the stack push instructions which are executed when entering this program. +# - Generate instruction sequence body. +# - Generate the stack pop instructions which are executed before exiting this program. +# - Post-process the load/store/branch instructions. +# - Insert the jump instructions to its sub-programs (done by riscv_asm_program_gen). +# - Generate a return instruction at the end of the program. +# ----------------------------------------------------------------------------------------- + class riscv_instr_sequence: def __init__(self): - self.instr_cnt = 0 + self.instr_cnt = 0 # Instruction count of this sequence self.instr_stream = riscv_rand_instr_stream() - self.is_main_program = 0 - self.is_debug_program = 0 - self.label_name = "" + self.is_main_program = 0 # Main instruction streams + self.is_debug_program = 0 # Indicates whether sequence is debug program + self.label_name = "" # Label of the sequence (program name) self.instr_string_list = [] # Save the instruction list 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 - self.branch_idx = [None] * 30 self.instr_stack_enter = riscv_push_stack_instr() self.instr_stack_exit = riscv_pop_stack_instr() self.illegal_instr = riscv_illegal_instr() - def gen_instr(self, is_main_program, no_branch = 1): + # Main function to generate the instruction stream + # The main random instruction stream is generated by instr_stream.gen_instr(), which generates + # each instruction one by one with a separate randomization call. It's not done by a single + # randomization call for the entire instruction stream because this solution won't scale if + # we have hundreds of thousands of instructions to generate. The constraint solver slows down + # considerably as the instruction stream becomes longer. The downside is we cannot specify + # constraints between instructions. The way to solve it is to have a dedicated directed + # instruction stream for such scenarios, like hazard sequence. + def gen_instr(self, is_main_program, no_branch = 0): self.is_main_program = is_main_program self.instr_stream.initialize_instr_list(self.instr_cnt) - logging.info("Start generating %d instruction" % len(self.instr_stream.instr_list)) + logging.info("Start generating {} instruction".format(len(self.instr_stream.instr_list))) + # Do not generate load/store instruction here + # The load/store instruction will be inserted as directed instruction stream self.instr_stream.gen_instr(no_branch = no_branch, no_load_store = 1, is_debug_program = self.is_debug_program) - if not is_main_program: self.gen_stack_enter_instr() self.gen_stack_exit_instr() + logging.info("Finishing instruction generation") + # Generate the stack push operations for this program + # It pushes the necessary context to the stack like RA, T0,loop registers etc. The stack + # pointer(SP) is reduced by the amount the stack space allocated to this program. def gen_stack_enter_instr(self): allow_branch = 0 if (self.illegal_instr_pct > 0 or self.hint_instr_pct > 0) else 1 allow_branch &= not cfg.no_branch_jump @@ -63,6 +92,7 @@ def gen_stack_enter_instr(self): 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)) + # Keep stack len word aligned to avoid unaligned load/store self.program_stack_len % (rcs.XLEN // 8) == 0 except Exception: logging.critical("Cannot randomize program_stack_len") @@ -79,50 +109,44 @@ def gen_stack_exit_instr(self): self.instr_stack_exit.gen_pop_stack_instr(self.program_stack_len, self.instr_stack_enter.saved_regs) - ''' - ---------------------------------------------------------------------------------------------- - Instruction post-process + # ---------------------------------------------------------------------------------------------- + # Instruction post-process - Post-process is required for branch instructions: - - Need to assign a valid branch target. This is done by picking a random instruction label in - this sequence and assigning to the branch instruction. All the non-atomic instructions - will have a unique numeric label as the local branch target identifier. - The atomic instruction streams don't have labels except for the first instruction. This is - to avoid branching into an atomic instruction stream which breaks its atomicy. The - definition of an atomic instruction stream here is a sequence of instructions which must be - executed in-order. - In this sequence, only forward branch is handled. The backward branch target is implemented - in a dedicated loop instruction sequence. Randomly choosing a backward branch target could - lead to dead loops in the absence of proper loop exiting conditions. - ---------------------------------------------------------------------------------------------- - ''' + # Post-process is required for branch instructions: + # Need to assign a valid branch target. This is done by picking a random instruction label in + # this sequence and assigning to the branch instruction. All the non-atomic instructions + # will have a unique numeric label as the local branch target identifier. + # The atomic instruction streams don't have labels except for the first instruction. This is + # to avoid branching into an atomic instruction stream which breaks its atomicy. The + # definition of an atomic instruction stream here is a sequence of instructions which must be + # executed in-order. + # In this sequence, only forward branch is handled. The backward branch target is implemented + # in a dedicated loop instruction sequence. Randomly choosing a backward branch target could + # lead to dead loops in the absence of proper loop exiting conditions. + # ---------------------------------------------------------------------------------------------- def post_process_instr(self): label_idx = 0 branch_cnt = 0 + branch_idx = [None] * 30 j = 0 branch_target = defaultdict(lambda: None) - + # Insert directed instructions, it's randomly mixed with the random instruction stream. for instr in self.directed_instr: self.instr_stream.insert_instr_stream(instr.instr_list) - ''' - Assign an index for all instructions, these indexes wont change - even a new instruction is injected in the post process. - ''' + # Assign an index for all instructions, these indexes wont change + # even a new instruction is injected in the post process. for i in range(len(self.instr_stream.instr_list)): self.instr_stream.instr_list[i].idx = label_idx if(self.instr_stream.instr_list[i].has_label and not(self.instr_stream.instr_list[i].atomic)): if((self.illegal_instr_pct > 0) and (self.instr_stream.instr_list[i].insert_illegal_instr == 0)): - ''' - The illegal instruction generator always increase PC by 4 when resume execution, - need to make sure PC + 4 is at the correct instruction boundary. - ''' - if(self.instr_stream.instr_list[i].is_compressed): + # The illegal instruction generator always increase PC by 4 when resume + # execution, need to make sure PC + 4 is at the correct instruction boundary. + if self.instr_stream.instr_list[i].is_compressed: if(i < (len(self.instr_stream.instr_list) - 1)): - if(self.instr_stream.instr_list[i + 1].is_compressed): + if self.instr_stream.instr_list[i + 1].is_compressed: self.instr_stream.instr_list[i].is_illegal_instr = random.randrange( 0, min(100, self.illegal_instr_pct)) else: @@ -130,54 +154,54 @@ def post_process_instr(self): 0, min(100, self.illegal_instr_pct)) if(self.hint_instr_pct > 0 and (self.instr_stream.instr_list[i].is_illegal_instr == 0)): - if(self.instr_stream.instr_list[i].is_compressed): + if self.instr_stream.instr_list[i].is_compressed: self.instr_stream.instr_list[i].is_hint_instr = random.randrange( 0, min(100, self.hint_instr_pct)) self.instr_stream.instr_list[i].label = "{}".format(label_idx) self.instr_stream.instr_list[i].is_local_numeric_label = 1 label_idx += 1 - # Generate branch target - for i in range(len(self.branch_idx)): - self.branch_idx[i] = random.randint(1, cfg.max_branch_step) + for i in range(len(branch_idx)): + branch_idx[i] = random.randint(1, cfg.max_branch_step) - while(j < len(self.instr_stream.instr_list)): + while j < len(self.instr_stream.instr_list): if((self.instr_stream.instr_list[j].category == riscv_instr_category_t.BRANCH) and (not self.instr_stream.instr_list[j].branch_assigned) and (not self.instr_stream.instr_list[j].is_illegal_instr)): - ''' - Post process the branch instructions to give a valid local label - Here we only allow forward branch to avoid unexpected infinite loop - The loop structure will be inserted with a separate routine using - reserved loop registers - ''' + # Post process the branch instructions to give a valid local label + # Here we only allow forward branch to avoid unexpected infinite loop + # The loop structure will be inserted with a separate routine using + # reserved loop registers branch_target_label = 0 - # branch_byte_offset = 0 branch_target_label = self.instr_stream.instr_list[j].idx + \ - self.branch_idx[branch_cnt] + branch_idx[branch_cnt] if(branch_target_label >= label_idx): branch_target_label = label_idx - 1 branch_cnt += 1 - if(branch_cnt == len(self.branch_idx)): + if(branch_cnt == len(branch_idx)): branch_cnt = 0 - random.shuffle(self.branch_idx) + random.shuffle(branch_idx) 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) 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 - # Remove the local label which is not used as branch target if(self.instr_stream.instr_list[j].has_label and self.instr_stream.instr_list[j].is_local_numeric_label): idx = int(self.instr_stream.instr_list[j].label) - if(not branch_target[idx]): + if not branch_target[idx]: self.instr_stream.instr_list[j].has_label = 0 j += 1 logging.info("Finished post-processing instructions") + # Inject a jump instruction stream + # This function is called by riscv_asm_program_gen with the target program label + # The jump routine is implmented with an atomic instruction stream(riscv_jump_instr). Similar + # to load/store instructions, JALR/JAL instructions also need a proper base address and offset + # as the jump target. def insert_jump_instr(self): # TODO riscv_jump_instr class implementation """ @@ -194,6 +218,9 @@ def insert_jump_instr(self): """ pass + # Convert the instruction stream to the string format. + # Label is attached to the instruction if available, otherwise attach proper space to make + # the code indent consistent. def generate_instr_stream(self, no_label = 0): prefix = '' string = '' @@ -208,15 +235,15 @@ def generate_instr_stream(self, no_label = 0): self.label_name), length = pkg_ins.LABEL_STR_LEN) self.instr_stream.instr_list[i].has_label = 1 else: - if(self.instr_stream.instr_list[i].has_label): + if self.instr_stream.instr_list[i].has_label: prefix = pkg_ins.format_string(string = '{}:'.format( self.instr_stream.instr_list[i].label), length = pkg_ins.LABEL_STR_LEN) else: prefix = pkg_ins.format_string(string = " ", length = pkg_ins.LABEL_STR_LEN) string = prefix + self.instr_stream.instr_list[i].convert2asm() self.instr_string_list.append(string) - if(rcs.support_pmp and not re.search("main", self.label_name)): - self.instr_string_list.insert(0, ".align 2") + if(rcs.support_pmp and not re.search("main", self.label_name)): + self.instr_string_list.insert(0, ".align 2") self.insert_illegal_hint_instr() prefix = pkg_ins.format_string(str(i), pkg_ins.LABEL_STR_LEN) if not self.is_main_program: diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py index 5b957d1c43..ac2fbdbcc4 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_instr_stream.py @@ -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 @@ -10,6 +9,7 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ + import random import logging import sys @@ -20,15 +20,12 @@ from pygen_src.riscv_instr_gen_config import cfg +# Base class for RISC-V instruction stream +# A instruction stream here is a queue of RISC-V basic instructions. +# This class also provides some functions to manipulate the instruction stream, like insert a new +# instruction, mix two instruction streams etc. @vsc.randobj class riscv_instr_stream: - ''' - Base class for RISC-V instruction stream - A instruction stream here is a queue of RISC-V basic instructions. - This class also provides some functions to manipulate the instruction stream, like insert a new - instruction, mix two instruction streams etc. - ''' - def __init__(self): self.instr_list = [] self.instr_cnt = 0 @@ -40,6 +37,7 @@ def __init__(self): self.reserved_rd = vsc.list_t(vsc.enum_t(riscv_reg_t)) self.hart = 0 + # Initialize the instruction stream, create each instruction instance def initialize_instr_list(self, instr_cnt): self.instr_list.clear() self.instr_cnt = instr_cnt @@ -50,12 +48,11 @@ def create_instr_instance(self): instr = riscv_instr() self.instr_list.append(instr) + # Insert an instruction to the existing instruction stream at the given index + # When index is -1, the instruction is injected at a random location def insert_instr(self, instr, idx = -1): - """ - Insert an instruction to the existing instruction stream at the given index - When index is -1, the instruction is injected at a random location - """ current_instr_cnt = len(self.instr_list) + # TODO if idx == -1: idx = random.randint(0, current_instr_cnt - 1) while self.instr_list[idx].atomic: @@ -64,16 +61,14 @@ def insert_instr(self, instr, idx = -1): self.instr_list.append(instr) return elif idx > current_instr_cnt or idx < 0: - logging.error("Cannot insert instr:%0s at idx %0d", instr.convert2asm(), idx) + logging.error("Cannot insert instr:{} at idx {}".format(instr.convert2asm(), idx)) sys.exit(1) self.instr_list.insert(idx, instr) + # Insert an instruction to the existing instruction stream at the given index + # When index is -1, the instruction is injected at a random location + # When replace is 1, the original instruction at the inserted position will be replaced def insert_instr_stream(self, new_instr, idx = -1, replace = 0): - """ - Insert an instruction to the existing instruction stream at the given index - When index is -1, the instruction is injected at a random location - When replace is 1, the original instruction at the inserted position will be replaced - """ current_instr_cnt = len(self.instr_list) if current_instr_cnt == 0: @@ -97,7 +92,7 @@ def insert_instr_stream(self, new_instr, idx = -1, replace = 0): logging.critical("Cannot inject the instruction") sys.exit(1) elif idx > current_instr_cnt or idx < 0: - logging.error("Cannot insert instr stream at idx %0d", idx) + logging.error("Cannot insert instr stream at idx {}".format(idx)) sys.exit(1) # When replace is 1, the original instruction at this index will be removed. # The label of the original instruction will be copied to the head @@ -117,17 +112,15 @@ def insert_instr_stream(self, new_instr, idx = -1, replace = 0): self.instr_list = self.instr_list[0:idx] + new_instr + \ self.instr_list[idx:current_instr_cnt] + # Mix the input instruction stream with the original instruction, the instruction order is + # preserved. When 'contained' is set, the original instruction stream will be inside the + # new instruction stream with the first and last instruction from the input instruction stream. + # new_instr is a list of riscv_instr def mix_instr_stream(self, new_instr, contained = 0): - """ - Mix the input instruction stream with the original instruction, the instruction order is - preserved. When 'contained' is set, the original instruction stream will be inside the - new instruction stream with the first and last instruction from the input instruction - stream. - new_instr is a list of riscv_instr - """ current_instr_cnt = len(self.instr_list) new_instr_cnt = len(new_instr) insert_instr_position = [0] * new_instr_cnt + # TODO if len(insert_instr_position) > 0: insert_instr_position.sort() for i in range(new_instr_cnt): @@ -148,16 +141,13 @@ def convert2string(self): return s +# Generate a random instruction stream based on the configuration +# There are two ways to use this class to generate instruction stream +# 1. For short instruction stream, you can call randomize() directly. +# 2. For long instruction stream (>1K), randomize() all instructions together might take a +# long time for the constraint solver. In this case, you can call gen_instr to generate +# instructions one by one. The time only grows linearly with the instruction count class riscv_rand_instr_stream(riscv_instr_stream): - """ - Generate a random instruction stream based on the configuration - There are two ways to use this class to generate instruction stream - 1. For short instruction stream, you can call randomize() directly. - 2. For long instruction stream (>1K), randomize() all instructions together might take a - long time for the constraint solver. In this case, you can call gen_instr to generate - instructions one by one. The time only grows linearly with the instruction count - """ - def __init__(self): # calling super constructor super().__init__() @@ -196,7 +186,7 @@ def randomize_avail_regs(self): 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)) + self.reserved_rd)) except Exception: logging.critical("Cannot randomize avail_regs") sys.exit(1)''' @@ -209,12 +199,14 @@ def setup_instruction_dist(self, no_branch = 0, no_load_store = 1): if no_load_store: self.category_dist[riscv_instr_category_t.LOAD.name] = 0 self.category_dist[riscv_instr_category_t.STORE.name] = 0 - logging.info("setup_instruction_dist: %0d", len(self.category_dist)) + logging.info("setup_instruction_dist: {}".format(len(self.category_dist))) def gen_instr(self, no_branch = 0, no_load_store = 1, is_debug_program = 0): self.setup_allowed_instr(no_branch, no_load_store) for i in range(len(self.instr_list)): self.instr_list[i] = self.randomize_instr(self.instr_list[i], is_debug_program) + # Do not allow branch instruction as the last instruction because there's no + # forward branch target while self.instr_list[-1].category == riscv_instr_category_t.BRANCH: self.instr_list.pop() if len(self.instr_list) == 0: @@ -268,3 +260,11 @@ def randomize_gpr(self, instr): instr.rs1 != cfg.reserved_regs[i] # TODO: Add constraint for CSR, floating point register return instr + + def get_init_gpr_instr(self, gpr, val): + # TODO + pass + + def add_init_vector_gpr_instr(self, gpr, val): + # TODO + pass diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py index 7df1cb7791..bf0160e7eb 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_load_store_instr_lib.py @@ -32,6 +32,7 @@ class locality_e(IntEnum): SPARSE = auto() +# Base class for all load/store instruction stream @vsc.randobj class riscv_load_store_base_instr_stream(riscv_mem_access_stream): def __init__(self): @@ -213,6 +214,7 @@ def gen_load_store_instr(self): self.load_store_instr.append(instr) +# A single load/store instruction @vsc.randobj class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream): def __init__(self): @@ -224,6 +226,7 @@ def legal_c(self): self.num_mixed_instr < 5 +# Back to back load/store instructions @vsc.randobj class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream): def __init__(self): @@ -237,6 +240,19 @@ def legal_c(self): self.num_mixed_instr == 0 +# Back to back load/store instructions +@vsc.randobj +class riscv_load_store_shared_mem_stream(riscv_load_store_stress_instr_stream): + def __init__(self): + super().__init__() + + def pre_randomize(self): + self.load_store_shared_memory = 1 + super().pre_randomize() + + +# Random load/store sequence +# A random mix of load/store instructions and other instructions @vsc.randobj class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream): def __init__(self): @@ -248,6 +264,7 @@ def legal_c(self): self.num_mixed_instr.inside(vsc.rangelist(vsc.rng(10, 30))) +# Use a small set of GPR to create various WAW, RAW, WAR hazard scenario @vsc.randobj class riscv_load_store_hazard_instr_stream(riscv_load_store_base_instr_stream): def __init__(self): diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py index 4631a2a21b..49e7c0c7aa 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privil_reg.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -30,7 +29,7 @@ def init_reg(self, reg_name): super().init_reg(reg_name) # ---------------Machine mode register ---------------- # Machine status Register - if(reg_name == privileged_reg_t.MSTATUS): + if reg_name == privileged_reg_t.MSTATUS: self.privil_level = privileged_level_t.M_LEVEL self.add_field("UIE", 1, reg_field_access_t.WARL) self.add_field("SIE", 1, reg_field_access_t.WARL) @@ -51,7 +50,7 @@ def init_reg(self, reg_name): self.add_field("TVM", 1, reg_field_access_t.WARL) self.add_field("TW", 1, reg_field_access_t.WARL) self.add_field("TSR", 1, reg_field_access_t.WARL) - if(rcs.XLEN == 32): + if rcs.XLEN == 32: self.add_field("WPRI3", 8, reg_field_access_t.WPRI) else: self.add_field("WPRI3", 9, reg_field_access_t.WPRI) @@ -60,7 +59,7 @@ def init_reg(self, reg_name): self.add_field("WPRI4", rcs.XLEN - 37, reg_field_access_t.WPRI) self.add_field("SD", 1, reg_field_access_t.WARL) # Machine interrupt-enable register - elif(reg_name == privileged_reg_t.MIE): + elif reg_name == privileged_reg_t.MIE: self.privil_level = privileged_level_t.M_LEVEL self.add_field("USIE", 1, reg_field_access_t.WARL) self.add_field("SSIE", 1, reg_field_access_t.WARL) @@ -75,5 +74,6 @@ def init_reg(self, reg_name): self.add_field("WPEI2", 1, reg_field_access_t.WPRI) self.add_field("MEIE", 1, reg_field_access_t.WARL) self.add_field("WPRI3", rcs.XLEN - 12, reg_field_access_t.WPRI) + # TODO add condition for rest of the modes else: logging.error("reg %0s is not supported yet", reg_name.name) diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py index ce612a1803..1fdf1bfb1f 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_privileged_common_seq.py @@ -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 @@ -9,7 +8,6 @@ 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 logging @@ -22,6 +20,7 @@ rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") +# This class provides some common routines for privileged mode operations @vsc.randobj class riscv_privileged_common_seq(): def __init___(self): @@ -79,8 +78,8 @@ def setup_umode_reg(self, 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), + instrs.append("li x{}, {}".format(cfg.gpr[0], hex(regs[i].get_val()))) + instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name), cfg.gpr[0], regs[i].reg_name.name)) def setup_satp(self, instrs): diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py index c573634f2e..a47b20544b 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_pseudo_instr.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -9,7 +8,6 @@ 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 @@ -36,11 +34,12 @@ def __init__(self): riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I) ''' + # 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) + # instr rd,imm asm_str = "{}{}, {}".format(asm_str, self.rd.name, self.get_imm()) - - if(self.comment != ""): + if self.comment != "": asm_str = "{} #{}".format(asm_str, self.comment) return asm_str.lower() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py index 395b2d023e..9550119f63 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_reg.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -21,7 +20,10 @@ rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting") +# ----------------------------------------------- # Light weight RISC-V register class library +# ----------------------------------------------- + # Base class for RISC-V register field @vsc.randobj class riscv_reg_field: diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py index 1f67bcb908..65a395ef92 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_signature_pkg.py @@ -12,9 +12,8 @@ from enum import IntEnum, auto -# Will be the lowest 8 bits of the data word - +# Will be the lowest 8 bits of the data word class signature_type_t(IntEnum): ''' Information sent to the core relating its current status. diff --git a/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py b/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py index 127b08513e..543f1a9b51 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/riscv_utils.py @@ -26,6 +26,10 @@ riscv_single_load_store_instr_stream) +# ---------------------------------------------------------- +# pyflow commmon utility helpers functions +# ---------------------------------------------------------- + def factory(obj_of): objs = { "riscv_directed_instr_stream": riscv_directed_instr_stream, diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py index d984036a23..d5d9349f35 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/multi_harts/riscv_core_setting.py @@ -1,7 +1,6 @@ """ Copyright 2020 Google LLC Copyright 2020 PerfectVIPs Inc. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -10,74 +9,109 @@ 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) - +import math +from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, + riscv_instr_group_t, mtvec_mode_t, + privileged_mode_t) +# ----------------------------------------------------------------------------- +# Processor feature configuration +# ----------------------------------------------------------------------------- +# XLEN 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] - +# set to BARE if address translation is not supported SATP_MODE = satp_mode_t.BARE +# Supported Privileged mode +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +# Unsupported instructions +unsupported_instr = [] + +# ISA supported by the processor supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, riscv_instr_group_t.RV32C, riscv_instr_group_t.RV32A] -supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] - +# Interrupt mode support supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] +# The number of interrupt vectors to be generated, only used if VECTORED +# interrupt mode is supported max_interrupt_vector_num = 16 -support_debug_mode = 0 - -NUM_HARTS = 2 - +# Physical memory protection support support_pmp = 0 -unsupported_instr = [] +# Debug mode support +support_debug_mode = 0 +# Support delegate trap to user mode support_umode_trap = 0 +# Support sfence.vma instruction support_sfence = 0 +# Support unaligned load/store support_unaligned_load_store = 1 +# GPR Setting NUM_FLOAT_GPR = 32 - NUM_GPR = 32 - NUM_VEC_GPR = 32 +# ----------------------------------------------------------------------------- +# Vector extension configuration +# ----------------------------------------------------------------------------- + +# Parameter for vector extension VECTOR_EXTENSION_ENABLE = 0 VLEN = 512 +# Maximum size of a single vector element ELEN = 32 +# Minimum size of a sub-element, which must be at most 8-bits. SELEN = 8 -#VELEN = +# Maximum size of a single vector element (encoded in vsew format) +VELEN = int(math.log(ELEN) // math.log(2)) - 3 + +# Maxium LMUL supported by the core +MAX_LMUL = 8 -MAX_MUL = 8 -implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, - interrupt_cause_t.M_TIMER_INTR, - interrupt_cause_t.M_EXTERNAL_INTR] +# ----------------------------------------------------------------------------- +# Multi-harts configuration +# ----------------------------------------------------------------------------- + +# Number of harts +NUM_HARTS = 2 -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] +# ----------------------------------------------------------------------------- +# Previleged CSR implementation +# ----------------------------------------------------------------------------- + +# Implemented previlieged CSR list +implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID + privileged_reg_t.MARCHID, # Architecture ID + privileged_reg_t.MIMPID, # Implementation ID + privileged_reg_t.MHARTID, # Hardware thread ID + privileged_reg_t.MSTATUS, # Machine status + privileged_reg_t.MISA, # ISA and extensions + privileged_reg_t.MIE, # Machine interrupt-enable register + privileged_reg_t.MTVEC, # Machine trap-handler base address + privileged_reg_t.MCOUNTEREN, # Machine counter enable + privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers + privileged_reg_t.MEPC, # Machine exception program counter + privileged_reg_t.MCAUSE, # Machine trap cause + privileged_reg_t.MTVAL, # Machine bad address or instruction + privileged_reg_t.MIP # Machine interrupt pending + ] + +# Implementation-specific custom CSRs +custom_csr = [] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py index fbcc4510e1..ef9ee53c7f 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32i/riscv_core_setting.py @@ -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 @@ -10,37 +9,108 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ + +import math from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, - riscv_instr_group_t, privileged_mode_t) + riscv_instr_group_t, mtvec_mode_t, + privileged_mode_t) -XLEN = 32 +# ----------------------------------------------------------------------------- +# Processor feature configuration +# ----------------------------------------------------------------------------- -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] +# XLEN +XLEN = 32 +# set to BARE if address translation is not supported SATP_MODE = satp_mode_t.BARE +# Supported Privileged mode +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +# Unsupported instructions +unsupported_instr = [] + +# ISA supported by the processor supported_isa = [riscv_instr_group_t.RV32I] -supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] -NUM_HARTS = 1 +# Interrupt mode support +supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] + +# The number of interrupt vectors to be generated, only used if VECTORED +# interrupt mode is supported +max_interrupt_vector_num = 16 +# Physical memory protection support support_pmp = 0 +# Debug mode support support_debug_mode = 0 -unsupported_instr = [] - +# Support delegate trap to user mode support_umode_trap = 0 +# Support sfence.vma instruction +support_sfence = 0 + +# Support unaligned load/store +support_unaligned_load_store = 1 + # GPR Setting NUM_FLOAT_GPR = 32 NUM_GPR = 32 NUM_VEC_GPR = 32 -max_interrupt_vector_num = 16 +# ----------------------------------------------------------------------------- +# Vector extension configuration +# ----------------------------------------------------------------------------- + +# Parameter for vector extension +VECTOR_EXTENSION_ENABLE = 0 + +VLEN = 512 + +# Maximum size of a single vector element +ELEN = 32 + +# Minimum size of a sub-element, which must be at most 8-bits. +SELEN = 8 + +# Maximum size of a single vector element (encoded in vsew format) +VELEN = int(math.log(ELEN) // math.log(2)) - 3 + +# Maxium LMUL supported by the core +MAX_LMUL = 8 + + +# ----------------------------------------------------------------------------- +# Multi-harts configuration +# ----------------------------------------------------------------------------- + +# Number of harts +NUM_HARTS = 1 + +# ----------------------------------------------------------------------------- +# Previleged CSR implementation +# ----------------------------------------------------------------------------- + +# Implemented previlieged CSR list +implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID + privileged_reg_t.MARCHID, # Architecture ID + privileged_reg_t.MIMPID, # Implementation ID + privileged_reg_t.MHARTID, # Hardware thread ID + privileged_reg_t.MSTATUS, # Machine status + privileged_reg_t.MISA, # ISA and extensions + privileged_reg_t.MIE, # Machine interrupt-enable register + privileged_reg_t.MTVEC, # Machine trap-handler base address + privileged_reg_t.MCOUNTEREN, # Machine counter enable + privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers + privileged_reg_t.MEPC, # Machine exception program counter + privileged_reg_t.MCAUSE, # Machine trap cause + privileged_reg_t.MTVAL, # Machine bad address or instruction + privileged_reg_t.MIP # Machine interrupt pending + ] + +# Implementation-specific custom CSRs +custom_csr = [] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py index ae18332264..5de8125c66 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imafdc/riscv_core_setting.py @@ -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 @@ -10,71 +9,111 @@ 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) +import math +from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, + riscv_instr_group_t, mtvec_mode_t, + privileged_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] +# ----------------------------------------------------------------------------- +# Processor feature configuration +# ----------------------------------------------------------------------------- + +# XLEN +XLEN = 32 +# set to BARE if address translation is not supported SATP_MODE = satp_mode_t.BARE +# Supported Privileged mode +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +# Unsupported instructions +unsupported_instr = [] + +# ISA supported by the processor 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] - +# Interrupt mode support supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] +# The number of interrupt vectors to be generated, only used if VECTORED +# interrupt mode is supported max_interrupt_vector_num = 16 -support_debug_mode = 0 - -NUM_HARTS = 1 - +# Physical memory protection support support_pmp = 0 -unsupported_instr = [] +# Debug mode support +support_debug_mode = 0 +# Support delegate trap to user mode support_umode_trap = 0 +# Support sfence.vma instruction support_sfence = 0 +# Support unaligned load/store support_unaligned_load_store = 1 +# GPR Setting NUM_FLOAT_GPR = 32 - NUM_GPR = 32 - NUM_VEC_GPR = 32 +# ----------------------------------------------------------------------------- +# Vector extension configuration +# ----------------------------------------------------------------------------- + +# Parameter for vector extension VECTOR_EXTENSION_ENABLE = 0 VLEN = 512 +# Maximum size of a single vector element ELEN = 32 -SELEN = 0 +# Minimum size of a sub-element, which must be at most 8-bits. +SELEN = 8 + +# Maximum size of a single vector element (encoded in vsew format) +VELEN = int(math.log(ELEN) // math.log(2)) - 3 + +# Maxium LMUL supported by the core +MAX_LMUL = 8 -MAX_MUL = 8 -implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, - interrupt_cause_t.M_TIMER_INTR, - interrupt_cause_t.M_EXTERNAL_INTR] +# ----------------------------------------------------------------------------- +# Multi-harts configuration +# ----------------------------------------------------------------------------- + +# Number of harts +NUM_HARTS = 1 -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] +# ----------------------------------------------------------------------------- +# Previleged CSR implementation +# ----------------------------------------------------------------------------- + +# Implemented previlieged CSR list +implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID + privileged_reg_t.MARCHID, # Architecture ID + privileged_reg_t.MIMPID, # Implementation ID + privileged_reg_t.MHARTID, # Hardware thread ID + privileged_reg_t.MSTATUS, # Machine status + privileged_reg_t.MISA, # ISA and extensions + privileged_reg_t.MIE, # Machine interrupt-enable register + privileged_reg_t.MTVEC, # Machine trap-handler base address + privileged_reg_t.MCOUNTEREN, # Machine counter enable + privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers + privileged_reg_t.MEPC, # Machine exception program counter + privileged_reg_t.MCAUSE, # Machine trap cause + privileged_reg_t.MTVAL, # Machine bad address or instruction + privileged_reg_t.MIP # Machine interrupt pending + ] + +# Implementation-specific custom CSRs +custom_csr = [] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py index 7f464765c5..d91f2ede91 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imc/riscv_core_setting.py @@ -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 @@ -10,44 +9,52 @@ 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) +import math +from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, + riscv_instr_group_t, mtvec_mode_t, + privileged_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] +# ----------------------------------------------------------------------------- +# Processor feature configuration +# ----------------------------------------------------------------------------- -SATP_MODE = satp_mode_t.BARE +# XLEN +XLEN = 32 -supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, - riscv_instr_group_t.RV32C] +# set to BARE if address translation is not supported +SATP_MODE = satp_mode_t.BARE +# Supported Privileged mode supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] -supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] +# Unsupported instructions +unsupported_instr = [] -max_interrupt_vector_num = 16 +# ISA supported by the processor +supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M, riscv_instr_group_t.RV32C] -support_debug_mode = 0 +# Interrupt mode support +supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] -NUM_HARTS = 1 +# The number of interrupt vectors to be generated, only used if VECTORED +# interrupt mode is supported +max_interrupt_vector_num = 16 +# Physical memory protection support support_pmp = 0 -unsupported_instr = [] +# Debug mode support +support_debug_mode = 0 +# Support delegate trap to user mode support_umode_trap = 0 +# Support sfence.vma instruction support_sfence = 0 +# Support unaligned load/store support_unaligned_load_store = 1 # GPR Setting @@ -55,22 +62,55 @@ NUM_GPR = 32 NUM_VEC_GPR = 32 +# ----------------------------------------------------------------------------- +# Vector extension configuration +# ----------------------------------------------------------------------------- + +# Parameter for vector extension VECTOR_EXTENSION_ENABLE = 0 VLEN = 512 +# Maximum size of a single vector element ELEN = 32 -SELEN = 0 +# Minimum size of a sub-element, which must be at most 8-bits. +SELEN = 8 -MAX_MUL = 8 +# Maximum size of a single vector element (encoded in vsew format) +VELEN = int(math.log(ELEN) // math.log(2)) - 3 -implemented_interrupt = [interrupt_cause_t.M_SOFTWARE_INTR, - interrupt_cause_t.M_TIMER_INTR, - interrupt_cause_t.M_EXTERNAL_INTR] +# Maxium LMUL supported by the core +MAX_LMUL = 8 + + +# ----------------------------------------------------------------------------- +# Multi-harts configuration +# ----------------------------------------------------------------------------- + +# Number of harts +NUM_HARTS = 1 -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] +# ----------------------------------------------------------------------------- +# Previleged CSR implementation +# ----------------------------------------------------------------------------- + +# Implemented previlieged CSR list +implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID + privileged_reg_t.MARCHID, # Architecture ID + privileged_reg_t.MIMPID, # Implementation ID + privileged_reg_t.MHARTID, # Hardware thread ID + privileged_reg_t.MSTATUS, # Machine status + privileged_reg_t.MISA, # ISA and extensions + privileged_reg_t.MIE, # Machine interrupt-enable register + privileged_reg_t.MTVEC, # Machine trap-handler base address + privileged_reg_t.MCOUNTEREN, # Machine counter enable + privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers + privileged_reg_t.MEPC, # Machine exception program counter + privileged_reg_t.MCAUSE, # Machine trap cause + privileged_reg_t.MTVAL, # Machine bad address or instruction + privileged_reg_t.MIP # Machine interrupt pending + ] + +# Implementation-specific custom CSRs +custom_csr = [] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py index 8a11e93ce2..0299170585 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/target/rv32imcb/riscv_core_setting.py @@ -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 @@ -10,45 +9,53 @@ 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) +import math +from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t, + riscv_instr_group_t, mtvec_mode_t, + privileged_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] +# ----------------------------------------------------------------------------- +# Processor feature configuration +# ----------------------------------------------------------------------------- + +# XLEN +XLEN = 32 +# set to BARE if address translation is not supported SATP_MODE = satp_mode_t.BARE +# Supported Privileged mode +supported_privileged_mode = [privileged_mode_t.MACHINE_MODE] + +# Unsupported instructions +unsupported_instr = [] + +# ISA supported by the processor 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] - +# Interrupt mode support supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED] +# The number of interrupt vectors to be generated, only used if VECTORED +# interrupt mode is supported max_interrupt_vector_num = 16 -support_debug_mode = 0 - -NUM_HARTS = 1 - +# Physical memory protection support support_pmp = 0 -unsupported_instr = [] +# Debug mode support +support_debug_mode = 0 +# Support delegate trap to user mode support_umode_trap = 0 +# Support sfence.vma instruction support_sfence = 0 +# Support unaligned load/store support_unaligned_load_store = 1 # GPR Setting @@ -56,23 +63,55 @@ NUM_GPR = 32 NUM_VEC_GPR = 32 +# ----------------------------------------------------------------------------- +# Vector extension configuration +# ----------------------------------------------------------------------------- + +# Parameter for vector extension VECTOR_EXTENSION_ENABLE = 0 VLEN = 512 +# Maximum size of a single vector element ELEN = 32 +# Minimum size of a sub-element, which must be at most 8-bits. SELEN = 8 +# Maximum size of a single vector element (encoded in vsew format) +VELEN = int(math.log(ELEN) // math.log(2)) - 3 + +# Maxium LMUL supported by the core 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] +# ----------------------------------------------------------------------------- +# Multi-harts configuration +# ----------------------------------------------------------------------------- + +# Number of harts +NUM_HARTS = 1 + +# ----------------------------------------------------------------------------- +# Previleged CSR implementation +# ----------------------------------------------------------------------------- + +# Implemented previlieged CSR list +implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID + privileged_reg_t.MARCHID, # Architecture ID + privileged_reg_t.MIMPID, # Implementation ID + privileged_reg_t.MHARTID, # Hardware thread ID + privileged_reg_t.MSTATUS, # Machine status + privileged_reg_t.MISA, # ISA and extensions + privileged_reg_t.MIE, # Machine interrupt-enable register + privileged_reg_t.MTVEC, # Machine trap-handler base address + privileged_reg_t.MCOUNTEREN, # Machine counter enable + privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers + privileged_reg_t.MEPC, # Machine exception program counter + privileged_reg_t.MCAUSE, # Machine trap cause + privileged_reg_t.MTVAL, # Machine bad address or instruction + privileged_reg_t.MIP # Machine interrupt pending + ] + +# Implementation-specific custom CSRs +custom_csr = [] diff --git a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py index 75e29d597a..66287dafc8 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_base_test.py @@ -24,6 +24,7 @@ from pygen_src.riscv_utils import gen_config_table +# Base test class riscv_instr_base_test: def __init__(self): self.start_idx = cfg.argv.start_idx @@ -41,17 +42,23 @@ def run_phase(self, num): if cfg.asm_test_suffix != "": self.asm_file_name = "{}.{}".format(self.asm_file_name, cfg.asm_test_suffix) + self.asm.get_directed_instr_stream() test_name = "{}_{}.S".format(self.asm_file_name, num + self.start_idx) - self.asm.get_directed_instr_stream() + self.apply_directed_instr() + logging.info("All directed instruction is applied") self.asm.gen_program() self.asm.gen_test_file(test_name) + logging.info("TEST GENERATION DONE") def randomize_cfg(self): cfg.randomize() logging.info("riscv_instr_gen_config is randomized") gen_config_table() + def apply_directed_instr(self): + pass + start_time = time.time() riscv_base_test_ins = riscv_instr_base_test() diff --git a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py index 6d406f9fbb..a1cabab778 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_instr_cov_test.py @@ -106,6 +106,11 @@ def run_phase(self): def get_coverage_report(self): model = vsc.get_coverage_report_model() cov_dir = cfg.argv.log_file_name.split("/")[0] + file = open('{}/CoverageGroups.txt'.format(cov_dir), 'w') + file.write("CoverGroups, CoverPoints and Bins Summary\n") + str_report = vsc.get_coverage_report(details=True) + file.write("{}\n".format(str_report)) + file.close() file = open('{}/CoverageReport.txt'.format(cov_dir), 'w') file.write("Groups Coverage Summary\n") file.write("Total groups in report: {}\n".format( @@ -125,18 +130,6 @@ def post_process_trace(self): pass def sample(self): - binary = vsc.int_t(rcs.XLEN) - binary.set_val(get_val(self.trace["binary"], hexa=1)) - # TODO: Currently handled using string formatting as part select - # isn't yet supported for global vsc variables - # width is rcs.XLEN+2 because of 0b in the beginning of binary_bin - binary_bin = format(binary.get_val(), '#0{}b'.format(rcs.XLEN + 2)) - if binary_bin[-2:] != "11": # TODO: and RV32C in supported_isa - # TODO: sample compressed instruction - pass - if binary_bin[-2:] == "11": - # TODO: sampling - pass processed_instr_name = self.process_instr_name(self.trace["instr"]) if processed_instr_name in riscv_instr_name_t.__members__: instr_name = riscv_instr_name_t[processed_instr_name] @@ -145,9 +138,10 @@ def sample(self): # cov_instr is created, time to manually assign attributes # TODO: This will get fixed later when we get an inst from template instruction.assign_attributes() - if instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I", + if (instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I", "RV64M", "RV64C", "RV32F", "RV64F", - "RV32D", "RV64D", "RV32B", "RV64B"]: + "RV32D", "RV64D", "RV32B", "RV64B"]) \ + and (instruction.group in rcs.supported_isa): self.assign_trace_info_to_instr(instruction) instruction.pre_sample() self.instr_cg.sample(instruction) @@ -178,7 +172,7 @@ def assign_trace_info_to_instr(self, instruction): def process_instr_name(self, instruction): instruction = instruction.upper() - instruction.replace(".", "_") + instruction = instruction.replace(".", "_") instruction = self.update_instr_name(instruction) return instruction diff --git a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py index 352c52091d..2c61df22db 100644 --- a/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py +++ b/vendor/google_riscv-dv/pygen/pygen_src/test/riscv_rand_instr_test.py @@ -31,13 +31,14 @@ def randomize_cfg(self): gen_config_table() def apply_directed_instr(self): + # Mix below directed instruction streams with the random instructions 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_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_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) + # 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) start_time = time.time() diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 0458b01af8..c4765048c2 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -380,11 +380,21 @@ def gen(test_list, argv, output_dir, cwd): # Run the instruction generator if not argv.co: seed_gen = SeedGen(argv.start_seed, argv.seed, argv.seed_yaml) + if argv.simulator == 'pyflow': + """Default timeout of Pyflow is 20 minutes, if the user + doesn't specified their own gen_timeout value from CMD + """ + if argv.gen_timeout == 360: + gen_timeout = 1200 + else: + gen_timeout = argv.gen_timeout + else: + gen_timeout = argv.gen_timeout do_simulate(sim_cmd, argv.simulator, test_list, cwd, argv.sim_opts, seed_gen, argv.csr_yaml, argv.isa, argv.end_signature_addr, argv.lsf_cmd, - argv.gen_timeout, argv.log_suffix, argv.batch_size, + gen_timeout, argv.log_suffix, argv.batch_size, output_dir, argv.verbose, check_return_code, argv.debug, argv.target) diff --git a/vendor/google_riscv-dv/scripts/gen_csr_test.py b/vendor/google_riscv-dv/scripts/gen_csr_test.py index 76c6bd1983..9a51a1a9d9 100644 --- a/vendor/google_riscv-dv/scripts/gen_csr_test.py +++ b/vendor/google_riscv-dv/scripts/gen_csr_test.py @@ -214,7 +214,6 @@ def gen_setup(test_file): test_file.write(".section .text.init\n") test_file.write(".globl _start\n") test_file.write(".option norvc\n") - test_file.write(".org 0x80\n") test_file.write("_start:\n") diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index 045ef20256..e3ca8440c1 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -157,7 +157,7 @@ def run_parallel_cmd(cmd_list, timeout_s=999, exit_on_error=0, stderr=subprocess.STDOUT) children.append(ps) for i in range(len(children)): - logging.info("Command progress: {}/{}".format(i, len(children))) + logging.info("Command progress: {}/{}".format(i + 1, len(children))) logging.debug("Waiting for command: {}".format(cmd_list[i])) try: output = children[i].communicate(timeout=timeout_s)[0] diff --git a/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv old mode 100755 new mode 100644 index 22c7b7f70c..335c5e4255 --- a/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_b_instr.sv @@ -31,7 +31,7 @@ class riscv_b_instr extends riscv_instr; has_rs3 = 1'b0; case (format) inside R_FORMAT: begin - if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP, + if (instr_name inside {BMATFLIP, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D, CRC32C_D}) begin has_rs2 = 1'b0; @@ -61,21 +61,12 @@ class riscv_b_instr extends riscv_instr; if (format inside {I_FORMAT}) begin if (category inside {SHIFT, LOGICAL}) begin - if (group == RV64B && !(instr_name inside {SLLIU_W})) begin - imm_len = $clog2(XLEN) - 1; - end else begin - imm_len = $clog2(XLEN); - end + imm_len = $clog2(XLEN); end - // ARITHMETIC RV32B if (instr_name inside {SHFLI, UNSHFLI}) begin imm_len = $clog2(XLEN) - 1; end - // ARITHMETIC RV64B - if (instr_name inside {ADDIWU}) begin - imm_len = 12; - end end imm_mask = imm_mask << imm_len; @@ -117,63 +108,38 @@ class riscv_b_instr extends riscv_instr; function bit [6:0] get_opcode(); case (instr_name) inside - ANDN, ORN, XNOR, GORC, SLO, SRO, ROL, ROR, SBCLR, SBSET, SBINV, SBEXT, - GREV: get_opcode = 7'b0110011; - SLOI, SROI, RORI, SBCLRI, SBSETI, SBINVI, SBEXTI, GORCI, GREVI, CMIX, CMOV, - FSL: get_opcode = 7'b0010011; - FSR, FSRI, CLZ, CTZ, PCNT, BMATFLIP, SEXT_B, SEXT_H, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, - CRC32C_H: get_opcode = 7'b0010011; + GORC, SLO, SRO, GREV, XPERM_N, XPERM_B, XPERM_H, XPERM_W: get_opcode = 7'b0110011; + GORCI, SLOI, SROI, GREVI, CMIX, CMOV, FSL: get_opcode = 7'b0010011; + FSR, FSRI, BMATFLIP, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H: get_opcode = 7'b0010011; CRC32C_W, CRC32_D, CRC32C_D: get_opcode = 7'b0010011; - CLMUL, CLMULR, CLMULH, MIN, MAX, MINU, MAXU, SHFL, UNSHFL, BDEP, BEXT, PACK, PACKU, BMATOR, - BMATXOR, PACKH, BFP: get_opcode = 7'b0110011; + SHFL, UNSHFL, BCOMPRESS, BDECOMPRESS, PACK, PACKU, BMATOR, BMATXOR, PACKH, BFP: get_opcode + = 7'b0110011; SHFLI, UNSHFLI: get_opcode = 7'b0010011; - ADDIWU, SLLIU_W: get_opcode = 7'b0011011; - ADDWU, SUBWU, ADDU_W, SUBU_W, SLOW, SROW, ROLW, RORW, SBCLRW, SBSETW, SBINVW, SBEXTW, GORCW, - GREVW: get_opcode = 7'b0111011; - SLOIW, SROIW, RORIW, SBCLRIW, SBSETIW, SBINVIW, GORCIW, GREVIW: get_opcode = 7'b0011011; + SLOW, SROW, GORCW, GREVW: get_opcode = 7'b0111011; + SLOIW, SROIW, GORCIW, GREVIW: get_opcode = 7'b0011011; FSLW, FSRW: get_opcode = 7'b0111011; - FSRIW, CLZW, CTZW, PCNTW: get_opcode = 7'b0011011; - CLMULW, CLMULRW, CLMULHW, SHFLW, UNSHFLW, BDEPW, BEXTW, PACKW, PACKUW, - BFPW: get_opcode = 7'b0111011; + FSRIW: get_opcode = 7'b0011011; + SHFLW, UNSHFLW, BCOMPRESSW, BDECOMPRESSW, PACKW, PACKUW, BFPW: get_opcode = 7'b0111011; default: get_opcode = super.get_opcode(); endcase endfunction virtual function bit [2:0] get_func3(); case (instr_name) inside - ANDN: get_func3 = 3'b111; - ORN: get_func3 = 3'b110; - XNOR: get_func3 = 3'b100; GORC: get_func3 = 3'b101; + GORCI: get_func3 = 3'b101; SLO: get_func3 = 3'b001; SRO: get_func3 = 3'b101; - ROL: get_func3 = 3'b001; - ROR: get_func3 = 3'b101; - SBCLR: get_func3 = 3'b001; - SBSET: get_func3 = 3'b001; - SBINV: get_func3 = 3'b001; - SBEXT: get_func3 = 3'b101; - GREV: get_func3 = 3'b101; SLOI: get_func3 = 3'b001; SROI: get_func3 = 3'b101; - RORI: get_func3 = 3'b101; - SBCLRI: get_func3 = 3'b001; - SBSETI: get_func3 = 3'b001; - SBINVI: get_func3 = 3'b001; - SBEXTI: get_func3 = 3'b101; - GORCI: get_func3 = 3'b101; + GREV: get_func3 = 3'b101; GREVI: get_func3 = 3'b101; CMIX: get_func3 = 3'b001; CMOV: get_func3 = 3'b101; FSL: get_func3 = 3'b001; FSR: get_func3 = 3'b101; FSRI: get_func3 = 3'b101; - CLZ: get_func3 = 3'b001; - CTZ: get_func3 = 3'b001; - PCNT: get_func3 = 3'b001; BMATFLIP: get_func3 = 3'b001; - SEXT_B: get_func3 = 3'b001; - SEXT_H: get_func3 = 3'b001; CRC32_B: get_func3 = 3'b001; CRC32_H: get_func3 = 3'b001; CRC32_W: get_func3 = 3'b001; @@ -182,17 +148,10 @@ class riscv_b_instr extends riscv_instr; CRC32C_W: get_func3 = 3'b001; CRC32_D: get_func3 = 3'b001; CRC32C_D: get_func3 = 3'b001; - CLMUL: get_func3 = 3'b001; - CLMULR: get_func3 = 3'b010; - CLMULH: get_func3 = 3'b011; - MIN: get_func3 = 3'b100; - MAX: get_func3 = 3'b101; - MINU: get_func3 = 3'b110; - MAXU: get_func3 = 3'b111; SHFL: get_func3 = 3'b001; UNSHFL: get_func3 = 3'b101; - BDEP: get_func3 = 3'b110; - BEXT: get_func3 = 3'b110; + BCOMPRESS: get_func3 = 3'b110; + BDECOMPRESS: get_func3 = 3'b110; PACK: get_func3 = 3'b100; PACKU: get_func3 = 3'b100; BMATOR: get_func3 = 3'b011; @@ -201,46 +160,30 @@ class riscv_b_instr extends riscv_instr; BFP: get_func3 = 3'b111; SHFLI: get_func3 = 3'b001; UNSHFLI: get_func3 = 3'b101; - ADDIWU: get_func3 = 3'b100; - SLLIU_W: get_func3 = 3'b001; - ADDWU: get_func3 = 3'b000; - SUBWU: get_func3 = 3'b000; - ADDU_W: get_func3 = 3'b000; - SUBU_W: get_func3 = 3'b000; SLOW: get_func3 = 3'b001; SROW: get_func3 = 3'b101; ROLW: get_func3 = 3'b001; - RORW: get_func3 = 3'b101; - SBCLRW: get_func3 = 3'b001; - SBSETW: get_func3 = 3'b001; - SBINVW: get_func3 = 3'b001; - SBEXTW: get_func3 = 3'b101; GORCW: get_func3 = 3'b101; GREVW: get_func3 = 3'b101; SLOIW: get_func3 = 3'b001; SROIW: get_func3 = 3'b101; RORIW: get_func3 = 3'b101; - SBCLRIW: get_func3 = 3'b001; - SBSETIW: get_func3 = 3'b001; - SBINVIW: get_func3 = 3'b001; GORCIW: get_func3 = 3'b101; GREVIW: get_func3 = 3'b101; FSLW: get_func3 = 3'b001; FSRW: get_func3 = 3'b101; FSRIW: get_func3 = 3'b101; - CLZW: get_func3 = 3'b001; - CTZW: get_func3 = 3'b001; - PCNTW: get_func3 = 3'b001; - CLMULW: get_func3 = 3'b001; - CLMULRW: get_func3 = 3'b010; - CLMULHW: get_func3 = 3'b011; SHFLW: get_func3 = 3'b001; UNSHFLW: get_func3 = 3'b101; - BDEPW: get_func3 = 3'b110; - BEXTW: get_func3 = 3'b110; + BCOMPRESSW: get_func3 = 3'b110; + BDECOMPRESSW: get_func3 = 3'b110; PACKW: get_func3 = 3'b100; PACKUW: get_func3 = 3'b100; BFPW: get_func3 = 3'b111; + XPERM_N: get_func3 = 3'b010; + XPERM_B: get_func3 = 3'b100; + XPERM_H: get_func3 = 3'b110; + XPERM_W: get_func3 = 3'b000; default: get_func3 = super.get_func3(); endcase ; @@ -256,17 +199,8 @@ class riscv_b_instr extends riscv_instr; SRO: get_func7 = 7'b0010000; ROL: get_func7 = 7'b0110000; ROR: get_func7 = 7'b0110000; - SBCLR: get_func7 = 7'b0100100; - SBSET: get_func7 = 7'b0010100; - SBINV: get_func7 = 7'b0110100; - SBEXT: get_func7 = 7'b0100100; GREV: get_func7 = 7'b0110100; - CLZ: get_func7 = 7'b0110000; - CTZ: get_func7 = 7'b0110000; - PCNT: get_func7 = 7'b0110000; BMATFLIP: get_func7 = 7'b0110000; - SEXT_B: get_func7 = 7'b0110000; - SEXT_H: get_func7 = 7'b0110000; CRC32_B: get_func7 = 7'b0110000; CRC32_H: get_func7 = 7'b0110000; CRC32_W: get_func7 = 7'b0110000; @@ -275,58 +209,35 @@ class riscv_b_instr extends riscv_instr; CRC32C_W: get_func7 = 7'b0110000; CRC32_D: get_func7 = 7'b0110000; CRC32C_D: get_func7 = 7'b0110000; - CLMUL: get_func7 = 7'b0000101; - CLMULR: get_func7 = 7'b0000101; - CLMULH: get_func7 = 7'b0000101; - MIN: get_func7 = 7'b0000101; - MAX: get_func7 = 7'b0000101; - MINU: get_func7 = 7'b0000101; - MAXU: get_func7 = 7'b0000101; SHFL: get_func7 = 7'b0000100; UNSHFL: get_func7 = 7'b0000100; - BDEP: get_func7 = 7'b0100100; - BEXT: get_func7 = 7'b0000100; + BCOMPRESS: get_func7 = 7'b0000100; + BDECOMPRESS: get_func7 = 7'b0100100; PACK: get_func7 = 7'b0000100; PACKU: get_func7 = 7'b0100100; BMATOR: get_func7 = 7'b0000100; BMATXOR: get_func7 = 7'b0100100; PACKH: get_func7 = 7'b0000100; BFP: get_func7 = 7'b0100100; - ADDWU: get_func7 = 7'b0000101; - SUBWU: get_func7 = 7'b0100101; - ADDU_W: get_func7 = 7'b0000100; - SUBU_W: get_func7 = 7'b0100100; SLOW: get_func7 = 7'b0010000; SROW: get_func7 = 7'b0010000; - ROLW: get_func7 = 7'b0110000; - RORW: get_func7 = 7'b0110000; - SBCLRW: get_func7 = 7'b0100100; - SBSETW: get_func7 = 7'b0010100; - SBINVW: get_func7 = 7'b0110100; - SBEXTW: get_func7 = 7'b0100100; GORCW: get_func7 = 7'b0010100; + GORCIW: get_func7 = 7'b0010100; GREVW: get_func7 = 7'b0110100; + GREVIW: get_func7 = 7'b0110100; SLOIW: get_func7 = 7'b0010000; SROIW: get_func7 = 7'b0010000; - RORIW: get_func7 = 7'b0110000; - SBCLRIW: get_func7 = 7'b0100100; - SBSETIW: get_func7 = 7'b0010100; - SBINVIW: get_func7 = 7'b0110100; - GORCIW: get_func7 = 7'b0010100; - GREVIW: get_func7 = 7'b0110100; - CLZW: get_func7 = 7'b0110000; - CTZW: get_func7 = 7'b0110000; - PCNTW: get_func7 = 7'b0110000; - CLMULW: get_func7 = 7'b0000101; - CLMULRW: get_func7 = 7'b0000101; - CLMULHW: get_func7 = 7'b0000101; SHFLW: get_func7 = 7'b0000100; UNSHFLW: get_func7 = 7'b0000100; - BDEPW: get_func7 = 7'b0100100; - BEXTW: get_func7 = 7'b0000100; + BCOMPRESSW: get_func7 = 7'b0000100; + BDECOMPRESSW: get_func7 = 7'b0100100; PACKW: get_func7 = 7'b0000100; PACKUW: get_func7 = 7'b0100100; BFPW: get_func7 = 7'b0100100; + XPERM_N: get_func7 = 7'b0010100; + XPERM_B: get_func7 = 7'b0010100; + XPERM_H: get_func7 = 7'b0010100; + XPERM_W: get_func7 = 7'b0010100; default: get_func7 = super.get_func7(); endcase @@ -337,17 +248,9 @@ class riscv_b_instr extends riscv_instr; SLOI: get_func5 = 5'b00100; SROI: get_func5 = 5'b00100; RORI: get_func5 = 5'b01100; - SBCLRI: get_func5 = 5'b01001; - SBSETI: get_func5 = 5'b01001; - SBINVI: get_func5 = 5'b01101; - SBEXTI: get_func5 = 5'b01001; GORCI: get_func5 = 5'b00101; GREVI: get_func5 = 5'b01101; - CLZW: get_func5 = 5'b00000; - CTZW: get_func5 = 5'b00001; - PCNTW: get_func5 = 5'b00010; - CRC32_B: get_func5 = 5'b10000; CRC32_H: get_func5 = 5'b10001; CRC32_W: get_func5 = 5'b10010; @@ -357,12 +260,7 @@ class riscv_b_instr extends riscv_instr; CRC32_D: get_func5 = 5'b10011; CRC32C_D: get_func5 = 5'b11011; - CLZ: get_func5 = 5'b00000; - CTZ: get_func5 = 5'b00001; - PCNT: get_func5 = 5'b00010; BMATFLIP: get_func5 = 5'b00011; - SEXT_B: get_func5 = 5'b00100; - SEXT_H: get_func5 = 5'b00101; default: `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) endcase endfunction @@ -385,23 +283,15 @@ class riscv_b_instr extends riscv_instr; string binary = ""; case (format) R_FORMAT: begin - if ((category inside {LOGICAL}) && (group == RV32B)) begin - if (instr_name inside {SEXT_B, SEXT_H}) begin - binary = - $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()}); - end - end - if ((category inside {ARITHMETIC}) && (group == RV32B)) begin - if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CLZ, CTZ, - PCNT}) begin + if (instr_name inside {CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W}) begin binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()}); end end if ((category inside {ARITHMETIC}) && (group == RV64B)) begin - if (instr_name inside {CLZW, CTZW, PCNTW, CRC32_D, CRC32C_D, BMATFLIP}) begin + if (instr_name inside {CRC32_D, CRC32C_D, BMATFLIP}) begin binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()}); end @@ -413,8 +303,6 @@ class riscv_b_instr extends riscv_instr; binary = $sformatf("%8h", {get_func5(), imm[6:0], rs1, get_func3(), rd, get_opcode()}); end else if ((category inside {SHIFT, LOGICAL}) && (group == RV64B)) begin binary = $sformatf("%8h", {get_func7(), imm[4:0], rs1, get_func3(), rd, get_opcode()}); - if (instr_name == SLLIU_W) - binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()}); end if (instr_name inside {FSRI}) begin @@ -450,37 +338,19 @@ class riscv_b_instr extends riscv_instr; virtual function bit is_supported(riscv_instr_gen_config cfg); return cfg.enable_b_extension && ( - (ZBB inside {cfg.enable_bitmanip_groups} && instr_name inside { - 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 - }) || - (ZBS inside {cfg.enable_bitmanip_groups} && instr_name inside { - SBSET, SBSETW, SBSETI, SBSETIW, - SBCLR, SBCLRW, SBCLRI, SBCLRIW, - SBINV, SBINVW, SBINVI, SBINVIW, - SBEXT, SBEXTW, SBEXTI - }) || (ZBP inside {cfg.enable_bitmanip_groups} && instr_name inside { GREV, GREVW, GREVI, GREVIW, GORC, GORCW, GORCI, GORCIW, - SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI + SHFL, SHFLW, UNSHFL, UNSHFLW, SHFLI, UNSHFLI, + XPERM_N, XPERM_B, XPERM_H, XPERM_W, + SLO, SLOW, SLOI, SLOIW, + SRO, SROW, SROI, SROIW }) || (ZBE inside {cfg.enable_bitmanip_groups} && instr_name inside { - BEXT, BEXTW, - BDEP, BDEPW + BCOMPRESS, BCOMPRESSW, + BDECOMPRESS, BDECOMPRESSW }) || (ZBF inside {cfg.enable_bitmanip_groups} && instr_name inside {BFP, BFPW}) || - (ZBC inside {cfg.enable_bitmanip_groups} && instr_name inside { - CLMUL, CLMULW, CLMULH, CLMULHW, CLMULR, CLMULRW - }) || (ZBR inside {cfg.enable_bitmanip_groups} && instr_name inside { CRC32_B, CRC32_H, CRC32_W, CRC32_D, CRC32C_B, CRC32C_H, CRC32C_W, CRC32C_D @@ -490,10 +360,7 @@ class riscv_b_instr extends riscv_instr; }) || (ZBT inside {cfg.enable_bitmanip_groups} && instr_name inside { CMOV, CMIX, - FSL, FSLW, FSR, FSRW, FSRI, FSRIW}) || - // TODO, spec 0.92 doesn't categorize these 2 instr, put them in ZB_TMP #572 - (ZB_TMP inside {cfg.enable_bitmanip_groups} && instr_name inside { - SEXT_B, SEXT_H}) + FSL, FSLW, FSR, FSRW, FSRI, FSRIW}) ); endfunction diff --git a/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv index 385af7b0ea..04fdcb7825 100644 --- a/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_compressed_instr.sv @@ -318,11 +318,11 @@ class riscv_compressed_instr extends riscv_instr; C_ADD: binary = $sformatf("%4h", {get_func3(), 1'b1, rd, rs2, get_c_opcode()}); C_FSDSP, C_SDSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:3], imm[8:6], rs2, get_c_opcode()}); + binary = $sformatf("%4h", {get_func3(), imm[5:3], imm[8:6], rs2, get_c_opcode()}); C_SQSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:4], imm[9:6], rs2, get_c_opcode()}); + binary = $sformatf("%4h", {get_func3(), imm[5:4], imm[9:6], rs2, get_c_opcode()}); C_SWSP, C_FSWSP: - binary = $sformatf("%4h", {get_func3(), 1'b0, imm[5:2], imm[7:6], rs2, get_c_opcode()}); + binary = $sformatf("%4h", {get_func3(), imm[5:2], imm[7:6], rs2, get_c_opcode()}); default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name())) endcase return {prefix, binary}; diff --git a/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv index 66390900f1..088f389d4d 100644 --- a/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_floating_point_instr.sv @@ -248,7 +248,7 @@ class riscv_floating_point_instr extends riscv_instr; if (group inside {RV32F, RV64F}) begin fs1_sign = get_fp_operand_sign(fs1_value, 31); fs2_sign = get_fp_operand_sign(fs2_value, 31); - fs3_sign = get_fp_operand_sign(fs2_value, 31); + fs3_sign = get_fp_operand_sign(fs3_value, 31); fd_sign = get_fp_operand_sign(fd_value, 31); end else if (instr_name == FCVT_S_D) begin fs1_sign = get_fp_operand_sign(fs1_value, 63); @@ -259,7 +259,7 @@ class riscv_floating_point_instr extends riscv_instr; end else begin fs1_sign = get_fp_operand_sign(fs1_value, 63); fs2_sign = get_fp_operand_sign(fs2_value, 63); - fs3_sign = get_fp_operand_sign(fs2_value, 63); + fs3_sign = get_fp_operand_sign(fs3_value, 63); fd_sign = get_fp_operand_sign(fd_value, 63); end endfunction : pre_sample diff --git a/vendor/google_riscv-dv/src/isa/riscv_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_instr.sv index c444adcfbc..2b2f32273b 100644 --- a/vendor/google_riscv-dv/src/isa/riscv_instr.sv +++ b/vendor/google_riscv-dv/src/isa/riscv_instr.sv @@ -344,7 +344,7 @@ class riscv_instr extends uvm_object; if(imm_type == UIMM) begin imm_len = 5; end else begin - imm_len = 11; + imm_len = 12; end end imm_mask = imm_mask << imm_len; @@ -580,7 +580,7 @@ class riscv_instr extends uvm_object; if(instr_name inside {FENCE, FENCE_I}) binary = $sformatf("%8h", {17'b0, get_func3(), 5'b0, get_opcode()}); else if(category == CSR) - binary = $sformatf("%8h", {csr[10:0], imm[4:0], get_func3(), rd, get_opcode()}); + binary = $sformatf("%8h", {csr[11:0], imm[4:0], get_func3(), rd, get_opcode()}); else if(instr_name == ECALL) binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()}); else if(instr_name inside {URET, SRET, MRET}) @@ -604,7 +604,7 @@ class riscv_instr extends uvm_object; end R_FORMAT: begin if(category == CSR) - binary = $sformatf("%8h", {csr[10:0], rs1, get_func3(), rd, get_opcode()}); + binary = $sformatf("%8h", {csr[11:0], rs1, get_func3(), rd, get_opcode()}); else if(instr_name == SFENCE_VMA) binary = $sformatf("%8h", {get_func7(), 18'b0, get_opcode()}); else diff --git a/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv new file mode 100644 index 0000000000..0600ac4e4c --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv @@ -0,0 +1,99 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class riscv_zba_instr extends riscv_instr; + `uvm_object_utils(riscv_zba_instr) + + function new(string name = ""); + super.new(name); + endfunction : new + + function void pre_randomize(); + super.pre_randomize(); + endfunction + + virtual function void set_imm_len(); + if (!(instr_name inside {SLLI_UW})) begin + imm_len = $clog2(XLEN) - 1; + end else begin + imm_len = $clog2(XLEN); + end + imm_mask = imm_mask << imm_len; + endfunction : set_imm_len + + function bit[6:0] get_opcode(); + case (instr_name) inside + SH1ADD, SH2ADD, SH3ADD : get_opcode = 7'b0110011; + SH1ADD_UW, SH2ADD_UW, SH3ADD_UW : get_opcode = 7'b0111011; + SLLI_UW : get_opcode = 7'b0011011; + default : get_opcode = super.get_opcode(); + endcase + endfunction : get_opcode + + virtual function bit [2:0] get_func3(); + case (instr_name) inside + ADD_UW : get_func3 = 3'b000; + SH1ADD : get_func3 = 3'b010; + SH2ADD : get_func3 = 3'b100; + SH3ADD : get_func3 = 3'b110; + SH1ADD_UW : get_func3 = 3'b010; + SH2ADD_UW : get_func3 = 3'b100; + SH3ADD_UW : get_func3 = 3'b110; + SLLI_UW : get_func3 = 3'b001; + default : get_func3 = super.get_func3(); + endcase + endfunction : get_func3 + + function bit [6:0] get_func7(); + case (instr_name) inside + ADD_UW : get_func7 = 7'b0000100; + SH1ADD : get_func7 = 7'b0010000; + SH2ADD : get_func7 = 7'b0010000; + SH3ADD : get_func7 = 7'b0010000; + SH1ADD_UW : get_func7 = 7'b0010000; + SH2ADD_UW : get_func7 = 7'b0010000; + SH3ADD_UW : get_func7 = 7'b0010000; + SLLI_UW : get_func7 = 7'b0010000; + default : get_func7 = super.get_func7(); + endcase + endfunction : get_func7 + + virtual function string convert2bin(string prefix = ""); + string binary = ""; + if (instr_name inside {SLLI_UW}) begin + binary = $sformatf("%8h", {5'b0_0001, imm[6:0], rs1, get_func3(), rd, get_opcode()}); + end + else begin + binary = super.convert2bin(prefix); + end + endfunction : convert2bin + + virtual function bit is_supported(riscv_instr_gen_config cfg); + return (cfg.enable_zba_extension && + (RV32ZBA inside { supported_isa } || RV64ZBA inside { supported_isa }) && + instr_name inside { + ADD_UW, + SH1ADD, SH1ADD_UW, + SH2ADD, SH2ADD_UW, + SH3ADD, SH3ADD_UW, + SLLI_UW + }); + endfunction : is_supported + +endclass : riscv_zba_instr + + + diff --git a/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv new file mode 100644 index 0000000000..26b280c0ee --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv @@ -0,0 +1,238 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class riscv_zbb_instr extends riscv_instr; + `uvm_object_utils(riscv_zbb_instr) + + function new(string name = ""); + super.new(name); + endfunction : new + + virtual function void set_rand_mode(); + super.set_rand_mode(); + case (format) inside + R_FORMAT: begin + if (instr_name inside { ZEXT_H }) begin + has_rs2 = 1'b0; + end + end + + I_FORMAT: begin + if (instr_name inside { CLZ, CLZW, CTZ, CTZW, CPOP, CPOPW, ORC_B, SEXT_B, SEXT_H, REV8 }) begin + has_imm = 1'b0; + end + end + + endcase + endfunction : set_rand_mode + + function void pre_randomize(); + super.pre_randomize(); + endfunction + + function bit is_rv64(); + is_rv64 = (group == RV64B); + endfunction : is_rv64 + + virtual function void set_imm_len(); + if (format inside {I_FORMAT}) begin + if (instr_name inside {RORI}) begin + imm_len = $clog2(XLEN); + end else begin + imm_len = 5; + end + end + imm_mask = imm_mask << imm_len; + endfunction : set_imm_len + + virtual function string convert2asm(string prefix = ""); + string asm_str_final; + string asm_str; + + asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN); + + case (format) + I_FORMAT : begin // instr rd rs1 + if (!has_imm) begin + asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name()); + end + end + + R_FORMAT : begin // instr rd rs1 + if (!has_rs2) begin + asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name()); + end + end + + default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW) + endcase + + if (asm_str_final == "") begin + return super.convert2asm(prefix); + end + + if (comment != "") begin + asm_str_final = { asm_str_final, " #", comment }; + end + + return asm_str_final.tolower(); + + endfunction : convert2asm + + function bit[6:0] get_opcode(); + case (instr_name) inside + ANDN, MAX, MAXU, MIN, MINU, + ORN, ROL, ROR, XNOR : get_opcode = 7'b011_0011; + ZEXT_H : get_opcode = 7'b011_0011 | (is_rv64() << 3); + ROLW, RORW : get_opcode = 7'b011_1011; + CLZ, CPOP, CTZ, ORC_B, + CLZW, CPOPW, CTZW, RORIW : get_opcode = 7'b001_1011; + REV8, RORI, SEXT_B, SEXT_H : get_opcode = 7'b001_0011; + default : get_opcode = super.get_opcode(); + endcase + endfunction : get_opcode + + virtual function bit [2:0] get_func3(); + case (instr_name) inside + ANDN : get_func3 = 3'b111; + CLZ : get_func3 = 3'b001; + CLZW : get_func3 = 3'b001; + CPOP : get_func3 = 3'b001; + CPOPW : get_func3 = 3'b001; + CTZ : get_func3 = 3'b001; + CTZW : get_func3 = 3'b001; + MAX : get_func3 = 3'b110; + MAXU : get_func3 = 3'b111; + MIN : get_func3 = 3'b100; + MINU : get_func3 = 3'b101; + ORC_B : get_func3 = 3'b101; + ORN : get_func3 = 3'b110; + REV8 : get_func3 = 3'b101; + ROL : get_func3 = 3'b001; + ROLW : get_func3 = 3'b001; + ROR : get_func3 = 3'b101; + RORW : get_func3 = 3'b101; + RORI : get_func3 = 3'b101; + RORIW : get_func3 = 3'b101; + SEXT_B : get_func3 = 3'b001; + SEXT_H : get_func3 = 3'b001; + XNOR : get_func3 = 3'b100; + ZEXT_H : get_func3 = 3'b100; + default : get_func3 = super.get_func3(); + endcase + endfunction : get_func3 + + virtual function bit [4:0] get_func5(); + case (instr_name) inside + CLZ : get_func5 = 5'b0_0000; + CLZW : get_func5 = 5'b0_0000; + CPOP : get_func5 = 5'b0_0010; + CPOPW : get_func5 = 5'b0_0010; + CTZ : get_func5 = 5'b0_0001; + CTZW : get_func5 = 5'b0_0001; + ORC_B : get_func5 = 5'b0_0111; + REV8 : get_func5 = 5'b1_1000; + SEXT_B : get_func5 = 5'b0_0100; + SEXT_H : get_func5 = 5'b0_0101; + endcase + endfunction : get_func5 + + virtual function bit [6:0] get_func7(); + case (instr_name) inside + ANDN : get_func7 = 7'b010_0000; + CLZ : get_func7 = 7'b011_0000; + CLZW : get_func7 = 7'b011_0000; + CPOP : get_func7 = 7'b011_0000; + CPOPW : get_func7 = 7'b011_0000; + CTZ : get_func7 = 7'b011_0000; + CTZW : get_func7 = 7'b011_0000; + MAX : get_func7 = 7'b000_0101; + MAXU : get_func7 = 7'b000_0101; + MIN : get_func7 = 7'b000_0101; + MINU : get_func7 = 7'b000_0101; + ORC_B : get_func7 = 7'b001_0100; + ORN : get_func7 = 7'b010_0000; + REV8 : get_func7 = 7'b011_0100 | is_rv64(); // 0110101 64 bit + ROL : get_func7 = 7'b011_0000; + ROLW : get_func7 = 7'b011_0000; + ROR : get_func7 = 7'b011_0000; + RORW : get_func7 = 7'b011_0000; + RORI : get_func7 = 7'b011_0000; + RORIW : get_func7 = 7'b011_0000; + SEXT_B : get_func7 = 7'b011_0000; + SEXT_H : get_func7 = 7'b011_0000; + XNOR : get_func7 = 7'b010_0000; + ZEXT_H : get_func7 = 7'b000_0100; + default : get_func7 = super.get_func7(); + endcase + endfunction : get_func7 + + virtual function string convert2bin(string prefix = ""); + string binary = ""; + + case (format) + R_FORMAT: begin + if (instr_name inside { ZEXT_H }) begin + binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()}); + end + end + + I_FORMAT: begin + case (instr_name) inside + CLZ, CLZW, CPOP, CPOPW, CTZ, CTZW, ORC_B, REV8, SEXT_B, SEXT_H: begin + binary = $sformatf("%8h", {get_func7(), get_func5(), rs1, get_func3(), rd, get_opcode()}); + end + RORIW: begin + binary = $sformatf("%8h", {get_func7(), imm[5:0], rs1, get_func3(), rd, get_opcode()}); + end + RORI: begin + // set bit 0 of funct7 only if rv64 and shamt[MSB] is set + binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1, get_func3(), rd, get_opcode()}); + end + endcase + end + + default: begin + if (binary == "") begin + binary = super.convert2bin(prefix); + end + end + + endcase // case (format) + endfunction : convert2bin + + virtual function bit is_supported(riscv_instr_gen_config cfg); + return (cfg.enable_zbb_extension && + (RV32ZBB inside { supported_isa } || RV64ZBB inside { supported_isa }) && + instr_name inside { + ANDN, + CLZ, CLZW, + CPOP, CPOPW, + CTZ, CTZW, + MAX, MAXU, + MIN, MINU, + ORC_B, ORN, + REV8, + ROL, ROLW, + ROR, RORW, + RORI, RORIW, + SEXT_B, SEXT_H, + XNOR, + ZEXT_H + }); + endfunction : is_supported + +endclass : riscv_zbb_instr diff --git a/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv new file mode 100644 index 0000000000..8bc825eac7 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class riscv_zbc_instr extends riscv_instr; + `uvm_object_utils(riscv_zbc_instr) + + function new(string name = ""); + super.new(name); + endfunction : new + + function void pre_randomize(); + super.pre_randomize(); + endfunction : pre_randomize + + function bit[6:0] get_opcode(); + case (instr_name) inside + CLMUL, + CLMULH, + CLMULR : get_opcode = 7'b011_0011; + default : get_opcode = super.get_opcode(); + endcase + endfunction : get_opcode + + function bit [2:0] get_func3(); + case (instr_name) inside + CLMUL : get_func3 = 3'b001; + CLMULH : get_func3 = 3'b011; + CLMULR : get_func3 = 3'b010; + default : get_func3 = super.get_func3(); + endcase + endfunction : get_func3 + + function bit [6:0] get_func7(); + case (instr_name) inside + CLMUL : get_func7 = 7'b000_0101; + CLMULH : get_func7 = 7'b000_0101; + CLMULR : get_func7 = 7'b000_0101; + default : get_func7 = super.get_func7(); + endcase + endfunction : get_func7 + + virtual function string convert2bin(string prefix = ""); + string binary = ""; + if (instr_name inside {CLMUL, CLMULH, CLMULR}) begin + binary = $sformatf("%8h", {get_func7(), rs2, rs1, get_func3(), rd, get_opcode()}); + end + else begin + binary = super.convert2bin(prefix); + end + endfunction : convert2bin + + virtual function bit is_supported(riscv_instr_gen_config cfg); + return (cfg.enable_zbc_extension && + (RV32ZBC inside { supported_isa } || RV64ZBC inside { supported_isa }) && + instr_name inside { + CLMUL, CLMULH, CLMULR + }); + endfunction : is_supported + +endclass : riscv_zbc_instr diff --git a/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv b/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv new file mode 100644 index 0000000000..eb0208d701 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class riscv_zbs_instr extends riscv_instr; + `uvm_object_utils(riscv_zbs_instr) + + function new(string name = ""); + super.new(name); + endfunction : new + + function void pre_randomize(); + super.pre_randomize(); + endfunction : pre_randomize + + function bit is_rv64(); + is_rv64 = (group == RV64B); + endfunction : is_rv64 + + virtual function void set_imm_len(); + if (format inside {I_FORMAT}) begin + if (instr_name inside { BCLRI, BEXTI, BINVI, BSETI }) begin + imm_len = $clog2(XLEN); + end + end + imm_mask = imm_mask << imm_len; + endfunction : set_imm_len + + function bit [6:0] get_opcode(); + case (instr_name) inside + BCLR, BEXT, BINV, BSET, + BCLRI, BEXTI, BINVI, BSETI : begin + get_opcode = 7'b0010011; + end + default : get_opcode = super.get_opcode(); + endcase + endfunction : get_opcode + + function bit [2:0] get_func3(); + case (instr_name) inside + BCLR : get_func3 = 3'b001; + BCLRI : get_func3 = 3'b001; + BEXT : get_func3 = 3'b101; + BEXTI : get_func3 = 3'b101; + BINV : get_func3 = 3'b001; + BINVI : get_func3 = 3'b001; + BSET : get_func3 = 3'b001; + BSETI : get_func3 = 3'b001; + default : get_func3 = super.get_func3(); + endcase + endfunction : get_func3 + + function bit [6:0] get_func7(); + case (instr_name) inside + BCLR : get_func7 = 7'b0100100; + BCLRI : get_func7 = 7'b0100100; + BEXT : get_func7 = 7'b0100100; + BEXTI : get_func7 = 7'b0100100; + BINV : get_func7 = 7'b0110100; + BINVI : get_func7 = 7'b0110100; + BSET : get_func7 = 7'b0010100; + BSETI : get_func7 = 7'b0010100; + default : get_func7 = super.get_func7(); + endcase + endfunction : get_func7 + + virtual function string convert2bin(string prefix = ""); + string binary = ""; + + case (format) inside + I_FORMAT : begin + case (instr_name) inside + BCLRI, BEXTI, BINVI, BSETI : begin + binary = $sformatf("%8h", {(get_func7() | (is_rv64() && imm[5])), imm[4:0], rs1, get_func3(), rd, get_opcode()}); + end + endcase + end + default : begin + if (binary == "") begin + return super.convert2bin(prefix); + end + end + endcase + endfunction : convert2bin + + virtual function bit is_supported(riscv_instr_gen_config cfg); + return (cfg.enable_zbs_extension && + (RV32ZBS inside { supported_isa } || RV64ZBS inside { supported_isa }) && + instr_name inside { + BCLR, BEXT, BINV, BSET, + BCLRI, BEXTI, BINVI, BSETI + }); + endfunction : is_supported + +endclass : riscv_zbs_instr diff --git a/vendor/google_riscv-dv/src/isa/rv32b_instr.sv b/vendor/google_riscv-dv/src/isa/rv32b_instr.sv index 984a1d4b34..4c568cce1d 100755 --- a/vendor/google_riscv-dv/src/isa/rv32b_instr.sv +++ b/vendor/google_riscv-dv/src/isa/rv32b_instr.sv @@ -15,62 +15,40 @@ * limitations under the License. */ +// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). + // LOGICAL instructions -`DEFINE_B_INSTR(SEXT_B, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(SEXT_H, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(ANDN, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(ORN , R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(XNOR, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(GORC, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(GORCI, I_FORMAT, LOGICAL, RV32B, UIMM) -`DEFINE_B_INSTR(CMIX, R4_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(CMOV, R4_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(PACK, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(PACKU, R_FORMAT, LOGICAL, RV32B) -`DEFINE_B_INSTR(PACKH, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(GORC, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(GORCI, I_FORMAT, LOGICAL, RV32B, UIMM) +`DEFINE_B_INSTR(CMIX, R4_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(CMOV, R4_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(PACK, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(PACKU, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(PACKH, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(XPERM_N, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(XPERM_B, R_FORMAT, LOGICAL, RV32B) +`DEFINE_B_INSTR(XPERM_H, R_FORMAT, LOGICAL, RV32B) // SHIFT intructions -`DEFINE_B_INSTR(SLO, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(SRO, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(ROL, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(ROR, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(SBCLR, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(SBSET, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(SBINV, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(SBEXT, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(GREV, R_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(GREVI, I_FORMAT, SHIFT, RV32B , UIMM) -`DEFINE_B_INSTR(SLOI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(SROI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(RORI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(SBCLRI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(SBSETI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(SBINVI , I_FORMAT, SHIFT, RV32B ,UIMM) -`DEFINE_B_INSTR(SBEXTI , I_FORMAT, SHIFT, RV32B ,UIMM) +`DEFINE_B_INSTR(SLO, R_FORMAT, SHIFT, RV32B) +`DEFINE_B_INSTR(SRO, R_FORMAT, SHIFT, RV32B) +`DEFINE_B_INSTR(SLOI, I_FORMAT, SHIFT, RV32B, UIMM) +`DEFINE_B_INSTR(SROI, I_FORMAT, SHIFT, RV32B, UIMM) +`DEFINE_B_INSTR(GREV, R_FORMAT, SHIFT, RV32B) +`DEFINE_B_INSTR(GREVI, I_FORMAT, SHIFT, RV32B, UIMM) `DEFINE_B_INSTR(FSL, R4_FORMAT, SHIFT, RV32B) `DEFINE_B_INSTR(FSR, R4_FORMAT, SHIFT, RV32B) -`DEFINE_B_INSTR(FSRI, I_FORMAT, SHIFT, RV32B ,UIMM) +`DEFINE_B_INSTR(FSRI, I_FORMAT, SHIFT, RV32B, UIMM) // ARITHMETIC intructions -`DEFINE_B_INSTR(CLZ, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CTZ, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(PCNT, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32_B, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32_H, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32_W, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32C_B, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32C_H, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CRC32C_W, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CLMUL, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(MIN, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(MAX, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(MINU, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(MAXU, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(SHFL, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(UNSHFL, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(BDEP, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(BEXT, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(BFP, R_FORMAT, ARITHMETIC, RV32B) -`DEFINE_B_INSTR(SHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM) -`DEFINE_B_INSTR(UNSHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM) - +`DEFINE_B_INSTR(CRC32_B, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(CRC32_H, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(CRC32_W, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(CRC32C_B, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(CRC32C_H, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(CRC32C_W, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(SHFL, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(UNSHFL, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(SHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM) +`DEFINE_B_INSTR(UNSHFLI, I_FORMAT, ARITHMETIC, RV32B, UIMM) +`DEFINE_B_INSTR(BCOMPRESS, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(BDECOMPRESS, R_FORMAT, ARITHMETIC, RV32B) +`DEFINE_B_INSTR(BFP, R_FORMAT, ARITHMETIC, RV32B) diff --git a/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv b/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv new file mode 100644 index 0000000000..91edfd1df8 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv32zba_instr.sv @@ -0,0 +1,20 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBA_INSTR(SH1ADD, R_FORMAT, ARITHMETIC, RV32ZBA); +`DEFINE_ZBA_INSTR(SH2ADD, R_FORMAT, ARITHMETIC, RV32ZBA); +`DEFINE_ZBA_INSTR(SH3ADD, R_FORMAT, ARITHMETIC, RV32ZBA); diff --git a/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv b/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv new file mode 100644 index 0000000000..afa88d8b71 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBB_INSTR(ANDN, R_FORMAT, LOGICAL, RV32ZBB); +`DEFINE_ZBB_INSTR(CLZ, I_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(CPOP, I_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(CTZ, I_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(MAX, R_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(MAXU, R_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(MIN, R_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(MINU, R_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(ORC_B, I_FORMAT, LOGICAL, RV32ZBB); +`DEFINE_ZBB_INSTR(ORN, R_FORMAT, LOGICAL, RV32ZBB); +`DEFINE_ZBB_INSTR(REV8, I_FORMAT, SHIFT, RV32ZBB); +`DEFINE_ZBB_INSTR(ROL, R_FORMAT, SHIFT, RV32ZBB); +`DEFINE_ZBB_INSTR(ROR, R_FORMAT, SHIFT, RV32ZBB); +`DEFINE_ZBB_INSTR(RORI, I_FORMAT, SHIFT, RV32ZBB, UIMM); +`DEFINE_ZBB_INSTR(SEXT_B, I_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(SEXT_H, I_FORMAT, ARITHMETIC, RV32ZBB); +`DEFINE_ZBB_INSTR(XNOR, R_FORMAT, LOGICAL, RV32ZBB); +`DEFINE_ZBB_INSTR(ZEXT_H, R_FORMAT, ARITHMETIC, RV32ZBB); diff --git a/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv b/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv new file mode 100644 index 0000000000..032e18aeb4 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv @@ -0,0 +1,20 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBC_INSTR(CLMUL, R_FORMAT, ARITHMETIC, RV32ZBC) +`DEFINE_ZBC_INSTR(CLMULH, R_FORMAT, ARITHMETIC, RV32ZBC) +`DEFINE_ZBC_INSTR(CLMULR, R_FORMAT, ARITHMETIC, RV32ZBC) diff --git a/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv b/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv new file mode 100644 index 0000000000..9cbc0b227b --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv @@ -0,0 +1,25 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBS_INSTR(BCLR, R_FORMAT, SHIFT, RV32ZBS) +`DEFINE_ZBS_INSTR(BCLRI, I_FORMAT, SHIFT, RV32ZBS, UIMM) +`DEFINE_ZBS_INSTR(BEXT, R_FORMAT, SHIFT, RV32ZBS) +`DEFINE_ZBS_INSTR(BEXTI, I_FORMAT, SHIFT, RV32ZBS, UIMM) +`DEFINE_ZBS_INSTR(BINV, R_FORMAT, SHIFT, RV32ZBS) +`DEFINE_ZBS_INSTR(BINVI, I_FORMAT, SHIFT, RV32ZBS, UIMM) +`DEFINE_ZBS_INSTR(BSET, R_FORMAT, SHIFT, RV32ZBS) +`DEFINE_ZBS_INSTR(BSETI, I_FORMAT, SHIFT, RV32ZBS, UIMM) diff --git a/vendor/google_riscv-dv/src/isa/rv64b_instr.sv b/vendor/google_riscv-dv/src/isa/rv64b_instr.sv index 9c681c4056..7cafd68fe7 100755 --- a/vendor/google_riscv-dv/src/isa/rv64b_instr.sv +++ b/vendor/google_riscv-dv/src/isa/rv64b_instr.sv @@ -15,54 +15,32 @@ * limitations under the License. */ -// ARITHMETIC intructions -`DEFINE_B_INSTR(BMATOR, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(BMATXOR, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(BMATFLIP, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CRC32_D, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CRC32C_D, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(ADDIWU, I_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(ADDWU, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(SUBWU, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(ADDU_W, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(SUBU_W, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CLZW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CTZW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(PCNTW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CLMULW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CLMULRW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(CLMULHW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(SHFLW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(UNSHFLW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(BDEPW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(BEXTW, R_FORMAT, ARITHMETIC, RV64B) -`DEFINE_B_INSTR(BFPW, R_FORMAT, ARITHMETIC, RV64B) +// Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). +// ARITHMETIC intructions +`DEFINE_B_INSTR(BMATOR, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(BMATXOR, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(BMATFLIP, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(CRC32_D, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(CRC32C_D, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(SHFLW, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(UNSHFLW, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(BCOMPRESSW, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(BDECOMPRESSW, R_FORMAT, ARITHMETIC, RV64B) +`DEFINE_B_INSTR(BFPW, R_FORMAT, ARITHMETIC, RV64B) // SHIFT intructions -`DEFINE_B_INSTR(SLLIU_W, I_FORMAT, SHIFT, RV64B, UIMM) `DEFINE_B_INSTR(SLOW, R_FORMAT, SHIFT, RV64B) `DEFINE_B_INSTR(SROW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(ROLW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(RORW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(SBCLRW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(SBSETW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(SBINVW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(SBEXTW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(GREVW, R_FORMAT, SHIFT, RV64B) -`DEFINE_B_INSTR(SLOIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(SROIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(RORIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(SBCLRIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(SBSETIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(SBINVIW , I_FORMAT, SHIFT, RV64B, UIMM) -`DEFINE_B_INSTR(GREVIW, I_FORMAT, SHIFT, RV64B, UIMM) +`DEFINE_B_INSTR(SLOIW, I_FORMAT, SHIFT, RV64B, UIMM) +`DEFINE_B_INSTR(SROIW, I_FORMAT, SHIFT, RV64B, UIMM) +`DEFINE_B_INSTR(GREVW, R_FORMAT, SHIFT, RV64B) +`DEFINE_B_INSTR(GREVIW, I_FORMAT, SHIFT, RV64B, UIMM) `DEFINE_B_INSTR(FSLW, R4_FORMAT, SHIFT, RV64B) `DEFINE_B_INSTR(FSRW, R4_FORMAT, SHIFT, RV64B) `DEFINE_B_INSTR(FSRIW, I_FORMAT, SHIFT, RV64B, UIMM) - // LOGICAL instructions -`DEFINE_B_INSTR(GORCW, R_FORMAT, LOGICAL, RV64B) -`DEFINE_B_INSTR(GORCIW, I_FORMAT, LOGICAL, RV64B, UIMM) -`DEFINE_B_INSTR(PACKW, R_FORMAT, LOGICAL, RV64B) -`DEFINE_B_INSTR(PACKUW, R_FORMAT, LOGICAL, RV64B) - +`DEFINE_B_INSTR(GORCW, R_FORMAT, LOGICAL, RV64B) +`DEFINE_B_INSTR(GORCIW, I_FORMAT, LOGICAL, RV64B, UIMM) +`DEFINE_B_INSTR(PACKW, R_FORMAT, LOGICAL, RV64B) +`DEFINE_B_INSTR(PACKUW, R_FORMAT, LOGICAL, RV64B) +`DEFINE_B_INSTR(XPERM_W, R_FORMAT, LOGICAL, RV64B) diff --git a/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv b/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv new file mode 100644 index 0000000000..e354430454 --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv64zba_instr.sv @@ -0,0 +1,22 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBA_INSTR(ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA); +`DEFINE_ZBA_INSTR(SH1ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA); +`DEFINE_ZBA_INSTR(SH2ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA); +`DEFINE_ZBA_INSTR(SH3ADD_UW, R_FORMAT, ARITHMETIC, RV64ZBA); +`DEFINE_ZBA_INSTR(SLLI_UW, I_FORMAT, SHIFT, RV64ZBA, UIMM); diff --git a/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv b/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv new file mode 100644 index 0000000000..e1c278c23a --- /dev/null +++ b/vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Google LLC + * Copyright 2021 Silicon Labs, 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +`DEFINE_ZBB_INSTR(CLZW, I_FORMAT, ARITHMETIC, RV64ZBB); +`DEFINE_ZBB_INSTR(CPOPW, I_FORMAT, ARITHMETIC, RV64ZBB); +`DEFINE_ZBB_INSTR(CTZW, I_FORMAT, ARITHMETIC, RV64ZBB); +`DEFINE_ZBB_INSTR(ROLW, R_FORMAT, SHIFT, RV64ZBB); +`DEFINE_ZBB_INSTR(RORW, R_FORMAT, SHIFT, RV64ZBB); +`DEFINE_ZBB_INSTR(RORIW, I_FORMAT, SHIFT, RV64ZBB, UIMM); diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index 96cca5fb8d..9822d67413 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -452,6 +452,8 @@ class riscv_asm_program_gen extends uvm_object; RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1; RVV : misa[MISA_EXT_V] = 1'b1; RV32X, RV64X : misa[MISA_EXT_X] = 1'b1; + RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS, + RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS : ; // No Misa bit for Zb* extensions default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported", supported_isa[i].name())) endcase diff --git a/vendor/google_riscv-dv/src/riscv_defines.svh b/vendor/google_riscv-dv/src/riscv_defines.svh index fc30b4168d..aee215c4e6 100644 --- a/vendor/google_riscv-dv/src/riscv_defines.svh +++ b/vendor/google_riscv-dv/src/riscv_defines.svh @@ -105,3 +105,22 @@ class riscv_``instr_n``_instr extends riscv_b_instr; \ `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp) +//Zba-extension instruction +`define DEFINE_ZBA_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \ + class riscv_``instr_n``_instr extends riscv_zba_instr; \ + `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp) + +//Zbb-extension instruction +`define DEFINE_ZBB_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \ + class riscv_``instr_n``_instr extends riscv_zbb_instr; \ + `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp) + +//Zbc-extension instruction +`define DEFINE_ZBC_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \ + class riscv_``instr_n``_instr extends riscv_zbc_instr; \ + `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp) + +//Zbs-extension instruction +`define DEFINE_ZBS_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \ + class riscv_``instr_n``_instr extends riscv_zbs_instr; \ + `INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp) diff --git a/vendor/google_riscv-dv/src/riscv_illegal_instr.sv b/vendor/google_riscv-dv/src/riscv_illegal_instr.sv index 91ced689d0..60ff4b546c 100644 --- a/vendor/google_riscv-dv/src/riscv_illegal_instr.sv +++ b/vendor/google_riscv-dv/src/riscv_illegal_instr.sv @@ -181,6 +181,38 @@ class riscv_illegal_instr extends uvm_object; } } + constraint zba_extension_c { + if (RV32ZBA inside {supported_isa}) { + if (exception inside {kIllegalFunc3, kIllegalFunc7}) { + !(opcode inside {7'b0110011, 7'b0111011, 7'b0011011}); + } + } + } + + constraint zbb_extension_c { + if (RV32ZBB inside {supported_isa}) { + if (exception inside {kIllegalFunc3, kIllegalFunc7}) { + !(opcode inside {7'b0110011, 7'b0010011, 7'b0111011, 7'b0011011}); + } + } + } + + constraint zbc_extension_c { + if (RV32ZBB inside {supported_isa}) { + if (exception inside {kIllegalFunc3, kIllegalFunc7}) { + !(opcode inside {7'b0110011}); + } + } + } + + constraint zbs_extension_c { + if (RV32ZBS inside {supported_isa}) { + if (exception inside {kIllegalFunc3, kIllegalFunc7}) { + !(opcode inside {7'b0110011, 7'b0010011}); + } + } + } + constraint illegal_compressed_op_c { if (exception == kIllegalCompressedOpcode) { c_op != 2'b01; diff --git a/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv b/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv index 33896ad80f..badc423d65 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_cover_group.sv @@ -34,6 +34,10 @@ `define SAMPLE_F(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_floating_point_instr) `define SAMPLE_B(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_b_instr) +`define SAMPLE_ZBA(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zba_instr) +`define SAMPLE_ZBB(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbb_instr) +`define SAMPLE_ZBC(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbc_instr) +`define SAMPLE_ZBS(cg, val) `SAMPLE_W_TYPE(cg, val, riscv_zbs_instr) `define INSTR_CG_BEGIN(INSTR_NAME, INSTR_CLASS = riscv_instr) \ covergroup ``INSTR_NAME``_cg with function sample(INSTR_CLASS instr); @@ -377,6 +381,58 @@ `FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \ `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ +`define ZBA_I_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) + +`define ZBA_R_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zba_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rs2 : coverpoint instr.rs2; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ + +`define ZBB_I_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) + +`define ZBB_R_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbb_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rs2 : coverpoint instr.rs2; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ + +`define ZBC_I_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) + +`define ZBC_R_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbc_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rs2 : coverpoint instr.rs2; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ + +`define ZBS_I_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) + +`define ZBS_R_INSTR_CG_BEGIN(INSTR_NAME) \ + `INSTR_CG_BEGIN(INSTR_NAME, riscv_zbs_instr) \ + cp_rs1 : coverpoint instr.rs1; \ + cp_rs2 : coverpoint instr.rs2; \ + cp_rd : coverpoint instr.rd; \ + `DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \ + `define B_I_INSTR_CG_BEGIN(INSTR_NAME) \ `INSTR_CG_BEGIN(INSTR_NAME, riscv_b_instr) \ cp_rs1 : coverpoint instr.rs1; \ @@ -857,82 +913,83 @@ class riscv_instr_cover_group; `FCLASS_INSTR_CG_BEGIN(fclass_d, D) `CG_END - // B extension - // Count Leading/Trailing Zeros (clz, ctz) - `B_R_INSTR_NO_RS2_CG_BEGIN(clz) - `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1) + // B extension instructions ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). + `ZBA_R_INSTR_CG_BEGIN(sh1add) `CG_END - - `B_R_INSTR_NO_RS2_CG_BEGIN(ctz) - `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1) + `ZBA_R_INSTR_CG_BEGIN(sh2add) `CG_END - - `B_R_INSTR_NO_RS2_CG_BEGIN(clzw) - `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN/2-1) + `ZBA_R_INSTR_CG_BEGIN(sh3add) `CG_END - - `B_R_INSTR_NO_RS2_CG_BEGIN(ctzw) - `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN/2-1) + `ZBA_R_INSTR_CG_BEGIN(sh1add_uw) + `CG_END + `ZBA_R_INSTR_CG_BEGIN(sh2add_uw) + `CG_END + `ZBA_R_INSTR_CG_BEGIN(sh3add_uw) `CG_END - // Count Bits Set (pcnt) - `B_R_INSTR_NO_RS2_CG_BEGIN(pcnt) - `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1) + // Count Leading/Trailing Zeros (clz, ctz) + `ZBB_I_INSTR_CG_BEGIN(clz) + `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1) `CG_END - `B_R_INSTR_NO_RS2_CG_BEGIN(pcntw) - `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN/2-1) + `ZBB_I_INSTR_CG_BEGIN(ctz) + `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1) `CG_END - // Logic-with-negate (andn, orn, xnor) - `B_R_INSTR_CG_BEGIN(andn) + `ZBB_I_INSTR_CG_BEGIN(clzw) + `CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1) `CG_END - `B_R_INSTR_CG_BEGIN(orn) + `ZBB_I_INSTR_CG_BEGIN(ctzw) + `CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1) `CG_END - `B_R_INSTR_CG_BEGIN(xnor) + `ZBB_I_INSTR_CG_BEGIN(cpop) + `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1) `CG_END - // Pack two words in one register (pack, packu, packh) - `B_R_INSTR_CG_BEGIN(pack) + `ZBB_I_INSTR_CG_BEGIN(cpopw) + `CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1) `CG_END - `B_R_INSTR_CG_BEGIN(packu) + // Logic-with-negate (andn, orn, xnor) + `ZBB_R_INSTR_CG_BEGIN(andn) `CG_END - `B_R_INSTR_CG_BEGIN(packh) + `ZBB_R_INSTR_CG_BEGIN(orn) `CG_END - `B_R_INSTR_CG_BEGIN(packw) + `ZBB_R_INSTR_CG_BEGIN(xnor) `CG_END - `B_R_INSTR_CG_BEGIN(packuw) + // Or-combine + `ZBB_R_INSTR_CG_BEGIN(orc_b) + `CP_VALUE_RANGE(or_combine_mode, instr.imm, 0, XLEN-1) `CG_END // Min/max instructions (min, max, minu, maxu) - `B_R_INSTR_CG_BEGIN(min) + `ZBB_R_INSTR_CG_BEGIN(min) cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value)); cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) { bins equal = {1}; } `CG_END - `B_R_INSTR_CG_BEGIN(max) + `ZBB_R_INSTR_CG_BEGIN(max) cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value)); cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) { bins equal = {1}; } `CG_END - `B_R_INSTR_CG_BEGIN(minu) + `ZBB_R_INSTR_CG_BEGIN(minu) cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value); cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) { bins equal = {1}; } `CG_END - `B_R_INSTR_CG_BEGIN(maxu) + `ZBB_R_INSTR_CG_BEGIN(maxu) cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value); cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) { bins equal = {1}; @@ -940,45 +997,109 @@ class riscv_instr_cover_group; `CG_END // Sign-extend instructions (sext.b, sext.h) - `B_R_INSTR_NO_RS2_CG_BEGIN(sext_b) + `ZBB_I_INSTR_CG_BEGIN(sext_b) `CG_END - `B_R_INSTR_NO_RS2_CG_BEGIN(sext_h) + `ZBB_I_INSTR_CG_BEGIN(sext_h) `CG_END - // Single-bit instructions (sbset, sbclr, sbinv, sbext) - `B_R_INSTR_CG_BEGIN(sbset) - `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + `ZBB_I_INSTR_CG_BEGIN(zext_h) `CG_END - `B_R_INSTR_CG_BEGIN(sbclr) - `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + // Rotate (Left/Right) (rol, ror, rori) + `ZBB_R_INSTR_CG_BEGIN(ror) + `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1) `CG_END - `B_R_INSTR_CG_BEGIN(sbinv) - `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + `ZBB_R_INSTR_CG_BEGIN(rol) + `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1) + `CG_END + + `ZBB_I_INSTR_CG_BEGIN(rori) + `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1) + `CG_END + + `ZBB_R_INSTR_CG_BEGIN(rorw) + `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1) + `CG_END + + `ZBB_R_INSTR_CG_BEGIN(rolw) + `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1) + `CG_END + + `ZBB_I_INSTR_CG_BEGIN(roriw) + `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1) + `CG_END + + `ZBB_R_INSTR_CG_BEGIN(rev8) + `CG_END + + // Multiplication + `ZBC_R_INSTR_CG_BEGIN(clmul) + `CG_END + + `ZBC_R_INSTR_CG_BEGIN(clmulh) `CG_END - `B_R_INSTR_CG_BEGIN(sbext) + `ZBC_R_INSTR_CG_BEGIN(clmulr) + `CG_END + + `ZBA_I_INSTR_CG_BEGIN(slli_uw) + `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1) + `CG_END + + `ZBA_R_INSTR_CG_BEGIN(add_uw) + `CG_END + + `ZBS_R_INSTR_CG_BEGIN(bclr) `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) `CG_END - `B_I_INSTR_CG_BEGIN(sbseti) + `ZBS_I_INSTR_CG_BEGIN(bclri) `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1) `CG_END - `B_I_INSTR_CG_BEGIN(sbclri) + `ZBS_R_INSTR_CG_BEGIN(bext) + `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + `CG_END + + `ZBS_I_INSTR_CG_BEGIN(bexti) `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1) `CG_END - `B_I_INSTR_CG_BEGIN(sbinvi) + `ZBS_R_INSTR_CG_BEGIN(binv) + `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + `CG_END + + `ZBS_I_INSTR_CG_BEGIN(binvi) `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1) `CG_END - `B_I_INSTR_CG_BEGIN(sbexti) + `ZBS_R_INSTR_CG_BEGIN(bset) + `CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1) + `CG_END + + `ZBS_I_INSTR_CG_BEGIN(bseti) `CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1) `CG_END + // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). + // Pack two words in one register (pack, packu, packh) + `B_R_INSTR_CG_BEGIN(pack) + `CG_END + + `B_R_INSTR_CG_BEGIN(packu) + `CG_END + + `B_R_INSTR_CG_BEGIN(packh) + `CG_END + + `B_R_INSTR_CG_BEGIN(packw) + `CG_END + + `B_R_INSTR_CG_BEGIN(packuw) + `CG_END + // Shift Ones (Left/Right) (slo, sloi, sro, sroi) `B_R_INSTR_CG_BEGIN(slo) `CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1) @@ -1012,31 +1133,6 @@ class riscv_instr_cover_group; `CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN/2-1) `CG_END - // Rotate (Left/Right) (rol, ror, rori) - `B_R_INSTR_CG_BEGIN(ror) - `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1) - `CG_END - - `B_R_INSTR_CG_BEGIN(rol) - `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1) - `CG_END - - `B_I_INSTR_CG_BEGIN(rori) - `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1) - `CG_END - - `B_R_INSTR_CG_BEGIN(rorw) - `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1) - `CG_END - - `B_R_INSTR_CG_BEGIN(rolw) - `CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1) - `CG_END - - `B_I_INSTR_CG_BEGIN(roriw) - `CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1) - `CG_END - // Generalized Reverse (grev, grevi, rev) `B_R_INSTR_CG_BEGIN(grev) `CP_VALUE_RANGE(reverse_mode, instr.rs2_value, 0, XLEN-1) @@ -1135,34 +1231,16 @@ class riscv_instr_cover_group; `CP_VALUE_RANGE(offset, instr.rs2_value[20:16], 0, XLEN/2-1) `CG_END - `B_R_INSTR_CG_BEGIN(bext) + `B_R_INSTR_CG_BEGIN(bcompress) `CG_END - `B_R_INSTR_CG_BEGIN(bextw) + `B_R_INSTR_CG_BEGIN(bcompressw) `CG_END - `B_R_INSTR_CG_BEGIN(bdep) + `B_R_INSTR_CG_BEGIN(bdecompress) `CG_END - `B_R_INSTR_CG_BEGIN(bdepw) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmul) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmulh) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmulr) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmulw) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmulhw) - `CG_END - - `B_R_INSTR_CG_BEGIN(clmulrw) + `B_R_INSTR_CG_BEGIN(bdecompressw) `CG_END `B_R_INSTR_NO_RS2_CG_BEGIN(crc32_b) @@ -1230,25 +1308,6 @@ class riscv_instr_cover_group; `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN/2-1) `CG_END - `B_R_INSTR_CG_BEGIN(addwu) - `CG_END - - `B_R_INSTR_CG_BEGIN(subwu) - `CG_END - - `B_I_INSTR_CG_BEGIN(addiwu) - `CG_END - - `B_R_INSTR_CG_BEGIN(addu_w) - `CG_END - - `B_R_INSTR_CG_BEGIN(subu_w) - `CG_END - - `B_I_INSTR_CG_BEGIN(slliu_w) - `CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1) - `CG_END - // CSR instructions `CSR_INSTR_CG_BEGIN(csrrw) cp_rs1 : coverpoint instr.rs1; @@ -1971,103 +2030,120 @@ class riscv_instr_cover_group; fcvt_d_lu_cg = new(); `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV32ZBA) + sh1add_cg = new(); + sh2add_cg = new(); + sh3add_cg = new(); + `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV32ZBB) + andn_cg = new(); + clz_cg = new(); + cpop_cg = new(); + ctz_cg = new(); + max_cg = new(); + maxu_cg = new(); + min_cg = new(); + minu_cg = new(); + orc_b_cg = new(); + orn_cg = new(); + rev8_cg = new(); + rol_cg = new(); + ror_cg = new(); + rori_cg = new(); + sext_b_cg = new(); + sext_h_cg = new(); + xnor_cg = new(); + zext_h_cg = new(); + `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV32ZBC) + clmul_cg = new(); + clmulh_cg = new(); + clmulr_cg = new(); + `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV32ZBS) + bclr_cg = new(); + bclri_cg = new(); + bext_cg = new(); + bexti_cg = new(); + binv_cg = new(); + binvi_cg = new(); + bset_cg = new(); + bseti_cg = new(); + `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV32B) - clz_cg = new(); - ctz_cg = new(); - pcnt_cg = new(); - andn_cg = new(); - orn_cg = new(); - xnor_cg = new(); - pack_cg = new(); - packh_cg = new(); - min_cg = new(); - max_cg = new(); - minu_cg = new(); - maxu_cg = new(); - sext_b_cg = new(); - sext_h_cg = new(); - sbset_cg = new(); - sbclr_cg = new(); - sbinv_cg = new(); - sbext_cg = new(); - sbseti_cg = new(); - sbclri_cg = new(); - sbinvi_cg = new(); - sbexti_cg = new(); - slo_cg = new(); - sro_cg = new(); - sloi_cg = new(); - sroi_cg = new(); - ror_cg = new(); - rol_cg = new(); - rori_cg = new(); - grev_cg = new(); - grevi_cg = new(); - shfli_cg = new(); - unshfli_cg = new(); - shfl_cg = new(); - unshfl_cg = new(); - gorc_cg = new(); - gorci_cg = new(); - bfp_cg = new(); - bext_cg = new(); - bdep_cg = new(); - clmul_cg = new(); - clmulh_cg = new(); - clmulr_cg = new(); - crc32_b_cg = new(); - crc32_h_cg = new(); - crc32_w_cg = new(); - crc32c_b_cg = new(); - crc32c_h_cg = new(); - crc32c_w_cg = new(); - cmix_cg = new(); - cmov_cg = new(); - fsl_cg = new(); - fsr_cg = new(); - fsri_cg = new(); + pack_cg = new(); + packh_cg = new(); + slo_cg = new(); + sro_cg = new(); + sloi_cg = new(); + sroi_cg = new(); + grev_cg = new(); + grevi_cg = new(); + shfli_cg = new(); + unshfli_cg = new(); + shfl_cg = new(); + unshfl_cg = new(); + gorc_cg = new(); + gorci_cg = new(); + bfp_cg = new(); + bcompress_cg = new(); + bdecompress_cg = new(); + crc32_b_cg = new(); + crc32_h_cg = new(); + crc32_w_cg = new(); + crc32c_b_cg = new(); + crc32c_h_cg = new(); + crc32c_w_cg = new(); + cmix_cg = new(); + cmov_cg = new(); + fsl_cg = new(); + fsr_cg = new(); + fsri_cg = new(); + `CG_SELECTOR_END + + `CG_SELECTOR_BEGIN(RV64ZBA) + add_uw_cg = new(); + sh1add_uw_cg = new(); + sh2add_uw_cg = new(); + sh3add_uw_cg = new(); + slli_uw_cg = new(); + `CG_SELECTOR_END + `CG_SELECTOR_BEGIN(RV64ZBB) + clzw_cg = new(); + cpopw_cg = new(); + ctzw_cg = new(); + rolw_cg = new(); + rorw_cg = new(); + roriw_cg = new(); `CG_SELECTOR_END `CG_SELECTOR_BEGIN(RV64B) - clzw_cg = new(); - ctzw_cg = new(); - pcntw_cg = new(); - packw_cg = new(); - packuw_cg = new(); - slow_cg = new(); - srow_cg = new(); - sloiw_cg = new(); - sroiw_cg = new(); - rorw_cg = new(); - rolw_cg = new(); - roriw_cg = new(); - grevw_cg = new(); - greviw_cg = new(); - shflw_cg = new(); - unshflw_cg = new(); - gorcw_cg = new(); - gorciw_cg = new(); - bfpw_cg = new(); - bextw_cg = new(); - bdepw_cg = new(); - clmulw_cg = new(); - clmulhw_cg = new(); - clmulrw_cg = new(); - crc32_d_cg = new(); - crc32c_d_cg = new(); - bmator_cg = new(); - bmatxor_cg = new(); - bmatflip_cg = new(); - fslw_cg = new(); - fsrw_cg = new(); - fsriw_cg = new(); - addwu_cg = new(); - subwu_cg = new(); - addiwu_cg = new(); - addu_w_cg = new(); - subu_w_cg = new(); - slliu_w_cg = new(); + packw_cg = new(); + packuw_cg = new(); + slow_cg = new(); + srow_cg = new(); + sloiw_cg = new(); + sroiw_cg = new(); + grevw_cg = new(); + greviw_cg = new(); + shflw_cg = new(); + unshflw_cg = new(); + gorcw_cg = new(); + gorciw_cg = new(); + bfpw_cg = new(); + bcompressw_cg = new(); + bdecompressw_cg = new(); + crc32_d_cg = new(); + crc32c_d_cg = new(); + bmator_cg = new(); + bmatxor_cg = new(); + bmatflip_cg = new(); + fslw_cg = new(); + fsrw_cg = new(); + fsriw_cg = new(); `CG_SELECTOR_END + // Ignore the exception which cannot be covered when running with ISS if (iss_mode) begin int i; @@ -2284,36 +2360,49 @@ class riscv_instr_cover_group; FLE_D : `SAMPLE_F(fle_d_cg, instr) FCLASS_S : `SAMPLE_F(fclass_s_cg, instr) FCLASS_D : `SAMPLE_F(fclass_d_cg, instr) + // RV32ZBA + SH1ADD : `SAMPLE_ZBA(sh1add_cg, instr) + SH2ADD : `SAMPLE_ZBA(sh2add_cg, instr) + SH3ADD : `SAMPLE_ZBA(sh3add_cg, instr) + // RV32ZBB + ANDN : `SAMPLE_ZBB(andn_cg, instr) + CLZ : `SAMPLE_ZBB(clz_cg, instr) + CPOP : `SAMPLE_ZBB(cpop_cg, instr) + CTZ : `SAMPLE_ZBB(ctz_cg, instr) + MAX : `SAMPLE_ZBB(max_cg, instr) + MAXU : `SAMPLE_ZBB(maxu_cg, instr) + MIN : `SAMPLE_ZBB(min_cg, instr) + MINU : `SAMPLE_ZBB(minu_cg, instr) + ORC_B : `SAMPLE_ZBB(orc_b_cg, instr) + ORN : `SAMPLE_ZBB(orn_cg, instr) + REV8 : `SAMPLE_ZBB(rev8_cg, instr) + ROL : `SAMPLE_ZBB(rol_cg, instr) + ROR : `SAMPLE_ZBB(ror_cg, instr) + RORI : `SAMPLE_ZBB(rori_cg, instr) + SEXT_B : `SAMPLE_ZBB(sext_b_cg, instr) + SEXT_H : `SAMPLE_ZBB(sext_h_cg, instr) + XNOR : `SAMPLE_ZBB(xnor_cg, instr) + ZEXT_H : `SAMPLE_ZBB(zext_h_cg, instr) + // RV32ZBC + CLMUL : `SAMPLE_ZBC(clmul_cg, instr) + CLMULH : `SAMPLE_ZBC(clmulh_cg, instr) + CLMULR : `SAMPLE_ZBC(clmulr_cg, instr) + // RV32ZBS + BCLR : `SAMPLE_ZBS(bclr_cg, instr) + BCLRI : `SAMPLE_ZBS(bclri_cg, instr) + BEXT : `SAMPLE_ZBS(bext_cg, instr) + BEXTI : `SAMPLE_ZBS(bexti_cg, instr) + BINV : `SAMPLE_ZBS(binv_cg, instr) + BINVI : `SAMPLE_ZBS(binvi_cg, instr) + BSET : `SAMPLE_ZBS(bset_cg, instr) + BSETI : `SAMPLE_ZBS(bseti_cg, instr) // RV32B - CLZ : `SAMPLE_B(clz_cg, instr) - CTZ : `SAMPLE_B(ctz_cg, instr) - PCNT : `SAMPLE_B(pcnt_cg, instr) - ANDN : `SAMPLE_B(andn_cg, instr) - ORN : `SAMPLE_B(orn_cg, instr) - XNOR : `SAMPLE_B(xnor_cg, instr) PACK : `SAMPLE_B(pack_cg, instr) PACKH : `SAMPLE_B(packh_cg, instr) - MIN : `SAMPLE_B(min_cg, instr) - MAX : `SAMPLE_B(max_cg, instr) - MINU : `SAMPLE_B(minu_cg, instr) - MAXU : `SAMPLE_B(maxu_cg, instr) - SEXT_B : `SAMPLE_B(sext_b_cg, instr) - SEXT_H : `SAMPLE_B(sext_h_cg, instr) - SBSET : `SAMPLE_B(sbset_cg, instr) - SBCLR : `SAMPLE_B(sbclr_cg, instr) - SBINV : `SAMPLE_B(sbinv_cg, instr) - SBEXT : `SAMPLE_B(sbext_cg, instr) - SBSETI : `SAMPLE_B(sbseti_cg, instr) - SBCLRI : `SAMPLE_B(sbclri_cg, instr) - SBINVI : `SAMPLE_B(sbinvi_cg, instr) - SBEXTI : `SAMPLE_B(sbexti_cg, instr) SLO : `SAMPLE_B(slo_cg, instr) SRO : `SAMPLE_B(sro_cg, instr) SLOI : `SAMPLE_B(sloi_cg, instr) SROI : `SAMPLE_B(sroi_cg, instr) - ROR : `SAMPLE_B(ror_cg, instr) - ROL : `SAMPLE_B(rol_cg, instr) - RORI : `SAMPLE_B(rori_cg, instr) GREV : `SAMPLE_B(grev_cg, instr) GREVI : `SAMPLE_B(grevi_cg, instr) SHFLI : `SAMPLE_B(shfli_cg, instr) @@ -2323,11 +2412,8 @@ class riscv_instr_cover_group; GORC : `SAMPLE_B(gorc_cg, instr) GORCI : `SAMPLE_B(gorci_cg, instr) BFP : `SAMPLE_B(bfp_cg, instr) - BEXT : `SAMPLE_B(bext_cg, instr) - BDEP : `SAMPLE_B(bdep_cg, instr) - CLMUL : `SAMPLE_B(clmul_cg, instr) - CLMULH : `SAMPLE_B(clmulh_cg, instr) - CLMULR : `SAMPLE_B(clmulr_cg, instr) + BCOMPRESS : `SAMPLE_B(bcompress_cg, instr) + BDECOMPRESS: `SAMPLE_B(bdecompress_cg, instr) CRC32_B : `SAMPLE_B(crc32_b_cg, instr) CRC32_H : `SAMPLE_B(crc32_h_cg, instr) CRC32_W : `SAMPLE_B(crc32_w_cg, instr) @@ -2339,45 +2425,43 @@ class riscv_instr_cover_group; FSL : `SAMPLE_B(fsl_cg, instr) FSR : `SAMPLE_B(fsr_cg, instr) FSRI : `SAMPLE_B(fsri_cg, instr) + // RV64ZBA + ADD_UW : `SAMPLE_ZBA(add_uw_cg, instr) + SH1ADD_UW : `SAMPLE_ZBA(sh1add_uw_cg, instr) + SH2ADD_UW : `SAMPLE_ZBA(sh2add_uw_cg, instr) + SH3ADD_UW : `SAMPLE_ZBA(sh3add_uw_cg, instr) + SLLI_UW : `SAMPLE_ZBA(slli_uw_cg, instr) + // RV64ZBB + CLZW : `SAMPLE_ZBB(clzw_cg, instr) + CPOPW : `SAMPLE_ZBB(cpopw_cg, instr) + CTZW : `SAMPLE_ZBB(ctzw_cg, instr) + ROLW : `SAMPLE_ZBB(rolw_cg, instr) + RORW : `SAMPLE_ZBB(rorw_cg, instr) + RORIW : `SAMPLE_ZBB(roriw_cg, instr) // RV64B - CLZW : `SAMPLE_B(clzw_cg, instr) - CTZW : `SAMPLE_B(ctzw_cg, instr) - PCNTW : `SAMPLE_B(pcntw_cg, instr) - PACKW : `SAMPLE_B(packw_cg, instr) - PACKUW : `SAMPLE_B(packuw_cg, instr) - SLOW : `SAMPLE_B(slow_cg, instr) - SROW : `SAMPLE_B(srow_cg, instr) - SLOIW : `SAMPLE_B(sloiw_cg, instr) - SROIW : `SAMPLE_B(sroiw_cg, instr) - RORW : `SAMPLE_B(rorw_cg, instr) - ROLW : `SAMPLE_B(rolw_cg, instr) - RORIW : `SAMPLE_B(roriw_cg, instr) - GREVW : `SAMPLE_B(grevw_cg, instr) - GREVIW : `SAMPLE_B(greviw_cg, instr) - SHFLW : `SAMPLE_B(shflw_cg, instr) - UNSHFLW : `SAMPLE_B(unshflw_cg, instr) - GORCW : `SAMPLE_B(gorcw_cg, instr) - GORCIW : `SAMPLE_B(gorciw_cg, instr) - BFPW : `SAMPLE_B(bfpw_cg, instr) - BEXTW : `SAMPLE_B(bextw_cg, instr) - BDEPW : `SAMPLE_B(bdepw_cg, instr) - CLMULW : `SAMPLE_B(clmulw_cg, instr) - CLMULHW : `SAMPLE_B(clmulhw_cg, instr) - CLMULRW : `SAMPLE_B(clmulrw_cg, instr) - CRC32_D : `SAMPLE_B(crc32_d_cg, instr) - CRC32C_D : `SAMPLE_B(crc32c_d_cg, instr) - BMATOR : `SAMPLE_B(bmator_cg, instr) - BMATXOR : `SAMPLE_B(bmatxor_cg, instr) - BMATFLIP : `SAMPLE_B(bmatflip_cg, instr) - FSLW : `SAMPLE_B(fslw_cg, instr) - FSRW : `SAMPLE_B(fsrw_cg, instr) - FSRIW : `SAMPLE_B(fsriw_cg, instr) - ADDWU : `SAMPLE_B(addwu_cg, instr) - SUBWU : `SAMPLE_B(subwu_cg, instr) - ADDIWU : `SAMPLE_B(addiwu_cg, instr) - ADDU_W : `SAMPLE_B(addu_w_cg, instr) - SUBU_W : `SAMPLE_B(subu_w_cg, instr) - SLLIU_W : `SAMPLE_B(slliu_w_cg, instr) + PACKW : `SAMPLE_B(packw_cg, instr) + PACKUW : `SAMPLE_B(packuw_cg, instr) + SLOW : `SAMPLE_B(slow_cg, instr) + SROW : `SAMPLE_B(srow_cg, instr) + SLOIW : `SAMPLE_B(sloiw_cg, instr) + SROIW : `SAMPLE_B(sroiw_cg, instr) + GREVW : `SAMPLE_B(grevw_cg, instr) + GREVIW : `SAMPLE_B(greviw_cg, instr) + SHFLW : `SAMPLE_B(shflw_cg, instr) + UNSHFLW : `SAMPLE_B(unshflw_cg, instr) + GORCW : `SAMPLE_B(gorcw_cg, instr) + GORCIW : `SAMPLE_B(gorciw_cg, instr) + BFPW : `SAMPLE_B(bfpw_cg, instr) + BCOMPRESSW : `SAMPLE_B(bcompressw_cg, instr) + BDECOMPRESSW : `SAMPLE_B(bdecompressw_cg, instr) + CRC32_D : `SAMPLE_B(crc32_d_cg, instr) + CRC32C_D : `SAMPLE_B(crc32c_d_cg, instr) + BMATOR : `SAMPLE_B(bmator_cg, instr) + BMATXOR : `SAMPLE_B(bmatxor_cg, instr) + BMATFLIP : `SAMPLE_B(bmatflip_cg, instr) + FSLW : `SAMPLE_B(fslw_cg, instr) + FSRW : `SAMPLE_B(fsrw_cg, instr) + FSRIW : `SAMPLE_B(fsriw_cg, instr) `VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv") default: begin if (instr.group == RV32I) begin @@ -2459,7 +2543,9 @@ class riscv_instr_cover_group; instr = riscv_instr::create_instr(instr_name); if ((instr.group inside {supported_isa}) && (instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C, - RVV, RV64B, RV32B})) begin + RVV, RV64B, RV32B, + RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS, + RV64ZBA, RV64ZBB, RV64ZBC, RV64ZBS})) begin if (((instr_name inside {URET}) && !support_umode_trap) || ((instr_name inside {SRET, SFENCE_VMA}) && !(SUPERVISOR_MODE inside {supported_privileged_mode})) || diff --git a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv index 4aeb819a4a..9a2fdd1825 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -252,6 +252,12 @@ class riscv_instr_gen_config extends uvm_object; bit vector_instr_only; // Bit manipulation extension support bit enable_b_extension; + + bit enable_zba_extension; + bit enable_zbb_extension; + bit enable_zbc_extension; + bit enable_zbs_extension; + b_ext_group_t enable_bitmanip_groups[] = {ZBB, ZBS, ZBP, ZBE, ZBF, ZBC, ZBR, ZBM, ZBT, ZB_TMP}; @@ -516,6 +522,10 @@ class riscv_instr_gen_config extends uvm_object; `uvm_field_int(vector_instr_only, UVM_DEFAULT) `uvm_field_int(enable_b_extension, UVM_DEFAULT) `uvm_field_array_enum(b_ext_group_t, enable_bitmanip_groups, UVM_DEFAULT) + `uvm_field_int(enable_zba_extension, UVM_DEFAULT) + `uvm_field_int(enable_zbb_extension, UVM_DEFAULT) + `uvm_field_int(enable_zbc_extension, UVM_DEFAULT) + `uvm_field_int(enable_zbs_extension, UVM_DEFAULT) `uvm_field_int(use_push_data_section, UVM_DEFAULT) `uvm_object_utils_end @@ -575,6 +585,10 @@ class riscv_instr_gen_config extends uvm_object; get_bool_arg_value("+enable_floating_point=", enable_floating_point); get_bool_arg_value("+enable_vector_extension=", enable_vector_extension); get_bool_arg_value("+enable_b_extension=", enable_b_extension); + get_bool_arg_value("+enable_zba_extension=", enable_zba_extension); + get_bool_arg_value("+enable_zbb_extension=", enable_zbb_extension); + get_bool_arg_value("+enable_zbc_extension=", enable_zbc_extension); + get_bool_arg_value("+enable_zbs_extension=", enable_zbs_extension); cmdline_enum_processor #(b_ext_group_t)::get_array_values("+enable_bitmanip_groups=", enable_bitmanip_groups); if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin @@ -600,6 +614,27 @@ class riscv_instr_gen_config extends uvm_object; if (!(RV32C inside {supported_isa})) begin disable_compressed_instr = 1; end + + if (!((RV32ZBA inside {supported_isa}) || + (RV64ZBA inside {supported_isa}))) begin + enable_zba_extension = 0; + end + + if (!((RV32ZBB inside {supported_isa}) || + (RV64ZBB inside {supported_isa}))) begin + enable_zbb_extension = 0; + end + + if (!((RV32ZBC inside {supported_isa}) || + (RV64ZBC inside {supported_isa}))) begin + enable_zbc_extension = 0; + end + + if (!((RV32ZBS inside {supported_isa}) || + (RV64ZBS inside {supported_isa}))) begin + enable_zbs_extension = 0; + end + vector_cfg = riscv_vector_cfg::type_id::create("vector_cfg"); pmp_cfg = riscv_pmp_cfg::type_id::create("pmp_cfg"); pmp_cfg.rand_mode(pmp_cfg.pmp_randomize); diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index 5376def4aa..0524f66d2f 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -99,7 +99,15 @@ package riscv_instr_pkg; RV128C, RVV, RV32B, + RV32ZBA, + RV32ZBB, + RV32ZBC, + RV32ZBS, RV64B, + RV64ZBA, + RV64ZBB, + RV64ZBC, + RV64ZBS, RV32X, RV64X } riscv_instr_group_t; @@ -154,108 +162,115 @@ package riscv_instr_pkg; CSRRWI, CSRRSI, CSRRCI, - // RV32B instructions + // RV32ZBA instructions + SH1ADD, + SH2ADD, + SH3ADD, + // RV32ZBB instructions ANDN, + CLZ, + CPOP, + CTZ, + MAX, + MAXU, + MIN, + MINU, + ORC_B, ORN, + REV8, + ROL, + ROR, + RORI, + SEXT_B, + SEXT_H, XNOR, + ZEXT_H, + // RV32ZBC instructions + CLMUL, + CLMULH, + CLMULR, + // RV32ZBS instructions + BCLR, + BCLRI, + BEXT, + BEXTI, + BINV, + BINVI, + BSET, + BSETI, + // RV32B instructions + // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). GORC, + GORCI, + CMIX, + CMOV, + PACK, + PACKU, + PACKH, + XPERM_N, + XPERM_B, + XPERM_H, SLO, SRO, - ROL, - ROR, - SBCLR, - SBSET, - SBINV, - SBEXT, - GREV, SLOI, SROI, - RORI, - SBCLRI, - SBSETI, - SBINVI, - SBEXTI, - GORCI, + GREV, GREVI, - CMIX, - CMOV, FSL, FSR, FSRI, - CLZ, - CTZ, - PCNT, - SEXT_B, - SEXT_H, CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, - CLMUL, - CLMULR, - CLMULH, - MIN, - MAX, - MINU, - MAXU, SHFL, UNSHFL, - BDEP, - BEXT, - PACK, - PACKU, - BMATOR, - BMATXOR, - PACKH, - BFP, SHFLI, UNSHFLI, + BCOMPRESS, + BDECOMPRESS, + BFP, + // RV64ZBA instructions + ADD_UW, + SH1ADD_UW, + SH2ADD_UW, + SH3ADD_UW, + SLLI_UW, + // RV64ZBB instructions + CLZW, + CPOPW, + CTZW, + ROLW, + RORW, + RORIW, //RV64B instructions - ADDIWU, - SLLIU_W, - ADDWU, - SUBWU, + // Remaining bitmanip instructions of draft v.0.93 not ratified in v.1.00 (Zba, Zbb, Zbc, Zbs). + BMATOR, + BMATXOR, BMATFLIP, CRC32_D, CRC32C_D, - ADDU_W, - SUBU_W, + SHFLW, + UNSHFLW, + BCOMPRESSW, + BDECOMPRESSW, + BFPW, SLOW, SROW, - ROLW, - RORW, - SBCLRW, - SBSETW, - SBINVW, - SBEXTW, - GORCW, - GREVW, SLOIW, SROIW, - RORIW, - SBCLRIW, - SBSETIW, - SBINVIW, - GORCIW, + GREVW, GREVIW, FSLW, FSRW, FSRIW, - CLZW, - CTZW, - PCNTW, - CLMULW, - CLMULRW, - CLMULHW, - SHFLW, - UNSHFLW, - BDEPW, - BEXTW, + GORCW, + GORCIW, PACKW, PACKUW, - BFPW, + XPERM_W, // RV32M instructions MUL, MULH, @@ -1151,6 +1166,7 @@ package riscv_instr_pkg; } vxrm_t; typedef enum int { + ZBA, ZBB, ZBS, ZBP, @@ -1178,7 +1194,7 @@ package riscv_instr_pkg; parameter int DATA_WIDTH = 32; // Parameters for output assembly program formatting - parameter int MAX_INSTR_STR_LEN = 11; + parameter int MAX_INSTR_STR_LEN = 13; parameter int LABEL_STR_LEN = 18; // Parameter for program generation @@ -1372,10 +1388,18 @@ package riscv_instr_pkg; `include "riscv_vector_cfg.sv" `include "riscv_pmp_cfg.sv" typedef class riscv_instr; + typedef class riscv_zba_instr; + typedef class riscv_zbb_instr; + typedef class riscv_zbc_instr; + typedef class riscv_zbs_instr; typedef class riscv_b_instr; `include "riscv_instr_gen_config.sv" `include "isa/riscv_instr.sv" `include "isa/riscv_amo_instr.sv" + `include "isa/riscv_zba_instr.sv" + `include "isa/riscv_zbb_instr.sv" + `include "isa/riscv_zbc_instr.sv" + `include "isa/riscv_zbs_instr.sv" `include "isa/riscv_b_instr.sv" `include "isa/riscv_floating_point_instr.sv" `include "isa/riscv_vector_instr.sv" @@ -1388,9 +1412,15 @@ package riscv_instr_pkg; `include "isa/rv32f_instr.sv" `include "isa/rv32i_instr.sv" `include "isa/rv32b_instr.sv" + `include "isa/rv32zba_instr.sv" + `include "isa/rv32zbb_instr.sv" + `include "isa/rv32zbc_instr.sv" + `include "isa/rv32zbs_instr.sv" `include "isa/rv32m_instr.sv" `include "isa/rv64a_instr.sv" `include "isa/rv64b_instr.sv" + `include "isa/rv64zba_instr.sv" + `include "isa/rv64zbb_instr.sv" `include "isa/rv64c_instr.sv" `include "isa/rv64d_instr.sv" `include "isa/rv64f_instr.sv" diff --git a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv index 91693c060b..478465756b 100644 --- a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv +++ b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv @@ -89,7 +89,8 @@ class riscv_privileged_common_seq extends uvm_sequence; mstatus.set_field("SPP", 0); // Enable interrupt mstatus.set_field("MPIE", cfg.enable_interrupt); - mstatus.set_field("MIE", cfg.enable_interrupt); + // MIE is set when returning with mret, avoids trapping before returning + mstatus.set_field("MIE", 0); mstatus.set_field("SPIE", cfg.enable_interrupt); mstatus.set_field("SIE", cfg.enable_interrupt); mstatus.set_field("UPIE", cfg.enable_interrupt); diff --git a/vendor/google_riscv-dv/target/ml/testlist.yaml b/vendor/google_riscv-dv/target/ml/testlist.yaml index 11048dc527..e255cb8dbb 100644 --- a/vendor/google_riscv-dv/target/ml/testlist.yaml +++ b/vendor/google_riscv-dv/target/ml/testlist.yaml @@ -34,24 +34,24 @@ description: > Random test with all useful knobs gen_opts: > - +instr_cnt=10000 + +instr_cnt=100000 +num_of_sub_program=5 +illegal_instr_ratio=5 +hint_instr_ratio=5 +stream_name_0=riscv_load_store_rand_instr_stream - +stream_freq_0=4 + +stream_freq_0=20 +stream_name_1=riscv_loop_instr - +stream_freq_1=4 + +stream_freq_1=20 +stream_name_2=riscv_hazard_instr_stream - +stream_freq_2=4 + +stream_freq_2=20 +stream_name_3=riscv_load_store_hazard_instr_stream - +stream_freq_3=4 + +stream_freq_3=20 +stream_name_4=riscv_mem_region_stress_test - +stream_freq_4=4 + +stream_freq_4=20 +stream_name_5=riscv_jal_instr - +stream_freq_5=4 + +stream_freq_5=20 +stream_name_6=riscv_int_numeric_corner_stream - +stream_freq_6=4 + +stream_freq_6=20 +dist_control_mode=1 +dist_shift=10 +dist_arithmetic=10