Update google_riscv-dv to google/riscv-dv@cb4295f

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

* Update list search (Matthew Ballance)
* Trap and report exceptions encountered in sub-processes and
  propagate error back (Matthew Ballance)
* Workaround fix for loop test colon issue (aneels3)
* Fix typo (aneels3)
* Add support for RV64AFD (aneels3)
* Fix typo (aneels3)
* Update README.md (aneels3)
* Add support for sub_programs (aneels3)
* fix issue with imm value for 64 bit instr (aneels3)
* Allow for underscores and capital letters in ISA for ISS (Pirmin
  Vogel)
* implement rv64i (shrujal20)
* Add support for RV32FD coverage (aneels3)
* Integrate random seed for pyflow (aneels3)
* Add riscv_loop_test (ShraddhaDevaiya)

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
This commit is contained in:
Pirmin Vogel 2022-04-01 15:34:53 +02:00
parent 2fc4cde7d2
commit fe3e029108
29 changed files with 7277 additions and 178 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 605301400555c235564f9336cc5fc220af7e951c
rev: cb4295f9ce5da2881d7746015a6105adb8f09071
}
}

View file

@ -4,12 +4,13 @@ RISCV-DV-PyFlow is a purely Python based open-source instruction generator for R
verification. It uses [PyVSC](https://github.com/fvutils/pyvsc) as the main library for
randomization and coverage collection. It currently supports the following features:
- Supported instruction set: RV32IMAFDC
- Supported instruction set: RV32IMAFDC, RV64IMAFDC
- Supported privileged modes: For now only machine mode is supported.
- Illegal instruction and HINT instruction generation
- Random forward/backward branch instructions
- Supports mixing directed instructions with random instruction stream
- Support for direct & vectored interrupt table.
- Sub-program generation and random program calls
- Multi-hart support
- Functional coverage framework (reports GUI as well as text, currently
supports RV32IMFDC extensions)

View file

@ -13,12 +13,10 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import os
import sys
import vsc
import logging
from importlib import import_module
from enum import Enum, IntEnum, auto
from enum import IntEnum, auto
from pygen_src.riscv_instr_pkg import *
from pygen_src.riscv_instr_gen_config import cfg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
@ -77,14 +75,14 @@ class riscv_cov_instr:
# self.operands = "None" # Instruction operands (srcss/dests)
# self.pad = None # Not used
self.rs1_value = vsc.int_t(rcs.XLEN)
self.rs2_value = vsc.int_t(rcs.XLEN)
self.rs3_value = vsc.int_t(rcs.XLEN)
self.rd_value = vsc.int_t(rcs.XLEN)
self.fs1_value = vsc.int_t(rcs.XLEN)
self.fs2_value = vsc.int_t(rcs.XLEN)
self.fs3_value = vsc.int_t(rcs.XLEN)
self.fd_value = vsc.int_t(rcs.XLEN)
self.rs1_value = vsc.bit_t(rcs.XLEN)
self.rs2_value = vsc.bit_t(rcs.XLEN)
self.rs3_value = vsc.bit_t(rcs.XLEN)
self.rd_value = vsc.bit_t(rcs.XLEN)
self.fs1_value = vsc.bit_t(rcs.XLEN)
self.fs2_value = vsc.bit_t(rcs.XLEN)
self.fs3_value = vsc.bit_t(rcs.XLEN)
self.fd_value = vsc.bit_t(rcs.XLEN)
self.mem_addr = vsc.int_t(rcs.XLEN)
self.unaligned_pc = 0
@ -117,8 +115,9 @@ class riscv_cov_instr:
self.imm_type = None
self.csr = vsc.bit_t(12)
''' TODO: rs2, rs1, rd, group, format, category, imm_type will be
changed to vsc.enum_t once the issue with set/get_val is fixed '''
''' TODO: rs2, rs1, rd, group, format, category, imm_type
fs1, fs2, fs3, fd will be changed to vsc.enum_t once
the issue with set/get_val is fixed '''
self.rs2 = 0
self.rs1 = 0
self.rd = 0
@ -128,6 +127,14 @@ class riscv_cov_instr:
self.has_rd = 1
self.has_imm = 1
self.imm_len = 0
self.has_fs1 = 1
self.has_fs2 = 1
self.has_fs3 = 0
self.has_fd = 1
self.fs1 = 0
self.fs2 = 0
self.fs3 = 0
self.fd = 0
def assign_attributes(self):
attr_list = get_attr_list(self.instr)
@ -139,6 +146,8 @@ class riscv_cov_instr:
self.imm_type = attr_list[3]
self.set_imm_len()
self.set_mode()
if self.group.name in ["RV32D", "RV32F"]:
self.set_fd_mode()
def set_imm_len(self):
if self.format.name in ["U_FORMAT", "J_FORMAT"]:
@ -167,6 +176,50 @@ class riscv_cov_instr:
if self.format.name == "I_FORMAT":
self.has_rs1 = 0
# mode setting for F and D Instruction
def set_fd_mode(self):
if self.format == riscv_instr_format_t.I_FORMAT:
self.has_fs2 = 0
if self.category == riscv_instr_category_t.LOAD:
self.has_imm = 1
elif self.instr.name in ['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_W_D', 'FCVT_WU_D']:
self.has_fd = 0
self.has_rd = 1
elif self.instr.name in ['FMV_W_X', 'FMV_D_X', 'FCVT_S_W', 'FCVT_S_WU',
'FCVT_S_L', 'FCVT_D_L', 'FCVT_S_LU', 'FCVT_D_W',
'FCVT_D_LU', 'FCVT_D_WU']:
self.has_rs1 = 1
self.has_fs1 = 0
elif self.format == riscv_instr_format_t.S_FORMAT:
self.has_imm = 1
self.has_rs1 = 1
self.has_fs1 = 0
self.has_fs3 = 0
elif self.format == riscv_instr_format_t.R_FORMAT:
if self.category == riscv_instr_category_t.COMPARE:
self.has_rd = 1
self.has_fd = 0
elif self.instr.name in ['FCLASS_S', 'FCLASS_D']:
self.has_rd = 1
self.has_fd = 0
self.has_fs2 = 0
elif self.format == riscv_instr_format_t.R4_FORMAT:
self.has_fs3 = 1
elif self.format == riscv_instr_format_t.CL_FORMAT:
self.has_imm = 1
self.has_rs1 = 1
self.has_fs1 = 0
self.has_fs2 = 0
elif self.format == riscv_instr_format_t.CS_FORMAT:
self.has_imm = 1
self.has_rs1 = 1
self.has_fs1 = 0
self.has_fd = 0
else:
logging.info("Unsupported format {}".format(self.format.name))
def pre_sample(self):
unaligned_pc = self.pc.get_val() % 4 != 0
self.rs1_sign = self.get_operand_sign(self.rs1_value)
@ -326,7 +379,7 @@ class riscv_cov_instr:
explicitly extract the destination register from the operands '''
if pre_instr.has_rd:
if ((self.has_rs1 and (self.rs1 == pre_instr.rd)) or
(self.has_rs2 and (self.rs1 == pre_instr.rd))):
(self.has_rs2 and (self.rs2 == pre_instr.rd))):
logging.info("pre_instr {}".format(pre_instr.instr.name))
self.gpr_hazard = hazard_e["RAW_HAZARD"]
elif self.has_rd and (self.rd == pre_instr.rd):
@ -352,6 +405,20 @@ class riscv_cov_instr:
self.lsu_hazard = hazard_e["WAR_HAZARD"]
else:
self.lsu_hazard = hazard_e["NO_HAZARD"]
# Hazard Condition check for RV32D and RV32F instructions
if pre_instr.has_fd:
if ((self.has_fs1 and (self.fs1 == pre_instr.fd)) or
(self.has_fs2 and (self.fs2 == pre_instr.fd)) or
(self.has_fs3 and (self.fs3 == pre_instr.fd))):
self.gpr_hazard = hazard_e["RAW_HAZARD"]
elif (self.has_fd and (self.fd == pre_instr.fd)):
self.gpr_hazard = hazard_e["WAW_HAZARD"]
elif (self.has_fd and ((pre_instr.has_fs1 and (pre_instr.fs1 == self.fd)) or
(pre_instr.has_fs2 and (pre_instr.fs2 == self.fd)) or
(pre_instr.has_fs3 and (pre_instr.fs3 == self.fd)))):
self.gpr_hazard = hazard_e["WAR_HAZARD"]
else:
self.gpr_hazard = hazard_e["NO_HAZARD"]
logging.debug("Pre PC/name: {}/{}, Cur PC/name: {}/{}, "
"Hazard: {}/{}".format(pre_instr.pc.get_val(),
pre_instr.instr.name,

View file

@ -14,8 +14,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import logging
import vsc
from pygen_src.isa.riscv_instr import riscv_instr
from pygen_src.isa.riscv_cov_instr import riscv_cov_instr, operand_sign_e
from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_fpr_t, riscv_instr_format_t,
riscv_instr_category_t)
riscv_instr_category_t, get_val)
@vsc.randobj
@ -30,6 +31,7 @@ class riscv_floating_point_instr(riscv_instr):
self.has_fs2 = vsc.bit_t(1, 1)
self.has_fs3 = vsc.bit_t(1)
self.has_fd = vsc.bit_t(1, 1)
self.riscv_cov_ins = None
def convert2asm(self, prefix = " "):
asm_str = pkg_ins.format_string(string = self.get_instr_name(),
@ -127,20 +129,85 @@ class riscv_floating_point_instr(riscv_instr):
self.fd.rand_mode = bool(self.has_fd)
# coverage related functons
def update_src_regs(self, operands = []):
pass
def update_src_regs(self, instruction, operands):
if self.riscv_cov_ins is None:
self.riscv_cov_ins = riscv_cov_instr()
if instruction.category in ["LOAD", "CSR"]:
self.riscv_cov_ins.update_src_regs(operands)
if instruction.format.name == "I_FORMAT":
logging.info("instr = {}".format(instruction.__dict__))
if instruction.has_fs1:
instruction.fs1 = self.get_fpr(operands[1])
instruction.fs1_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[1]))
elif instruction.has_rs1:
instruction.rs1 = self.riscv_cov_ins.get_gpr(operands[1])
instruction.rs1_value = self.riscv_cov_ins.get_gpr_state(operands[1])
elif instruction.format.name == "S_FORMAT":
assert len(operands) == 3
instruction.fs2 = self.get_fpr(operands[0])
instruction.fs2_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[0]))
instruction.rs1 = self.riscv_cov_ins.get_gpr(operands[1])
instruction.rs1_value = self.riscv_cov_ins.get_gpr_state(operands[1])
instruction.imm = get_val(operands[2])
elif instruction.format.name == "R_FORMAT":
if len(operands) == 2 and instruction.instr.name in ["FSGNJ_S", "FSGNJX_S",
"FSGNJN_S", "FSGNJ_D",
"FSGNJX_D", "FSGNJN_D"]:
operands.append(operands[-1])
if instruction.has_fs2 or instruction.category.name == "CSR":
assert len(operands) == 3
else:
assert len(operands) == 2
if instruction.category.name != "CSR":
instruction.fs1 = self.get_fpr(operands[1])
instruction.fs1_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[1]))
if instruction.has_fs2:
instruction.fs2 = self.get_fpr(operands[0])
instruction.fs2_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[0]))
elif instruction.format.name == "R4_FORMAT":
assert len(operands) == 4
instruction.fs1 = self.get_fpr(operands[1])
instruction.fs1_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[1]))
instruction.fs2 = self.get_fpr(operands[2])
instruction.fs2_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[2]))
instruction.fs3 = self.get_fpr(operands[3])
instruction.fs3_value.set_val(self.riscv_cov_ins.get_gpr_state(operands[3]))
else:
logging.error("Unsupported format {}".format(instruction.format.name))
def update_dst_regs(self, reg_name, val_str):
pass
def update_dst_regs(self, instruction, reg_name, val_str):
self.riscv_cov_ins.gpr_state[reg_name] = get_val(val_str, hexa=1)
if instruction.has_fd:
instruction.fd = self.get_fpr(reg_name)
instruction.fd_value.set_val(self.riscv_cov_ins.get_gpr_state(reg_name))
elif instruction.has_rd:
instruction.rd = self.riscv_cov_ins.get_gpr(reg_name)
instruction.rd_value = self.riscv_cov_ins.get_gpr_state(reg_name)
def get_fpr(self, reg_name):
pass
result = riscv_fpr_t[reg_name.upper()]
return result
def get_pre_sample(self):
pass
def pre_sample(self, instr):
if instr.group.name in ["RV32F", "RV64F"]:
instr.fs1_sign = self.get_fp_operand_sign(instr.fs1_value, 31)
instr.fs2_sign = self.get_fp_operand_sign(instr.fs2_value, 31)
instr.fs3_sign = self.get_fp_operand_sign(instr.fs3_value, 31)
instr.fd_sign = self.get_fp_operand_sign(instr.fd_value, 31)
elif instr.instr.name == "FCVT_S_D":
instr.fs1_sign = self.get_fp_operand_sign(instr.fs1_value, 63)
instr.fd_sign = self.get_fp_operand_sign(instr.fd_value, 31)
elif instr.instr.name == "FCVT_D_S":
instr.fs1_sign = self.get_fp_operand_sign(instr.fs1_value, 31)
instr.fd_sign = self.get_fp_operand_sign(instr.fd_value, 63)
else:
instr.fs1_sign = self.get_fp_operand_sign(instr.fs1_value, 63)
instr.fs2_sign = self.get_fp_operand_sign(instr.fs2_value, 63)
instr.fs3_sign = self.get_fp_operand_sign(instr.fs3_value, 63)
instr.fd_sign = self.get_fp_operand_sign(instr.fd_value, 63)
def get_fp_operand_sign(self, value, idx):
pass
def check_hazard_condition(self, pre_instr):
pass
if value[idx]:
return operand_sign_e.NEGATIVE
else:
return operand_sign_e.POSITIVE

View file

@ -90,6 +90,7 @@ class riscv_instr:
self.has_rd = 1
self.has_imm = 1
self.shift_t = vsc.uint32_t(0xffffffff)
self.mask = 32
self.XLEN = vsc.uint32_t(32) # XLEN is used in constraint throughout the generator.
# Hence, XLEN should be of PyVSC type in order to use it in a constraint block
self.XLEN = rcs.XLEN
@ -525,8 +526,8 @@ class riscv_instr:
self.imm_str = str(self.uintToInt(self.imm))
def uintToInt(self, x):
if x < (2 ** rcs.XLEN) / 2:
if x < (2 ** self.mask) / 2:
signed_x = x
else:
signed_x = x - 2 ** rcs.XLEN
signed_x = x - 2 ** self.mask
return signed_x

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.
"""
from pygen_src.riscv_defines import DEFINE_AMO_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t)
DEFINE_AMO_INSTR(riscv_instr_name_t.LR_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.SC_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOSWAP_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOADD_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOAND_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOOR_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOXOR_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMIN_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMAX_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMINU_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())
DEFINE_AMO_INSTR(riscv_instr_name_t.AMOMAXU_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.AMO, riscv_instr_group_t.RV64A, g=globals())

View file

@ -0,0 +1,33 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
from pygen_src.riscv_defines import DEFINE_C_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t)
DEFINE_C_INSTR(riscv_instr_name_t.C_ADDIW, riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_SUBW, riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_ADDW, riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_LD, riscv_instr_format_t.CL_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_SD, riscv_instr_format_t.CS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_LDSP, riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV64C, g=globals())
DEFINE_C_INSTR(riscv_instr_name_t.C_SDSP, riscv_instr_format_t.CSS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV64C, g=globals())

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.
"""
from pygen_src.riscv_defines import DEFINE_FP_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t)
DEFINE_FP_INSTR(riscv_instr_name_t.FMV_X_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMV_D_X, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_L_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_LU_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_D_L, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_D_LU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64D, g=globals())

View file

@ -0,0 +1,25 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
from pygen_src.riscv_defines import DEFINE_FP_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t)
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_L_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_LU_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_S_L, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_S_LU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64F, g=globals())

View file

@ -0,0 +1,45 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
from pygen_src.riscv_defines import DEFINE_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t)
DEFINE_INSTR(riscv_instr_name_t.LWU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.LD, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SD, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV64I, g=globals())
# SHIFT intructions
DEFINE_INSTR(riscv_instr_name_t.SLLW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SLLIW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRLW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRLIW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRAW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SRAIW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.SHIFT, riscv_instr_group_t.RV64I, g=globals())
# ARITHMETIC intructions
DEFINE_INSTR(riscv_instr_name_t.ADDW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.ADDIW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64I, g=globals())
DEFINE_INSTR(riscv_instr_name_t.SUBW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64I, g=globals())

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.
"""
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)
DEFINE_INSTR(riscv_instr_name_t.MULW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64M, g=globals())
DEFINE_INSTR(riscv_instr_name_t.DIVW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64M, g=globals())
DEFINE_INSTR(riscv_instr_name_t.DIVUW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64M, g=globals())
DEFINE_INSTR(riscv_instr_name_t.REMW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64M, g=globals())
DEFINE_INSTR(riscv_instr_name_t.REMUW, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV64M, g=globals())

View file

@ -1,6 +1,7 @@
"""
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
@ -17,6 +18,7 @@ import sys
import vsc
from importlib import import_module
from pygen_src.riscv_instr_sequence import riscv_instr_sequence
from pygen_src.riscv_callstack_gen import riscv_callstack_gen
from pygen_src.riscv_instr_pkg import (pkg_ins, privileged_reg_t,
privileged_mode_t, mtvec_mode_t,
misa_ext_t, riscv_instr_group_t,
@ -49,7 +51,7 @@ class riscv_asm_program_gen:
self.hart = 0
self.page_table_list = []
self.main_program = []
self.sub_program = []
self.sub_program = [0] * rcs.NUM_HARTS
self.data_page_gen = None
self.spf_val = vsc.rand_bit_t(32)
self.dpf_val = vsc.rand_bit_t(64)
@ -64,9 +66,7 @@ class riscv_asm_program_gen:
# Generate program header
self.gen_program_header()
for hart in range(cfg.num_of_harts):
# Commenting out for now
# TODO support for sub_program
# sub_program_name = []
sub_program_name = []
self.instr_stream.append(f"h{int(hart)}_start:")
if not cfg.bare_program_mode:
self.setup_misa()
@ -93,7 +93,8 @@ class riscv_asm_program_gen:
if hart == 0:
self.gen_test_done()
# Generate sub program
# TODO gen_sub_program()
self.gen_sub_program(hart, self.sub_program[hart],
sub_program_name, cfg.num_of_sub_program)
# Generate main program
gt_lbl_str = pkg_ins.get_label("main", hart)
label_name = gt_lbl_str
@ -110,7 +111,8 @@ class riscv_asm_program_gen:
instr_stream=self.main_program[hart].directed_instr)
self.main_program[hart].gen_instr(is_main_program=1, no_branch=cfg.no_branch_jump)
# Setup jump instruction among main program and sub programs
# TODO gen_callstack()
self.gen_callstack(self.main_program[hart], self.sub_program[hart],
sub_program_name, cfg.num_of_sub_program)
self.main_program[hart].post_process_instr()
logging.info("Post-processing main program...done")
self.main_program[hart].generate_instr_stream()
@ -128,7 +130,7 @@ class riscv_asm_program_gen:
if(hart == 0 and not(rcs.support_pmp)):
self.gen_test_done()
# Shuffle the sub programs and insert to the instruction stream
# TODO inser_sub_program()
self.insert_sub_program(self.sub_program[hart], self.instr_stream)
logging.info("Main/sub program generation...done")
# program end
self.gen_program_end(hart)
@ -202,17 +204,57 @@ class riscv_asm_program_gen:
def gen_sub_program(self, hart, sub_program,
sub_program_name, num_sub_program,
is_debug = 0, prefix = "sub"):
# TODO
pass
if num_sub_program > 0:
self.sub_program = [0] * num_sub_program
for i in range(len(self.sub_program)):
gt_label_str = pkg_ins.get_label("{}_{}".format(prefix, i + 1), hart)
label_name = gt_label_str
gt_label_str = riscv_instr_sequence()
self.sub_program[i] = gt_label_str
if(is_debug):
self.sub_program[i].instr_cnt = cfg.debug_sub_program_instr_cnt[i]
else:
self.sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i]
self.generate_directed_instr_stream(hart=hart,
label=label_name,
original_instr_cnt=
self.sub_program[i].instr_cnt,
min_insert_cnt=0,
instr_stream=self.sub_program[i].directed_instr)
self.sub_program[i].label_name = label_name
self.sub_program[i].gen_instr(is_main_program=0, no_branch=cfg.no_branch_jump)
sub_program_name.append(self.sub_program[i].label_name)
def gen_callstack(self, main_program, sub_program,
sub_program_name, num_sub_program):
# TODO
pass
if num_sub_program != 0:
callstack_gen = riscv_callstack_gen()
self.callstack_gen.init(num_sub_program + 1)
if callstack_gen.randomize():
idx = 0
# Insert the jump instruction based on the call stack
for i in range(len(callstack_gen.program_h)):
for j in range(len(callstack_gen.program_h.sub_program_id)):
idx += 1
pid = callstack_gen.program_id[i].sub_program_id[j] - 1
logging.info("Gen jump instr %0s -> sub[%0d] %0d", i, j, pid + 1)
if(i == 0):
self.main_program[i].insert_jump_instr(sub_program_name[pid], idx)
else:
self.sub_program[i - 1].insert_jump_instr(sub_program_name[pid], idx)
else:
logging.critical("Failed to generate callstack")
sys.exit(1)
logging.info("Randomizing call stack..done")
def insert_sub_program(self, sub_program, instr_list):
# TODO
pass
if cfg.num_of_sub_program != 0:
random.shuffle(self.sub_program)
for i in range(len(self.sub_program)):
self.sub_program[i].post_process_instr()
self.sub_program[i].generate_instr_stream()
instr_list.extend((self.sub_program[i].instr_string_list))
# ----------------------------------------------------------------------------------
# Major sections - init, stack, data, test_done etc.
# ----------------------------------------------------------------------------------
@ -455,16 +497,20 @@ class riscv_asm_program_gen:
def get_rng(self, val0, val1, spf_dpf, flag):
if flag == 0 and spf_dpf == 32:
with vsc.raw_mode():
with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] > 0
with vsc.randomize_with(self.spf_val):
self.spf_val[val0:val1] > 0
elif flag == 0 and spf_dpf == 64:
with vsc.raw_mode():
with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] > 0
with vsc.randomize_with(self.dpf_val):
self.dpf_val[val0:val1] > 0
elif flag == 1 and spf_dpf == 32:
with vsc.raw_mode():
with vsc.randomize_with(self.spf_val): self.spf_val[val0 : val1] == 0
with vsc.randomize_with(self.spf_val):
self.spf_val[val0:val1] == 0
else:
with vsc.raw_mode():
with vsc.randomize_with(self.dpf_val): self.dpf_val[val0 : val1] == 0
with vsc.randomize_with(self.dpf_val):
self.dpf_val[val0:val1] == 0
def get_rand_spf_value(self):
vsc.randselect([
@ -493,7 +539,7 @@ class riscv_asm_program_gen:
# NaN
(1, lambda: self.get_randselect(0x7ff0_0000_0000_0001, 0x7ff8_0000_0000_0000, 1)),
# Normal
(1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64 , 0)),
(1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64, 0)),
# Subnormal
(1, lambda: self.get_rng(62, pkg_ins.DOUBLE_PRECISION_FRACTION_BITS, 64, 1))])
return self.dpf_val

View file

@ -0,0 +1,148 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import logging
import random
import vsc
@vsc.randobj
class riscv_program:
def __init__(self):
self.program_id = vsc.rand_bit_t(16)
self.call_stack_level = vsc.rand_uint32_t()
self.sub_program_id = vsc.rand_list_t(vsc.bit_t(16))
@vsc.constraint
def legel_c(self):
vsc.unique(self.sub_program_id)
with vsc.foreach(self.sub_program_id, idx = True) as i:
self.sub_program_id[i] != self.program_id
def convert2string(self):
string = "PID[{}] Lv[{}] :".format(self.program_id, self.call_stack_level)
for i in range(len(self.sub_program_id)):
string = "{} {}".format(string, self.sub_program_id[i])
return string
# -----------------------------------------------------------------------------------------
# RISC-V assembly program call stack generator
#
# The call stack is generated as a tree structure to avoid dead call loop.
# Level 0: P0
# / | \
# Level 1: P1 P2 P3
# | \/ \
# Level 2: P4 P5 P6
# |
# Level 3: P7
#
# Rules: A program can only call the program in the next level.
# A program can be called many times by other upper level programs.
# A program can call the same lower level programs multiple times.
# -----------------------------------------------------------------------------------------
@vsc.randobj
class riscv_callstack_gen:
def __init__(self):
# Number of programs in the call stack
self.program_cnt = vsc.int_t(10)
# Handles of all programs
self.program_h = []
# Maximum call stack level
self.max_stack_level = vsc.int_t(50)
# Call stack level of each program
self.stack_level = vsc.randsz_list_t(vsc.bit_t(11))
@vsc.constraint
def program_stack_level_c(self):
# The stack level is assigned in ascending order to avoid call loop
self.stack_level.size == self.program_cnt
self.stack_level[0] == 0
with vsc.foreach(self.stack_level, idx=True) as i:
with vsc.if_then(i > 0):
self.stack_level[i] in vsc.rangelist(vsc.rng(1, self.program_cnt - 1))
self.stack_level[i] >= self.stack_level[i - 1]
self.stack_level[i] <= self.stack_level[i - 1] + 1
self.stack_level[i] <= self.max_stack_level
# Init all program instances before randomization
def init(self, program_cnt):
self.program_cnt = program_cnt
self.program_h = [0] * program_cnt
for i in range(len(self.program_h)):
self.program_h[i] = riscv_program("program_{}".format(i))
# In the randomization stage, only the stack level of each program is specified. The call stack
# generation process is to build the call relationship between different programs. This is
# implemented with post randomize rather than constraints for performance considerations.
def post_randomize(self):
last_level = 0
last_level = self.stack_level[self.program_cnt - 1]
for i in range(len(self.program_h)):
self.program_h[i].program_id = i
self.program_h[i].call_stack_level = self.stack_level[i]
# Top-down generate the entire call stack.
# A program can only call the programs in the next level.
for i in range(last_level):
program_list = []
next_program_list = []
sub_program_id_pool = vsc.randlist_t()
sub_program_cnt = []
idx = 0
for j in range(self.program_cnt):
if self.stack_level[j] == i:
program_list.append(j)
if self.stack_level[j] == i + 1:
next_program_list.append(j)
# Randmly duplicate some sub programs in the pool to create a case that
# one sub program is called by multiple caller. Also it's possible to call
# the same sub program in one program multiple times.
total_sub_program_cnt = random.randrange(len(next_program_list),
len(next_program_list) + 1)
sub_program_id_pool = [0] * total_sub_program_cnt
for i in range(len(sub_program_id_pool)):
with sub_program_id_pool[i].randomize_with():
with vsc.if_then(sub_program_id_pool[i]):
sub_program_id_pool[i] == next_program_list[i]
with vsc.else_then():
sub_program_id_pool[i].inside(vsc.rangelist(next_program_list))
random.shuffle(sub_program_id_pool)
sub_program_cnt = [0] * len(program_list)
logging.info("{} programs @Lv{}-> {} programs at next level".format(
len(program_list), i, len(sub_program_id_pool)))
# Distribute the programs of the next level among the programs of current level
# Make sure all program has a caller so that no program is obsolete.
for j in range(len(sub_program_id_pool)):
caller_id = random.randrange(0, len(sub_program_cnt) - 1)
sub_program_cnt[caller_id] += 1
for j in range(len(program_list)):
id = program_list[j]
self.program_h[id].sub_program_id = [0] * sub_program_cnt[j]
logging.info("{} sub programs are assigned to program[{}]".format(
sub_program_cnt[j], id))
for k in range(len(self.program_h[id].sub_program_id)):
self.program_h[id].sub_program_id[k] = sub_program_id_pool[idx]
idx += 1
def print_call_stack(self, program_id_t, i, string_str):
if len(self.program_h[i].sub_program_id) == 0:
logging.info("{}", string_str)
else:
for j in range(len(self.program_h[i].sub_program_id)):
self.print_call_stack(self.program_h[i].sub_program_id[j], "{} -> {}".format(
string_str, self.program_h[i].sub_program_id[j]))

View file

@ -121,7 +121,7 @@ class riscv_jal_instr(riscv_rand_instr_stream):
# First instruction
self.jump_start = riscv_instr.get_instr(riscv_instr_name_t.JAL)
with self.jump_start.randomize_with() as it:
with self.jump_start.randomize_with():
self.jump_start.rd == RA
self.jump_start.imm_str = "{}f".format(order[0])
self.jump_start.label = self.label
@ -131,7 +131,7 @@ class riscv_jal_instr(riscv_rand_instr_stream):
self.jump_end.label = "{}".format(self.num_of_jump_instr)
for i in range(self.num_of_jump_instr):
self.jump[i] = riscv_instr.get_rand_instr(include_instr = [jal[0]])
with self.jump[i].randomize_with() as it:
with self.jump[i].randomize_with():
if self.jump[i].has_rd:
vsc.dist(self.jump[i].rd, [vsc.weight(riscv_reg_t.RA, 5), vsc.weight(
vsc.rng(riscv_reg_t.SP, riscv_reg_t.T0), 1),
@ -245,12 +245,13 @@ class riscv_push_stack_instr(riscv_rand_instr_stream):
def gen_push_stack_instr(self, stack_len, allow_branch=1):
self.stack_len = stack_len
self.init()
self.gen_instr(1)
self.push_stack_instr = [0] * (self.num_of_reg_to_save + 1)
for i in range(len(self.push_stack_instr)):
self.push_stack_instr[i] = riscv_instr()
self.push_stack_instr[0] = \
riscv_instr.get_instr(riscv_instr_name_t.ADDI.name)
with self.push_stack_instr[0].randomize_with() as it:
riscv_instr.get_instr(riscv_instr_name_t.ADDI)
with self.push_stack_instr[0].randomize_with():
self.push_stack_instr[0].rd == cfg.sp
self.push_stack_instr[0].rs1 == cfg.sp
self.push_stack_instr[0].imm == (~cfg.stack_len + 1)
@ -258,23 +259,22 @@ class riscv_push_stack_instr(riscv_rand_instr_stream):
self.push_stack_instr[0].imm_str = '-{}'.format(self.stack_len)
for i in range(len(self.saved_regs)):
if rcs.XLEN == 32:
self.push_stack_instr[i + 1] = riscv_instr.get_instr(riscv_instr_name_t.SW.name)
with self.push_stack_instr[i + 1].randomize_with() as it:
self.push_stack_instr[i + 1] = riscv_instr.get_instr(riscv_instr_name_t.SW)
with self.push_stack_instr[i + 1].randomize_with():
self.push_stack_instr[i + 1].rs2 == self.saved_regs[i]
self.push_stack_instr[i + 1].rs1 == cfg.sp
self.push_stack_instr[i + 1].imm == 4 * (i + 1)
else:
self.push_stack_instr[i + 1] = riscv_instr.get_instr(riscv_instr_name_t.SD.name)
with self.push_stack_instr[i + 1].randomize_with() as it:
self.push_stack_instr[i + 1] = riscv_instr.get_instr(riscv_instr_name_t.SD)
with self.push_stack_instr[i + 1].randomize_with():
self.push_stack_instr[i + 1].instr_name == riscv_instr_name_t.SD
self.push_stack_instr[i + 1].rs2 == self.saved_regs[i]
self.push_stack_instr[i + 1].rs1 == cfg.sp
self.push_stack_instr[i + 1].imm == 8 * (i + 1)
self.push_stack_instr[i + 1].process_load_store = 0
if allow_branch:
# TODO
# vsc.randomize(self.enable_branch)
pass
self.enable_branch = random.randrange(0, 1)
else:
self.enable_branch = 0
if self.enable_branch:
@ -285,7 +285,7 @@ class riscv_push_stack_instr(riscv_rand_instr_stream):
self.branch_instr.brach_assigned = 1
self.push_stack_instr[0].label = self.push_start_label
self.push_stack_instr[0].has_label = 1
self.branch_instr.extend(self.push_stack_instr)
self.push_stack_instr.extend(self.branch_instr)
self.mix_instr_stream(self.push_stack_instr)
for i in range(len(self.instr_list)):
self.instr_list[i].atomic = 1
@ -318,30 +318,30 @@ class riscv_pop_stack_instr(riscv_rand_instr_stream):
self.saved_regs = saved_regs
self.init()
self.gen_instr(1)
self.pop_stack_instr = [None] * (self.num_of_reg_to_save + 1)
self.pop_stack_instr = [0] * (self.num_of_reg_to_save + 1)
for i in range(len(self.pop_stack_instr)):
self.pop_stack_instr[i] = riscv_instr()
for i in range(len(self.saved_regs)):
if rcs.XLEN == 32:
self.pop_stack_instr[i] = riscv_instr.get_instr(riscv_instr_name_t.LW.name)
with self.pop_stack_instr[i].randomize_with() as it:
self.rd == self.saved_regs[i]
self.rs1 == cfg.sp
self.imm == 4 * (i + 1)
self.pop_stack_instr[i] = riscv_instr.get_instr(riscv_instr_name_t.LW)
with self.pop_stack_instr[i].randomize_with():
self.pop_stack_instr[i].rd == self.saved_regs[i]
self.pop_stack_instr[i].rs1 == cfg.sp
self.pop_stack_instr[i].imm == 4 * (i + 1)
else:
self.pop_stack_instr[i] = riscv_instr.get_instr(riscv_instr_name_t.LD.name)
with self.pop_stack_instr[i].randomize_with() as it:
self.rd == self.saved_regs[i]
self.rs1 == cfg.sp
self.imm == 8 * (i + 1)
self.pop_stack_instr[i] = riscv_instr.get_instr(riscv_instr_name_t.LD)
with self.pop_stack_instr[i].randomize_with():
self.pop_stack_instr[i].rd == self.saved_regs[i]
self.pop_stack_instr[i].rs1 == cfg.sp
self.pop_stack_instr[i].imm == 8 * (i + 1)
self.pop_stack_instr[i].process_load_store = 0
# addi sp,sp,imm
with self.pop_stack_instr[self.num_of_reg_to_save].randomize_with() as it:
self.rd == cfg.sp
self.rs1 == cfg.sp
self.imm == self.stack_len
self.pop_stack_instr[self.num_of_reg_to_save] = riscv_instr.get_instr(
riscv_instr_name_t.ADDI.name)
riscv_instr_name_t.ADDI)
with self.pop_stack_instr[self.num_of_reg_to_save].randomize_with():
self.pop_stack_instr[self.num_of_reg_to_save].rd == cfg.sp
self.pop_stack_instr[self.num_of_reg_to_save].rs1 == cfg.sp
self.pop_stack_instr[self.num_of_reg_to_save].imm == self.stack_len
self.pop_stack_instr[self.num_of_reg_to_save].imm_str = pkg_ins.format_string(
'{}'.format(self.stack_len))
self.mix_instr_stream(self.pop_stack_instr)

File diff suppressed because it is too large Load diff

View file

@ -39,13 +39,13 @@ class riscv_instr_gen_config:
self.main_program_instr_cnt = vsc.rand_int32_t()
# Instruction count of each sub-program
self.sub_program_instr_cnt = []
self.sub_program_instr_cnt = vsc.randsz_list_t(vsc.int32_t())
# Instruction count of the debug rom
self.debug_program_instr_cnt = 0
# Instruction count of debug sub-programs
self.debug_sub_program_instr_cnt = []
self.debug_sub_program_instr_cnt = vsc.randsz_list_t(vsc.int32_t())
# Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
self.data_page_pattern = vsc.rand_enum_t(data_pattern_t)
@ -241,6 +241,7 @@ class riscv_instr_gen_config:
self.force_m_delegation = self.argv.force_m_delegation
self.force_s_delegation = self.argv.force_s_delegation
self.support_supervisor_mode = 0 # TODO
self.disable_compressed_instr = vsc.uint8_t(1)
self.disable_compressed_instr = self.argv.disable_compressed_instr
self.require_signature_addr = self.argv.require_signature_addr
if self.require_signature_addr:
@ -315,8 +316,11 @@ class riscv_instr_gen_config:
@vsc.constraint
def default_c(self):
# TODO Add constraint related to sub_program
self.sub_program_instr_cnt.size == self.num_of_sub_program
self.debug_sub_program_instr_cnt.size == self.num_debug_sub_program
self.main_program_instr_cnt in vsc.rangelist(vsc.rng(10, self.instr_cnt))
with vsc.foreach(self.sub_program_instr_cnt, idx=True) as i:
self.sub_program_instr_cnt[i].inside(vsc.rangelist(vsc.rng(10, self.instr_cnt)))
@vsc.constraint
def debug_mode_c(self):
@ -662,6 +666,7 @@ class riscv_instr_gen_config:
parse.add_argument("--enable_visualization", action="store_true", default=False,
help="Enabling coverage report visualization for pyflow")
parse.add_argument('--trace_csv', help='List of csv traces', default="")
parse.add_argument('--seed', help='Seed value', default=None)
args, unknown = parse.parse_known_args()
# TODO
'''

View file

@ -1175,6 +1175,7 @@ class jalr_riscv_reg_t(IntEnum):
RA = 0
T1 = auto()
# PMP address matching mode
class pmp_addr_mode_t(Enum):
OFF = 0b00
@ -1275,6 +1276,7 @@ class all_categories(IntEnum):
INTERRUPT = auto()
AMO = auto()
# Ignore ZERO and SP
class riscv_reg_ex_zero_sp_t(IntEnum):
RA = 1
@ -1308,6 +1310,7 @@ class riscv_reg_ex_zero_sp_t(IntEnum):
T5 = auto()
T6 = auto()
# Ignore ZERO only
class riscv_reg_ex_zero_t(IntEnum):
RA = 1
@ -1342,6 +1345,7 @@ class riscv_reg_ex_zero_t(IntEnum):
T5 = auto()
T6 = auto()
# Currently PyVSC doesn't supports ignore bins
# TODO riscv_reg_ex_zero_sp_t and riscv_reg_ex_zero_t is added as a WA and it can be removed later.
@ -1533,113 +1537,271 @@ def get_attr_list(instr_name):
riscv_instr_name_t.CSRRCI: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.CSR,
riscv_instr_group_t.RV32I, imm_t.UIMM],
#RV32M
# RV32M
riscv_instr_name_t.MUL: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.MULH: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.MULHU: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.MULHSU: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.DIV: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.DIVU: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.REM: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_name_t.REMU: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
# RV32C
riscv_instr_name_t.C_LW: [riscv_instr_format_t.CL_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_SW: [riscv_instr_format_t.CS_FORMAT,
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_LWSP: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_SWSP: [riscv_instr_format_t.CSS_FORMAT,
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_ADDI4SPN: [riscv_instr_format_t.CIW_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_name_t.C_ADDI: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_name_t.C_ADDI16SP: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_name_t.C_LI: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_LUI: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZIMM],
riscv_instr_name_t.C_SUB: [riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_ADD: [riscv_instr_format_t.CR_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_NOP: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_MV: [riscv_instr_format_t.CR_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_ANDI: [riscv_instr_format_t.CB_FORMAT,
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_XOR: [riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_OR: [riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_AND: [riscv_instr_format_t.CA_FORMAT,
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.LOGICAL,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_BEQZ: [riscv_instr_format_t.CB_FORMAT,
riscv_instr_category_t.BRANCH,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.BRANCH,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_BNEZ: [riscv_instr_format_t.CB_FORMAT,
riscv_instr_category_t.BRANCH,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.BRANCH,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_SRLI: [riscv_instr_format_t.CB_FORMAT,
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_name_t.C_SRAI: [riscv_instr_format_t.CB_FORMAT,
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_name_t.C_SLLI: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_category_t.SHIFT,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],
riscv_instr_name_t.C_J: [riscv_instr_format_t.CJ_FORMAT,
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_JAL: [riscv_instr_format_t.CJ_FORMAT,
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_JR: [riscv_instr_format_t.CR_FORMAT,
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_JALR: [riscv_instr_format_t.CR_FORMAT,
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.JUMP,
riscv_instr_group_t.RV32C],
riscv_instr_name_t.C_EBREAK: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.SYSTEM,
riscv_instr_group_t.RV32C],
riscv_instr_category_t.SYSTEM,
riscv_instr_group_t.RV32C],
# RV32F
riscv_instr_name_t.FLW: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSW: [riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMADD_S: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMSUB_S: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FNMSUB_S: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FNMADD_S: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FADD_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSUB_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMUL_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FDIV_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSQRT_S: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSGNJ_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSGNJN_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FSGNJX_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMIN_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMAX_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FCVT_W_S: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FCVT_WU_S: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMV_X_W: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FEQ_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FLT_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FLE_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FCLASS_S: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FCVT_S_W: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FCVT_S_WU: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
riscv_instr_name_t.FMV_W_X: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32F],
# RV32D
riscv_instr_name_t.FLD: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSD: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FMADD_D: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FMSUB_D: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FNMSUB_D: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FNMADD_D: [riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FADD_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSUB_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FMUL_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FDIV_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSQRT_D: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSGNJ_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSGNJN_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FSGNJX_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FMIN_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FMAX_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_S_D: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_D_S: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FEQ_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FLT_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FLE_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCLASS_D: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_W_D: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_WU_D: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_D_W: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
riscv_instr_name_t.FCVT_D_WU: [riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32D],
}
# if instruction is not present in the dictionary,second argument well
# be assigned as default value of passed argument
@ -1679,6 +1841,18 @@ class riscv_instr_pkg:
SINGLE_PRECISION_FRACTION_BITS = 23
DOUBLE_PRECISION_FRACTION_BITS = 52
# Coverage related helper fields
# spf coverpoints
spf_val_r1 = 2139095040
spf_val_r2 = 428657868
spf_zero_r = 2147483648
spf_nan_r = 2143289344
# dpf coverpoints
dpf_val_r1 = 9218868437227405312
dpf_val_r2 = 18442240474082181120
dpf_zero_r = 9223372036854775808
dpf_nan_r = 9221120237041090560
def hart_prefix(self, hart=0):
if rcs.NUM_HARTS <= 1:
return ""

View file

@ -77,9 +77,11 @@ class riscv_instr_sequence:
# The load/store instruction will be inserted as directed instruction stream
self.instr_stream.gen_instr(no_branch = no_branch, no_load_store = 1,
is_debug_program = self.is_debug_program)
if not is_main_program:
self.gen_stack_enter_instr()
self.gen_stack_exit_instr()
# TODO Commenting for now as it is blocking sub_program
# if not is_main_program:
# self.gen_stack_enter_instr()
# self.gen_stack_exit_instr()
logging.info("Finishing instruction generation")
# Generate the stack push operations for this program
@ -108,6 +110,7 @@ class riscv_instr_sequence:
self.instr_stack_exit.cfg = cfg
self.instr_stack_exit.gen_pop_stack_instr(self.program_stack_len,
self.instr_stack_enter.saved_regs)
self.instr_stream.instr_list.extend((self.instr_stack_exit.instr_list))
# ----------------------------------------------------------------------------------------------
# Instruction post-process
@ -245,7 +248,7 @@ class riscv_instr_sequence:
if(rcs.support_pmp and not re.search("main", self.label_name)):
self.instr_string_list.insert(0, ".align 2")
self.insert_illegal_hint_instr()
prefix = pkg_ins.format_string(str(i), pkg_ins.LABEL_STR_LEN)
prefix = pkg_ins.format_string("{}:".format(i), pkg_ins.LABEL_STR_LEN)
if not self.is_main_program:
self.generate_return_routine(prefix)
@ -261,19 +264,19 @@ class riscv_instr_sequence:
except Exception:
logging.critical("Cannot randomize ra")
sys.exit(1)
routine_str = prefix + "addi x{} x{} {}".format(ra.name, cfg.ra.name, rand_lsb)
routine_str = prefix + "addi x{} x{} {}".format(ra.get_val(), cfg.ra, rand_lsb)
self.instr_string_list.append(routine_str)
if not cfg.disable_compressed_instr:
jump_instr.append(riscv_instr_name_t.C_JR)
if not (riscv_reg_t.RA in cfg.reserved_regs):
jump_instr.append(riscv_instr_name_t.C_JALR)
i = random.randrange(0, len(jump_instr) - 1)
if jump_instr[i] == riscv_instr_name_t.C_JAL:
routine_str = prefix + "c.jalr x{}".format(ra.name)
if jump_instr[i] == riscv_instr_name_t.C_JALR:
routine_str = prefix + "c.jalr x{}".format(ra.get_val())
elif jump_instr[i] == riscv_instr_name_t.C_JR:
routine_str = prefix + "c.jr x{}".format(ra.name)
routine_str = prefix + "c.jr x{}".format(ra.get_val())
elif jump_instr[i] == riscv_instr_name_t.JALR:
routine_str = prefix + "jalr x{} x{} 0".format(ra.name, ra.name)
routine_str = prefix + "jalr x{} x{} 0".format(ra.get_val(), ra.get_val())
else:
logging.critical("Unsupported jump_instr: {}".format(jump_instr[i]))
sys.exit(1)

View file

@ -0,0 +1,255 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import vsc
import sys
import logging
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.isa.riscv_instr import riscv_instr
from pygen_src.riscv_instr_stream import riscv_rand_instr_stream
from pygen_src.riscv_instr_pkg import (riscv_reg_t, riscv_instr_name_t, pkg_ins,
riscv_instr_format_t, riscv_instr_category_t,
compressed_gpr)
@vsc.randobj
class riscv_loop_instr(riscv_rand_instr_stream):
def __init__(self):
super().__init__()
self.loop_cnt_reg = vsc.randsz_list_t(vsc.enum_t(riscv_reg_t))
self.loop_limit_reg = vsc.randsz_list_t(vsc.enum_t(riscv_reg_t))
self.loop_init_val = vsc.randsz_list_t(vsc.int32_t())
self.loop_step_val = vsc.randsz_list_t(vsc.int32_t())
self.loop_limit_val = vsc.randsz_list_t(vsc.int32_t())
self.num_of_nested_loop = vsc.rand_bit_t(3)
self.num_of_instr_in_loop = vsc.rand_int32_t(0)
self.branch_type = vsc.randsz_list_t(vsc.enum_t(riscv_instr_name_t))
self.loop_init_instr = []
self.loop_update_instr = []
self.loop_branch_instr = []
self.loop_branch_target_instr = []
# Aggregated loop instruction stream
self.loop_instr = []
@vsc.constraint
def legal_loop_regs_c(self):
self.num_of_nested_loop.inside(vsc.rangelist(1, 2))
self.loop_limit_reg.size.inside(vsc.rangelist((1, 32)))
self.loop_cnt_reg.size.inside(vsc.rangelist((1, 8)))
vsc.solve_order(self.num_of_nested_loop, self.loop_cnt_reg)
vsc.solve_order(self.num_of_nested_loop, self.loop_limit_reg)
with vsc.foreach(self.loop_cnt_reg, idx = True) as i:
self.loop_cnt_reg[i] != riscv_reg_t.ZERO
with vsc.foreach(cfg.reserved_regs, idx = True) as j:
self.loop_cnt_reg[i] != cfg.reserved_regs[j]
with vsc.foreach(self.loop_limit_reg, idx = True) as i:
with vsc.foreach(cfg.reserved_regs, idx = True) as j:
self.loop_limit_reg[i] != cfg.reserved_regs[j]
vsc.unique(self.loop_cnt_reg)
vsc.unique(self.loop_limit_reg)
self.loop_cnt_reg.size == self.num_of_nested_loop
self.loop_limit_reg.size == self.num_of_nested_loop
@vsc.constraint
def loop_c(self):
vsc.solve_order(self.num_of_nested_loop, self.loop_init_val)
vsc.solve_order(self.num_of_nested_loop, self.loop_step_val)
vsc.solve_order(self.num_of_nested_loop, self.loop_limit_val)
vsc.solve_order(self.loop_limit_val, self.loop_limit_reg)
vsc.solve_order(self.branch_type, self.loop_init_val)
vsc.solve_order(self.branch_type, self.loop_step_val)
vsc.solve_order(self.branch_type, self.loop_limit_val)
self.num_of_instr_in_loop.inside(vsc.rangelist((1, 25)))
self.num_of_nested_loop.inside(vsc.rangelist(1, 2))
self.loop_init_val.size.inside(vsc.rangelist(1, 2))
self.loop_step_val.size.inside(vsc.rangelist(1, 2))
self.loop_limit_val.size.inside(vsc.rangelist(1, 2))
self.branch_type.size.inside(vsc.rangelist(1, 2))
self.loop_init_val.size == self.num_of_nested_loop
self.branch_type.size == self.num_of_nested_loop
self.loop_step_val.size == self.num_of_nested_loop
self.loop_limit_val.size == self.num_of_nested_loop
self.branch_type.size == self.num_of_nested_loop
with vsc.foreach(self.branch_type, idx = True) as i:
with vsc.if_then(cfg.disable_compressed_instr == 0):
self.branch_type[i].inside(vsc.rangelist(riscv_instr_name_t.C_BNEZ,
riscv_instr_name_t.C_BEQZ,
riscv_instr_name_t.BEQ,
riscv_instr_name_t.BNE,
riscv_instr_name_t.BLTU,
riscv_instr_name_t.BLT,
riscv_instr_name_t.BGEU,
riscv_instr_name_t.BGE))
with vsc.else_then():
self.branch_type[i].inside(vsc.rangelist(riscv_instr_name_t.BEQ,
riscv_instr_name_t.BNE,
riscv_instr_name_t.BLTU,
riscv_instr_name_t.BLT,
riscv_instr_name_t.BGEU,
riscv_instr_name_t.BGE))
with vsc.foreach(self.loop_init_val, idx = True) as i:
with vsc.if_then(self.branch_type[i].inside(vsc.rangelist(riscv_instr_name_t.C_BNEZ,
riscv_instr_name_t.C_BEQZ))):
self.loop_limit_val[i] == 0
self.loop_limit_reg[i] == riscv_reg_t.ZERO
self.loop_cnt_reg[i].inside(vsc.rangelist(compressed_gpr))
with vsc.else_then:
self.loop_limit_val[i].inside(vsc.rangelist((-20, 20)))
self.loop_limit_reg[i] != riscv_reg_t.ZERO
with vsc.if_then(self.branch_type[i].inside(vsc.rangelist(riscv_instr_name_t.C_BNEZ,
riscv_instr_name_t.C_BEQZ,
riscv_instr_name_t.BEQ,
riscv_instr_name_t.BNE))):
self.loop_limit_val[i] != self.loop_init_val[i]
((self.loop_limit_val[i] - self.loop_init_val[i]) % self.loop_step_val[i]) == 0
with vsc.else_if(self.branch_type[i] == riscv_instr_name_t.BGE):
self.loop_step_val[i] < 0
with vsc.else_if(self.branch_type[i].inside(vsc.rangelist(riscv_instr_name_t.BGEU))):
self.loop_step_val[i] < 0
self.loop_init_val[i] > 0
# Avoid count to negative
(self.loop_step_val[i] + self.loop_limit_val[i]) > 0
with vsc.else_if(self.branch_type[i] == riscv_instr_name_t.BLT):
self.loop_step_val[i] > 0
with vsc.else_if(self.branch_type[i] == riscv_instr_name_t.BLTU):
self.loop_step_val[i] > 0
self.loop_limit_val[i] > 0
self.loop_init_val[i].inside(vsc.rangelist((-10, 10)))
self.loop_step_val[i].inside(vsc.rangelist((-10, 10)))
with vsc.if_then(self.loop_init_val[i] < self.loop_limit_val[i]):
self.loop_step_val[i] > 0
with vsc.else_then:
self.loop_step_val[i] < 0
def post_randomize(self):
for i in range(len(self.loop_cnt_reg)):
self.reserved_rd.append(self.loop_cnt_reg[i])
for i in range(len(self.loop_limit_reg)):
self.reserved_rd.append(self.loop_limit_reg[i])
# Generate instructions that mixed with the loop instructions
self.initialize_instr_list(self.num_of_instr_in_loop)
self.gen_instr(1)
# Randomize the key loop instructions
self.loop_init_instr = [0] * 2 * self.num_of_nested_loop
self.loop_update_instr = [0] * self.num_of_nested_loop
self.loop_branch_instr = [0] * self.num_of_nested_loop
self.loop_branch_target_instr = [0] * self.num_of_nested_loop
for i in range(self.num_of_nested_loop):
# Instruction to init the loop counter
try:
self.loop_init_instr.insert(2 * i, riscv_instr.get_rand_instr())
# TODO
'''self.loop_update_instr[i] = riscv_instr.get_rand_instr(
include_instr = [riscv_instr_name_t.ADDI])'''
# Removed include_instr ADDI for now to avoid unrecognized colon
with self.loop_init_instr[2 * i].randomize_with():
self.loop_init_instr[2 * i].rd == self.loop_cnt_reg[i]
self.loop_init_instr[2 * i].rs1 == riscv_reg_t.ZERO
self.loop_init_instr[2 * i].imm == self.loop_init_val[i]
self.loop_init_instr[2 * i].comment = \
pkg_ins.format_string("init loop {} counter".format(i))
except Exception:
logging.critical("Cannot randomize loop init1 instruction")
sys.exit(1)
# Instruction to init loop limit
try:
self.loop_init_instr[2 * i + 1] = riscv_instr.get_rand_instr()
# TODO
'''self.loop_update_instr[i] = riscv_instr.get_rand_instr(
include_instr = [riscv_instr_name_t.ADDI])'''
# Removed include_instr ADDI for now to avoid unrecognized colon
with self.loop_init_instr[2 * i + 1].randomize_with():
self.loop_init_instr[2 * i + 1].rd == self.loop_limit_reg[i]
self.loop_init_instr[2 * i + 1].rs1 == riscv_reg_t.ZERO
self.loop_init_instr[2 * i + 1].imm == self.loop_limit_val[i]
self.loop_init_instr[2 * i + 1].comment = \
pkg_ins.format_string("init loop {} limit".format(i))
except Exception:
logging.critical("Cannot randomize loop init2 instruction")
sys.exit(1)
# Branch target instruction, can be anything
self.loop_branch_target_instr[i] = riscv_instr.get_rand_instr(
include_category = [riscv_instr_category_t.ARITHMETIC.name,
riscv_instr_category_t.LOGICAL.name,
riscv_instr_category_t.COMPARE.name],
exclude_instr = [riscv_instr_name_t.C_ADDI16SP])
try:
with self.loop_branch_target_instr[i].randomize_with():
with vsc.if_then(self.loop_branch_target_instr[i].format ==
riscv_instr_format_t.CB_FORMAT):
self.loop_branch_target_instr[i].rs1.not_inside(
vsc.rangelist(self.reserved_rd))
self.loop_branch_target_instr[i].rs1.not_inside(
vsc.rangelist(cfg.reserved_regs))
with vsc.if_then(self.loop_branch_target_instr[i].has_rd == 1):
self.loop_branch_target_instr[i].rd.not_inside(
vsc.rangelist(self.reserved_rd))
self.loop_branch_target_instr[i].rd.not_inside(
vsc.rangelist(cfg.reserved_regs))
except Exception:
logging.critical("Cannot randomize branch target instruction")
sys.exit(1)
self.loop_branch_target_instr[i].label = pkg_ins.format_string(
"{}_{}_t".format(self.label, i))
# Instruction to update loop counter
self.loop_update_instr[i] = riscv_instr.get_rand_instr()
# TODO
'''self.loop_update_instr[i] = riscv_instr.get_rand_instr(
include_instr = [riscv_instr_name_t.ADDI])'''
# Removing include_instr ADDI for now to avoid unrecognized colon
# Commenting for now due to key error
'''with self.loop_update_instr[i].randomize_with():
self.loop_update_instr[i].rd == self.loop_cnt_reg[i]
self.loop_update_instr[i].rs1 == self.loop_cnt_reg[i]
self.loop_update_instr[i].imm == self.loop_step_val[i]'''
self.loop_update_instr[i].comment = pkg_ins.format_string(
"update loop {} counter".format(i))
# Backward branch instruction
self.loop_branch_instr[i] = riscv_instr.get_rand_instr(
include_instr = [self.branch_type[i]])
self.loop_branch_instr[i].randomize()
with self.loop_branch_instr[i].randomize_with():
self.loop_branch_instr[i].rs1 == self.loop_cnt_reg[i]
# Getting PyVSC related error
# TODO
'''with vsc.if_then((self.branch_type[i] != riscv_instr_name_t.C_BEQZ) or
(self.branch_type[i] != riscv_instr_name_t.C_BNEZ)):
self.loop_branch_instr[i].rs2 == self.loop_limit_reg[i]
'''
self.loop_branch_instr[i].comment = pkg_ins.format_string(
"branch for loop {}".format(i))
self.loop_branch_instr[i].imm_str = self.loop_branch_target_instr[i].label
self.loop_branch_instr[i].branch_assigned = 1
# Randomly distribute the loop instruction in the existing instruction stream
self.build_loop_instr_stream()
self.mix_instr_stream(self.loop_instr, 1)
for i in range(len(self.instr_list)):
if (self.instr_list[i].label != ""):
self.instr_list[i].has_label = 1
else:
self.instr_list[i].has_label = 0
self.instr_list[i].atomic = 1
# Build the whole loop structure from innermost loop to the outermost loop
def build_loop_instr_stream(self):
self.loop_instr = []
for i in range(self.num_of_nested_loop):
self.loop_instr.append(self.loop_init_instr[2 * i])
self.loop_instr.append(self.loop_init_instr[2 * i + 1])
self.loop_instr.append(self.loop_branch_target_instr[i])
self.loop_instr.append(self.loop_update_instr[i])
self.loop_instr.append(self.loop_instr[i])
self.loop_instr.append(self.loop_branch_instr[i])
logging.info("Totally {} instructions have been added".format(len(self.loop_instr)))

View file

@ -16,6 +16,7 @@ import logging
import pandas as pd
from tabulate import tabulate
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_loop_instr import riscv_loop_instr
from pygen_src.riscv_directed_instr_lib import (riscv_directed_instr_stream,
riscv_int_numeric_corner_stream,
riscv_jal_instr, riscv_mem_access_stream)
@ -41,7 +42,8 @@ def factory(obj_of):
"riscv_load_store_rand_instr_stream": riscv_load_store_rand_instr_stream,
"riscv_load_store_hazard_instr_stream": riscv_load_store_hazard_instr_stream,
"riscv_load_store_stress_instr_stream": riscv_load_store_stress_instr_stream,
"riscv_single_load_store_instr_stream": riscv_single_load_store_instr_stream
"riscv_single_load_store_instr_stream": riscv_single_load_store_instr_stream,
"riscv_loop_instr": riscv_loop_instr
}
try:

View file

@ -0,0 +1,146 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import math
from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
riscv_instr_group_t, mtvec_mode_t,
privileged_mode_t)
# -----------------------------------------------------------------------------
# Processor feature configuration
# -----------------------------------------------------------------------------
# XLEN
XLEN = 64
# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.SV39
# Supported Privileged mode
supported_privileged_mode = [privileged_mode_t.USER_MODE,
privileged_mode_t.SUPERVISOR_MODE,
privileged_mode_t.MACHINE_MODE]
# Unsupported instructions
unsupported_instr = []
# ISA supported by the processor
supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
riscv_instr_group_t.RV64I, riscv_instr_group_t.RV64M,
riscv_instr_group_t.RV32C, riscv_instr_group_t.RV64C,
riscv_instr_group_t.RV32A, riscv_instr_group_t.RV64A,
riscv_instr_group_t.RV32F, riscv_instr_group_t.RV64F,
riscv_instr_group_t.RV32D, riscv_instr_group_t.RV64D]
# Interrupt mode support
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
# The number of interrupt vectors to be generated, only used if VECTORED
# interrupt mode is supported
max_interrupt_vector_num = 16
# Physical memory protection support
support_pmp = 0
# Debug mode support
support_debug_mode = 0
# Support delegate trap to user mode
support_umode_trap = 0
# Support sfence.vma instruction
support_sfence = 0
# Support unaligned load/store
support_unaligned_load_store = 1
# GPR Setting
NUM_FLOAT_GPR = 32
NUM_GPR = 32
NUM_VEC_GPR = 32
# -----------------------------------------------------------------------------
# Vector extension configuration
# -----------------------------------------------------------------------------
# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
# Maximum size of a single vector element
ELEN = 32
# Minimum size of a sub-element, which must be at most 8-bits.
SELEN = 8
# Maximum size of a single vector element (encoded in vsew format)
VELEN = int(math.log(ELEN) // math.log(2)) - 3
# Maxium LMUL supported by the core
MAX_LMUL = 8
# -----------------------------------------------------------------------------
# Multi-harts configuration
# -----------------------------------------------------------------------------
# Number of harts
NUM_HARTS = 1
# -----------------------------------------------------------------------------
# Previleged CSR implementation
# -----------------------------------------------------------------------------
# Implemented previlieged CSR list
implemented_csr = [privileged_reg_t.USTATUS, # User status
privileged_reg_t.UIE, # User interrupt-enable register
privileged_reg_t.UTVEC, # User trap-handler base address
privileged_reg_t.USCRATCH, # Scratch register for user trap handlers
privileged_reg_t.UEPC, # User exception program counter
privileged_reg_t.UCAUSE, # User trap cause
privileged_reg_t.UTVAL, # User bad address or instruction
privileged_reg_t.UIP, # User interrupt pending
# Supervisor mode CSR
privileged_reg_t.SSTATUS, # Supervisor status
privileged_reg_t.SEDELEG, # Supervisor exception delegation register
privileged_reg_t.SIDELEG, # Supervisor interrupt delegation register
privileged_reg_t.SIE, # Supervisor interrupt-enable register
privileged_reg_t.STVEC, # Supervisor trap-handler base address
privileged_reg_t.SCOUNTEREN, # Supervisor counter enable
privileged_reg_t.SSCRATCH, # Scratch register for supervisor trap handlers
privileged_reg_t.SEPC, # Supervisor exception program counter
privileged_reg_t.SCAUSE, # Supervisor trap cause
privileged_reg_t.STVAL, # Supervisor bad address or instruction
privileged_reg_t.SIP, # Supervisor interrupt pending
privileged_reg_t.SATP, # Supervisor address translation and protection
# Machine mode mode CSR
privileged_reg_t.MVENDORID, # Vendor ID
privileged_reg_t.MARCHID, # Architecture ID
privileged_reg_t.MIMPID, # Implementation ID
privileged_reg_t.MHARTID, # Hardware thread ID
privileged_reg_t.MSTATUS, # Machine status
privileged_reg_t.MISA, # ISA and extensions
privileged_reg_t.MIE, # Machine interrupt-enable register
privileged_reg_t.MTVEC, # Machine trap-handler base address
privileged_reg_t.MCOUNTEREN, # Machine counter enable
privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
privileged_reg_t.MEPC, # Machine exception program counter
privileged_reg_t.MCAUSE, # Machine trap cause
privileged_reg_t.MTVAL, # Machine bad address or instruction
privileged_reg_t.MIP # Machine interrupt pending
]
# Implementation-specific custom CSRs
custom_csr = []

View file

@ -0,0 +1,119 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import math
from pygen_src.riscv_instr_pkg import (privileged_reg_t, satp_mode_t,
riscv_instr_group_t, mtvec_mode_t,
privileged_mode_t)
# -----------------------------------------------------------------------------
# Processor feature configuration
# -----------------------------------------------------------------------------
# XLEN
XLEN = 64
# set to BARE if address translation is not supported
SATP_MODE = satp_mode_t.BARE
# Supported Privileged mode
supported_privileged_mode = [privileged_mode_t.MACHINE_MODE]
# Unsupported instructions
unsupported_instr = []
# ISA supported by the processor
supported_isa = [riscv_instr_group_t.RV32I, riscv_instr_group_t.RV32M,
riscv_instr_group_t.RV32C, riscv_instr_group_t.RV64I,
riscv_instr_group_t.RV64M, riscv_instr_group_t.RV64C]
# Interrupt mode support
supported_interrupt_mode = [mtvec_mode_t.DIRECT, mtvec_mode_t.VECTORED]
# The number of interrupt vectors to be generated, only used if VECTORED
# interrupt mode is supported
max_interrupt_vector_num = 16
# Physical memory protection support
support_pmp = 0
# Debug mode support
support_debug_mode = 0
# Support delegate trap to user mode
support_umode_trap = 0
# Support sfence.vma instruction
support_sfence = 0
# Support unaligned load/store
support_unaligned_load_store = 1
# GPR Setting
NUM_FLOAT_GPR = 32
NUM_GPR = 32
NUM_VEC_GPR = 32
# -----------------------------------------------------------------------------
# Vector extension configuration
# -----------------------------------------------------------------------------
# Parameter for vector extension
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
# Maximum size of a single vector element
ELEN = 32
# Minimum size of a sub-element, which must be at most 8-bits.
SELEN = 8
# Maximum size of a single vector element (encoded in vsew format)
VELEN = int(math.log(ELEN) // math.log(2)) - 3
# Maxium LMUL supported by the core
MAX_LMUL = 8
# -----------------------------------------------------------------------------
# Multi-harts configuration
# -----------------------------------------------------------------------------
# Number of harts
NUM_HARTS = 1
# -----------------------------------------------------------------------------
# Previleged CSR implementation
# -----------------------------------------------------------------------------
# Implemented previlieged CSR list
implemented_csr = [privileged_reg_t.MVENDORID, # Vendor ID
privileged_reg_t.MARCHID, # Architecture ID
privileged_reg_t.MIMPID, # Implementation ID
privileged_reg_t.MHARTID, # Hardware thread ID
privileged_reg_t.MSTATUS, # Machine status
privileged_reg_t.MISA, # ISA and extensions
privileged_reg_t.MIE, # Machine interrupt-enable register
privileged_reg_t.MTVEC, # Machine trap-handler base address
privileged_reg_t.MCOUNTEREN, # Machine counter enable
privileged_reg_t.MSCRATCH, # Scratch register for machine trap handlers
privileged_reg_t.MEPC, # Machine exception program counter
privileged_reg_t.MCAUSE, # Machine trap cause
privileged_reg_t.MTVAL, # Machine bad address or instruction
privileged_reg_t.MIP # Machine interrupt pending
]
# Implementation-specific custom CSRs
custom_csr = []

View file

@ -13,6 +13,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import sys
import logging
import time
import random
import traceback
import multiprocessing
sys.path.append("pygen/")
from pygen_src.riscv_instr_pkg import *
@ -33,9 +35,28 @@ class riscv_instr_base_test:
def run(self):
with multiprocessing.Pool(processes = cfg.num_of_tests) as pool:
pool.map(self.run_phase, list(range(cfg.num_of_tests)))
ret = pool.map(self.run_phase, list(range(cfg.num_of_tests)))
if 1 in ret:
raise Exception("Test-generation jobs failed")
def run_phase(self, num):
try:
self._run_phase(num)
return 0
except Exception as e:
traceback.print_exc()
return 1
def _run_phase(self, num):
if num == 0:
'''Get the user specified seed value otherwise
generate a random seed value from SeedGen method of run.py'''
rand_seed = cfg.argv.seed.split("--")[0]
else:
# Generate random seed value everytime for multiple test iterations
rand_seed = random.getrandbits(31)
# Assign the global seed value for a particular iteration
random.seed(rand_seed)
self.randomize_cfg()
self.asm = riscv_asm_program_gen()
riscv_instr.create_instr_list(cfg)
@ -49,6 +70,7 @@ class riscv_instr_base_test:
logging.info("All directed instruction is applied")
self.asm.gen_program()
self.asm.gen_test_file(test_name)
logging.info("TEST GENERATED USING SEED VALUE = {}".format(rand_seed))
logging.info("TEST GENERATION DONE")
def randomize_cfg(self):

View file

@ -16,11 +16,12 @@ limitations under the License.
import sys
import vsc
import csv
from tabulate import *
from tabulate import * # NOQA
sys.path.append("pygen/")
from pygen_src.riscv_instr_pkg import *
from pygen_src.riscv_instr_pkg import * # NOQA
from pygen_src.isa.riscv_cov_instr import riscv_cov_instr
from pygen_src.riscv_instr_cover_group import *
from pygen_src.riscv_instr_cover_group import * # NOQA
from pygen_src.isa.riscv_floating_point_instr import riscv_floating_point_instr
class riscv_instr_cov_test:
@ -28,6 +29,7 @@ class riscv_instr_cov_test:
def __init__(self):
self.instr_cg = riscv_instr_cover_group()
self.fd_ins = riscv_floating_point_instr()
self.trace = {}
self.csv_trace = []
self.entry_cnt, self.total_entry_cnt, self.skipped_cnt, \
@ -43,6 +45,7 @@ class riscv_instr_cov_test:
sys.exit("No CSV file found!")
logging.info("{} CSV trace files to be "
"processed...\n".format(len(self.csv_trace)))
expect_illegal_instr = False
for csv_file in self.csv_trace:
with open("{}".format(csv_file)) as trace_file:
@ -105,12 +108,9 @@ class riscv_instr_cov_test:
def get_coverage_report(self):
model = vsc.get_coverage_report_model()
cov_dir = cfg.argv.log_file_name.split("/")[0]
file = open('{}/CoverageGroups.txt'.format(cov_dir), 'w')
file.write("CoverGroups, CoverPoints and Bins Summary\n")
str_report = vsc.get_coverage_report(details=True)
file.write("{}\n".format(str_report))
file.close()
logging.info("Report:\n" + str_report)
cov_dir = cfg.argv.log_file_name.split("/")[0]
file = open('{}/CoverageReport.txt'.format(cov_dir), 'w')
file.write("Groups Coverage Summary\n")
file.write("Total groups in report: {}\n".format(
@ -139,12 +139,17 @@ class riscv_instr_cov_test:
# TODO: This will get fixed later when we get an inst from template
instruction.assign_attributes()
if (instruction.group.name in ["RV32I", "RV32M", "RV32C", "RV64I",
"RV64M", "RV64C", "RV32F", "RV64F",
"RV32D", "RV64D", "RV32B", "RV64B"]) \
and (instruction.group in rcs.supported_isa):
"RV64M", "RV64C", "RV64F",
"RV64D", "RV32B", "RV64B"]) \
and (instruction.group in rcs.supported_isa):
self.assign_trace_info_to_instr(instruction)
instruction.pre_sample()
self.instr_cg.sample(instruction)
elif instruction.group.name in ["RV32D", "RV32F"] \
and instruction.group in rcs.supported_isa:
self.assign_trace_info_to_instr(instruction)
self.fd_ins.pre_sample(instruction)
self.instr_cg.sample(instruction)
return True
logging.info("Cannot find opcode: {}".format(processed_instr_name))
return False
@ -159,7 +164,10 @@ class riscv_instr_cov_test:
"URET"]:
return
operands = self.trace["operand"].split(",")
instruction.update_src_regs(operands)
if instruction.group.name in ["RV32D", "RV32F"]:
self.fd_ins.update_src_regs(instruction, operands)
else:
instruction.update_src_regs(operands)
gpr_update = self.trace["gpr"].split(";")
if len(gpr_update) == 1 and gpr_update[0] == "":
@ -168,7 +176,10 @@ class riscv_instr_cov_test:
pair = dest.split(":")
if len(pair) != 2:
logging.error("Illegal gpr update format: {}".format(dest))
instruction.update_dst_regs(pair[0], pair[1])
if instruction.group.name in ["RV32D", "RV32F"]:
self.fd_ins.update_dst_regs(instruction, pair[0], pair[1])
else:
instruction.update_dst_regs(pair[0], pair[1])
def process_instr_name(self, instruction):
instruction = instruction.upper()
@ -183,12 +194,12 @@ class riscv_instr_cov_test:
"FMV_S_X": "FMV_W_X",
"FMV_X_S": "FMV_X_W",
# Convert pseudoinstructions
"FMV_S" : "FSGNJ_S",
"FABS_S" : "FSGNJX_S",
"FNEG_S" : "FSGNJN_S",
"FMV_D" : "FSGNJ_D",
"FABS_D" : "FSGNJX_D",
"FNEG_D" : "FSGNJN_D",
"FMV_S": "FSGNJ_S",
"FABS_S": "FSGNJX_S",
"FNEG_S": "FSGNJN_S",
"FMV_D": "FSGNJ_D",
"FABS_D": "FSGNJX_D",
"FNEG_D": "FSGNJN_D",
}
# if instruction is not present in the dictionary,second argument well
# be assigned as default value of passed argument
@ -196,7 +207,5 @@ class riscv_instr_cov_test:
return instruction
cov_test = riscv_instr_cov_test()
cov_test.run_phase()

View file

@ -147,7 +147,7 @@ def parse_iss_yaml(iss, iss_yaml, isa, setting_dir, debug_cmd):
cmd = re.sub("\<path_var\>",
get_env_var(entry['path_var'], debug_cmd=debug_cmd),
cmd)
m = re.search(r"rv(?P<xlen>[0-9]+?)(?P<variant>[a-z]+?)$", isa)
m = re.search(r"rv(?P<xlen>[0-9]+?)(?P<variant>[a-zA-Z_]+?)$", isa)
if m:
cmd = re.sub("\<xlen\>", m.group('xlen'), cmd)
else:
@ -303,7 +303,8 @@ def do_simulate(sim_cmd, simulator, test_list, cwd, sim_opts, seed_gen,
output_dir,
test['test'], i, log_suffix)) + \
(" --target=%s " % (target)) + \
(" --gen_test=%s " % (test['gen_test']))
(" --gen_test=%s " % (test['gen_test'])) + \
(" --seed={} ".format(rand_seed))
else:
cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
(" +UVM_TESTNAME={} ".format(test['gen_test'])) + \
@ -767,7 +768,8 @@ def parse_args(cwd):
parser.add_argument("--target", type=str, default="rv32imc",
help="Run the generator with pre-defined targets: \
rv32imc, rv32i, rv32imafdc, rv64imc, rv64gc")
rv32imc, rv32i, rv32imafdc, rv64imc, rv64gc, \
rv64imafdc")
parser.add_argument("-o", "--output", type=str,
help="Output directory name", dest="o")
parser.add_argument("-tl", "--testlist", type=str, default="",
@ -959,6 +961,9 @@ def load_config(args, cwd):
elif args.target == "ml":
args.mabi = "lp64"
args.isa = "rv64imc"
elif args.target == "rv64imafdc":
args.mabi = "lp64"
args.isa = "rv64imafdc"
else:
sys.exit("Unsupported pre-defined target: {}".format(args.target))
else:

View file

@ -0,0 +1,21 @@
# riscOVPsim configuration file converted from YAML
--variant RV64GC
--override riscvOVPsim/cpu/misa_MXL=2
--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0
--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0
--override riscvOVPsim/cpu/unaligned=T
--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0
--override riscvOVPsim/cpu/user_version=2.3
--override riscvOVPsim/cpu/priv_version=1.11
--override riscvOVPsim/cpu/mvendorid=0
--override riscvOVPsim/cpu/marchid=0
--override riscvOVPsim/cpu/mimpid=0
--override riscvOVPsim/cpu/mhartid=0
--override riscvOVPsim/cpu/cycle_undefined=F
--override riscvOVPsim/cpu/instret_undefined=F
--override riscvOVPsim/cpu/time_undefined=T
--override riscvOVPsim/cpu/reset_address=0x80000000
--override riscvOVPsim/cpu/simulateexceptions=T
--override riscvOVPsim/cpu/defaultsemihost=F
--override riscvOVPsim/cpu/wfi_is_nop=T
--exitonsymbol _exit

View file

@ -0,0 +1,185 @@
/*
* Copyright 2019 Google LLC
*
* 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.
*/
//-----------------------------------------------------------------------------
// Processor feature configuration
//-----------------------------------------------------------------------------
// XLEN
parameter int XLEN = 64;
// Parameter for SATP mode, set to BARE if address translation is not supported
parameter satp_mode_t SATP_MODE = SV39;
// Supported Privileged mode
privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
// Unsupported instructions
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, RV32X};
// Interrupt mode support
mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is
// supported
int max_interrupt_vector_num = 16;
// Physical memory protection support
bit support_pmp = 0;
// Debug mode support
bit support_debug_mode = 0;
// Support delegate trap to user mode
bit support_umode_trap = 0;
// Support sfence.vma instruction
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;
// 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
// ----------------------------------------------------------------------------
// Implemented previlieged CSR list
`ifdef DSIM
privileged_reg_t implemented_csr[] = {
`else
const privileged_reg_t implemented_csr[] = {
`endif
// User mode CSR
USTATUS, // User status
UIE, // User interrupt-enable register
UTVEC, // User trap-handler base address
USCRATCH, // Scratch register for user trap handlers
UEPC, // User exception program counter
UCAUSE, // User trap cause
UTVAL, // User bad address or instruction
UIP, // User interrupt pending
// Supervisor mode CSR
SSTATUS, // Supervisor status
SEDELEG, // Supervisor exception delegation register
SIDELEG, // Supervisor interrupt delegation register
SIE, // Supervisor interrupt-enable register
STVEC, // Supervisor trap-handler base address
SCOUNTEREN, // Supervisor counter enable
SSCRATCH, // Scratch register for supervisor trap handlers
SEPC, // Supervisor exception program counter
SCAUSE, // Supervisor trap cause
STVAL, // Supervisor bad address or instruction
SIP, // Supervisor interrupt pending
SATP, // Supervisor address translation and protection
// Machine mode mode CSR
MVENDORID, // Vendor ID
MARCHID, // Architecture ID
MIMPID, // Implementation ID
MHARTID, // Hardware thread ID
MSTATUS, // Machine status
MISA, // ISA and extensions
MEDELEG, // Machine exception delegation register
MIDELEG, // Machine interrupt delegation register
MIE, // Machine interrupt-enable register
MTVEC, // Machine trap-handler base address
MCOUNTEREN, // Machine counter enable
MSCRATCH, // Scratch register for machine trap handlers
MEPC, // Machine exception program counter
MCAUSE, // Machine trap cause
MTVAL, // Machine bad address or instruction
MIP, // Machine interrupt pending
// Floating point CSR
FCSR // Floating point control and status
};
// Implementation-specific custom CSRs
bit [11:0] custom_csr[] = {
};
// ----------------------------------------------------------------------------
// Supported interrupt/exception setting, used for functional coverage
// ----------------------------------------------------------------------------
`ifdef DSIM
interrupt_cause_t implemented_interrupt[] = {
`else
const interrupt_cause_t implemented_interrupt[] = {
`endif
U_SOFTWARE_INTR,
S_SOFTWARE_INTR,
M_SOFTWARE_INTR,
U_TIMER_INTR,
S_TIMER_INTR,
M_TIMER_INTR,
U_EXTERNAL_INTR,
S_EXTERNAL_INTR,
M_EXTERNAL_INTR
};
`ifdef DSIM
exception_cause_t implemented_exception[] = {
`else
const exception_cause_t implemented_exception[] = {
`endif
INSTRUCTION_ACCESS_FAULT,
ILLEGAL_INSTRUCTION,
BREAKPOINT,
LOAD_ADDRESS_MISALIGNED,
LOAD_ACCESS_FAULT,
STORE_AMO_ADDRESS_MISALIGNED,
STORE_AMO_ACCESS_FAULT,
ECALL_UMODE,
ECALL_SMODE,
ECALL_MMODE,
INSTRUCTION_PAGE_FAULT,
LOAD_PAGE_FAULT,
STORE_AMO_PAGE_FAULT
};

View file

@ -0,0 +1,149 @@
# Copyright Google LLC
#
# 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 test list format
# --------------------------------------------------------------------------------
# test : Assembly test name
# description : Description of this test
# gen_opts : Instruction generator options
# iterations : Number of iterations of this test
# no_iss : Enable/disable ISS simulator (Optional)
# gen_test : Test name used by the instruction generator
# asm_tests : Path to directed, hand-coded assembly test file or directory
# rtl_test : RTL simulation test name
# cmp_opts : Compile options passed to the instruction generator
# sim_opts : Simulation options passed to the instruction generator
# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional)
# compare_opts : Options for the RTL & ISS trace comparison
# gcc_opts : gcc compile options
# --------------------------------------------------------------------------------
- import: <riscv_dv_root>/target/rv64imc/testlist.yaml
- test: riscv_machine_mode_rand_test
description: >
Machine mode random instruction test
iterations: 2
gen_test: riscv_instr_base_test
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=5
+boot_mode=m
rtl_test: core_base_test
- test: riscv_privileged_mode_rand_test
description: >
Random previliged mode test
iterations: 2
gen_test: riscv_instr_base_test
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=5
rtl_test: core_base_test
# TODO: Only enable booting into U-mode for now, as OVPsim doesn't support some debug CSRs
- test: riscv_invalid_csr_test
description: >
Boot core into random privileged mode and generate csr accesses to invalid CSRs (at a higher priv mode)
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+instr_cnt=6000
+num_of_sub_program=0
+enable_access_invalid_csr_level=1
+boot_mode=u
rtl_test: core_invalid_csr_test
sim_opts: >
+require_signature_addr=1
# TODO: Re-enable this test after all the data/instruction page organization changes are done
- test: riscv_page_table_exception_test
description: >
Test random page table exception handling. An exception handling routine is
designed to fix the page table error and resume execution.
iterations: 0
gen_test: riscv_rand_instr_test
gen_opts: >
+enable_page_table_exception=1
rtl_test: core_base_test
- test: riscv_sfence_exception_test
description: >
Random instruction test with S.FENCE exceptions
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+allow_sfence_exception=1
rtl_test: core_base_test
- test: riscv_amo_test
description: >
RISC-V atomic instruction extension test
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+instr_cnt=5000
+num_of_sub_program=5
+directed_instr_0=riscv_lr_sc_instr_stream,10
+directed_instr_1=riscv_amo_instr_stream,10
rtl_test: core_base_test
- test: riscv_floating_point_arithmetic_test
description: >
Enable floating point instructions
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=0
+no_fence=1
+no_data_page=1
+no_branch_jump=1
+enable_floating_point=1
+boot_mode=m
iterations: 1
gen_test: riscv_instr_base_test
rtl_test: core_base_test
- test: riscv_floating_point_rand_test
description: >
Enable floating point instructions
gen_opts: >
+enable_floating_point=1
+instr_cnt=10000
+num_of_sub_program=5
+directed_instr_0=riscv_load_store_rand_instr_stream,4
+directed_instr_1=riscv_loop_instr,4
+directed_instr_2=riscv_multi_page_load_store_instr_stream,4
+directed_instr_3=riscv_mem_region_stress_test,4
+directed_instr_4=riscv_jal_instr,4
iterations: 1
gen_test: riscv_instr_base_test
rtl_test: core_base_test
- test: riscv_floating_point_mmu_stress_test
description: >
Test with different patterns of load/store instructions, stress test MMU
operations.
iterations: 2
gen_test: riscv_instr_base_test
gen_opts: >
+instr_cnt=5000
+num_of_sub_program=5
+enable_floating_point=1
+directed_instr_0=riscv_load_store_rand_instr_stream,40
+directed_instr_1=riscv_load_store_hazard_instr_stream,40
+directed_instr_2=riscv_multi_page_load_store_instr_stream,10
+directed_instr_3=riscv_mem_region_stress_test,10
rtl_test: core_base_test