Update google_riscv-dv to google/riscv-dv@6cf6b4f

Update code from upstream repository https://github.com/google/riscv-
dv to revision 6cf6b4f389272d8ff5e2b397af43ac6c0dfba2e2

* Update init value for floating point reg (google/riscv-dv#615)
  (weicaiyang)
* temporarily comment out 4 vector instructions to re-enable coverage
  flow (google/riscv-dv#616) (udinator)
* Fix vector load/store instruction encoding (google/riscv-dv#614)
  (taoliug)
* Add user_init.s to allow custom initialization routine
  (google/riscv-dv#613) (taoliug)
* Fix vector extension config register initialization (google/riscv-
  dv#610) (taoliug)
* Add floating point coverage part2 (google/riscv-dv#600) (weicaiyang)
* Add MAX LMUL configure (google/riscv-dv#609) (taoliug)
* Fix vector unit strided load/store instruction stream name
  (google/riscv-dv#608) (taoliug)
* Update pygen source files (google/riscv-dv#602) (ANIL SHARMA)
* Add vector strided load/store test (google/riscv-dv#601) (taoliug)
* make <main> 4-byte aligned when enabling PMP (google/riscv-dv#596)
  (udinator)
* Fix ius compilation issue (google/riscv-dv#599) (taoliug)
* Integrate Andes's vector extension work to upstream (google/riscv-
  dv#598) (taoliug)
* Fix kernal setcion  PTE setting issue (google/riscv-dv#594)
  (taoliug)
* Add flake8 check for pygen (google/riscv-dv#589) (Hai Hoang Dang)
* Fix MPRV setting issue, it's causing problem for exception handling
  with virtual address translation on (google/riscv-dv#593) (taoliug)
* Fix VSETVL generation issue (google/riscv-dv#591) (taoliug)
* Fix jump instruction stream label issue (google/riscv-dv#590)
  (taoliug)
* Add pygen_src files (aneels3)

Signed-off-by: Udi <udij@google.com>
This commit is contained in:
Udi 2020-06-17 19:12:35 -07:00 committed by udinator
parent b302b6da92
commit e8a71c8ac8
37 changed files with 2914 additions and 344 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 1ad73cc43f8f84d93d49040f8b2928e74efdd854
rev: 6cf6b4f389272d8ff5e2b397af43ac6c0dfba2e2
}
}

10
vendor/google_riscv-dv/.flake8 vendored Normal file
View file

@ -0,0 +1,10 @@
[flake8]
# Maximum line length
max-line-length = 100
ignore =
# Ignore unexpected spaces around keyword / parameter equals
E251,
# Do not complain about line breaks after operators
W504

View file

@ -2,8 +2,6 @@ language: python
dist: xenial
matrix:
include:
- python: 3.5
env: TOX_ENV=py35
- python: 3.6
env: TOX_ENV=py36
- python: 3.7
@ -15,3 +13,4 @@ install:
script:
- sphinx-build -E -W -b linkcheck docs/source build
- pip uninstall -y riscv-dv
- flake8 --show-source pygen/pygen_src/ --config=.flake8

View file

@ -0,0 +1,408 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
from collections import defaultdict
from pygen_src.riscv_instr_gen_config import riscv_instr_gen_config
from pygen_src.riscv_instr_pkg import riscv_instr_group_t
from pygen_src.isa import rv32i_instr # NOQA
import random
from bitstring import BitArray
import logging
from copy import copy
import sys
class riscv_instr:
logging.basicConfig(level=logging.INFO)
instr_registry = {}
def __init__(self):
self.instr_names = []
self.instr_group = defaultdict(list)
self.instr_category = defaultdict(list)
self.basic_instr = []
self.instr_template = {}
self.exclude_reg = []
self.include_reg = []
self.group = None
self.format = None
self.category = None
self.instr_name = None
self.imm_type = None
self.imm_len = 0
self.csr = None
self.rs2 = None
self.rs1 = None
self.rd = None
self.imm = BitArray(hex="0x00000000")
self.imm_mask = BitArray(hex="0xffffffff")
self.is_branch_target = None
self.has_label = 1
self.atomic = 0
self.branch_assigned = None
self.process_load_store = 1
self.is_compressed = None
self.is_illegal_instr = None
self.is_hint_instr = None
self.is_floating_point = None
self.imm_str = None
self.comment = None
self.label = None
self.is_local_numeric_label = None
self.idx = -1
self.has_rs1 = 1
self.has_rs2 = 1
self.has_rd = 1
self.has_imm = 1
# Fields Added for debugging These fields are actually from a different files.
self.unsupported_instr = []
self.XLEN = 32
self.supported_isa = [riscv_instr_group_t.RV32I]
self.implemented_csr = []
@classmethod
def register(cls, instr_name):
logging.info("Registering %s", instr_name.name)
cls.instr_registry[instr_name.name] = 1
if(instr_name is None):
print("\n")
return 1
def create_instr_list(self, cfg):
self.instr_names.clear()
self.instr_group.clear()
self.instr_category.clear()
for instr_name, values in self.instr_registry.items():
if(instr_name in self.unsupported_instr):
continue
instr_inst = self.create_instr(instr_name)
self.instr_template[instr_name] = instr_inst
if (not instr_inst.is_supported(cfg)):
continue
if ((self.XLEN != 32) and (instr_name == "C_JAL")):
continue
if (("SP" in cfg.reserved_regs) and (instr_name == "C_ADDI16SP")):
continue
if (cfg.enable_sfence and instr_name == "SFENCE_VMA"):
continue
if (instr_name in ["FENCE", "FENCE_I", "SFENCE_VMA"]):
continue
if (instr_inst.group in self.supported_isa and
not(cfg.disable_compressed_instr and
instr_inst.group in ["RV32C", "RV64C", "RV32DC", "RV32FC", "RV128C"]) and
not(not(cfg.enable_floating_point) and instr_inst.group in
["RV32F", "RV64F", "RV32D", "RV64D"])):
self.instr_category[instr_inst.category.name].append(instr_name)
self.instr_group[instr_inst.group.name].append(instr_name)
self.instr_names.append(instr_name)
self.build_basic_instruction_list(cfg)
self.create_csr_filter(cfg)
def create_instr(self, instr_name):
"""TODO This method is specific to RV32I instruction only.
It must be scaled to all instruction extensions."""
try:
instr_inst = eval("rv32i_instr.riscv_" + instr_name + "_instr()")
except Exception:
logging.critical("Failed to create instr: %0s", instr_name)
sys.exit(1)
return instr_inst
def is_supported(self, cfg):
return 1
def build_basic_instruction_list(self, cfg):
self.basic_instr = (self.instr_category["SHIFT"] + self.instr_category["ARITHMETIC"] +
self.instr_category["LOGICAL"] + self.instr_category["COMPARE"])
if(cfg.no_ebreak == 0):
self.basic_instr.append("EBREAK")
for items in self.supported_isa:
if("RV32C" in self.supported_isa and not(cfg.disable_compressed_instr)):
self.basic_instr.append("C_EBREAK")
break
if(cfg.no_dret == 0):
self.basic_instr.append("DRET")
if(cfg.no_fence == 0):
self.basic_instr.append(self.instr_category["SYNCH"])
if(cfg.no_csr_instr == 0 and cfg.init_privileged_mode == "MACHINE_MODE"):
self.basic_instr.append(self.instr_category["CSR"])
if(cfg.no_wfi == 0):
self.basic_instr.append("WFI")
def create_csr_filter(self, cfg):
self.include_reg.clear()
self.exclude_reg.clear()
if(cfg.enable_illegal_csr_instruction):
self.exclude_reg = self.implemented_csr
elif(cfg.enable_access_invalid_csr_level):
self.include_reg = cfg.invalid_priv_mode_csrs
else:
if(cfg.init_privileged_mode == "MACHINE_MODE"): # Machine Mode
self.include_reg.append("MSCRATCH")
elif(cfg.init_privileged_mode == "SUPERVISOR_MODE"): # Supervisor Mode
self.include_reg.append("SSCRATCH")
else: # User Mode
self.include_reg.append("USCRATCH")
def get_rand_instr(self, include_instr=[], exclude_instr=[],
include_category=[], exclude_category=[],
include_group=[], exclude_group=[]):
idx = BitArray(uint = 0, length = 32)
name = ""
allowed_instr = []
disallowed_instr = []
# allowed_categories = []
for items in include_category:
allowed_instr.append(self.instr_category[items])
for items in exclude_category:
if(items in self.instr_category):
disallowed_instr.append(self.instr_category[items])
for items in include_group:
allowed_instr.append(self.instr_group[items])
for items in exclude_group:
if(items in self.instr_group):
disallowed_instr.append(self.instr_group[items])
disallowed_instr.extend(exclude_instr)
if(len(disallowed_instr) == 0):
if(len(include_instr) > 0):
idx = random.randrange(0, len(include_instr) - 1)
name = include_instr[idx]
elif(len(allowed_instr > 0)):
idx = random.randrange(0, len(allowed_instr) - 1)
name = allowed_instr[idx]
else:
idx = random.randrange(0, len(self.instr_names) - 1)
name = self.instr_names[idx]
else:
# TODO
instr_names_set = set(self.instr_names)
disallowed_instr_set = set(disallowed_instr)
allowed_instr_set = set(allowed_instr)
include_instr_set = set(include_instr)
excluded_instr_names_list = list(instr_names_set - disallowed_instr_set)
excluded_allowed_instr_list = list(allowed_instr_set - disallowed_instr_set)
include_instr_list = list(include_instr_set - disallowed_instr_set)
name = random.choice(excluded_instr_names_list)
if(len(include_instr) > 0):
name = random.choice(include_instr_list)
if(len(allowed_instr) > 0):
name = random.choice(excluded_allowed_instr_list)
if(name is None):
logging.critical("%s Cannot generate random instruction", riscv_instr.__name__)
sys.exit(1)
instr_h = copy(self.instr_template[name])
return instr_h
def get_load_store_instr(self, load_store_instr):
instr_h = riscv_instr()
if(len(load_store_instr) == 0):
load_store_instr = self.instr_category["LOAD"] + \
self.instr_category["STORE"]
self.idx = random.randrange(0, len(load_store_instr) - 1)
name = load_store_instr[self.idx]
instr_h = copy(self.instr_template[name])
return instr_h
def get_instr(self, name):
if (not self.instr_template.get(name)):
logging.critical("Cannot get instr %s", name)
instr_h = copy(self.instr_template[name])
return instr_h
def set_rand_mode(self):
# rand_mode setting for Instruction Format
if(self.format.name == "R_FORMAT"):
self.has_imm = 0
if(self.format.name == "I_FORMAT"):
self.has_rs2 = 0
if(self.format.name in ["S_FORMAT", "B_FORMAT"]):
self.has_rd = 0
if(self.format.name in ["U_FORMAT", "J_FORMAT"]):
self.has_rs1 = 0
self.has_rs2 = 0
# rand_mode setting for Instruction Category
if(self.category.name == "CSR"):
self.has_rs2 = 0
if(self.format.name == "I_FORMAT"):
self.has_rs1 = 0
def pre_randomize(self):
pass # TODO
def set_imm_len(self):
if(self.format.name in ["U_FORMAT", "J_FORMAT"]):
self.imm_len = 20
elif(self.format.name in ["I_FORMAT", "S_FORMAT", "B_FORMAT"]):
if(self.imm_type.name == "UIMM"):
self.imm_len = 5
else:
self.imm_len = 11
self.imm_mask = self.imm_mask << self.imm_len
def extend_imm(self):
sign = 0
self.imm = self.imm << (32 - self.imm_len)
# sign = imm[31]
sign = self.imm.bin[0:1:1]
self.imm = self.imm >> (32 - self.imm_len)
# Signed extension
if((sign and not(self.format == "U_FORMAT")) or (self.imm_type in ["UIMM", "NZUIMM"])):
self.imm = self.imm_mask | self.imm
def post_randomize(self):
self.extend_imm()
self.update_imm_str()
def convert2asm(self):
pass
def get_opcode(self):
if(self.instr_name.name == "LUI"):
return (BitArray(uint = 55, length = 7).bin)
elif(self.instr_name.name == "AUIPC"):
return (BitArray(uint = 23, length = 7).bin)
elif(self.instr_name.name == "JAL"):
return (BitArray(uint = 23, length = 7).bin)
elif(self.instr_name.name == "JALR"):
return (BitArray(uint = 111, length = 7).bin)
elif(self.instr_name.name in ["BEQ", "BNE", "BLT", "BGE", "BLTU", "BGEU"]):
return (BitArray(uint = 103, length = 7).bin)
elif(self.instr_name.name in ["LB", "LH", "LW", "LBU", "LHU", "LWU", "LD"]):
return (BitArray(uint = 99, length = 7).bin)
elif(self.instr_name.name in ["SB", "SH", "SW", "SD"]):
return (BitArray(uint = 35, length = 7).bin)
elif(self.instr_name.name in ["ADDI", "SLTI", "SLTIU", "XORI", "ORI", "ANDI",
"SLLI", "SRLI", "SRAI", "NOP"]):
return (BitArray(uint = 19, length = 7).bin)
elif(self.instr_name.name in ["ADD", "SUB", "SLL", "SLT", "SLTU", "XOR", "SRL",
"SRA", "OR", "AND", "MUL", "MULH", "MULHSU", "MULHU",
"DIV", "DIVU", "REM", "REMU"]):
return (BitArray(uint = 51, length = 7).bin)
elif(self.instr_name.name in ["ADDIW", "SLLIW", "SRLIW", "SRAIW"]):
return (BitArray(uint = 27, length = 7).bin)
elif(self.instr_name.name in ["MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM", "REMU"]):
return (BitArray(uint = 51, length = 7).bin)
elif(self.instr_name.name in ["FENCE", "FENCE_I"]):
return (BitArray(uint = 15, length = 7).bin)
elif(self.instr_name.name in ["ECALL", "EBREAK", "CSRRW", "CSRRS", "CSRRC", "CSRRWI",
"CSRRSI", "CSRRCI"]):
return (BitArray(uint = 115, length = 7).bin)
elif(self.instr_name.name in ["ADDW", "SUBW", "SLLW", "SRLW", "SRAW", "MULW", "DIVW",
"DIVUW", "REMW", "REMUW"]):
return (BitArray(uint = 59, length = 7).bin)
elif(self.instr_name.name in ["ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET", "WFI",
"SFENCE_VMA"]):
return (BitArray(uint = 115, length = 7).bin)
else:
logging.critical("Unsupported instruction %0s", self.instr_name.name)
sys.exit(1)
def get_func3(self):
if(self.instr_name.name in ["JALR", "BEQ", "LB", "SB", "ADDI", "NOP", "ADD", "SUB",
"FENCE", "ECALL", "EBREAK", "ADDIW", "ADDW", "SUBW", "MUL",
"MULW", "ECALL", "EBREAK", "URET", "SRET", "MRET", "DRET",
"WFI", "SFENCE_VMA"]):
return (BitArray(uint = 0, length = 3).bin)
elif(self.instr_name.name in ["BNE", "LH", "SH", "SLLI", "SLL", "FENCE_I", "CSRRW", "SLLIW",
"SLLW", "MULH"]):
return (BitArray(uint = 1, length = 3).bin)
elif(self.instr_name.name in ["LW", "SW", "SLTI", "SLT", "CSRRS", "MULHS"]):
return (BitArray(uint = 2, length = 3).bin)
elif(self.instr_name.name in ["SLTIU", "SLTU", "CSRRC", "LD", "SD", "MULHU"]):
return (BitArray(uint = 3, length = 3).bin)
elif(self.instr_name.name in ["BLT", "LBU", "XORI", "XOR", "DIV", "DIVW"]):
return (BitArray(uint = 4, length = 3).bin)
elif(self.instr_name.name in ["BGE", "LHU", "SRLI", "SRAI", "SRL", "SRA", "CSRRWI", "SRLIW",
"SRAIW", "SRLW",
"SRAW", "DIVU", "DIVUW"]):
return (BitArray(uint = 5, length = 3).bin)
elif(self.instr_name.name in ["BLTU", "ORI", "OR", "CSRRSI", "LWU", "REM", "REMW"]):
return (BitArray(uint = 6, length = 3).bin)
elif(self.instr_name.name in ["BGEU", "ANDI", "AND", "CSRRCI", "REMU", "REMUW"]):
return (BitArray(uint = 7, length = 3).bin)
else:
logging.critical("Unsupported instruction %0s", self.instr_name.name)
sys.exit(1)
def get_func7(self):
if(self.instr_name.name in ["SLLI", "SRLI", "ADD", "SLL", "SLT", "SLTU", "XOR",
"SRL", "OR", "AND", "FENCE", "FENCE_I", "SLLIW",
"SRLIW", "ADDW", "SLLW", "SRLW", "ECALL", "EBREAK", "URET"]):
return (BitArray(uint = 0, length = 7).bin)
elif(self.instr_name.name in ["SUB", "SRA", "SRAIW", "SUBW", "SRAW"]):
return (BitArray(uint = 32, length = 7).bin)
elif(self.instr_name.name in ["MUL", "MULH", "MULHSU", "MULHU", "DIV", "DIVU", "REM",
"REMU", "MULW", "DIVW", "DIVUW", "REMW", "REMUW"]):
return (BitArray(uint = 1, length = 7).bin)
elif(self.instr_name.name in ["SRET", "WFI"]):
return (BitArray(uint = 8, length = 7).bin)
elif(self.instr_name.name == "MRET"):
return (BitArray(uint = 24, length = 7).bin)
elif(self.instr_name.name == "DRET"):
return (BitArray(uint = 61, length = 7).bin)
elif(self.instr_name.name == "SFENCE_VMA"):
return (BitArray(uint = 9, length = 7).bin)
else:
logging.critical("Unsupported instruction %0s", self.instr_name.name)
sys.exit(1)
def convert2bin(self):
pass # TODO
def get_instr_name(self):
get_instr_name = self.instr_name.name
for i in get_instr_name:
if(i == "_"):
get_instr_name = get_instr_name.replace(i, ".")
return get_instr_name
def get_c_gpr(self, gpr):
return self.gpr
def get_imm(self):
return self.imm_str
def clear_unused_label(self):
if(self.has_label and not(self.is_branch_target) and self.is_local_numeric_label):
self.has_label = 0
def do_copy(self):
pass # TODO
def update_imm_str(self):
self.imm_str = str(self.imm)
riscv_instr_ins = riscv_instr()
cfg = riscv_instr_gen_config()

View file

@ -0,0 +1,141 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
from pygen_src.riscv_defines import DEFINE_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t, imm_t)
# LOAD instructions
DEFINE_INSTR(riscv_instr_name_t.LB, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LH, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LBU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LHU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32I, g=globals())
# STORE instructions
DEFINE_INSTR(riscv_instr_name_t.SB, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SH, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SW, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32I, g=globals())
# SHIFT intructions
DEFINE_INSTR(riscv_instr_name_t.SLL, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SLLI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRL, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRLI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRA, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRAI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV32I, g=globals())
# ARITHMETIC intructions
DEFINE_INSTR(riscv_instr_name_t.ADD, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.ADDI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.NOP, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SUB, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LUI, riscv_instr_format_t.U_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.AUIPC, riscv_instr_format_t.U_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
# LOGICAL instructions
DEFINE_INSTR(riscv_instr_name_t.XOR, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.XORI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.OR, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.ORI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.AND, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.ANDI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOGICAL, riscv_instr_group_t.RV32I, g=globals())
# COMPARE instructions
DEFINE_INSTR(riscv_instr_name_t.SLT, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SLTI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SLTU, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SLTIU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32I, g=globals())
# BRANCH instructions
DEFINE_INSTR(riscv_instr_name_t.BEQ, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.BNE, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.BLT, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.BGE, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.BLTU, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.BGEU, riscv_instr_format_t.B_FORMAT,
riscv_instr_category_t.BRANCH, riscv_instr_group_t.RV32I, g=globals())
# JUMP instructions
DEFINE_INSTR(riscv_instr_name_t.JAL, riscv_instr_format_t.J_FORMAT,
riscv_instr_category_t.JUMP, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.JALR, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.JUMP, riscv_instr_group_t.RV32I, g=globals())
# SYNCH instructions
DEFINE_INSTR(riscv_instr_name_t.FENCE, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.FENCE_I, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SFENCE_VMA, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SYNCH, riscv_instr_group_t.RV32I, g=globals())
# SYSTEM instructions
DEFINE_INSTR(riscv_instr_name_t.ECALL, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.EBREAK, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.URET, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRET, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.MRET, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.DRET, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SYSTEM, riscv_instr_group_t.RV32I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.WFI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.INTERRUPT, riscv_instr_group_t.RV32I, g=globals())
# CSR instructions
DEFINE_INSTR(riscv_instr_name_t.CSRRW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.CSRRS, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.CSRRC, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.CSRRWI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.CSRRSI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())
DEFINE_INSTR(riscv_instr_name_t.CSRRCI, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.CSR, riscv_instr_group_t.RV32I, imm_t.UIMM, g=globals())

View file

@ -0,0 +1,39 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
from pygen_src.riscv_instr_pkg import imm_t
from pygen_src.isa.riscv_instr import riscv_instr
def DEFINE_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=imm_t.IMM, g=globals()):
class_name = f"riscv_{instr_n.name}_instr"
def __init__(self):
riscv_instr.__init__(self)
self.instr_name = instr_n
self.format = instr_format
self.category = instr_category
self.group = instr_group
self.imm_type = imm_tp
self.set_imm_len()
self.set_rand_mode()
NewClass = type(class_name, (riscv_instr,), {
"__init__": __init__,
"valid": riscv_instr.register(instr_n)
})
g[class_name] = NewClass

View file

@ -0,0 +1,34 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
class riscv_instr_gen_config:
def __init__(self):
self.enable_floating_point = 1
self.disable_compressed_instr = 1
self.num_of_test = 3
self.no_fence = 1
self.enable_sfence = 0
self.reserved_regs = []
self.enable_illegal_csr_instruction = 0
self.enable_access_invalid_csr_level = 0
self.invalid_priv_mode_csrs = []
self.init_privileged_mode = "MACHINE_MODE"
self.no_ebreak = 1
self.no_dret = 1
self.no_csr_instr = 1
self.no_wfi = 1

View file

@ -0,0 +1,602 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
from enum import Enum, auto
class riscv_instr_name_t(Enum):
# RV32I instructions
LUI = 0
AUIPC = auto()
JAL = auto()
JALR = auto()
BEQ = auto()
BNE = auto()
BLT = auto()
BGE = auto()
BLTU = auto()
BGEU = auto()
LB = auto()
LH = auto()
LW = auto()
LBU = auto()
LHU = auto()
SB = auto()
SH = auto()
SW = auto()
ADDI = auto()
SLTI = auto()
SLTIU = auto()
XORI = auto()
ORI = auto()
ANDI = auto()
SLLI = auto()
SRLI = auto()
SRAI = auto()
ADD = auto()
SUB = auto()
SLL = auto()
SLT = auto()
SLTU = auto()
XOR = auto()
SRL = auto()
SRA = auto()
OR = auto()
AND = auto()
NOP = auto()
FENCE = auto()
FENCE_I = auto()
ECALL = auto()
EBREAK = auto()
CSRRW = auto()
CSRRS = auto()
CSRRC = auto()
CSRRWI = auto()
CSRRSI = auto()
CSRRCI = auto()
# RV32B instructions
ANDN = auto()
ORN = auto()
XNOR = auto()
GORC = auto()
SLO = auto()
SRO = auto()
ROL = auto()
ROR = auto()
SBCLR = auto()
SBSET = auto()
SBINV = auto()
SBEXT = auto()
GREV = auto()
SLOI = auto()
SROI = auto()
RORI = auto()
SBCLRI = auto()
SBSETI = auto()
SBINVI = auto()
SBEXTI = auto()
GORCI = auto()
GREVI = auto()
CMIX = auto()
CMOV = auto()
FSL = auto()
FSR = auto()
FSRI = auto()
CLZ = auto()
CTZ = auto()
PCNT = auto()
SEXT_B = auto()
SEXT_H = auto()
CRC32_B = auto()
CRC32_H = auto()
CRC32_W = auto()
CRC32C_B = auto()
CRC32C_H = auto()
CRC32C_W = auto()
CLMUL = auto()
CLMULR = auto()
CLMULH = auto()
MIN = auto()
MAX = auto()
MINU = auto()
MAXU = auto()
SHFL = auto()
UNSHFL = auto()
BDEP = auto()
BEXT = auto()
PACK = auto()
PACKU = auto()
BMATOR = auto()
BMATXOR = auto()
PACKH = auto()
BFP = auto()
SHFLI = auto()
UNSHFLI = auto()
# RV64B instructions
ADDIWU = auto()
SLLIU_W = auto()
ADDWU = auto()
SUBWU = auto()
BMATFLIP = auto()
CRC32_D = auto()
CRC32C_D = auto()
ADDU_W = auto()
SUBU_W = auto()
SLOW = auto()
SROW = auto()
ROLW = auto()
RORW = auto()
SBCLRW = auto()
SBSETW = auto()
SBINVW = auto()
SBEXTW = auto()
GORCW = auto()
GREVW = auto()
SLOIW = auto()
SROIW = auto()
RORIW = auto()
SBCLRIW = auto()
SBSETIW = auto()
SBINVIW = auto()
GORCIW = auto()
GREVIW = auto()
FSLW = auto()
FSRW = auto()
FSRIW = auto()
CLZW = auto()
CTZW = auto()
PCNTW = auto()
CLMULW = auto()
CLMULRW = auto()
CLMULHW = auto()
SHFLW = auto()
UNSHFLW = auto()
BDEPW = auto()
BEXTW = auto()
PACKW = auto()
PACKUW = auto()
BFPW = auto()
# RV32M instructions
MUL = auto()
MULH = auto()
MULHSU = auto()
MULHU = auto()
DIV = auto()
DIVU = auto()
REM = auto()
REMU = auto()
# RV64M instructions
MULW = auto()
DIVW = auto()
DIVUW = auto()
REMW = auto()
REMUW = auto()
# RV32F instructions
FLW = auto()
FSW = auto()
FMADD_S = auto()
FMSUB_S = auto()
FNMSUB_S = auto()
FNMADD_S = auto()
FADD_S = auto()
FSUB_S = auto()
FMUL_S = auto()
FDIV_S = auto()
FSQRT_S = auto()
FSGNJ_S = auto()
FSGNJN_S = auto()
FSGNJX_S = auto()
FMIN_S = auto()
FMAX_S = auto()
FCVT_W_S = auto()
FCVT_WU_S = auto()
FMV_X_W = auto()
FEQ_S = auto()
FLT_S = auto()
FLE_S = auto()
FCLASS_S = auto()
FCVT_S_W = auto()
FCVT_S_WU = auto()
FMV_W_X = auto()
# RV64F instruction
FCVT_L_S = auto()
FCVT_LU_S = auto()
FCVT_S_L = auto()
FCVT_S_LU = auto()
# RV32D instructions
FLD = auto()
FSD = auto()
FMADD_D = auto()
FMSUB_D = auto()
FNMSUB_D = auto()
FNMADD_D = auto()
FADD_D = auto()
FSUB_D = auto()
FMUL_D = auto()
FDIV_D = auto()
FSQRT_D = auto()
FSGNJ_D = auto()
FSGNJN_D = auto()
FSGNJX_D = auto()
FMIN_D = auto()
FMAX_D = auto()
FCVT_S_D = auto()
FCVT_D_S = auto()
FEQ_D = auto()
FLT_D = auto()
FLE_D = auto()
FCLASS_D = auto()
FCVT_W_D = auto()
FCVT_WU_D = auto()
FCVT_D_W = auto()
FCVT_D_WU = auto()
# RV64D
FCVT_L_D = auto()
FCVT_LU_D = auto()
FMV_X_D = auto()
FCVT_D_L = auto()
FCVT_D_LU = auto()
FMV_D_X = auto()
# RV64I
LWU = auto()
LD = auto()
SD = auto()
ADDIW = auto()
SLLIW = auto()
SRLIW = auto()
SRAIW = auto()
ADDW = auto()
SUBW = auto()
SLLW = auto()
SRLW = auto()
SRAW = auto()
# RV32C
C_LW = auto()
C_SW = auto()
C_LWSP = auto()
C_SWSP = auto()
C_ADDI4SPN = auto()
C_ADDI = auto()
C_LI = auto()
C_ADDI16SP = auto()
C_LUI = auto()
C_SRLI = auto()
C_SRAI = auto()
C_ANDI = auto()
C_SUB = auto()
C_XOR = auto()
C_OR = auto()
C_AND = auto()
C_BEQZ = auto()
C_BNEZ = auto()
C_SLLI = auto()
C_MV = auto()
C_EBREAK = auto()
C_ADD = auto()
C_NOP = auto()
C_J = auto()
C_JAL = auto()
C_JR = auto()
C_JALR = auto()
# RV64C
C_ADDIW = auto()
C_SUBW = auto()
C_ADDW = auto()
C_LD = auto()
C_SD = auto()
C_LDSP = auto()
C_SDSP = auto()
# RV128C
C_SRLI64 = auto()
C_SRAI64 = auto()
C_SLLI64 = auto()
C_LQ = auto()
C_SQ = auto()
C_LQSP = auto()
C_SQSP = auto()
# RV32FC
C_FLW = auto()
C_FSW = auto()
C_FLWSP = auto()
C_FSWSP = auto()
# RV32DC
C_FLD = auto()
C_FSD = auto()
C_FLDSP = auto()
C_FSDSP = auto()
# RV32A
LR_W = auto()
SC_W = auto()
AMOSWAP_W = auto()
AMOADD_W = auto()
AMOAND_W = auto()
AMOOR_W = auto()
AMOXOR_W = auto()
AMOMIN_W = auto()
AMOMAX_W = auto()
AMOMINU_W = auto()
AMOMAXU_W = auto()
# RV64A
LR_D = auto()
SC_D = auto()
AMOSWAP_D = auto()
AMOADD_D = auto()
AMOAND_D = auto()
AMOOR_D = auto()
AMOXOR_D = auto()
AMOMIN_D = auto()
AMOMAX_D = auto()
AMOMINU_D = auto()
AMOMAXU_D = auto()
# Vector instructions
VSETVL = auto()
VSETVLI = auto()
VADD = auto()
VSUB = auto()
VRSUB = auto()
VWADDU = auto()
VWSUBU = auto()
VWADD = auto()
VWSUB = auto()
VADC = auto()
VMADC = auto()
VSBC = auto()
VMSBC = auto()
VAND = auto()
VOR = auto()
VXOR = auto()
VSLL = auto()
VSRL = auto()
VSRA = auto()
VNSRL = auto()
VNSRA = auto()
VMSEQ = auto()
VMSNE = auto()
VMSLTU = auto()
VMSLT = auto()
VMSLEU = auto()
VMSLE = auto()
VMSGTU = auto()
VMSGT = auto()
VMINU = auto()
VMIN = auto()
VMAXU = auto()
VMAX = auto()
VMUL = auto()
VMULH = auto()
VMULHU = auto()
VMULHSU = auto()
VDIVU = auto()
VDIV = auto()
VREMU = auto()
VREM = auto()
VWMUL = auto()
VWMULU = auto()
VWMULSU = auto()
VMACC = auto()
VNMSAC = auto()
VMADD = auto()
VNMSUB = auto()
VWMACCU = auto()
VWMACC = auto()
VWMACCSU = auto()
VWMACCUS = auto()
'''
VQMACCU = auto()
VQMACC = auto()
VQMACCSU = auto()
VQMACCUS = auto()
'''
VMERGE = auto()
VMV = auto()
VSADDU = auto()
VSADD = auto()
VSSUBU = auto()
VSSUB = auto()
VAADDU = auto()
VAADD = auto()
VASUBU = auto()
VASUB = auto()
VSSRL = auto()
VSSRA = auto()
VNCLIPU = auto()
VNCLIP = auto()
VFADD = auto()
VFSUB = auto()
VFRSUB = auto()
VFMUL = auto()
VFDIV = auto()
VFRDIV = auto()
VFWMUL = auto()
VFMACC = auto()
VFNMACC = auto()
VFMSAC = auto()
VFNMSAC = auto()
VFMADD = auto()
VFNMADD = auto()
VFMSUB = auto()
VFNMSUB = auto()
VFWMACC = auto()
VFWNMACC = auto()
VFWMSAC = auto()
VFWNMSAC = auto()
VFSQRT_V = auto()
VFMIN = auto()
VFMAX = auto()
VFSGNJ = auto()
VFSGNJN = auto()
VFSGNJX = auto()
VMFEQ = auto()
VMFNE = auto()
VMFLT = auto()
VMFLE = auto()
VMFGT = auto()
VMFGE = auto()
VFCLASS_V = auto()
VFMERGE = auto()
VFMV = auto()
VFCVT_XU_F_V = auto()
VFCVT_X_F_V = auto()
VFCVT_F_XU_V = auto()
VFCVT_F_X_V = auto()
VFWCVT_XU_F_V = auto()
VFWCVT_X_F_V = auto()
VFWCVT_F_XU_V = auto()
VFWCVT_F_X_V = auto()
VFWCVT_F_F_V = auto()
VFNCVT_XU_F_W = auto()
VFNCVT_X_F_W = auto()
VFNCVT_F_XU_W = auto()
VFNCVT_F_X_W = auto()
VFNCVT_F_F_W = auto()
VFNCVT_ROD_F_F_W = auto()
# Vector reduction instruction
VREDSUM_VS = auto()
VREDMAXU_VS = auto()
VREDMAX_VS = auto()
VREDMINU_VS = auto()
VREDMIN_VS = auto()
VREDAND_VS = auto()
VREDOR_VS = auto()
VREDXOR_VS = auto()
VWREDSUMU_VS = auto()
VWREDSUM_VS = auto()
VFREDOSUM_VS = auto()
VFREDSUM_VS = auto()
VFREDMAX_VS = auto()
VFWREDOSUM_VS = auto()
VFWREDSUM_VS = auto()
# Vector mask instruction
VMAND_MM = auto()
VMNAND_MM = auto()
VMANDNOT_MM = auto()
VMXOR_MM = auto()
VMOR_MM = auto()
VMNOR_MM = auto()
VMORNOT_MM = auto()
VMXNOR_MM = auto()
VPOPC_M = auto()
VFIRST_M = auto()
VMSBF_M = auto()
VMSIF_M = auto()
VMSOF_M = auto()
VIOTA_M = auto()
VID_V = auto()
# Vector permutation instruction
VMV_X_S = auto()
VMV_S_X = auto()
VFMV_F_S = auto()
VFMV_S_F = auto()
VSLIDEUP = auto()
VSLIDEDOWN = auto()
VSLIDE1UP = auto()
VSLIDE1DOWN = auto()
VRGATHER = auto()
VCOMPRESS = auto()
VMV1R_V = auto()
VMV2R_V = auto()
VMV4R_V = auto()
VMV8R_V = auto()
# Supervisor instruction
DRET = auto()
MRET = auto()
URET = auto()
SRET = auto()
WFI = auto()
SFENCE_VMA = auto()
# Custom instructions
# import riscv_custom_instr_enum #TODO: Right now it's not working as expected fix it
# You can add other instructions here
INVALID_INSTR = auto()
class riscv_instr_format_t(Enum):
J_FORMAT = 0
U_FORMAT = auto()
I_FORMAT = auto()
B_FORMAT = auto()
R_FORMAT = auto()
S_FORMAT = auto()
R4_FORMAT = auto()
# Compressed instruction format
CI_FORMAT = auto()
CB_FORMAT = auto()
CJ_FORMAT = auto()
CR_FORMAT = auto()
CA_FORMAT = auto()
CL_FORMAT = auto()
CS_FORMAT = auto()
CSS_FORMAT = auto()
CIW_FORMAT = auto()
# Vector instruction format
VSET_FORMAT = auto()
VA_FORMAT = auto()
VS2_FORMAT = auto() # op vd,vs2
VL_FORMAT = auto()
VS_FORMAT = auto()
class riscv_instr_category_t(Enum):
LOAD = 0
STORE = auto()
SHIFT = auto()
ARITHMETIC = auto()
LOGICAL = auto()
COMPARE = auto()
BRANCH = auto()
JUMP = auto()
SYNCH = auto()
SYSTEM = auto()
COUNTER = auto()
CSR = auto()
CHANGELEVEL = auto()
TRAP = auto()
INTERRUPT = auto()
# `VECTOR_INCLUDE("riscv_instr_pkg_inc_riscv_instr_category_t.sv") TODO: Fix this
AMO = auto() # (last one)
class riscv_instr_group_t(Enum):
RV32I = 0
RV64I = auto()
RV32M = auto()
RV64M = auto()
RV32A = auto()
RV64A = auto()
RV32F = auto()
RV32FC = auto()
RV64F = auto()
RV32D = auto()
RV32DC = auto()
RV64D = auto()
RV32C = auto()
RV64C = auto()
RV128I = auto()
RV128C = auto()
RV32V = auto()
RV32B = auto()
RV64V = auto()
RV64B = auto()
RV32X = auto()
RV64X = auto()
class imm_t(Enum):
IMM = 0 # Signed immediate
UIMM = auto() # Unsigned immediate
NZUIMM = auto() # Non-zero unsigned immediate
NZIMM = auto() # Non-zero signed immediate

View file

@ -0,0 +1,29 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Regression script for RISC-V random instruction generator
"""
import sys
sys.path.append("../../")
from pygen_src.isa.rv32i_instr import * # NOQA
from pygen_src.isa.riscv_instr import cfg, riscv_instr_ins # NOQA
class riscv_instr_base_test:
def __init__(self):
pass
for _ in range(cfg.num_of_test):
riscv_instr_ins.create_instr_list(cfg)

View file

@ -6,3 +6,4 @@ sphinxcontrib-log-cabinet
sphinx-issues
sphinx_rtd_theme
rst2pdf
flake8

View file

@ -37,7 +37,7 @@ class riscv_floating_point_instr extends riscv_instr;
if (category == LOAD) begin
asm_str = $sformatf("%0s%0s, %0s(%0s)", asm_str, fd.name(), get_imm(), rs1.name());
end else if (instr_name inside {FMV_X_W, FMV_X_D, FCVT_W_S, FCVT_WU_S,
FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D, FCVT_LU_S,
FCVT_L_S, FCVT_LU_S, FCVT_L_D, FCVT_LU_D,
FCVT_W_D, FCVT_WU_D}) begin
asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), fs1.name());
end else if (instr_name inside {FMV_W_X, FMV_D_X, FCVT_S_W, FCVT_S_WU,
@ -158,7 +158,9 @@ class riscv_floating_point_instr extends riscv_instr;
end
case(format)
I_FORMAT: begin
`DV_CHECK_FATAL(operands.size() == 2)
// TODO ovpsim has an extra operand rte as below
// fcvt.d.s fs1,fs4,rte
//`DV_CHECK_FATAL(operands.size() == 2)
if (has_fs1) begin
fs1 = get_fpr(operands[1]);
fs1_value = get_gpr_state(operands[1]);
@ -177,6 +179,13 @@ class riscv_floating_point_instr extends riscv_instr;
get_val(operands[1], imm);
end
R_FORMAT: begin
// convert Pseudoinstructions for ovpsim
// fmv.s rd, rs -> fsgnj.s rd, rs, rs
if (operands.size() == 2 && instr_name inside {FSGNJ_S, FSGNJX_S, FSGNJN_S, FSGNJ_D,
FSGNJX_D, FSGNJN_D}) begin
operands.push_back(operands[$]);
end
if (has_fs2 || category == CSR) begin
`DV_CHECK_FATAL(operands.size() == 3)
end else begin
@ -205,7 +214,6 @@ class riscv_floating_point_instr extends riscv_instr;
endfunction : update_src_regs
virtual function void update_dst_regs(string reg_name, string val_str);
$display("update_dst_regs %0s", reg_name);
get_val(val_str, gpr_state[reg_name], .hex(1));
if (has_fd) begin
fd = get_fpr(reg_name);
@ -218,9 +226,59 @@ class riscv_floating_point_instr extends riscv_instr;
virtual function riscv_fpr_t get_fpr(input string str);
str = str.toupper();
if (!fpr_enum::from_name(str, get_fpr)) begin
if (!uvm_enum_wrapper#(riscv_fpr_t)::from_name(str, get_fpr)) begin
`uvm_fatal(`gfn, $sformatf("Cannot convert %0s to FPR", str))
end
endfunction : get_fpr
virtual function void pre_sample();
super.pre_sample();
// for single precision sign bit is bit 31, upper 32 bits are all 1s
// for double precision, it's 63
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);
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);
fd_sign = get_fp_operand_sign(fd_value, 31);
end else if (instr_name == FCVT_D_S) begin
fs1_sign = get_fp_operand_sign(fs1_value, 31);
fd_sign = get_fp_operand_sign(fd_value, 63);
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);
fd_sign = get_fp_operand_sign(fd_value, 63);
end
endfunction : pre_sample
virtual function operand_sign_e get_fp_operand_sign(bit [XLEN-1:0] value, int idx);
if (value[idx]) begin
return NEGATIVE;
end else begin
return POSITIVE;
end
endfunction
virtual function void check_hazard_condition(riscv_instr pre_instr);
riscv_floating_point_instr pre_fp_instr;
super.check_hazard_condition(pre_instr);
if ($cast(pre_fp_instr, pre_instr) && pre_fp_instr.has_fd) begin
if ((has_fs1 && (fs1 == pre_fp_instr.fd)) || (has_fs2 && (fs2 == pre_fp_instr.fd))
|| (has_fs3 && (fs3 == pre_fp_instr.fd))) begin
gpr_hazard = RAW_HAZARD;
end else if (has_fd && (fd == pre_fp_instr.fd)) begin
gpr_hazard = WAW_HAZARD;
end else if (has_fd && ((pre_fp_instr.has_fs1 && (pre_fp_instr.fs1 == fd)) ||
(pre_fp_instr.has_fs2 && (pre_fp_instr.fs2 == fd)) ||
(pre_fp_instr.has_fs3 && (pre_fp_instr.fs3 == fd)))) begin
gpr_hazard = WAR_HAZARD;
end else begin
gpr_hazard = NO_HAZARD;
end
end
endfunction
endclass

View file

@ -32,6 +32,8 @@ class riscv_instr extends uvm_object;
static privileged_reg_t exclude_reg[];
static privileged_reg_t include_reg[];
riscv_instr_gen_config m_cfg;
// Instruction attributes
riscv_instr_group_t group;
riscv_instr_format_t format;
@ -124,7 +126,9 @@ class riscv_instr extends uvm_object;
!(cfg.disable_compressed_instr &&
(instr_inst.group inside {RV32C, RV64C, RV32DC, RV32FC, RV128C})) &&
!(!cfg.enable_floating_point &&
(instr_inst.group inside {RV32F, RV64F, RV32D, RV64D}))
(instr_inst.group inside {RV32F, RV64F, RV32D, RV64D})) &&
!(!cfg.enable_vector_extension &&
(instr_inst.group inside {RVV}))
) begin
instr_category[instr_inst.category].push_back(instr_name);
instr_group[instr_inst.group].push_back(instr_name);

View file

@ -260,10 +260,6 @@
gpr_hazard.name(), lsu_hazard.name()), UVM_FULL)
endfunction
virtual function void sample_cov();
pre_sample();
endfunction
virtual function void update_src_regs(string operands[$]);
privileged_reg_t preg;
case(format)

View file

@ -1,5 +1,6 @@
/*
* Copyright 2020 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,6 +15,8 @@
* limitations under the License.
*/
// Base class for RISC-V vector exenstion ISA, implmented based on spec v0.8
class riscv_vector_instr extends riscv_floating_point_instr;
rand riscv_vreg_t vs1;
@ -21,14 +24,17 @@ class riscv_vector_instr extends riscv_floating_point_instr;
rand riscv_vreg_t vs3;
rand riscv_vreg_t vd;
rand va_variant_t va_variant;
rand bit vm;
rand bit wd;
bit has_vd = 1'b1;
bit has_vs1 = 1'b1;
bit has_vs2 = 1'b1;
bit has_vs3 = 1'b1;
bit has_vm = 1'b0;
bit has_va_variant;
bit is_widen_instr;
bit is_widening_instr;
bit is_narrowing_instr;
bit is_quad_widening_instr;
bit is_convert_instr;
va_variant_t allowed_va_variants[$];
@ -38,34 +44,132 @@ class riscv_vector_instr extends riscv_floating_point_instr;
}
}
// TODO: Handle different LMUL setting
// The destination vector register group cannot overlap a source vector
// register group of a different element width
constraint widen_instr_c {
int'(vd) % 2 == 0;
if (has_vs1) {
vs1 != vd;
vs1 != vd + 1;
}
if (has_vs2) {
vs2 != vd;
vs2 != vd + 1;
// Section 3.3.2: Vector Register Grouping (vlmul)
// Instructions specifying a vector operand with an odd-numbered vector register will raisean
// illegal instruction exception.
// TODO: Exclude the instruction that ignore VLMUL
constraint operand_group_c {
if (m_cfg.vector_cfg.vtype.vlmul > 0) {
vd % m_cfg.vector_cfg.vtype.vlmul == 0;
vs1 % m_cfg.vector_cfg.vtype.vlmul == 0;
vs2 % m_cfg.vector_cfg.vtype.vlmul == 0;
vs3 % m_cfg.vector_cfg.vtype.vlmul == 0;
}
}
// rs2 is double-width source register
// The destination vector register group cannot overlap the rst source
// vector register group (specied by vs2)
// Section 11.2: Widening Vector Arithmetic Instructions
constraint widening_instr_c {
if (is_widening_instr) {
// The destination vector register group results are arranged as if both
// SEW and LMUL were at twice their current settings.
vd % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
// The destination vector register group cannot overlap a source vector
// register group of a different element width (including the mask register if masked)
!(vs1 inside {[vd : vd + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
!(vs2 inside {[vd : vd + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
(vm == 0) -> (vd != 0);
// Double-width result, first source double-width, second source single-width
if (va_variant inside {WV, WX}) {
vs2 % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
}
}
}
// Section 11.3: Narrowing Vector Arithmetic Instructions
constraint narrowing_instr_c {
if (has_vs2) {
int'(vs2) % 2 == 0;
vd != vs2;
vd != vs2 + 1;
if (is_narrowing_instr) {
// The source and destination vector register numbers must be aligned
// appropriately for the vector registergroup size
vs2 % (m_cfg.vector_cfg.vtype.vlmul * 2) == 0;
// The destination vector register group cannot overlap the rst source
// vector register group (specied by vs2)
!(vd inside {[vs2 : vs2 + m_cfg.vector_cfg.vtype.vlmul * 2 - 1]});
// The destination vector register group cannot overlap the mask register
// if used, unless LMUL=1 (implemented in vmask_overlap_c)
}
}
// 12.3. Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
constraint add_sub_with_carry_c {
if (m_cfg.vector_cfg.vtype.vlmul > 1) {
// For vadc and vsbc, an illegal instruction exception is raised if the
// destination vector register is v0 and LMUL> 1
if (instr_name inside {VADC, VSBC}) {
vd != 0;
}
// For vmadc and vmsbc, an illegal instruction exception is raised if the
// destination vector register overlaps asource vector register group and LMUL > 1
if (instr_name inside {VMADC, VMSBC}) {
vd != vs2;
vd != vs1;
}
}
}
// 12.7. Vector Integer Comparison Instructions
// For all comparison instructions, an illegal instruction exception is raised if the
// destination vector register overlaps a source vector register group and LMUL > 1
constraint compare_instr_c {
if (category == COMPARE) {
vd != vs2;
vd != vs1;
}
}
// 16.8. Vector Iota Instruction
// An illegal instruction exception is raised if the destination vector register group
// overlaps the source vector mask register. If the instruction is masked, an illegal
// instruction exception is issued if the destination vector register group overlaps v0.
constraint vector_itoa_c {
if (instr_name == VIOTA_M) {
vd != vs2;
(vm == 0) -> (vd != 0);
}
}
// 16.9. Vector Element Index Instruction
// The vs2 eld of the instruction must be set to v0, otherwise the encoding is reserved
constraint vector_element_index_c {
if (instr_name == VID_V) {
vs2 == 0;
// TODO; Check if this constraint is needed
vd != vs2;
}
}
// Section 17.3 Vector Slide Instructions
// The destination vector register group for vslideup cannot overlap the vector register
// group of the source vector register group or the mask register
constraint vector_slide_c {
if (instr_name inside {VSLIDEUP, VSLIDE1UP, VSLIDEDOWN, VSLIDE1DOWN}) {
vd != vs2;
vd != vs1;
(vm == 0) -> (vd != 0);
}
}
// Section 17.4: Vector Register Gather Instruction
// For any vrgather instruction, the destination vector register group cannot overlap
// with the source vector register group
constraint vector_gather_c {
if (instr_name == VRGATHER) {
vd != vs2;
vd != vs1;
(vm == 0) -> (vd != 0);
}
}
// Section 17.5: Vector compress instruction
// The destination vector register group cannot overlap the source vector register
// group or the source vector mask register
constraint vector_compress_c {
if (instr_name == VCOMPRESS) {
vd != vs2;
vd != vs1;
(vm == 0) -> (vd != 0);
}
}
// The source and destination vector register numbers must be aligned
// appropriately for the vector registergroup size
constraint vmv_alignment_c {
if (instr_name == VMV2R_V) {
int'(vs2) % 2 == 0;
@ -81,9 +185,86 @@ class riscv_vector_instr extends riscv_floating_point_instr;
}
}
/////////////////// Vector mask constraint ///////////////////
// Section 5.3
// The destination vector register group for a masked vector instruction can only overlap
// the source mask register (v0) when LMUL=1
constraint vmask_overlap_c {
(vm == 0) && (m_cfg.vector_cfg.vtype.vlmul > 1) -> (vd != 0);
}
constraint vector_mask_enable_c {
// Below instruction is always masked
if (instr_name inside {VMERGE, VFMERGE, VADC, VSBC}) {
vm == 1'b0;
}
}
constraint vector_mask_disable_c {
// (vm=0) is reserved for below ops
if (instr_name inside {VMV, VFMV, VCOMPRESS, VFMV_F_S, VFMV_S_F, VMV_X_S, VMV_S_X,
VMV1R_V, VMV2R_V, VMV4R_V, VMV8R_V}) {
vm == 1'b1;
}
}
// 16.1. Vector Mask-Register Logical Instructions
// No vector mask for these instructions
constraint vector_mask_instr_c {
if (instr_name inside {[VMAND_MM : VMXNOR_MM]}) {
vm == 1'b1;
}
}
constraint disable_floating_point_varaint_c {
if (!m_cfg.vector_cfg.vec_fp) {
va_variant != VF;
}
}
// TODO: Check why this is needed?
constraint vector_load_store_mask_overlap_c {
if (category == STORE) {
(vm == 0) -> (vs3 != 0);
}
}
`uvm_object_utils(riscv_vector_instr)
`uvm_object_new
// Filter unsupported instructions based on configuration
virtual function bit is_supported(riscv_instr_gen_config cfg);
string name = instr_name.name();
// 19.2.2. Vector Add with Carry/Subtract with Borrow Reserved under EDIV>1
if ((cfg.vector_cfg.vtype.vediv > 1) &&
(instr_name inside {VADC, VSBC, VMADC, VMSBC})) begin
return 1'b0;
end
// Disable widening/narrowing instruction when LMUL == 8
if ((!cfg.vector_cfg.vec_narrowing_widening) &&
(is_widening_instr || is_narrowing_instr)) begin
return 1'b0;
end
if (!cfg.vector_cfg.vec_quad_widening && is_quad_widening_instr) begin
return 1'b0;
end
// TODO: Clean up this list, it's causing gcc compile error now
if (instr_name inside {VWMACCSU, VMERGE, VFMERGE, VMADC, VMSBC}) begin
return 1'b0;
end
// The standard vector floating-point instructions treat 16-bit, 32-bit, 64-bit,
// and 128-bit elements as IEEE-754/2008-compatible values. If the current SEW does
// not correspond to a supported IEEE floating-pointtype, an illegal instruction
// exception is raised
if (!cfg.vector_cfg.vec_fp) begin
if ((name.substr(0, 1) == "VF") || (name.substr(0, 2) == "VMF")) begin
return 1'b0;
end
end
return 1'b1;
endfunction
// Convert the instruction to assembly code
virtual function string convert2asm(string prefix = "");
string asm_str;
@ -148,17 +329,32 @@ class riscv_vector_instr extends riscv_floating_point_instr;
end
endcase
end
if (instr_name inside {VMADC, VADC, VSBC, VMSBC, VMERGE, VFMERGE}) begin
if (va_variant inside {VVM, VIM, VXM, VFM}) begin
asm_str = {asm_str, ",v0"};
end
end else begin
//asm_str = {asm_str, ",v0.t"};
end
end
end
default: `uvm_info(`gfn, $sformatf("Unsupported format %0s", format.name()), UVM_LOW)
VL_FORMAT: begin
asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vd.name(), rs1.name());
end
VS_FORMAT: begin
asm_str = $sformatf("%0s %s,(%s)", get_instr_name(), vs3.name(), rs1.name());
end
VLS_FORMAT: begin
asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), rs2.name());
end
VSS_FORMAT: begin
asm_str = $sformatf("%0s %0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), rs2.name());
end
VLV_FORMAT: begin
asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vd.name(), rs1.name(), vs2.name());
end
VSV_FORMAT: begin
asm_str = $sformatf("%0s,%0s,(%0s),%0s", get_instr_name(), vs3.name(), rs1.name(), vs2.name());
end
default: begin
`uvm_fatal(`gfn, $sformatf("Unsupported format %0s", format.name()))
end
endcase
// Add vector mask
asm_str = {asm_str, vec_vm_str()};
if(comment != "") begin
asm_str = {asm_str, " #",comment};
end
@ -183,10 +379,14 @@ class riscv_vector_instr extends riscv_floating_point_instr;
has_fs3 = 0;
has_fd = 0;
has_imm = 0;
if (name.substr(0, 1) == "VW") begin
is_widen_instr = 1'b1;
if ((name.substr(0, 1) == "VW") || (name.substr(0, 2) == "VFW")) begin
is_widening_instr = 1'b1;
end
if (name.substr(0, 1) == "VN") begin
if (name.substr(0, 2) == "VQW") begin
is_quad_widening_instr = 1'b1;
is_widening_instr = 1'b1;
end
if ((name.substr(0, 1) == "VN") || (name.substr(0, 2) == "VFN")) begin
is_narrowing_instr = 1'b1;
end
if (uvm_is_match("*CVT*", name)) begin
@ -204,4 +404,16 @@ class riscv_vector_instr extends riscv_floating_point_instr;
end
endfunction : set_rand_mode
virtual function string vec_vm_str();
if (vm) begin
return "";
end else begin
if (instr_name inside {VMERGE, VFMERGE, VADC, VSBC, VMADC, VMSBC}) begin
return ",v0";
end else begin
return ",v0.t";
end
end
endfunction
endclass : riscv_vector_instr

View file

@ -1,5 +1,6 @@
/*
* Copyright 2020 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -15,185 +16,237 @@
*/
// Vector CSR access instruction
`DEFINE_INSTR(VSETVLI, VSET_FORMAT, CSR, RV32V)
`DEFINE_INSTR(VSETVL, VSET_FORMAT, CSR, RV32V)
`DEFINE_INSTR(VSETVLI, VSET_FORMAT, CSR, RVV)
`DEFINE_INSTR(VSETVL, VSET_FORMAT, CSR, RVV)
// Vector integer arithmetic instruction
`DEFINE_VA_INSTR(VADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VRSUB, VA_FORMAT, ARITHMETIC, RV32V, {VX, VI})
`DEFINE_VA_INSTR(VWADDU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWSUBU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VADC, VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM})
`DEFINE_VA_INSTR(VMADC, VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM, VV, VX, VI})
`DEFINE_VA_INSTR(VSBC, VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM})
`DEFINE_VA_INSTR(VMSBC, VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VV, VX})
`DEFINE_VA_INSTR(VAND, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VOR, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VXOR, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSLL, VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSRL, VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSRA, VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VNSRL, VA_FORMAT, SHIFT, RV32V, {WV, WX, WI})
`DEFINE_VA_INSTR(VNSRA, VA_FORMAT, SHIFT, RV32V, {WV, WX, WI})
`DEFINE_VA_INSTR(VMSEQ, VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSNE, VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSLTU, VA_FORMAT, COMPARE, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMSLT, VA_FORMAT, COMPARE, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMSLEU, VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSLE, VA_FORMAT, COMPARE, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSGTU, VA_FORMAT, COMPARE, RV32V, {VX, VI})
`DEFINE_VA_INSTR(VMSGT, VA_FORMAT, COMPARE, RV32V, {VX, VI})
`DEFINE_VA_INSTR(VMINU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMIN, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMAXU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMAX, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMUL, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMULH, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMULHU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMULHSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VDIVU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VDIV, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VREMU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VREM, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMUL, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMULU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMULSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VNMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VMADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VNMSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMACCU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMACCSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VWMACCUS, VA_FORMAT, ARITHMETIC, RV32V, {VX})
/*
`DEFINE_VA_INSTR(VQMACCU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VQMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VQMACCSU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VQMACCUS, VA_FORMAT, ARITHMETIC, RV32V, {VX})
`DEFINE_VA_INSTR(VADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VRSUB, VA_FORMAT, ARITHMETIC, RVV, {VX, VI})
`DEFINE_VA_INSTR(VWADDU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWSUBU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VWSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, WV, WX})
`DEFINE_VA_INSTR(VADC, VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM})
`DEFINE_VA_INSTR(VMADC, VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM, VV, VX, VI})
`DEFINE_VA_INSTR(VSBC, VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM})
`DEFINE_VA_INSTR(VMSBC, VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VV, VX})
`DEFINE_VA_INSTR(VAND, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VOR, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VXOR, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSLL, VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSRL, VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSRA, VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VNSRL, VA_FORMAT, SHIFT, RVV, {WV, WX, WI})
`DEFINE_VA_INSTR(VNSRA, VA_FORMAT, SHIFT, RVV, {WV, WX, WI})
`DEFINE_VA_INSTR(VMSEQ, VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSNE, VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSLTU, VA_FORMAT, COMPARE, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMSLT, VA_FORMAT, COMPARE, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMSLEU, VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSLE, VA_FORMAT, COMPARE, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VMSGTU, VA_FORMAT, COMPARE, RVV, {VX, VI})
`DEFINE_VA_INSTR(VMSGT, VA_FORMAT, COMPARE, RVV, {VX, VI})
`DEFINE_VA_INSTR(VMINU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMIN, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMAXU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMAX, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMUL, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMULH, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMULHU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMULHSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VDIVU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VDIV, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VREMU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VREM, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMUL, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMULU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMULSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VNMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VMADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VNMSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMACCU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMACCSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VWMACCUS, VA_FORMAT, ARITHMETIC, RVV, {VX})
/* Quad widening is not yet supported
`DEFINE_VA_INSTR(VQMACCU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VQMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VQMACCSU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VQMACCUS, VA_FORMAT, ARITHMETIC, RVV, {VX})
*/
`DEFINE_VA_INSTR(VMERGE, VA_FORMAT, ARITHMETIC, RV32V, {VVM, VXM, VIM})
`DEFINE_VA_INSTR(VMV, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VMERGE, VA_FORMAT, ARITHMETIC, RVV, {VVM, VXM, VIM})
`DEFINE_VA_INSTR(VMV, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
// Vector Fixed-Point Arithmetic Instructions
`DEFINE_VA_INSTR(VSADDU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSSUBU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VSSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VAADDU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VAADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VASUBU, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VASUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VX})
`DEFINE_VA_INSTR(VSSRL, VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VSSRA, VA_FORMAT, SHIFT, RV32V, {VV, VX, VI})
`DEFINE_VA_INSTR(VNCLIPU, VA_FORMAT, ARITHMETIC, RV32V, {WV, WX, WI})
`DEFINE_VA_INSTR(VNCLIP, VA_FORMAT, ARITHMETIC, RV32V, {WV, WX, WI})
`DEFINE_VA_INSTR(VSADDU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSSUBU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VSSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VAADDU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VAADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VASUBU, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VASUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VX})
`DEFINE_VA_INSTR(VSSRL, VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VSSRA, VA_FORMAT, SHIFT, RVV, {VV, VX, VI})
`DEFINE_VA_INSTR(VNCLIPU, VA_FORMAT, ARITHMETIC, RVV, {WV, WX, WI})
`DEFINE_VA_INSTR(VNCLIP, VA_FORMAT, ARITHMETIC, RVV, {WV, WX, WI})
// Vector Floating-Point Instructions
`DEFINE_VA_INSTR(VFADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFRSUB, VA_FORMAT, ARITHMETIC, RV32V, {VF})
`DEFINE_VA_INSTR(VFMUL, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFDIV, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFRDIV, VA_FORMAT, ARITHMETIC, RV32V, {VF})
`DEFINE_VA_INSTR(VFWMUL, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFNMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFNMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFMADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFNMADD, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFMSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFNMSUB, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFWMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFWNMACC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFWMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFWNMSAC, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFSQRT_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFMIN, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFMAX, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJ, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJN, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJX, VA_FORMAT, ARITHMETIC, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VMFEQ, VA_FORMAT, COMPARE, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VMFNE, VA_FORMAT, COMPARE, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VMFLT, VA_FORMAT, COMPARE, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VMFLE, VA_FORMAT, COMPARE, RV32V, {VV, VF})
`DEFINE_VA_INSTR(VMFGT, VA_FORMAT, COMPARE, RV32V, {VF})
`DEFINE_VA_INSTR(VMFGE, VA_FORMAT, COMPARE, RV32V, {VF})
`DEFINE_VA_INSTR(VFCLASS_V,VS2_FORMAT, COMPARE, RV32V)
`DEFINE_VA_INSTR(VFMERGE, VA_FORMAT, ARITHMETIC, RV32V, {VFM})
`DEFINE_VA_INSTR(VFMV, VA_FORMAT, ARITHMETIC, RV32V, {VF})
`DEFINE_VA_INSTR(VFADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFRSUB, VA_FORMAT, ARITHMETIC, RVV, {VF})
`DEFINE_VA_INSTR(VFMUL, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFDIV, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFRDIV, VA_FORMAT, ARITHMETIC, RVV, {VF})
`DEFINE_VA_INSTR(VFWMUL, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFNMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFNMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFMADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFNMADD, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFMSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFNMSUB, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFWMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFWNMACC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFWMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFWNMSAC, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFSQRT_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFMIN, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFMAX, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJ, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJN, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VFSGNJX, VA_FORMAT, ARITHMETIC, RVV, {VV, VF})
`DEFINE_VA_INSTR(VMFEQ, VA_FORMAT, COMPARE, RVV, {VV, VF})
`DEFINE_VA_INSTR(VMFNE, VA_FORMAT, COMPARE, RVV, {VV, VF})
`DEFINE_VA_INSTR(VMFLT, VA_FORMAT, COMPARE, RVV, {VV, VF})
`DEFINE_VA_INSTR(VMFLE, VA_FORMAT, COMPARE, RVV, {VV, VF})
`DEFINE_VA_INSTR(VMFGT, VA_FORMAT, COMPARE, RVV, {VF})
`DEFINE_VA_INSTR(VMFGE, VA_FORMAT, COMPARE, RVV, {VF})
`DEFINE_VA_INSTR(VFCLASS_V,VS2_FORMAT, COMPARE, RVV)
`DEFINE_VA_INSTR(VFMERGE, VA_FORMAT, ARITHMETIC, RVV, {VFM})
`DEFINE_VA_INSTR(VFMV, VA_FORMAT, ARITHMETIC, RVV, {VF})
// Vector conversion instructions
`DEFINE_VA_INSTR(VFCVT_XU_F_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFCVT_X_F_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFCVT_F_XU_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFCVT_F_X_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWCVT_XU_F_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWCVT_X_F_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWCVT_F_XU_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWCVT_F_X_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWCVT_F_F_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_XU_F_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_X_F_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_F_XU_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_F_X_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_F_F_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFNCVT_ROD_F_F_W, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFCVT_XU_F_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFCVT_X_F_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFCVT_F_XU_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFCVT_F_X_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWCVT_XU_F_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWCVT_X_F_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWCVT_F_XU_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWCVT_F_X_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWCVT_F_F_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_XU_F_W, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_X_F_W, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_F_XU_W, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_F_X_W, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_F_F_W, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFNCVT_ROD_F_F_W, VS2_FORMAT, ARITHMETIC, RVV)
// Vector reduction instruction
`DEFINE_VA_INSTR(VREDSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDMAXU_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDMAX_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDMINU_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDMIN_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDAND_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDOR_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDXOR_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VWREDSUMU_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VWREDSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFREDOSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFREDSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFREDMAX_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWREDOSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFWREDSUM_VS, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VREDSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDMAXU_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDMAX_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDMINU_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDMIN_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDAND_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDOR_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VREDXOR_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VWREDSUMU_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VWREDSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFREDOSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFREDSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFREDMAX_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWREDOSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFWREDSUM_VS, VA_FORMAT, ARITHMETIC, RVV)
// Vector mask instruction
`DEFINE_VA_INSTR(VMAND_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMNAND_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMANDNOT_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMXOR_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMOR_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMNOR_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMORNOT_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMXNOR_MM, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMAND_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMNAND_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMANDNOT_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMXOR_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMOR_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMNOR_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMORNOT_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMXNOR_MM, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VPOPC_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFIRST_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMSBF_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMSIF_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMSOF_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VIOTA_M, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VID_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VPOPC_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFIRST_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMSBF_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMSIF_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMSOF_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VIOTA_M, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VID_V, VS2_FORMAT, ARITHMETIC, RVV)
// Vector permutation instruction
`DEFINE_VA_INSTR(VMV_X_S, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV_S_X, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFMV_F_S, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VFMV_S_F, VA_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV_X_S, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMV_S_X, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFMV_F_S, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VFMV_S_F, VA_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VSLIDEUP, VA_FORMAT, ARITHMETIC, RV32V, {VI,VX})
`DEFINE_VA_INSTR(VSLIDEDOWN, VA_FORMAT, ARITHMETIC, RV32V, {VI,VX})
`DEFINE_VA_INSTR(VSLIDE1UP, VA_FORMAT, ARITHMETIC, RV32V, {VX})
`DEFINE_VA_INSTR(VSLIDE1DOWN, VA_FORMAT, ARITHMETIC, RV32V, {VX})
`DEFINE_VA_INSTR(VRGATHER, VA_FORMAT, ARITHMETIC, RV32V, {VV,VX,VI})
`DEFINE_VA_INSTR(VCOMPRESS, VA_FORMAT, ARITHMETIC, RV32V, {VM})
`DEFINE_VA_INSTR(VSLIDEUP, VA_FORMAT, ARITHMETIC, RVV, {VI,VX})
`DEFINE_VA_INSTR(VSLIDEDOWN, VA_FORMAT, ARITHMETIC, RVV, {VI,VX})
`DEFINE_VA_INSTR(VSLIDE1UP, VA_FORMAT, ARITHMETIC, RVV, {VX})
`DEFINE_VA_INSTR(VSLIDE1DOWN, VA_FORMAT, ARITHMETIC, RVV, {VX})
`DEFINE_VA_INSTR(VRGATHER, VA_FORMAT, ARITHMETIC, RVV, {VV,VX,VI})
`DEFINE_VA_INSTR(VCOMPRESS, VA_FORMAT, ARITHMETIC, RVV, {VM})
`DEFINE_VA_INSTR(VMV1R_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV2R_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV4R_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV8R_V, VS2_FORMAT, ARITHMETIC, RV32V)
`DEFINE_VA_INSTR(VMV1R_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMV2R_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMV4R_V, VS2_FORMAT, ARITHMETIC, RVV)
`DEFINE_VA_INSTR(VMV8R_V, VS2_FORMAT, ARITHMETIC, RVV)
// -------------------------------------------------------------------------
// Section 7. Vector Loads and Stores
// -------------------------------------------------------------------------
// Section 7.4 - Vector Unit-Stride Instructions
`DEFINE_VA_INSTR(VLE_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSE_V, VS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VLB_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSB_V, VS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VLH_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSH_V, VS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VLW_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSW_V, VS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VLBU_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLHU_V, VS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLWU_V, VL_FORMAT, LOAD, RVV)
// Section 7.5 - Vector Strided Instructions
`DEFINE_VA_INSTR(VLSB_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSH_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSW_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSBU_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSHU_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSWU_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLSE_V, VLS_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSSB_V, VSS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSSH_V, VSS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSSW_V, VSS_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSSE_V, VSS_FORMAT, STORE, RVV)
// Section 7.6 - Vector Indexed Instructions
`DEFINE_VA_INSTR(VLXB_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXH_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXW_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXBU_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXHU_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXWU_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLXE_V, VLV_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VSXB_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSXH_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSXW_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSXE_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSUXB_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSUXH_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSUXW_V, VSV_FORMAT, STORE, RVV)
`DEFINE_VA_INSTR(VSUXE_V, VSV_FORMAT, STORE, RVV)
// Section 7.7 - Vector Unit-Stride Fault-Only-First Loads
`DEFINE_VA_INSTR(VLBFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLHFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLWFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLBUFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLHUFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLWUFF_V, VL_FORMAT, LOAD, RVV)
`DEFINE_VA_INSTR(VLEFF_V, VL_FORMAT, LOAD, RVV)

View file

@ -1,5 +1,6 @@
/*
* Copyright 2018 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -78,7 +79,7 @@ class riscv_asm_program_gen extends uvm_object;
gen_init_section(hart);
// 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
if (support_pmp && !cfg.bare_program_mode) begin
if (riscv_instr_pkg::support_pmp && !cfg.bare_program_mode) begin
gen_trap_handlers(hart);
// Ecall handler
gen_ecall_handler(hart);
@ -119,7 +120,7 @@ class riscv_asm_program_gen extends uvm_object;
instr_stream = {instr_stream, $sformatf("%sj test_done", indent)};
// Test done section
// If PMP isn't supported, generate this in the normal location
if (hart == 0 & !support_pmp) begin
if (hart == 0 & !riscv_instr_pkg::support_pmp) begin
gen_test_done();
end
// Shuffle the sub programs and insert to the instruction stream
@ -320,7 +321,8 @@ class riscv_asm_program_gen extends uvm_object;
if (cfg.disable_compressed_instr) begin
instr_stream.push_back(".option norvc;");
end
str = {"csrr x5, mhartid"};
str.push_back(".include \"user_init.s\"");
str.push_back("csrr x5, mhartid");
for (int hart = 0; hart < cfg.num_of_harts; hart++) begin
str = {str, $sformatf("li x6, %0d", hart),
$sformatf("beq x5, x6, %0df", hart)};
@ -411,19 +413,19 @@ class riscv_asm_program_gen extends uvm_object;
string str;
str = format_string(get_label("init:", hart), LABEL_STR_LEN);
instr_stream.push_back(str);
if (cfg.enable_floating_point) begin
init_floating_point_gpr();
end
init_gpr();
// Init stack pointer to point to the end of the user stack
str = {indent, $sformatf("la x%0d, %0suser_stack_end", cfg.sp, hart_prefix(hart))};
instr_stream.push_back(str);
if (cfg.enable_floating_point) begin
init_floating_point_gpr();
end
if (cfg.enable_vector_extension) begin
init_vector_engine();
randomize_vec_gpr_and_csr();
end
core_is_initialized();
gen_dummy_csr_write(); // TODO add a way to disable xStatus read
if (support_pmp) begin
if (riscv_instr_pkg::support_pmp) begin
str = {indent, "j main"};
instr_stream.push_back(str);
end
@ -446,7 +448,7 @@ class riscv_asm_program_gen extends uvm_object;
RV32B, RV64B : misa[MISA_EXT_B] = 1'b1;
RV32F, RV64F, RV32FC : misa[MISA_EXT_F] = 1'b1;
RV32D, RV64D, RV32DC : misa[MISA_EXT_D] = 1'b1;
RV32V, RV64V : misa[MISA_EXT_V] = 1'b1;
RVV : misa[MISA_EXT_V] = 1'b1;
RV32X, RV64X : misa[MISA_EXT_X] = 1'b1;
default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported",
supported_isa[i].name()))
@ -515,7 +517,7 @@ class riscv_asm_program_gen extends uvm_object;
string str;
bit [DATA_WIDTH-1:0] reg_val;
// Init general purpose registers with random values
for(int i = 0; i < 32; i++) begin
for(int i = 0; i < NUM_GPR; i++) begin
if (i inside {cfg.sp, cfg.tp}) continue;
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(reg_val,
reg_val dist {
@ -530,38 +532,132 @@ class riscv_asm_program_gen extends uvm_object;
end
endfunction
// Initialize vector general purpose registers
virtual function void init_vec_gpr();
int SEW;
int LMUL;
int EDIV = 1;
int len = (ELEN <= XLEN) ? ELEN : XLEN;
int num_elements = VLEN / len;
if (!(RVV inside {supported_isa})) return;
LMUL = 1;
SEW = (ELEN <= XLEN) ? ELEN : XLEN;
instr_stream.push_back($sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl));
// vec registers will be loaded from a scalar GPR, one element at a time
instr_stream.push_back($sformatf("%svsetvli x%0d, x%0d, e%0d, m%0d, d%0d",
indent, cfg.gpr[0], cfg.gpr[1], SEW, LMUL, EDIV));
instr_stream.push_back("vec_reg_init:");
for (int v = 1; v < NUM_VEC_GPR; v++) begin
for (int e = 0; e < num_elements; e++) begin
if (e > 0) instr_stream.push_back($sformatf("%0svmv.v.v v0, v%0d", indent, v));
instr_stream.push_back($sformatf("%0sli x%0d, 0x%0x",
indent, cfg.gpr[0], $urandom_range(0, 2 ** SEW - 1)));
instr_stream.push_back($sformatf("%0svslide1up.vx v%0d, v0, t0", indent, v));
end
end
endfunction
// Initialize floating point general purpose registers
virtual function void init_floating_point_gpr();
int int_gpr;
string str;
// TODO: Initialize floating point GPR with more interesting numbers
for(int i = 0; i < 32; i++) begin
int_gpr = $urandom_range(0, 31);
// Use a random integer GPR to initialize floating point GPR
if (RV64F inside {supported_isa}) begin
str = $sformatf("%0sfcvt.d.l f%0d, x%0d", indent, i, int_gpr);
end else begin
str = $sformatf("%0sfcvt.s.w f%0d, x%0d", indent, i, int_gpr);
end
instr_stream.push_back(str);
for(int i = 0; i < NUM_FLOAT_GPR; i++) begin
randcase
1: init_floating_point_gpr_with_spf(i);
RV64D inside {supported_isa}: init_floating_point_gpr_with_dpf(i);
endcase
end
// Initialize rounding mode of FCSR
str = $sformatf("%0sfsrmi %0d", indent, cfg.fcsr_rm);
instr_stream.push_back(str);
endfunction
// Initialize vector registers
virtual function void init_vector_engine();
string str[$];
// Initialize vtype, vl
str = {str, $sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl),
$sformatf("vsetvli x%0d, x%0d, e%0d",
cfg.gpr[0], cfg.gpr[1], 8 * (2 ** cfg.vector_cfg.vtype.vsew))};
for(int i = 0; i < 32; i++) begin
// Use integer register to initialize vector register
str = {str, $sformatf("vmv.v.x v%0d, x%0d", i, i)};
// get instructions initialize floating_point_gpr with single precision floating value
virtual function void init_floating_point_gpr_with_spf(int int_floating_gpr);
string str;
bit [31:0] imm = get_rand_spf_value();
int int_gpr = $urandom_range(0, NUM_GPR - 1);
str = $sformatf("%0sli x%0d, %0d", indent, int_gpr, imm);
instr_stream.push_back(str);
str = $sformatf("%0sfmv.w.x f%0d, x%0d", indent, int_floating_gpr, int_gpr);
instr_stream.push_back(str);
endfunction
// get instructions initialize floating_point_gpr with double precision floating value
virtual function void init_floating_point_gpr_with_dpf(int int_floating_gpr);
string str;
bit [63:0] imm = get_rand_dpf_value();
int int_gpr1 = $urandom_range(1, NUM_GPR - 1);
int int_gpr2 = $urandom_range(1, NUM_GPR - 1);
str = $sformatf("%0sli x%0d, %0d", indent, int_gpr1, imm[63:32]);
instr_stream.push_back(str);
// shift to upper 32bits
repeat (2) begin
str = $sformatf("%0sslli x%0d, x%0d, 16", indent, int_gpr1, int_gpr1);
instr_stream.push_back(str);
end
instr_stream = {instr_stream, str};
str = $sformatf("%0sli x%0d, %0d", indent, int_gpr2, imm[31:0]);
instr_stream.push_back(str);
str = $sformatf("%0sor x%0d, x%0d, x%0d", indent, int_gpr2, int_gpr2, int_gpr1);
instr_stream.push_back(str);
str = $sformatf("%0sfmv.d.x f%0d, x%0d", indent, int_floating_gpr, int_gpr2);
instr_stream.push_back(str);
endfunction
// get a random single precision floating value
virtual function bit [XLEN-1:0] get_rand_spf_value();
bit [31:0] value;
randcase
// infinity
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {32'h7f80_0000, 32'hff80_0000};)
// largest
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {32'h7f7f_ffff, 32'hff7f_ffff};)
// zero
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {32'h0000_0000, 32'h8000_0000};)
// NaN
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {32'h7f80_0001, 32'h7fc0_0000};)
// normal
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value[30:SINGLE_PRECISION_FRACTION_BITS] > 0;)
// subnormal
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value[30:SINGLE_PRECISION_FRACTION_BITS] == 0;)
endcase
return value;
endfunction
// get a random double precision floating value
virtual function bit [XLEN-1:0] get_rand_dpf_value();
bit [63:0] value;
randcase
// infinity
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {64'h7ff0_0000_0000_0000, 64'hfff0_0000_0000_0000};)
// largest
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {64'h7fef_ffff_ffff_ffff, 64'hffef_ffff_ffff_ffff};)
// zero
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {64'h0000_0000_0000_0000, 64'h8000_0000_0000_0000};)
// NaN
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value inside {64'h7ff0_0000_0000_0001, 64'h7ff8_0000_0000_0000};)
// normal
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value[62:DOUBLE_PRECISION_FRACTION_BITS] > 0;)
// subnormal
1: `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(value,
value[62:DOUBLE_PRECISION_FRACTION_BITS] == 0;)
endcase
return value;
endfunction
// Generate "test_done" section, test is finished by an ECALL instruction
@ -795,7 +891,7 @@ class riscv_asm_program_gen extends uvm_object;
virtual function void gen_all_trap_handler(int hart);
string instr[$];
// If PMP isn't supported, generate the relevant trap handler sections as per usual
if (!support_pmp) begin
if (!riscv_instr_pkg::support_pmp) begin
gen_trap_handlers(hart);
// Ecall handler
gen_ecall_handler(hart);
@ -1450,4 +1546,25 @@ class riscv_asm_program_gen extends uvm_object;
instr_stream = {instr_stream, debug_rom.instr_stream};
endfunction
//---------------------------------------------------------------------------------------
// Vector extension generation
//---------------------------------------------------------------------------------------
virtual function void randomize_vec_gpr_and_csr();
if (!(RVV inside {supported_isa})) return;
instr_stream.push_back({indent, $sformatf("li x%0d, %0d", cfg.gpr[0], cfg.vector_cfg.vxsat)});
instr_stream.push_back({indent, $sformatf("csrw vxsat, x%0d", cfg.gpr[0])});
instr_stream.push_back({indent, $sformatf("li x%0d, %0d", cfg.gpr[0], cfg.vector_cfg.vxrm)});
instr_stream.push_back({indent, $sformatf("csrw vxrm, x%0d", cfg.gpr[0])});
init_vec_gpr(); // GPR init uses a temporary SEW/LMUL setting before the final value set below.
instr_stream.push_back($sformatf("li x%0d, %0d", cfg.gpr[1], cfg.vector_cfg.vl));
instr_stream.push_back($sformatf("%svsetvli x%0d, x%0d, e%0d, m%0d, d%0d",
indent,
cfg.gpr[0],
cfg.gpr[1],
cfg.vector_cfg.vtype.vsew,
cfg.vector_cfg.vtype.vlmul,
cfg.vector_cfg.vtype.vediv));
endfunction
endclass

View file

@ -192,9 +192,9 @@ class riscv_jump_instr extends riscv_directed_instr_stream;
instr_list[i].atomic = 1'b1;
end
jump.has_label = 1'b1;
jump.label = "1";
jump.label = $sformatf("%0s_j%0d", label, idx);
jump.comment = $sformatf("jump %0s -> %0s", label, target_program_label);
branch.imm_str = "1f";
branch.imm_str = jump.label;
branch.comment = "branch to jump instr";
branch.branch_assigned = 1'b1;
endfunction

View file

@ -228,17 +228,62 @@
`INSTR_CG_BEGIN(INSTR_NAME) \
cp_imm_sign : coverpoint instr.imm_sign;
// TODO, will handle special value later
// single-precision floating point special values coverpoint
`define FP_SPECIAL_VALUES_CP(VAR, NAME) \
cp_fp_special_values_on_``NAME`` : coverpoint VAR { \
// single/double precision floating point special values coverpoint
`define FP_SPECIAL_VALUES_CP(VAR, NAME, PRECISION = S) \
cp_sfp_special_values_on_``NAME`` : coverpoint VAR[31:0] { \
option.weight = (`"PRECISION`" == "S"); \
type_option.weight = (`"PRECISION`" == "S"); \
bins infinity[] = {32'h7f80_0000, 32'hff80_0000}; \
bins largest[] = {32'h7f7f_ffff, 32'hff7f_ffff}; \
bins zeros[] = {32'h0000_0000, 32'h1000_0000}; \
bins NaN[] = {32'h7fc0_0000, 32'h7f80_0000}; \
bins zeros[] = {32'h0000_0000, 32'h8000_0000}; \
bins NaN[] = {32'h7f80_0001, 32'h7fc0_0000}; \
} \
cp_sfp_subnormal_on_``NAME`` : coverpoint VAR[30:SINGLE_PRECISION_FRACTION_BITS] == 0 { \
option.weight = (`"PRECISION`" == "S"); \
type_option.weight = (`"PRECISION`" == "S"); \
} \
cp_dfp_special_values_on_``NAME`` : coverpoint VAR { \
option.weight = (`"PRECISION`" == "D"); \
type_option.weight = (`"PRECISION`" == "D"); \
bins infinity[] = {64'h7ff0_0000_0000_0000, 64'hfff0_0000_0000_0000}; \
bins largest[] = {64'h7fef_ffff_ffff_ffff, 64'hffef_ffff_ffff_ffff}; \
bins zeros[] = {64'h0000_0000_0000_0000, 64'h8000_0000_0000_0000}; \
bins NaN[] = {64'h7ff0_0000_0000_0001, 64'h7ff8_0000_0000_0000}; \
} \
cp_dfp_subnormal_on_``NAME`` : coverpoint VAR[62:DOUBLE_PRECISION_FRACTION_BITS-1] == 0 { \
option.weight = (`"PRECISION`" == "D"); \
type_option.weight = (`"PRECISION`" == "D"); \
}
`define FP_R_INSTR_CG_BEGIN(INSTR_NAME) \
`define FP_LOAD_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_rs1 : coverpoint instr.rs1 { \
`DV(ignore_bins zero = {ZERO};) \
} \
cp_fd : coverpoint instr.fd; \
cp_imm_sign : coverpoint instr.imm_sign; \
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard { \
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
})
`define FP_STORE_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_rs1 : coverpoint instr.rs1 { \
`DV(ignore_bins zero = {ZERO};) \
} \
cp_fs2 : coverpoint instr.fs2; \
cp_imm_sign : coverpoint instr.imm_sign; \
`FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard { \
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD}; \
}) \
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard { \
bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD}; \
})
`define FP_R_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_fs2 : coverpoint instr.fs2; \
@ -246,9 +291,12 @@
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fs2_sign : coverpoint instr.fs2_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define FP_R4_INSTR_CG_BEGIN(INSTR_NAME) \
`define FP_R4_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_fs2 : coverpoint instr.fs2; \
@ -259,14 +307,74 @@
cp_fs3_sign : coverpoint instr.fs3_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fs3_sign, cp_fd_sign; \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fs3_value, fs3_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define FSQRT_INSTR_CG_BEGIN(INSTR_NAME) \
`define FSQRT_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_fd : coverpoint instr.fd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
// FCVT integer to floating
`define FP_I2F_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S, SIGN_TYP = SIGN) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_rs1 : coverpoint instr.rs1; \
cp_fd : coverpoint instr.fd; \
cp_rs1_sign : coverpoint instr.rs1_sign { \
option.weight = (`"SIGN_TYP`" == "SIGN"); \
type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
} \
cp_fd_sign : coverpoint instr.fd_sign { \
option.weight = (`"SIGN_TYP`" == "SIGN"); \
type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
} \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
// FCVT floating to integer
`define FP_F2I_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S, SIGN_TYP = SIGN) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_rd : coverpoint instr.rd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_rd_sign : coverpoint instr.rd_sign { \
option.weight = (`"SIGN_TYP`" == "SIGN"); \
type_option.weight = (`"SIGN_TYP`" == "SIGN"); \
} \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
// floating compare instructions
`define FP_CMP_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_fs2 : coverpoint instr.fs2; \
cp_rd : coverpoint instr.rd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fs2_sign : coverpoint instr.fs2_sign; \
`CP_VALUE_RANGE(compare_result, instr.rd_value, 0, 1) \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`FP_SPECIAL_VALUES_CP(instr.fs2_value, fs2_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define FCLASS_INSTR_CG_BEGIN(INSTR_NAME, PRECISION = S) \
`INSTR_CG_BEGIN(INSTR_NAME, riscv_floating_point_instr) \
cp_fs1 : coverpoint instr.fs1; \
cp_rd : coverpoint instr.rd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_rd_value : coverpoint instr.rd_value { \
bins values[] = {0, 'b1, 'b10, 'b100, 'b1000, 'b1_0000, 'b10_0000, \
'b100_0000, 'b1000_0000, 'b1_0000_0000, 'b10_0000_0000}; \
illegal_bins others = default; \
} \
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, PRECISION) \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define B_I_INSTR_CG_BEGIN(INSTR_NAME) \
@ -317,7 +425,6 @@
class riscv_instr_cover_group;
riscv_instr_gen_config cfg;
riscv_instr cur_instr;
riscv_instr pre_instr;
riscv_instr_name_t instr_list[$];
int unsigned instr_cnt;
@ -537,72 +644,219 @@ class riscv_instr_cover_group;
`CG_END
// floating instructions
`INSTR_CG_BEGIN(flw, riscv_floating_point_instr)
cp_rs1 : coverpoint instr.rs1 {
`DV(ignore_bins zero = {ZERO};)
}
cp_fd : coverpoint instr.fd;
cp_imm_sign : coverpoint instr.imm_sign;
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard {
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
})
`FP_LOAD_INSTR_CG_BEGIN(flw)
`CG_END
`INSTR_CG_BEGIN(fsw, riscv_floating_point_instr)
cp_rs1 : coverpoint instr.rs1 {
`DV(ignore_bins zero = {ZERO};)
}
cp_fs2 : coverpoint instr.fs2;
cp_imm_sign : coverpoint instr.imm_sign;
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard {
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
})
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard {
bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD};
})
`FP_LOAD_INSTR_CG_BEGIN(fld, D)
`CG_END
`FP_STORE_INSTR_CG_BEGIN(fsw)
`CG_END
`FP_STORE_INSTR_CG_BEGIN(fsd, D)
`CG_END
`FP_R_INSTR_CG_BEGIN(fadd_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fadd_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fsub_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fsub_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmul_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmul_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fdiv_s)
cp_div_result: coverpoint instr.div_result;
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fdiv_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FSQRT_INSTR_CG_BEGIN(fsqrt_s)
`CG_END
`FSQRT_INSTR_CG_BEGIN(fsqrt_d, D)
`CG_END
`FP_R_INSTR_CG_BEGIN(fmin_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmin_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmax_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmax_d, D)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmadd_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmadd_d, D)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmadd_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmadd_d, D)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmsub_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmsub_d, D)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmsub_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmsub_d, D)
`CG_END
// FCVT floating to floating
`INSTR_CG_BEGIN(fcvt_s_d, riscv_floating_point_instr)
cp_fs1 : coverpoint instr.fs1;
cp_fd : coverpoint instr.fd;
cp_fs1_sign : coverpoint instr.fs1_sign;
cp_fd_sign : coverpoint instr.fd_sign;
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, D)
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, S)
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
`CG_END
`INSTR_CG_BEGIN(fcvt_d_s, riscv_floating_point_instr)
cp_fs1 : coverpoint instr.fs1;
cp_fd : coverpoint instr.fd;
cp_fs1_sign : coverpoint instr.fs1_sign;
cp_fd_sign : coverpoint instr.fd_sign;
`FP_SPECIAL_VALUES_CP(instr.fs1_value, fs1_value, S)
`FP_SPECIAL_VALUES_CP(instr.fd_value, fd_value, D)
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_w_s)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_wu_s, , UNSIGN)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_l_s)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_lu_s, UNSIGN)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_l_d, D)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_lu_d, D, UNSIGN)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_w_d, D)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fcvt_wu_d, D, UNSIGN)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_s_w)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_s_wu, , UNSIGN)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_s_l)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_d_l, D)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_s_lu, , UNSIGN)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_d_w, D)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_d_lu, D, UNSIGN)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fcvt_d_wu, D, UNSIGN)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnj_s)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnj_d, D)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnjn_s)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnjn_d, D)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnjx_s)
`CG_END
`FP_R_INSTR_CG_BEGIN(fsgnjx_d, D)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fmv_x_w)
`CG_END
`FP_F2I_INSTR_CG_BEGIN(fmv_x_d, D)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fmv_w_x)
`CG_END
`FP_I2F_INSTR_CG_BEGIN(fmv_d_x, D)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(feq_s)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(feq_d, D)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(flt_s)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(flt_d, D)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(fle_s)
`CG_END
`FP_CMP_INSTR_CG_BEGIN(fle_d, D)
`CG_END
`FCLASS_INSTR_CG_BEGIN(fclass_s)
`CG_END
`FCLASS_INSTR_CG_BEGIN(fclass_d, D)
`CG_END
// B extension
// Count Leading/Trailing Zeros (clz, ctz)
`B_R_INSTR_NO_RS2_CG_BEGIN(clz)
@ -1462,8 +1716,6 @@ class riscv_instr_cover_group;
function new(riscv_instr_gen_config cfg);
string opts;
this.cfg = cfg;
cur_instr = riscv_instr::type_id::create("cur_instr");
pre_instr = riscv_instr::type_id::create("pre_instr");
build_instr_list();
`ifdef COMPLIANCE_MODE
compliance_mode = 1;
@ -1659,6 +1911,64 @@ class riscv_instr_cover_group;
fnmadd_s_cg = new();
fmsub_s_cg = new();
fnmsub_s_cg = new();
fcvt_w_s_cg = new();
fcvt_wu_s_cg = new();
fcvt_s_w_cg = new();
fcvt_s_wu_cg = new();
fsgnj_s_cg = new();
fsgnjn_s_cg = new();
fsgnjx_s_cg = new();
fmv_x_w_cg = new();
fmv_w_x_cg = new();
feq_s_cg = new();
flt_s_cg = new();
fle_s_cg = new();
fclass_s_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV32D)
fld_cg = new();
fsd_cg = new();
fadd_d_cg = new();
fsub_d_cg = new();
fdiv_d_cg = new();
fmul_d_cg = new();
fmadd_d_cg = new();
fnmadd_d_cg = new();
fmsub_d_cg = new();
fnmsub_d_cg = new();
fsqrt_d_cg = new();
fmin_d_cg = new();
fmax_d_cg = new();
fsgnj_d_cg = new();
fsgnjn_d_cg = new();
fsgnjx_d_cg = new();
feq_d_cg = new();
flt_d_cg = new();
fle_d_cg = new();
fcvt_w_d_cg = new();
fcvt_wu_d_cg = new();
fcvt_d_w_cg = new();
fcvt_d_wu_cg = new();
fclass_d_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV64F)
fcvt_l_s_cg = new();
fcvt_lu_s_cg = new();
fcvt_s_l_cg = new();
fcvt_s_lu_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV64D)
fmv_x_d_cg = new();
fmv_d_x_cg = new();
fcvt_d_s_cg = new();
fcvt_s_d_cg = new();
fcvt_l_d_cg = new();
fcvt_lu_d_cg = new();
fcvt_d_l_cg = new();
fcvt_d_lu_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV32B)
@ -1913,18 +2223,67 @@ class riscv_instr_cover_group;
C_ADDW : `SAMPLE(c_addw_cg, instr)
C_ADDIW : `SAMPLE(c_addiw_cg, instr)
FLW : `SAMPLE_F(flw_cg, instr)
FLD : `SAMPLE_F(fld_cg, instr)
FSW : `SAMPLE_F(fsw_cg, instr)
FSD : `SAMPLE_F(fsd_cg, instr)
FADD_S : `SAMPLE_F(fadd_s_cg, instr)
FADD_D : `SAMPLE_F(fadd_d_cg, instr)
FSUB_S : `SAMPLE_F(fsub_s_cg, instr)
FSUB_D : `SAMPLE_F(fsub_d_cg, instr)
FMUL_S : `SAMPLE_F(fmul_s_cg, instr)
FMUL_D : `SAMPLE_F(fmul_d_cg, instr)
FDIV_S : `SAMPLE_F(fdiv_s_cg, instr)
FDIV_D : `SAMPLE_F(fdiv_d_cg, instr)
FSQRT_S : `SAMPLE_F(fsqrt_s_cg, instr)
FSQRT_D : `SAMPLE_F(fsqrt_d_cg, instr)
FMIN_S : `SAMPLE_F(fmin_s_cg, instr)
FMIN_D : `SAMPLE_F(fmin_d_cg, instr)
FMAX_S : `SAMPLE_F(fmax_s_cg, instr)
FMAX_D : `SAMPLE_F(fmax_d_cg, instr)
FMADD_S : `SAMPLE_F(fmadd_s_cg, instr)
FMADD_D : `SAMPLE_F(fmadd_d_cg, instr)
FNMADD_S : `SAMPLE_F(fnmadd_s_cg, instr)
FNMADD_D : `SAMPLE_F(fnmadd_d_cg, instr)
FMSUB_S : `SAMPLE_F(fmsub_s_cg, instr)
FMSUB_D : `SAMPLE_F(fmsub_d_cg, instr)
FNMSUB_S : `SAMPLE_F(fnmsub_s_cg, instr)
FNMSUB_D : `SAMPLE_F(fnmsub_d_cg, instr)
FCVT_W_S : `SAMPLE_F(fcvt_w_s_cg, instr)
FCVT_WU_S : `SAMPLE_F(fcvt_wu_s_cg, instr)
FCVT_L_S : `SAMPLE_F(fcvt_l_s_cg, instr)
FCVT_LU_S : `SAMPLE_F(fcvt_lu_s_cg, instr)
FCVT_L_D : `SAMPLE_F(fcvt_l_d_cg, instr)
FCVT_LU_D : `SAMPLE_F(fcvt_lu_d_cg, instr)
FCVT_S_D : `SAMPLE_F(fcvt_s_d_cg, instr)
FCVT_D_S : `SAMPLE_F(fcvt_d_s_cg, instr)
FCVT_W_D : `SAMPLE_F(fcvt_w_d_cg, instr)
FCVT_WU_D : `SAMPLE_F(fcvt_wu_d_cg, instr)
FCVT_S_W : `SAMPLE_F(fcvt_s_w_cg, instr)
FCVT_S_WU : `SAMPLE_F(fcvt_s_wu_cg, instr)
FCVT_S_L : `SAMPLE_F(fcvt_s_l_cg, instr)
FCVT_D_L : `SAMPLE_F(fcvt_d_l_cg, instr)
FCVT_S_LU : `SAMPLE_F(fcvt_s_lu_cg, instr)
FCVT_D_W : `SAMPLE_F(fcvt_d_w_cg, instr)
FCVT_D_LU : `SAMPLE_F(fcvt_d_lu_cg, instr)
FCVT_D_WU : `SAMPLE_F(fcvt_d_wu_cg, instr)
FSGNJ_S : `SAMPLE_F(fsgnj_s_cg, instr)
FSGNJ_D : `SAMPLE_F(fsgnj_d_cg, instr)
FSGNJN_S : `SAMPLE_F(fsgnjn_s_cg, instr)
FSGNJN_D : `SAMPLE_F(fsgnjn_d_cg, instr)
FSGNJX_S : `SAMPLE_F(fsgnjx_s_cg, instr)
FSGNJX_D : `SAMPLE_F(fsgnjx_d_cg, instr)
FMV_X_W : `SAMPLE_F(fmv_x_w_cg, instr)
FMV_X_D : `SAMPLE_F(fmv_x_d_cg, instr)
FMV_W_X : `SAMPLE_F(fmv_w_x_cg, instr)
FMV_D_X : `SAMPLE_F(fmv_d_x_cg, instr)
FEQ_S : `SAMPLE_F(feq_s_cg, instr)
FEQ_D : `SAMPLE_F(feq_d_cg, instr)
FLT_S : `SAMPLE_F(flt_s_cg, instr)
FLT_D : `SAMPLE_F(flt_d_cg, instr)
FLE_S : `SAMPLE_F(fle_s_cg, instr)
FLE_D : `SAMPLE_F(fle_d_cg, instr)
FCLASS_S : `SAMPLE_F(fclass_s_cg, instr)
FCLASS_D : `SAMPLE_F(fclass_d_cg, instr)
// RV32B
CLZ : `SAMPLE_B(clz_cg, instr)
CTZ : `SAMPLE_B(ctz_cg, instr)
@ -2068,8 +2427,7 @@ class riscv_instr_cover_group;
end
end
`VECTOR_INCLUDE("riscv_instr_cover_group_inc_sample.sv")
pre_instr.copy(instr);
pre_instr.mem_addr = instr.mem_addr;
pre_instr = instr;
endfunction
// Check if the instruction is supported
@ -2096,11 +2454,12 @@ class riscv_instr_cover_group;
instr_name = instr_name.first;
do begin
riscv_instr instr;
if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR)) begin
if (!(instr_name inside {unsupported_instr}) && (instr_name != INVALID_INSTR) &&
riscv_instr::instr_registry.exists(instr_name)) begin
instr = riscv_instr::create_instr(instr_name);
if ((instr.group inside {supported_isa}) &&
(instr.group inside {RV32I, RV32M, RV64M, RV64I, RV32C, RV64C,
RV32V, RV64V, RV64B, RV32B})) begin
RVV, RV64B, RV32B})) begin
if (((instr_name inside {URET}) && !support_umode_trap) ||
((instr_name inside {SRET, SFENCE_VMA}) &&
!(SUPERVISOR_MODE inside {supported_privileged_mode})) ||

View file

@ -328,6 +328,8 @@ class riscv_instr_gen_config extends uvm_object;
constraint mstatus_c {
if (set_mstatus_mprv) {
mstatus_mprv == 1'b1;
} else {
mstatus_mprv == 1'b0;
}
if (SATP_MODE == BARE) {
mstatus_mxr == 0;
@ -591,7 +593,7 @@ class riscv_instr_gen_config extends uvm_object;
get_invalid_priv_lvl_csr();
endfunction
function void setup_instr_distribution();
virtual function void setup_instr_distribution();
string opts;
int val;
get_int_arg_value("+dist_control_mode=", dist_control_mode);
@ -643,7 +645,7 @@ class riscv_instr_gen_config extends uvm_object;
end
endfunction
function void get_non_reserved_gpr();
virtual function void get_non_reserved_gpr();
endfunction
function void post_randomize();
@ -659,7 +661,7 @@ class riscv_instr_gen_config extends uvm_object;
end
endfunction
function void check_setting();
virtual function void check_setting();
bit support_64b;
bit support_128b;
foreach (riscv_instr_pkg::supported_isa[i]) begin

View file

@ -1,5 +1,6 @@
/*
* Copyright 2018 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -89,9 +90,8 @@ package riscv_instr_pkg;
RV64C,
RV128I,
RV128C,
RV32V,
RVV,
RV32B,
RV64V,
RV64B,
RV32X,
RV64X
@ -474,12 +474,10 @@ package riscv_instr_pkg;
VWMACC,
VWMACCSU,
VWMACCUS,
/*
VQMACCU,
VQMACC,
VQMACCSU,
VQMACCUS,
*/
//VQMACCU,
//VQMACC,
//VQMACCSU,
//VQMACCUS,
VMERGE,
VMV,
VSADDU,
@ -494,6 +492,7 @@ package riscv_instr_pkg;
VSSRA,
VNCLIPU,
VNCLIP,
// 14. Vector Floating-Point Instructions
VFADD,
VFSUB,
VFRSUB,
@ -543,7 +542,7 @@ package riscv_instr_pkg;
VFNCVT_F_X_W,
VFNCVT_F_F_W,
VFNCVT_ROD_F_F_W,
// Vector reduction instruction
// 15. Vector reduction instruction
VREDSUM_VS,
VREDMAXU_VS,
VREDMAX_VS,
@ -590,6 +589,51 @@ package riscv_instr_pkg;
VMV2R_V,
VMV4R_V,
VMV8R_V,
// Vector load/store instruction
VLE_V,
VSE_V,
VLB_V,
VSB_V,
VLH_V,
VSH_V,
VLW_V,
VSW_V,
VLBU_V,
VLHU_V,
VLWU_V,
VLSB_V,
VLSH_V,
VLSW_V,
VLSBU_V,
VLSHU_V,
VLSWU_V,
VLSE_V,
VSSB_V,
VSSH_V,
VSSW_V,
VSSE_V,
VLXB_V,
VLXH_V,
VLXW_V,
VLXBU_V,
VLXHU_V,
VLXWU_V,
VLXE_V,
VSXB_V,
VSXH_V,
VSXW_V,
VSXE_V,
VSUXB_V,
VSUXH_V,
VSUXW_V,
VSUXE_V,
VLBFF_V,
VLHFF_V,
VLWFF_V,
VLBUFF_V,
VLHUFF_V,
VLWUFF_V,
VLEFF_V,
// Supervisor instruction
DRET,
MRET,
@ -606,6 +650,9 @@ package riscv_instr_pkg;
// Maximum virtual address bits used by the program
parameter int MAX_USED_VADDR_BITS = 30;
parameter int SINGLE_PRECISION_FRACTION_BITS = 23;
parameter int DOUBLE_PRECISION_FRACTION_BITS = 52;
typedef enum bit [4:0] {
ZERO = 5'b00000,
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
@ -645,7 +692,11 @@ package riscv_instr_pkg;
VA_FORMAT,
VS2_FORMAT, // op vd,vs2
VL_FORMAT,
VS_FORMAT
VS_FORMAT,
VLV_FORMAT,
VSV_FORMAT,
VLS_FORMAT,
VSS_FORMAT
} riscv_instr_format_t;
@ -1090,9 +1141,9 @@ package riscv_instr_pkg;
typedef struct packed {
bit ill;
bit [XLEN-2:7] reserved;
bit [1:0] vediv;
bit [2:0] vsew;
bit [1:0] vlmul;
int vediv;
int vsew;
int vlmul;
} vtype_t;
typedef enum bit [1:0] {

View file

@ -275,6 +275,12 @@ class riscv_instr_sequence extends uvm_sequence;
str = {prefix, instr_stream.instr_list[i].convert2asm()};
instr_string_list.push_back(str);
end
// If PMP is supported, need to align <main> to a 4-byte boundary.
// TODO(udi) - this might interfere with multi-hart programs,
// may need to specifically match hart0.
if (riscv_instr_pkg::support_pmp && !uvm_re_match("*main*", label_name)) begin
instr_string_list.push_front(".align 2");
end
insert_illegal_hint_instr();
prefix = format_string($sformatf("%0d:", i), LABEL_STR_LEN);
if(!is_main_program) begin

View file

@ -186,6 +186,18 @@ class riscv_rand_instr_stream extends riscv_instr_stream;
setup_instruction_dist(no_branch, no_load_store);
endfunction
virtual function void randomize_avail_regs();
if(avail_regs.size() > 0) begin
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(avail_regs,
unique{avail_regs};
avail_regs[0] inside {[S0 : A5]};
foreach(avail_regs[i]) {
!(avail_regs[i] inside {cfg.reserved_regs, reserved_rd});
},
"Cannot randomize avail_regs")
end
endfunction
function void setup_instruction_dist(bit no_branch = 1'b0, bit no_load_store = 1'b1);
if (cfg.dist_control_mode) begin
category_dist = cfg.category_dist;
@ -227,6 +239,7 @@ class riscv_rand_instr_stream extends riscv_instr_stream;
end
instr = riscv_instr::get_rand_instr(.include_instr(allowed_instr),
.exclude_instr(exclude_instr));
instr.m_cfg = cfg;
randomize_gpr(instr);
endfunction

View file

@ -1,5 +1,6 @@
/*
* Copyright 2018 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -120,19 +121,11 @@ class riscv_load_store_base_instr_stream extends riscv_mem_access_stream;
virtual function void gen_load_store_instr();
bit enable_compressed_load_store;
riscv_instr instr;
if(avail_regs.size() > 0) begin
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(avail_regs,
unique{avail_regs};
avail_regs[0] inside {[S0 : A5]};
foreach(avail_regs[i]) {
!(avail_regs[i] inside {cfg.reserved_regs, reserved_rd});
},
"Cannot randomize avail_regs")
end
randomize_avail_regs();
if ((rs1_reg inside {[S0 : A5], SP}) && !cfg.disable_compressed_instr) begin
enable_compressed_load_store = 1;
end
foreach(addr[i]) begin
foreach (addr[i]) begin
// Assign the allowed load/store instructions based on address alignment
// This is done separately rather than a constraint to improve the randomization performance
allowed_instr = {LB, LBU, SB};
@ -450,6 +443,7 @@ class riscv_load_store_rand_addr_instr_stream extends riscv_load_store_base_inst
}
`uvm_object_utils(riscv_load_store_rand_addr_instr_stream)
`uvm_object_new
virtual function void randomize_offset();
int offset_, addr_;
@ -465,7 +459,7 @@ class riscv_load_store_rand_addr_instr_stream extends riscv_load_store_base_inst
offset[i] = offset_;
addr[i] = addr_offset + offset_;
end
endfunction `uvm_object_new
endfunction
virtual function void add_rs1_init_la_instr(riscv_reg_t gpr, int id, int base = 0);
riscv_instr instr[$];
@ -524,3 +518,136 @@ class riscv_load_store_rand_addr_instr_stream extends riscv_load_store_base_inst
endfunction
endclass
class riscv_vector_unit_stride_load_store_instr_stream extends riscv_mem_access_stream;
typedef enum {B_ALIGNMENT, H_ALIGNMENT, W_ALIGNMENT, E_ALIGNMENT} alignment_e;
rand alignment_e alignment;
rand int unsigned data_page_id;
rand int unsigned num_mixed_instr;
rand riscv_reg_t rs1_reg;
constraint vec_mixed_instr_c {
num_mixed_instr inside {[0:10]};
}
constraint vec_rs1_c {
!(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO});
}
constraint vec_data_page_id_c {
data_page_id < max_data_page_id;
}
constraint alignment_sew_c {
if (cfg.vector_cfg.vtype.vsew <= 16) {alignment != W_ALIGNMENT;}
if (cfg.vector_cfg.vtype.vsew <= 8) {alignment != H_ALIGNMENT;}
}
int base;
int max_load_store_addr;
riscv_instr load_store_instr;
`uvm_object_utils(riscv_vector_unit_stride_load_store_instr_stream)
`uvm_object_new
virtual function int get_addr_alignment_mask(int alignment_bytes);
return alignment_bytes - 1;
endfunction
function void post_randomize();
randomize_base();
// rs1 cannot be modified by other instructions
if(!(rs1_reg inside {reserved_rd})) reserved_rd = {reserved_rd, rs1_reg};
randomize_avail_regs();
gen_load_store_instr();
add_mixed_instr(num_mixed_instr);
add_rs1_init_la_instr(rs1_reg, data_page_id, base);
super.post_randomize();
endfunction
virtual function void randomize_base();
int ss = stride_span();
bit success;
repeat (10) begin
max_load_store_addr = data_page[data_page_id].size_in_bytes - ss;
if (max_load_store_addr >= 0) begin
success = 1'b1;
break;
end
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(data_page_id, data_page_id < max_data_page_id;)
end
assert (success) else begin
`uvm_fatal(`gfn, $sformatf({"Expected positive value for max_load_store_addr, got %0d.",
" Perhaps more memory needs to be allocated in the data pages for vector loads and stores.",
"\ndata_page_id:%0d\ndata_page[data_page_id].size_in_bytes:%0d\nstride_span:%0d",
"\nalignment:%s\nstride_bytes:%0d\nVLEN:%0d\nLMUL:%0d\ncfg.vector_cfg.vtype.vsew:%0d\n\n"},
max_load_store_addr, data_page_id, data_page[data_page_id].size_in_bytes, ss,
alignment.name(), stride_bytes(), VLEN,
cfg.vector_cfg.vtype.vlmul, cfg.vector_cfg.vtype.vsew))
end
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(base, base >= 0; base <= max_load_store_addr;)
if (!cfg.enable_unaligned_load_store) begin
base &= ~get_addr_alignment_mask(stride_bytes());
end
endfunction
virtual function int stride_span();
int num_elements = VLEN * cfg.vector_cfg.vtype.vlmul / cfg.vector_cfg.vtype.vsew;
stride_span = num_elements * stride_bytes();
endfunction
virtual function int stride_bytes();
stride_bytes = 0;
if (alignment == B_ALIGNMENT) stride_bytes = 1;
else if (alignment == H_ALIGNMENT) stride_bytes = 2;
else if (alignment == W_ALIGNMENT) stride_bytes = 4;
else if (alignment == E_ALIGNMENT) stride_bytes = cfg.vector_cfg.vtype.vsew;
endfunction
// Generate each load/store instruction
virtual function void gen_load_store_instr();
build_allowed_instr();
randomize_vec_load_store_instr();
instr_list.push_back(load_store_instr);
endfunction
virtual function void build_allowed_instr();
if (alignment == B_ALIGNMENT) add_byte_aligned_vec_load_stores();
else if (alignment == H_ALIGNMENT) add_h_aligned_vec_load_stores();
else if (alignment == W_ALIGNMENT) add_w_aligned_vec_load_stores();
else if (alignment == E_ALIGNMENT) add_element_vec_load_stores();
endfunction
virtual function void add_element_vec_load_stores();
allowed_instr = {VLE_V, VSE_V, allowed_instr};
endfunction
virtual function void add_byte_aligned_vec_load_stores();
allowed_instr = {VLB_V, VSB_V, VLBU_V, allowed_instr};
endfunction
virtual function void add_h_aligned_vec_load_stores();
allowed_instr = {VLH_V, VSH_V, VLHU_V, allowed_instr};
endfunction
virtual function void add_w_aligned_vec_load_stores();
allowed_instr = {VLW_V, VSW_V, VLWU_V, allowed_instr};
endfunction
virtual function void randomize_vec_load_store_instr();
load_store_instr = riscv_instr::get_load_store_instr(allowed_instr);
load_store_instr.m_cfg = cfg;
load_store_instr.has_rs1 = 0;
load_store_instr.has_imm = 0;
randomize_gpr(load_store_instr);
load_store_instr.rs1 = rs1_reg;
load_store_instr.process_load_store = 0;
endfunction
endclass

View file

@ -495,7 +495,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object;
// Unset U bit
$sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]),
// Save PTE back to memory
$sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
$sformatf("s%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
// Move to the next PTE
$sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN/8),
// If not the end of the kernel space, process the next PTE
@ -513,14 +513,14 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object;
$sformatf("add x%0d, x%0d, x%0d", cfg.gpr[0], cfg.gpr[2], cfg.gpr[0]),
$sformatf("li x%0d, 0x%0x", cfg.gpr[2], ubit_mask),
// Assume 20 PTEs for kernel data pages
$sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], 20 * XLEN/8),
$sformatf("addi x%0d, x%0d, %0d", cfg.gpr[1], cfg.gpr[1], 20 * XLEN/8),
"2:",
// Load the PTE from the memory
$sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
// Unset U bit
$sformatf("and x%0d, x%0d, x%0d", cfg.gpr[3], cfg.gpr[3], cfg.gpr[2]),
// Save PTE back to memory
$sformatf("l%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
$sformatf("s%0s x%0d, 0(x%0d)", load_store_unit, cfg.gpr[3], cfg.gpr[0]),
// Move to the next PTE
$sformatf("addi x%0d, x%0d, %0d", cfg.gpr[0], cfg.gpr[0], XLEN/8),
// If not the end of the kernel space, process the next PTE

View file

@ -1,5 +1,6 @@
/*
* Copyright 2020 Google LLC
* Copyright 2020 Andes Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,21 +23,75 @@ class riscv_vector_cfg extends uvm_object;
rand vxrm_t vxrm;
rand bit vxsat;
// Allow only vector instructions from the random sequences
rand bit only_vec_instr;
constraint only_vec_instr_c {soft only_vec_instr == 0;}
// Allow vector floating-point instructions (Allows vtype.vsew to be set <16 or >32).
rand bit vec_fp;
// Allow vector narrowing or widening instructions.
rand bit vec_narrowing_widening;
// Allow vector quad-widening instructions.
rand bit vec_quad_widening;
constraint vec_quad_widening_c {
(!vec_narrowing_widening) -> (!vec_quad_widening);
// FP requires at least 16 bits and quad-widening requires no more than ELEN/4 bits.
(ELEN < 64) -> (!(vec_fp && vec_quad_widening));
}
rand bit allow_illegal_vec_instr;
constraint allow_illegal_vec_instr_c {soft allow_illegal_vec_instr == 0;}
// Cause frequent hazards for the Vector Registers:
// * Write-After-Read (WAR)
// * Read-After-Write (RAW)
// * Read-After-Read (RAR)
// * Write-After-Write (WAW)
// These hazard conditions are induced by keeping a small (~5) list of registers to select from.
rand bit vec_reg_hazards;
constraint legal_c {
solve vtype before vl;
solve vl before vstart;
vstart <= vl;
vtype.vsew <= $clog2(VLEN/8);
vl <= (1 << ($clog2(VLEN/8) - vtype.vsew));
vstart inside {[0:vl]};
vl inside {[1:VLEN/vtype.vsew]};
}
// Basic constraint for initial bringup
constraint bringup_c {
vstart == 0;
vl == (1 << ($clog2(VLEN/8) - vtype.vsew));
vtype.vlmul == 0;
vtype.vediv == 0;
vtype.vsew == 2;
vl == VLEN/vtype.vsew;
vtype.vediv == 1;
}
// For all widening instructions, the destination element width must be a supported element
// width and the destination LMUL value must also be a supported LMUL value
constraint vlmul_c {
vtype.vlmul inside {1, 2, 4, 8};
vtype.vlmul <= MAX_LMUL;
if (vec_narrowing_widening) {
vtype.vlmul < 8;
}
if (vec_quad_widening) {
vtype.vlmul < 4;
}
}
constraint vsew_c {
vtype.vsew inside {8, 16, 32, 64, 128};
vtype.vsew <= ELEN;
// TODO: Determine the legal range of floating point format
if (vec_fp) {vtype.vsew inside {32};}
if (vec_narrowing_widening) {vtype.vsew < ELEN;}
if (vec_quad_widening) {vtype.vsew < (ELEN >> 1);}
}
constraint vdeiv_c {
vtype.vediv inside {1, 2, 4, 8};
vtype.vediv <= (vtype.vsew / SELEN);
}
`uvm_object_utils_begin(riscv_vector_cfg)

View file

@ -54,14 +54,39 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;
// ----------------------------------------------------------------------------
// Previleged CSR implementation
// ----------------------------------------------------------------------------

View file

@ -54,11 +54,35 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 2;

View file

@ -54,14 +54,36 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;
// ----------------------------------------------------------------------------
// Previleged CSR implementation
// ----------------------------------------------------------------------------

View file

@ -54,11 +54,35 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;

View file

@ -54,11 +54,35 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;

View file

@ -54,11 +54,35 @@ bit support_sfence = 1;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;

View file

@ -21,17 +21,17 @@
parameter int XLEN = 64;
// Parameter for SATP mode, set to BARE if address translation is not supported
parameter satp_mode_t SATP_MODE = SV39;
parameter satp_mode_t SATP_MODE = BARE;
// Supported Privileged mode
privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
// Unsupported instructions
riscv_instr_name_t unsupported_instr[] = {VWMACCSU};
riscv_instr_name_t unsupported_instr[] = {};
// ISA supported by the processor
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C, RV32A, RV64A,
RV32F, RV64F, RV32D, RV64D, RV32V, RV64V};
RV32F, RV64F, RV32D, RV64D, RVV};
// Interrupt mode support
mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
@ -54,14 +54,38 @@ bit support_sfence = 1;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 1;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;
// ----------------------------------------------------------------------------
// Previleged CSR implementation
// ----------------------------------------------------------------------------

View file

@ -47,3 +47,19 @@
iterations: 2
gen_test: riscv_instr_base_test
rtl_test: core_base_test
- test: riscv_vector_load_store_test
description: >
Vector load/store random test
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=0
+enable_floating_point=1
+enable_vector_extension=1
+directed_instr_0=riscv_vector_unit_stride_load_store_instr_stream,4
+no_branch_jump=1
+boot_mode=m
+no_csr_instr=1
iterations: 2
gen_test: riscv_instr_base_test
rtl_test: core_base_test

View file

@ -54,11 +54,34 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;

View file

@ -54,11 +54,35 @@ bit support_sfence = 0;
// Support unaligned load/store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
parameter int ELEN = 64;
parameter int SLEN = 64;
// Maximum size of a single vector element
parameter int ELEN = 32;
// Minimum size of a sub-element, which must be at most 8-bits.
parameter int SELEN = 8;
// Maximum size of a single vector element (encoded in vsew format)
parameter int VELEN = int'($ln(ELEN)/$ln(2)) - 3;
// Maxium LMUL supported by the core
parameter int MAX_LMUL = 8;
// ----------------------------------------------------------------------------
// Multi-harts configuration
// ----------------------------------------------------------------------------
// Number of harts
parameter int NUM_HARTS = 1;

View file

@ -132,11 +132,12 @@ class riscv_instr_cov_test extends uvm_test;
riscv_instr instr;
instr = riscv_instr::get_instr(instr_name);
if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
RV32F, RV32B, RV64B}) begin
RV32F, RV64F, RV32D, RV64D,
RV32B, RV64B}) begin
assign_trace_info_to_instr(instr);
instr.pre_sample();
instr_cg.sample(instr);
end
instr.pre_sample();
instr_cg.sample(instr);
return 1'b1;
end
end
@ -177,6 +178,27 @@ class riscv_instr_cov_test extends uvm_test;
instr_name[i] = "_";
end
end
case (instr_name)
// rename to new name as ovpsim still uses old name
"FMV_S_X": instr_name = "FMV_W_X";
"FMV_X_S": instr_name = "FMV_X_W";
// convert Pseudoinstructions
// fmv.s rd, rs fsgnj.s rd, rs, rs Copy single-precision register
// fabs.s rd, rs fsgnjx.s rd, rs, rs Single-precision absolute value
// fneg.s rd, rs fsgnjn.s rd, rs, rs Single-precision negate
// fmv.d rd, rs fsgnj.d rd, rs, rs Copy double-precision register
// fabs.d rd, rs fsgnjx.d rd, rs, rs Double-precision absolute value
// fneg.d rd, rs fsgnjn.d rd, rs, rs Double-precision negate
"FMV_S": instr_name = "FSGNJ_S";
"FABS_S": instr_name = "FSGNJX_S";
"FNEG_S": instr_name = "FSGNJN_S";
"FMV_D": instr_name = "FSGNJ_D";
"FABS_D": instr_name = "FSGNJX_D";
"FNEG_D": instr_name = "FSGNJN_D";
default: ;
endcase
return instr_name;
endfunction : process_instr_name

View file

@ -0,0 +1,2 @@
# Add custom initialization assembly code here
# This file will be included at the very beginning of the program