mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-23 13:27:10 -04:00
Update google_riscv-dv to google/riscv-dv@ea8dd25
Update code from upstream repository https://github.com/google/riscv- dv to revision ea8dd25140178eed13c3e0f3d3a97a0c07ab44a0 * Upgrade bitmanip v.0.92 to v.0.93, enable simultaneous use with v.1.00 (Pirmin Vogel) * Added v1.0.0 bitmanip support (Henrik Fegran) * Remove the pyucis-viewer from requirements.txt (aneels3) * Update README.md for PyFlow & add pyucis-viewer in requiremen.txt (aneels3) * Fix typo with fs3_sign (aneels3) * Add hint_cg and illegal_compressed_instr_cg covergroups (aneels3) * override deepcopy method (aneels3) * Fix issue with illegal_instr_testi and randselect (aneels3) * Fixed b_extension_c() issue (shrujal20) * Fixed get_rand_spf_dpf_value() issue (shrujal20) * Add support for RV32C coverage (aneels3) * Add README.md for PyFlow (aneels3) * Add gen_timeout for PyFlow (aneels3) * Issue google/riscv-dv#778 fix, change mie behavior in setup_mmode_reg (Henrik Fegran) * Fixed wrong length of I, S, B-type immediates causing wrong sign extension for certain instructions (Henrik Fegran) * Update riscv_compressed_instr.sv (AryamanAg) * Update var binary of function convert2bin (AryamanAg) * Improve status reporting (Philipp Wagner) * update ml/testlist.yaml to get better coverage (Udi Jonnalagadda) * add m extension covgroup (ishita71) * Update pygen_src files (aneels3) Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
This commit is contained in:
parent
169785d071
commit
d8e50dcc2c
62 changed files with 4042 additions and 1611 deletions
|
@ -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 $@
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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"]
|
||||
|
|
2
vendor/google_riscv-dv.lock.hjson
vendored
2
vendor/google_riscv-dv.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/google/riscv-dv
|
||||
rev: 59dcd8c813484eb6dcca67e7e36089fe772b9cc8
|
||||
rev: ea8dd25140178eed13c3e0f3d3a97a0c07ab44a0
|
||||
}
|
||||
}
|
||||
|
|
99
vendor/google_riscv-dv/pygen/pygen_src/README.md
vendored
Normal file
99
vendor/google_riscv-dv/pygen/pygen_src/README.md
vendored
Normal file
|
@ -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.
|
|
@ -223,6 +223,6 @@ class riscv_compressed_instr(riscv_instr):
|
|||
def get_c_opcode(self):
|
||||
pass
|
||||
|
||||
# TOD0
|
||||
# TODO
|
||||
def get_func3(self):
|
||||
pass
|
||||
|
|
|
@ -19,11 +19,11 @@ import vsc
|
|||
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 @@ class riscv_cov_instr:
|
|||
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 @@ class riscv_cov_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 @@ class riscv_cov_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"]
|
||||
|
|
|
@ -116,7 +116,7 @@ class riscv_floating_point_instr(riscv_instr):
|
|||
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()
|
||||
|
|
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
@ -110,12 +108,32 @@ class riscv_instr:
|
|||
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 @@ class riscv_instr:
|
|||
|
||||
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 @@ class riscv_instr:
|
|||
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):
|
||||
|
|
|
@ -14,13 +14,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
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 @@ class riscv_amo_base_instr_stream(riscv_mem_access_stream):
|
|||
|
||||
@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 @@ class riscv_amo_base_instr_stream(riscv_mem_access_stream):
|
|||
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 @@ class riscv_amo_base_instr_stream(riscv_mem_access_stream):
|
|||
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)
|
||||
|
||||
|
|
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
@ -31,35 +29,43 @@ from pygen_src.riscv_privileged_common_seq import riscv_privileged_common_seq
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
# 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 @@ class riscv_asm_program_gen:
|
|||
# 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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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
|
||||
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
|
||||
|
||||
def init_vector_engine(self):
|
||||
pass
|
||||
# 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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
# 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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
"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 @@ class riscv_asm_program_gen:
|
|||
"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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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 @@ class riscv_asm_program_gen:
|
|||
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
|
||||
|
|
|
@ -14,16 +14,23 @@ import logging
|
|||
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 @@ class riscv_data_page_gen:
|
|||
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 @@ class riscv_data_page_gen:
|
|||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 enum import IntEnum, auto
|
|||
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 @@ class riscv_directed_instr_stream(riscv_rand_instr_stream):
|
|||
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 @@ class riscv_mem_access_stream(riscv_directed_instr_stream):
|
|||
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 @@ class riscv_mem_access_stream(riscv_directed_instr_stream):
|
|||
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 @@ class riscv_mem_access_stream(riscv_directed_instr_stream):
|
|||
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 @@ class riscv_jal_instr(riscv_rand_instr_stream):
|
|||
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 @@ class riscv_jal_instr(riscv_rand_instr_stream):
|
|||
jal.append(riscv_instr_name_t.C_J)
|
||||
if rcs.XLEN == 32:
|
||||
jal.append(riscv_instr_name_t.C_JAL)
|
||||
|
||||
# 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 @@ class riscv_int_numeric_corner_stream(riscv_directed_instr_stream):
|
|||
self.avail_regs[i] != riscv_reg_t.ZERO
|
||||
|
||||
def pre_randomize(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def post_randomize(self):
|
||||
|
@ -212,7 +219,6 @@ class riscv_int_numeric_corner_stream(riscv_directed_instr_stream):
|
|||
|
||||
# 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 @@ class riscv_push_stack_instr(riscv_rand_instr_stream):
|
|||
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 @@ class riscv_push_stack_instr(riscv_rand_instr_stream):
|
|||
|
||||
# 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 @@ class riscv_pop_stack_instr(riscv_rand_instr_stream):
|
|||
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)
|
||||
|
|
|
@ -162,8 +162,8 @@ class riscv_illegal_instr:
|
|||
@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 @@ class riscv_illegal_instr:
|
|||
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 @@ class riscv_illegal_instr:
|
|||
(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):
|
||||
|
|
|
@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
"""
|
||||
|
||||
import traceback
|
||||
from pygen_src.isa.riscv_cov_instr import *
|
||||
|
||||
|
||||
|
@ -1381,6 +1382,195 @@ class riscv_instr_cover_group:
|
|||
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 @@ class riscv_instr_cover_group:
|
|||
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 @@ class riscv_instr_cover_group:
|
|||
}
|
||||
)
|
||||
|
||||
@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 @@ class riscv_instr_cover_group:
|
|||
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 @@ class riscv_instr_cover_group:
|
|||
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()
|
||||
|
|
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
@ -22,19 +20,48 @@ from pygen_src.riscv_instr_pkg import (mtvec_mode_t, f_rounding_mode_t,
|
|||
riscv_reg_t, privileged_mode_t,
|
||||
riscv_instr_group_t, data_pattern_t,
|
||||
riscv_instr_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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
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,35 +315,26 @@ class riscv_instr_gen_config:
|
|||
|
||||
@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 sp_tp_c(self):
|
||||
if self.fix_sp:
|
||||
self.sp == riscv_reg_t.SP
|
||||
self.sp != self.tp
|
||||
self.sp.not_inside(vsc.rangelist(riscv_reg_t.GP,
|
||||
riscv_reg_t.RA, riscv_reg_t.ZERO))
|
||||
self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
|
||||
riscv_reg_t.RA, riscv_reg_t.ZERO))
|
||||
def debug_mode_c(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
# Keep the number of single step iterations relatively small
|
||||
@vsc.constraint
|
||||
def gpr_c(self):
|
||||
with vsc.foreach(self.gpr, idx = True) as i:
|
||||
self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
|
||||
riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
|
||||
vsc.unique(self.gpr)
|
||||
def debug_single_step_c(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
# Boot privileged mode distribution
|
||||
@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 boot_privileged_mode_dist_c(self):
|
||||
# Boot to higher privileged mode more often
|
||||
# TODO
|
||||
pass
|
||||
|
||||
@vsc.constraint
|
||||
def mtvec_c(self):
|
||||
|
@ -234,15 +342,10 @@ class riscv_instr_gen_config:
|
|||
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 floating_point_c(self):
|
||||
with vsc.if_then(self.enable_floating_point):
|
||||
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):
|
||||
|
@ -254,6 +357,124 @@ class riscv_instr_gen_config:
|
|||
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):
|
||||
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,
|
||||
riscv_reg_t.RA, riscv_reg_t.ZERO))
|
||||
self.tp.not_inside(vsc.rangelist(riscv_reg_t.GP,
|
||||
riscv_reg_t.RA, riscv_reg_t.ZERO))
|
||||
|
||||
# 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:
|
||||
self.gpr[i].not_inside(vsc.rangelist(self.sp, self.tp, self.scratch_reg, self.pmp_reg,
|
||||
riscv_reg_t.ZERO, riscv_reg_t.RA, riscv_reg_t.GP))
|
||||
vsc.unique(self.gpr)
|
||||
|
||||
@vsc.constraint
|
||||
def addr_translation_rnd_order_c(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
@vsc.constraint
|
||||
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():
|
||||
self.virtual_addr_translation_on == 0
|
||||
|
||||
@vsc.constraint
|
||||
def floating_point_c(self):
|
||||
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_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
|
||||
support_128b = 0
|
||||
|
@ -296,47 +517,8 @@ class riscv_instr_gen_config:
|
|||
.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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
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 @@ class riscv_instr_gen_config:
|
|||
get_invalid_priv_lvl_csr();
|
||||
'''
|
||||
args = parse.parse_args()
|
||||
|
||||
return args
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
import 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 @@ class riscv_instr_sequence:
|
|||
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 @@ class riscv_instr_sequence:
|
|||
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 @@ class riscv_instr_sequence:
|
|||
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 @@ class riscv_instr_sequence:
|
|||
"""
|
||||
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 @@ class riscv_instr_sequence:
|
|||
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:
|
||||
|
|
|
@ -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 @@ 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 random
|
||||
import logging
|
||||
import sys
|
||||
|
@ -20,15 +20,12 @@ from pygen_src.isa.riscv_instr import riscv_instr
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_instr_stream:
|
|||
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 @@ class riscv_rand_instr_stream(riscv_instr_stream):
|
|||
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 @@ class riscv_rand_instr_stream(riscv_instr_stream):
|
|||
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 @@ class riscv_rand_instr_stream(riscv_instr_stream):
|
|||
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
|
||||
|
|
|
@ -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 @@ class riscv_load_store_base_instr_stream(riscv_mem_access_stream):
|
|||
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 @@ class riscv_single_load_store_instr_stream(riscv_load_store_base_instr_stream):
|
|||
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 @@ class riscv_load_store_stress_instr_stream(riscv_load_store_base_instr_stream):
|
|||
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 @@ class riscv_load_store_rand_instr_stream(riscv_load_store_base_instr_stream):
|
|||
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):
|
||||
|
|
|
@ -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 @@ class riscv_privil_reg(riscv_reg):
|
|||
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 @@ class riscv_privil_reg(riscv_reg):
|
|||
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 @@ class riscv_privil_reg(riscv_reg):
|
|||
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 @@ class riscv_privil_reg(riscv_reg):
|
|||
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)
|
||||
|
|
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
@ -22,6 +20,7 @@ from pygen_src.riscv_privil_reg import riscv_privil_reg
|
|||
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 @@ class riscv_privileged_common_seq():
|
|||
|
||||
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):
|
||||
|
|
|
@ -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 @@ http://www.apache.org/licenses/LICENSE-2.0
|
|||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
"""
|
||||
|
||||
import vsc
|
||||
|
@ -36,11 +34,12 @@ class riscv_pseudo_instr(riscv_instr):
|
|||
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()
|
||||
|
||||
|
|
|
@ -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 @@ from pygen_src.riscv_instr_pkg import (
|
|||
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:
|
||||
|
|
|
@ -12,9 +12,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
|
||||
from enum import IntEnum, auto
|
||||
|
||||
|
||||
# Will be the lowest 8 bits of the data word
|
||||
|
||||
|
||||
class signature_type_t(IntEnum):
|
||||
'''
|
||||
Information sent to the core relating its current status.
|
||||
|
|
|
@ -26,6 +26,10 @@ from pygen_src.riscv_load_store_instr_lib import (riscv_load_store_rand_instr_st
|
|||
riscv_single_load_store_instr_stream)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# pyflow commmon utility helpers functions
|
||||
# ----------------------------------------------------------
|
||||
|
||||
def factory(obj_of):
|
||||
objs = {
|
||||
"riscv_directed_instr_stream": riscv_directed_instr_stream,
|
||||
|
|
|
@ -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 @@ Unless required by applicable law or agreed to in writing, software
|
|||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
|
||||
exception_cause_t, satp_mode_t,
|
||||
riscv_instr_group_t, privileged_mode_t,
|
||||
mtvec_mode_t)
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
MAX_MUL = 8
|
||||
# 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 = 2
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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 = []
|
||||
|
|
|
@ -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 @@ Unless required by applicable law or agreed to in writing, software
|
|||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import math
|
||||
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)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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_isa = [riscv_instr_group_t.RV32I]
|
||||
|
||||
# Supported Privileged mode
|
||||
supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
|
||||
NUM_HARTS = 1
|
||||
|
||||
support_pmp = 0
|
||||
|
||||
support_debug_mode = 0
|
||||
|
||||
# Unsupported instructions
|
||||
unsupported_instr = []
|
||||
|
||||
# ISA supported by the processor
|
||||
supported_isa = [riscv_instr_group_t.RV32I]
|
||||
|
||||
# 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
|
||||
|
||||
# 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 = []
|
||||
|
|
|
@ -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 @@ Unless required by applicable law or agreed to in writing, software
|
|||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
|
||||
exception_cause_t, satp_mode_t,
|
||||
riscv_instr_group_t, privileged_mode_t,
|
||||
mtvec_mode_t)
|
||||
|
||||
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.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
|
||||
|
||||
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
|
||||
|
||||
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 = []
|
||||
|
|
|
@ -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 @@ Unless required by applicable law or agreed to in writing, software
|
|||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
|
||||
exception_cause_t, satp_mode_t,
|
||||
riscv_instr_group_t, privileged_mode_t,
|
||||
mtvec_mode_t)
|
||||
|
||||
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_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
|
||||
riscv_instr_group_t.RV32C]
|
||||
|
||||
# Supported Privileged mode
|
||||
supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
|
||||
|
||||
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
|
||||
|
||||
max_interrupt_vector_num = 16
|
||||
|
||||
support_debug_mode = 0
|
||||
|
||||
NUM_HARTS = 1
|
||||
|
||||
support_pmp = 0
|
||||
|
||||
# Unsupported 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]
|
||||
|
||||
# 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
|
||||
|
||||
# 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_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
|
||||
|
||||
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
|
||||
|
||||
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 = []
|
||||
|
|
|
@ -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 @@ Unless required by applicable law or agreed to in writing, software
|
|||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
from pygen_src.riscv_instr_pkg import (privileged_reg_t, interrupt_cause_t,
|
||||
exception_cause_t, satp_mode_t,
|
||||
riscv_instr_group_t, privileged_mode_t,
|
||||
mtvec_mode_t)
|
||||
|
||||
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.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_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
|
||||
|
||||
# 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 = []
|
||||
|
|
|
@ -24,6 +24,7 @@ from pygen_src.riscv_asm_program_gen import riscv_asm_program_gen # NOQA
|
|||
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 @@ class riscv_instr_base_test:
|
|||
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()
|
||||
|
|
|
@ -106,6 +106,11 @@ class riscv_instr_cov_test:
|
|||
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 @@ class riscv_instr_cov_test:
|
|||
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 @@ class riscv_instr_cov_test:
|
|||
# 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 @@ class riscv_instr_cov_test:
|
|||
|
||||
def process_instr_name(self, instruction):
|
||||
instruction = instruction.upper()
|
||||
instruction.replace(".", "_")
|
||||
instruction = instruction.replace(".", "_")
|
||||
instruction = self.update_instr_name(instruction)
|
||||
return instruction
|
||||
|
||||
|
|
|
@ -31,13 +31,14 @@ class riscv_rand_instr_test(riscv_instr_base_test):
|
|||
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()
|
||||
|
|
12
vendor/google_riscv-dv/run.py
vendored
12
vendor/google_riscv-dv/run.py
vendored
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
2
vendor/google_riscv-dv/scripts/lib.py
vendored
2
vendor/google_riscv-dv/scripts/lib.py
vendored
|
@ -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]
|
||||
|
|
213
vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
vendored
Executable file → Normal file
213
vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
vendored
Executable file → Normal file
|
@ -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
|
||||
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
99
vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
vendored
Normal file
99
vendor/google_riscv-dv/src/isa/riscv_zba_instr.sv
vendored
Normal file
|
@ -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
|
||||
|
||||
|
||||
|
238
vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
vendored
Normal file
238
vendor/google_riscv-dv/src/isa/riscv_zbb_instr.sv
vendored
Normal file
|
@ -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
|
73
vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
vendored
Normal file
73
vendor/google_riscv-dv/src/isa/riscv_zbc_instr.sv
vendored
Normal file
|
@ -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
|
107
vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
vendored
Normal file
107
vendor/google_riscv-dv/src/isa/riscv_zbs_instr.sv
vendored
Normal file
|
@ -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
|
86
vendor/google_riscv-dv/src/isa/rv32b_instr.sv
vendored
86
vendor/google_riscv-dv/src/isa/rv32b_instr.sv
vendored
|
@ -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)
|
||||
|
|
20
vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
vendored
Normal file
20
vendor/google_riscv-dv/src/isa/rv32zba_instr.sv
vendored
Normal file
|
@ -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);
|
35
vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
vendored
Normal file
35
vendor/google_riscv-dv/src/isa/rv32zbb_instr.sv
vendored
Normal file
|
@ -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);
|
20
vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
vendored
Normal file
20
vendor/google_riscv-dv/src/isa/rv32zbc_instr.sv
vendored
Normal file
|
@ -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)
|
25
vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
vendored
Normal file
25
vendor/google_riscv-dv/src/isa/rv32zbs_instr.sv
vendored
Normal file
|
@ -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)
|
64
vendor/google_riscv-dv/src/isa/rv64b_instr.sv
vendored
64
vendor/google_riscv-dv/src/isa/rv64b_instr.sv
vendored
|
@ -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)
|
||||
|
|
22
vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
vendored
Normal file
22
vendor/google_riscv-dv/src/isa/rv64zba_instr.sv
vendored
Normal file
|
@ -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);
|
23
vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
vendored
Normal file
23
vendor/google_riscv-dv/src/isa/rv64zbb_instr.sv
vendored
Normal file
|
@ -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);
|
|
@ -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
|
||||
|
|
19
vendor/google_riscv-dv/src/riscv_defines.svh
vendored
19
vendor/google_riscv-dv/src/riscv_defines.svh
vendored
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,43 +913,177 @@ class riscv_instr_cover_group;
|
|||
`FCLASS_INSTR_CG_BEGIN(fclass_d, D)
|
||||
`CG_END
|
||||
|
||||
// B extension
|
||||
// B extension instructions ratified in v.1.00 (Zba, Zbb, Zbc, Zbs).
|
||||
`ZBA_R_INSTR_CG_BEGIN(sh1add)
|
||||
`CG_END
|
||||
`ZBA_R_INSTR_CG_BEGIN(sh2add)
|
||||
`CG_END
|
||||
`ZBA_R_INSTR_CG_BEGIN(sh3add)
|
||||
`CG_END
|
||||
`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 Leading/Trailing Zeros (clz, ctz)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(clz)
|
||||
`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(ctz)
|
||||
`ZBB_I_INSTR_CG_BEGIN(ctz)
|
||||
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(clzw)
|
||||
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN/2-1)
|
||||
`ZBB_I_INSTR_CG_BEGIN(clzw)
|
||||
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(ctzw)
|
||||
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN/2-1)
|
||||
`ZBB_I_INSTR_CG_BEGIN(ctzw)
|
||||
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
// Count Bits Set (pcnt)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(pcnt)
|
||||
`ZBB_I_INSTR_CG_BEGIN(cpop)
|
||||
`CP_VALUE_RANGE(num_set_bits, 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(cpopw)
|
||||
`CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
// Logic-with-negate (andn, orn, xnor)
|
||||
`B_R_INSTR_CG_BEGIN(andn)
|
||||
`ZBB_R_INSTR_CG_BEGIN(andn)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(orn)
|
||||
`ZBB_R_INSTR_CG_BEGIN(orn)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(xnor)
|
||||
`ZBB_R_INSTR_CG_BEGIN(xnor)
|
||||
`CG_END
|
||||
|
||||
// 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)
|
||||
`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
|
||||
|
||||
`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
|
||||
|
||||
`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
|
||||
|
||||
`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};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
// Sign-extend instructions (sext.b, sext.h)
|
||||
`ZBB_I_INSTR_CG_BEGIN(sext_b)
|
||||
`CG_END
|
||||
|
||||
`ZBB_I_INSTR_CG_BEGIN(sext_h)
|
||||
`CG_END
|
||||
|
||||
`ZBB_I_INSTR_CG_BEGIN(zext_h)
|
||||
`CG_END
|
||||
|
||||
// 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
|
||||
|
||||
`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
|
||||
|
||||
`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
|
||||
|
||||
`ZBS_I_INSTR_CG_BEGIN(bclri)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`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
|
||||
|
||||
`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
|
||||
|
||||
`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
|
||||
|
@ -910,75 +1100,6 @@ class riscv_instr_cover_group;
|
|||
`B_R_INSTR_CG_BEGIN(packuw)
|
||||
`CG_END
|
||||
|
||||
// Min/max instructions (min, max, minu, maxu)
|
||||
`B_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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
||||
// Sign-extend instructions (sext.b, sext.h)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(sext_b)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_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)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sbclr)
|
||||
`CP_VALUE_RANGE(bit_location, 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)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sbext)
|
||||
`CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbseti)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbclri)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbinvi)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbexti)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`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})) ||
|
||||
|
|
|
@ -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);
|
||||
|
|
166
vendor/google_riscv-dv/src/riscv_instr_pkg.sv
vendored
166
vendor/google_riscv-dv/src/riscv_instr_pkg.sv
vendored
|
@ -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,
|
||||
XNOR,
|
||||
GORC,
|
||||
SLO,
|
||||
SRO,
|
||||
REV8,
|
||||
ROL,
|
||||
ROR,
|
||||
SBCLR,
|
||||
SBSET,
|
||||
SBINV,
|
||||
SBEXT,
|
||||
GREV,
|
||||
SLOI,
|
||||
SROI,
|
||||
RORI,
|
||||
SBCLRI,
|
||||
SBSETI,
|
||||
SBINVI,
|
||||
SBEXTI,
|
||||
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,
|
||||
GREVI,
|
||||
CMIX,
|
||||
CMOV,
|
||||
PACK,
|
||||
PACKU,
|
||||
PACKH,
|
||||
XPERM_N,
|
||||
XPERM_B,
|
||||
XPERM_H,
|
||||
SLO,
|
||||
SRO,
|
||||
SLOI,
|
||||
SROI,
|
||||
GREV,
|
||||
GREVI,
|
||||
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"
|
||||
|
|
|
@ -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);
|
||||
|
|
16
vendor/google_riscv-dv/target/ml/testlist.yaml
vendored
16
vendor/google_riscv-dv/target/ml/testlist.yaml
vendored
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue