Update google_riscv-dv to google/riscv-dv@3467c37

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

* add VCS compile option for unicode (Udi Jonnalagadda)
* Add missing license header (aneels3)
* [Docs] Fix broken links and typos (db434)
* Add support for RV32D (ishita71)
* Fix google/riscv-dv#733 (aneels3)
* Fix Spike Issue (aneels3)
* add riscv_reg and riscv_privil_reg (pvipsyash)
* fix target issue for foating point (pvipsyash)
* add rv32fc target (pvipsyash)
* add riscv_floating_point_instr (pvipsyash)
* Add defines for floating point instructions (ShraddhaDevaiya)

Signed-off-by: Udi Jonnalagadda <udij@google.com>
This commit is contained in:
Udi Jonnalagadda 2020-10-30 15:59:26 -07:00 committed by udinator
parent 999140ded8
commit 7aeb2072aa
25 changed files with 1215 additions and 243 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 39797b2f07784e775149a4f05c90fee2427124e5
rev: 3467c3777cb428b2e30b30b7f895a8fd73873d4f
}
}

View file

@ -21,7 +21,7 @@ A standard CSV format is defined for the instruction execution trace. It's used
- The same format as the GPR field
- binary: Instruction binary
- instr_str: Instruction in assmebly format
- instr_str: Instruction in assembly format
- operand: Instruction operands
- pad: Unused

View file

@ -1,7 +1,7 @@
End to End Simulation Flow
==========================
We have collaborated with LowRISC to apply this flow for `IBEX RISC-V core verification`_.
We have collaborated with lowRISC to apply this flow for `Ibex RISC-V core verification`_.
You can use it as a reference to setup end-to-end co-simulation flow.
This repo is still under active development, this is the recommended approach to
customize the instruction generator while keeping the effort of merging
@ -27,13 +27,13 @@ upstream changes to a minimum.
``--sim_opts="+uvm_set_inst_override=riscv_asm_program_gen,<extended
class>,'uvm_test_top.asm_gen'"``
You can refer to `riscv-dv extension for ibex`_ for a working example.
You can refer to `riscv-dv extension for Ibex`_ for a working example.
We have plan to open-source the end-to-end environments of other advanced RISC-V
processors. Stay tuned!
.. _IBEX RISC-V core verification: https://github.com/lowRISC/ibex/blob/master/doc/verification.rst
.. _riscv-dv extension for ibex: https://github.com/lowRISC/ibex/blob/master/dv/uvm/Makefile#L68
.. _Ibex RISC-V core verification: https://github.com/lowRISC/ibex/blob/master/doc/03_reference/verification.rst
.. _riscv-dv extension for Ibex: https://github.com/lowRISC/ibex/blob/master/dv/uvm/core_ibex/Makefile#L110

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 logging
import vsc
from pygen_src.isa.riscv_instr import riscv_instr
from pygen_src.riscv_instr_pkg import (pkg_ins, riscv_fpr_t, riscv_instr_format_t,
riscv_instr_category_t)
@vsc.randobj
class riscv_floating_point_instr(riscv_instr):
def __init__(self):
super().__init__()
self.fs1 = vsc.rand_enum_t(riscv_fpr_t)
self.fs2 = vsc.rand_enum_t(riscv_fpr_t)
self.fs3 = vsc.rand_enum_t(riscv_fpr_t)
self.fd = vsc.rand_enum_t(riscv_fpr_t)
self.has_fs1 = vsc.bit_t(1, 1)
self.has_fs2 = vsc.bit_t(1, 1)
self.has_fs3 = vsc.bit_t(1)
self.has_fd = vsc.bit_t(1, 1)
def convert2asm(self, prefix = " "):
asm_str = pkg_ins.format_string(string = self.get_instr_name(),
length = pkg_ins.MAX_INSTR_STR_LEN)
if self.format == riscv_instr_format_t.I_FORMAT:
if self.category == riscv_instr_category_t.LOAD:
asm_str = "{}{}, {}({})".format(asm_str, self.fd.name,
self.get_imm(), self.rs1.name)
elif self.instr_name.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_W_D', 'FCVT_WU_D']:
asm_str = "{}{}, {}".format(asm_str, self.rd.name, self.fs1.name)
elif self.instr_name.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']:
asm_str = "{}{}, {}".format(asm_str, self.fd.name, self.rs1.name)
else:
asm_str = "{}{}, {}".format(asm_str, self.fd.name, self.fs1.name)
elif self.format == riscv_instr_format_t.S_FORMAT:
asm_str = "{}{}, {}({})".format(asm_str, self.fs2.name, self.get_imm(), self.rs1.name)
elif self.format == riscv_instr_format_t.R_FORMAT:
if self.category == riscv_instr_category_t.COMPARE:
asm_str = "{}{}, {}, {}".format(asm_str, self.rd.name, self.fs1.name, self.fs2.name)
elif self.instr_name.name in ['FCLASS_S', 'FCLASS_D']:
asm_str = "{}{}, {}".format(asm_str, self.rd.name, self.fs1.name)
else:
asm_str = "{}{}, {}, {}".format(asm_str, self.fd.name, self.fs1.name, self.fs2.name)
elif self.format == riscv_instr_format_t.R4_FORMAT:
asm_str = "{}{}, {}, {}, {}".format(
asm_str, self.fd.name, self.fs1.name, self.fs2.name, self.fs3.name)
elif self.format == riscv_instr_format_t.CL_FORMAT:
asm_str = "{}{}, {}({})".format(asm_str, self.fd.name, self.get_imm(), self.rs1.name)
elif self.format == riscv_instr_format_t.CS_FORMAT:
asm_str = "{}{}, {}({})".format(asm_str, self.fs2.name,
self.get_imm(), self.rs1.name)
else:
logging.error("Unsupported floating point format: %0s", self.format.name)
if self.comment != "":
asm_str = asm_str + " #" + self.comment
return asm_str.lower()
def set_rand_mode(self):
self.has_rs1 = 0
self.has_rs2 = 0
self.rd = 0
self.has_imm = 0
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.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.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.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 %0s", self.format.name)
def pre_randomize(self):
super().pre_randomize()
with vsc.raw_mode():
self.fs1.rand_mode = bool(self.has_fs1)
self.fs2.rand_mode = bool(self.has_fs2)
self.fs3.rand_mode = bool(self.has_fs3)
self.fd.rand_mode = bool(self.has_fd)
# coverage related functons
def update_src_regs(self, operands = []):
pass
def update_dst_regs(self, reg_name, val_str):
pass
def get_fpr(self, reg_name):
pass
def get_pre_sample(self):
pass
def get_fp_operand_sign(self, value, idx):
pass
def check_hazard_condition(self, pre_instr):
pass

View file

@ -111,11 +111,9 @@ class riscv_instr:
self.imm[11:6] == 0
@classmethod
def register(cls, instr_name):
logging.info("Registering %s", instr_name.name)
cls.instr_registry[instr_name] = 1
if instr_name is None:
print("\n")
def register(cls, instr_name, instr_group):
logging.info("Registering {}".format(instr_name.name))
cls.instr_registry[instr_name] = instr_group
return 1
@classmethod
@ -123,10 +121,10 @@ class riscv_instr:
cls.instr_names.clear()
cls.instr_group.clear()
cls.instr_category.clear()
for instr_name, values in cls.instr_registry.items():
for instr_name, instr_group in cls.instr_registry.items():
if instr_name in rcs.unsupported_instr:
continue
instr_inst = cls.create_instr(instr_name)
instr_inst = cls.create_instr(instr_name, instr_group)
cls.instr_template[instr_name] = instr_inst
if not instr_inst.is_supported(cfg):
@ -153,10 +151,13 @@ class riscv_instr:
cls.create_csr_filter(cfg)
@classmethod
def create_instr(cls, instr_name):
# Importing get_object here to eliminate the Cyclic dependency for DEFINE_INSTR
from pygen_src.riscv_utils import get_object
instr_inst = get_object(instr_name)
def create_instr(cls, instr_name, instr_group):
try:
module_name = import_module("pygen_src.isa." + instr_group.name.lower() + "_instr")
instr_inst = eval("module_name.riscv_" + instr_name.name + "_instr()")
except Exception:
logging.critical("Failed to create instr: {}".format(instr_name.name))
sys.exit(1)
return instr_inst
def is_supported(self, cfg):

View file

@ -0,0 +1,71 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
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.FLD, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSD, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMADD_D, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMSUB_D, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FNMSUB_D, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FNMADD_D, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FADD_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSUB_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMUL_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FDIV_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSQRT_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJ_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJN_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJX_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMIN_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMAX_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_S_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_D_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FEQ_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FLT_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FLE_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCLASS_D, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_W_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_WU_D, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_D_W, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_D_WU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32D, g=globals())

View file

@ -0,0 +1,27 @@
"""
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_FC_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t, imm_t)
DEFINE_FC_INSTR(riscv_instr_name_t.C_FLD, riscv_instr_format_t.CL_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32DC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FSD, riscv_instr_format_t.CS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32DC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FLDSP, riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32DC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FSDSP, riscv_instr_format_t.CSS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32DC, imm_t.UIMM, g=globals())

View file

@ -0,0 +1,71 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
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.FLW, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSW, riscv_instr_format_t.S_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMADD_S, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMSUB_S, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FNMSUB_S, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FNMADD_S, riscv_instr_format_t.R4_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FADD_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSUB_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMUL_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FDIV_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSQRT_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJ_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJN_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FSGNJX_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMIN_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMAX_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_W_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_WU_S, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMV_X_W, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FEQ_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FLT_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FLE_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.COMPARE, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCLASS_S, riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_S_W, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FCVT_S_WU, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())
DEFINE_FP_INSTR(riscv_instr_name_t.FMV_W_X, riscv_instr_format_t.I_FORMAT,
riscv_instr_category_t.ARITHMETIC, riscv_instr_group_t.RV32F, g=globals())

View file

@ -0,0 +1,27 @@
"""
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_FC_INSTR
from pygen_src.riscv_instr_pkg import (riscv_instr_name_t, riscv_instr_format_t,
riscv_instr_category_t, riscv_instr_group_t, imm_t)
DEFINE_FC_INSTR(riscv_instr_name_t.C_FLW, riscv_instr_format_t.CL_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32FC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FSW, riscv_instr_format_t.CS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32FC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FLWSP, riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.LOAD, riscv_instr_group_t.RV32FC, imm_t.UIMM, g=globals())
DEFINE_FC_INSTR(riscv_instr_name_t.C_FSWSP, riscv_instr_format_t.CSS_FORMAT,
riscv_instr_category_t.STORE, riscv_instr_group_t.RV32FC, imm_t.UIMM, g=globals())

View file

@ -25,6 +25,7 @@ from pygen_src.riscv_instr_pkg import (pkg_ins, privileged_reg_t,
misa_ext_t, riscv_instr_group_t)
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_data_page_gen import riscv_data_page_gen
from pygen_src.riscv_privileged_common_seq import riscv_privileged_common_seq
from pygen_src.riscv_utils import factory
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
@ -241,18 +242,17 @@ class riscv_asm_program_gen:
def gen_init_section(self, hart):
string = pkg_ins.format_string("init:", pkg_ins.LABEL_STR_LEN)
self.instr_stream.append(string)
if (cfg.enable_floating_point):
self.init_floating_point_gpr()
self.init_gpr()
# Init stack pointer to point to the end of the user stack
string = "{}la x{}, {}user_stack_end".format(
pkg_ins.indent, cfg.sp.value, pkg_ins.hart_prefix(hart))
self.instr_stream.append(string)
if (cfg.enable_floating_point):
self.init_floating_point_gpr()
if (cfg.enable_vector_extension):
self.init_vector_engine()
self.core_is_initialized()
self.gen_dummy_csr_write()
if (rcs.support_pmp):
string = pkg_ins.indent + "j main"
self.instr_stream.append(string)
@ -338,7 +338,50 @@ class riscv_asm_program_gen:
self.instr_stream.append(init_string)
def init_floating_point_gpr(self):
pass
for i in range(rcs.NUM_FLOAT_GPR):
# TODO randselect
'''
vsc.randselect([(1, lambda:self.init_floating_point_gpr_with_spf(i)),
('RV64D' in rcs.supported_isa, lambda:self.init_floating_point_gpr_with_dpf(i))])
'''
self.init_floating_point_gpr_with_spf(i)
# Initialize rounding mode of FCSR
fsrmi_instr = "{}fsrmi {}".format(pkg_ins.indent, cfg.fcsr_rm)
self.instr_stream.append(fsrmi_instr)
def init_floating_point_gpr_with_spf(self, int_floating_gpr):
imm = self.get_rand_spf_value()
li_instr = "{}li x{}, {}".format(pkg_ins.indent, cfg.gpr[0].value, hex(imm))
fmv_instr = "{}fmv.w.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr,
cfg.gpr[0].value)
self.instr_stream.extend((li_instr, fmv_instr))
def init_floating_point_gpr_with_dpf(self, int_floating_gpr):
imm = vsc.bit_t(64)
imm = self.get_rand_dpf_value()
int_gpr1 = cfg.gpr[0].value
int_gpr2 = cfg.gpr[1].value
li_instr0 = "{}li x{}, {}".format(pkg_ins.indent, int_gpr1, imm[63:32])
# shift to upper 32bits
for _ in range(2):
slli_instr = "{}slli x{}, x{}, 16".format(pkg_ins.indent, int_gpr1, int_gpr1)
li_instr1 = "{}li x{}, {}".format(pkg_ins.indent, int_gpr2, imm[31:0])
or_instr = "{}or x{}, x{}, x{}".format(pkg_ins.indent, int_gpr2, int_gpr2, int_gpr1)
fmv_instr = "{}fmv.d.x f{}, x{}".format(pkg_ins.indent, int_floating_gpr, int_gpr2)
self.instr_stream.extend((li_instr0, slli_instr, li_instr1, or_instr, fmv_instr))
# Get a random single precision floating value
def get_rand_spf_value(self):
# TODO randcase
value = random.randrange(0, 2**32 - 1)
return value
# Get a random double precision floating value
def get_rand_dpf_value(self):
value = vsc.bit_t(64)
# TODO randcase
return value
def init_vector_engine(self):
pass
@ -384,26 +427,42 @@ class riscv_asm_program_gen:
if(cfg.virtual_addr_translation_on):
self.page_table_list.process_page_table(instr)
self.gen_section(pkg_ins.get_label("process_pt", hart), instr)
# Commenting for now
# self.setup_epc(hart)
if(rcs.support_pmp):
self.gen_privileged_mode_switch_routine(hart)
self.setup_epc(hart)
self.gen_privileged_mode_switch_routine(hart)
def gen_privileged_mode_switch_routine(self, hart):
pass
privil_seq = riscv_privileged_common_seq()
for i in range(len(rcs.supported_privileged_mode)):
instr = []
csr_handshake = []
if(rcs.supported_privileged_mode[i] != cfg.init_privileged_mode.name):
continue
logging.info("Generating privileged mode routing for {}"
.format(rcs.supported_privileged_mode[i]))
# Enter Privileged mode
privil_seq.hart = hart
privil_seq.randomize()
privil_seq.enter_privileged_mode(rcs.supported_privileged_mode[i], instr)
# TODO
if cfg.require_signature_addr:
pass
self.instr_stream.extend(instr)
def setup_epc(self, hart):
instr = []
instr.append("la x{}, {}init".format(cfg.gpr[0].value, pkg_ins.hart_prefix(hart)))
# if(cfg.virtual_addr_translation_on):
# instr.append("slli x{}, x{}")
# TODO
mode_name = cfg.init_privileged_mode
instr.append("csrw mepc, x{}".format(cfg.gpr[0].value))
if(not rcs.support_pmp): # TODO
instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.name.lower()))
if(cfg.virtual_addr_translation_on):
# For supervisor and user mode, use virtual address instead of physical address.
# Virtual address starts from address 0x0, here only the lower 12 bits are kept
# as virtual address offset.
instr.append("slli x{}, x{}, {}".format(cfg.gpr[0].value,
cfg.gpr[0].value, rcs.XLEN - 12) +
"srli x{}, x{}, {}".format(cfg.gpr[0].value,
cfg.gpr[0].value, rcs.XLEN - 12))
mode_name = cfg.init_privileged_mode.name
instr.append("csrw {}, x{}".format(hex(privileged_reg_t.MEPC), cfg.gpr[0].value))
if not rcs.support_pmp:
instr.append("j {}init_{}".format(pkg_ins.hart_prefix(hart), mode_name.lower()))
self.gen_section(pkg_ins.get_label("mepc_setup", hart), instr)
def setup_pmp(self, hart):

View file

@ -15,9 +15,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
from pygen_src.riscv_instr_pkg import imm_t
from pygen_src.isa.riscv_instr import riscv_instr
from pygen_src.isa.riscv_compressed_instr import riscv_compressed_instr
from pygen_src.isa.riscv_floating_point_instr import riscv_floating_point_instr
def DEFINE_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=imm_t.IMM, g=globals()):
# Regular integer instruction
def DEFINE_INSTR(instr_n, instr_format, instr_category,
instr_group, imm_tp=imm_t.IMM, g=globals()):
class_name = "riscv_{}_instr".format(instr_n.name)
def __init__(self):
@ -32,12 +35,14 @@ def DEFINE_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=imm_
self.set_rand_mode()
NewClass = type(class_name, (riscv_instr,), {
"__init__": __init__,
"valid": riscv_instr.register(instr_n)
"valid": riscv_instr.register(instr_n, instr_group)
})
g[class_name] = NewClass
def DEFINE_C_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=imm_t.IMM, g=globals()):
# Compressed instruction
def DEFINE_C_INSTR(instr_n, instr_format, instr_category,
instr_group, imm_tp=imm_t.IMM, g=globals()):
class_name = "riscv_{}_instr".format(instr_n.name)
def __init__(self):
@ -51,7 +56,49 @@ def DEFINE_C_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp=im
self.set_rand_mode()
NewClass = type(class_name, (riscv_compressed_instr,), {
"__init__": __init__,
"valid": riscv_compressed_instr.register(instr_n)
"valid": riscv_compressed_instr.register(instr_n, instr_group)
})
g[class_name] = NewClass
# Floating point instruction
def DEFINE_FP_INSTR(instr_n, instr_format, instr_category,
instr_group, imm_tp=imm_t.IMM, g=globals()):
class_name = "riscv_{}_instr".format(instr_n.name)
def __init__(self):
riscv_floating_point_instr.__init__(self)
self.instr_name = instr_n
self.format = instr_format
self.category = instr_category
self.group = instr_group
self.imm_type = imm_tp
self.set_imm_len()
self.set_rand_mode()
NewClass = type(class_name, (riscv_floating_point_instr,), {
"__init__": __init__,
"valid": riscv_floating_point_instr.register(instr_n, instr_group)
})
g[class_name] = NewClass
# Floating point compressed instruction
def DEFINE_FC_INSTR(instr_n, instr_format, instr_category,
instr_group, imm_tp=imm_t.IMM, g=globals()):
class_name = "riscv_{}_instr".format(instr_n.name)
def __init__(self):
riscv_compressed_instr.__init__(self)
self.instr_name = instr_n
self.format = instr_format
self.category = instr_category
self.group = instr_group
self.imm_type = imm_tp
self.set_imm_len()
self.set_rand_mode()
NewClass = type(class_name, (riscv_compressed_instr,), {
"__init__": __init__,
"valid": riscv_compressed_instr.register(instr_n, instr_group)
})
g[class_name] = NewClass

View file

@ -16,7 +16,6 @@ import argparse
import logging
import sys
import vsc
from bitstring import BitArray
from importlib import import_module
from pygen_src.riscv_instr_pkg import (mtvec_mode_t, f_rounding_mode_t,
riscv_reg_t, privileged_mode_t,
@ -47,25 +46,25 @@ class riscv_instr_gen_config:
# init_privileged_mode default to MACHINE_MODE
self.init_privileged_mode = privileged_mode_t.MACHINE_MODE
self.mstatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.mie = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.sstatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.sie = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.ustatus = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.uie = BitArray(bin(0b0), length=rcs.XLEN - 1)
self.mstatus = vsc.rand_bit_t(rcs.XLEN - 1)
self.mie = vsc.rand_bit_t(rcs.XLEN - 1)
self.sstatus = vsc.rand_bit_t(rcs.XLEN - 1)
self.sie = vsc.rand_bit_t(rcs.XLEN - 1)
self.ustatus = vsc.rand_bit_t(rcs.XLEN - 1)
self.uie = vsc.rand_bit_t(rcs.XLEN - 1)
self.mstatus_mprv = 0
self.mstatus_mxr = 0
self.mstatus_sum = 0
self.mstatus_tvm = 0
self.mstatus_fs = BitArray(bin(0b0), length=2)
self.mstatus_vs = BitArray(bin(0b0), length=2)
self.mstatus_mprv = vsc.rand_bit_t(1)
self.mstatus_mxr = vsc.rand_bit_t(1)
self.mstatus_sum = vsc.rand_bit_t(1)
self.mstatus_tvm = vsc.rand_bit_t(1)
self.mstatus_fs = vsc.rand_bit_t(2)
self.mstatus_vs = vsc.rand_bit_t(2)
self.mtvec_mode = vsc.rand_enum_t(mtvec_mode_t)
self.tvec_alignment = vsc.rand_uint8_t(self.argv.tvec_alignment)
self.fcsr_rm = list(map(lambda csr_rm: csr_rm.name, f_rounding_mode_t))
self.enable_sfence = 0
self.fcsr_rm = vsc.rand_enum_t(f_rounding_mode_t)
self.enable_sfence = vsc.rand_bit_t(1)
self.gpr = []
# Helper fields for gpr
@ -225,51 +224,59 @@ class riscv_instr_gen_config:
else:
vsc.soft(self.tvec_alignment == (rcs.XLEN * 4) / 8)
@vsc.constraint
def floating_point_c(self):
if self.enable_floating_point:
self.mstatus_fs == 1
else:
self.mstatus_fs == 0
@vsc.constraint
def mstatus_c(self):
if self.set_mstatus_mprv:
self.mstatus_mprv == 1
else:
self.mstatus_mprv == 0
if rcs.SATP_MODE == "BARE":
self.mstatus_mxr == 0
self.mstatus_sum == 0
self.mstatus_tvm == 0
def check_setting(self):
support_64b = 0
support_128b = 0
# list of satp_mode_t from riscv_core_setting.py
stp_md_lst = rcs.SATP_MODE
# list of riscv_instr_group_t with names of riscv_instr_name_t in it.
supported_isa_lst = list(map(lambda z: z.name, riscv_instr_group_t))
# check the valid isa support
for x in rcs.supported_isa:
if x == (supported_isa_lst[1] or supported_isa_lst[3] or supported_isa_lst[5] or
supported_isa_lst[8] or supported_isa_lst[11] or supported_isa_lst[13] or
supported_isa_lst[19]):
if x in ["RV64I", "RV64M", "RV64A", "RV64F", "RV64D", "RV64C", "RV64B"]:
support_64b = 1
logging.info("support_64b=%d" % support_64b)
logging.debug("Supported ISA=%s" % x)
elif x == (supported_isa_lst[14] or supported_isa_lst[15]):
logging.info("support_64b = {}".format(support_64b))
logging.debug("Supported ISA = {}".format(x))
elif x in ["RV128I", "RV128C"]:
support_128b = 1
logging.info("support_128b=%d" % support_128b)
logging.debug("Supported ISA=%s" % x)
logging.info("support_128b = {}".format(support_128b))
logging.debug("Supported ISA = {}".format(x))
if (support_128b == 1) and (rcs.XLEN != 128):
if support_128b and rcs.XLEN != 128:
logging.critical("XLEN should be set to 128 based on \
riscv_core_setting.supported_isa setting")
logging.info("XLEN Value=%d" % rcs.XLEN)
logging.info("XLEN Value = {}".format(rcs.XLEN))
sys.exit("XLEN is not equal to 128, set it Accordingly!")
if (support_128b == 0) and (support_64b == 1) and (rcs.XLEN != 64):
if not(support_128b) and support_64b and rcs.XLEN != 64:
logging.critical("XLEN should be set to 64 based on \
riscv_core_setting.supported_isa setting")
logging.info("XLEN Value=%d" % rcs.XLEN)
logging.info("XLEN Value = {}".format(rcs.XLEN))
sys.exit("XLEN is not equal to 64, set it Accordingly!")
if not(support_128b or support_64b) and (rcs.XLEN != 32):
if not(support_128b or support_64b) and rcs.XLEN != 32:
logging.critical("XLEN should be set to 32 based on \
riscv_core_setting.supported_isa setting")
logging.info("XLEN Value=%d" % rcs.XLEN)
logging.info("XLEN Value = {}".format(rcs.XLEN))
sys.exit("XLEN is not equal to 32, set it Accordingly!")
if not(support_128b or support_64b) and not(('SV32' in stp_md_lst) or
('BARE' in stp_md_lst)):
logging.critical("SATP mode is not supported for RV32G ISA")
logging.info(stp_md_lst)
if not(support_128b or support_64b) and not(rcs.SATP_MODE in ['SV32', "BARE"]):
logging.critical("SATP mode {} is not supported for RV32G ISA".format(rcs.SATP_MODE))
sys.exit("Supported SATP mode is not provided")
# TODO
@ -309,12 +316,12 @@ class riscv_instr_gen_config:
self.reserved_regs.append(self.sp)
self.reserved_regs.append(self.scratch_reg)
self.min_stack_len_per_program = 2 * (rcs.XLEN / 8)
logging.info("min_stack_len_per_program value = %d"
% self.min_stack_len_per_program)
logging.info("min_stack_len_per_program value = {}"
.format(self.min_stack_len_per_program))
self.check_setting() # check if the setting is legal
if self.init_privileged_mode == privileged_mode_t.USER_MODE:
logging.info("mode=%s" % "USER_MODE")
logging.info("mode = USER_MODE")
self.no_wfi = 1
def get_invalid_priv_lvl_csr(self):

View file

@ -0,0 +1,79 @@
"""
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 vsc
from importlib import import_module
from pygen_src.riscv_instr_pkg import privileged_level_t, reg_field_access_t, privileged_reg_t
from pygen_src.riscv_reg import riscv_reg
from pygen_src.riscv_instr_gen_config import cfg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
# RISC-V privileged register class
@vsc.randobj
class riscv_privil_reg(riscv_reg):
def __init__(self):
super().__init__()
def init_reg(self, reg_name):
super().init_reg(reg_name)
# ---------------Machine mode register ----------------
# Machine status Register
if(reg_name == privileged_reg_t.MSTATUS):
self.privil_level = privileged_level_t.M_LEVEL
self.add_field("UIE", 1, reg_field_access_t.WARL)
self.add_field("SIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI0", 1, reg_field_access_t.WPRI)
self.add_field("MIE", 1, reg_field_access_t.WARL)
self.add_field("UPIE", 1, reg_field_access_t.WARL)
self.add_field("SPIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI1", 1, reg_field_access_t.WPRI)
self.add_field("MPIE", 1, reg_field_access_t.WARL)
self.add_field("SPP", 1, reg_field_access_t.WLRL)
self.add_field("VS", 2, reg_field_access_t.WARL)
self.add_field("MPP", 2, reg_field_access_t.WLRL)
self.add_field("FS", 2, reg_field_access_t.WARL)
self.add_field("XS", 2, reg_field_access_t.WARL)
self.add_field("MPRV", 1, reg_field_access_t.WARL)
self.add_field("SUM", 1, reg_field_access_t.WARL)
self.add_field("MXR", 1, reg_field_access_t.WARL)
self.add_field("TVM", 1, reg_field_access_t.WARL)
self.add_field("TW", 1, reg_field_access_t.WARL)
self.add_field("TSR", 1, reg_field_access_t.WARL)
if(rcs.XLEN == 32):
self.add_field("WPRI3", 8, reg_field_access_t.WPRI)
else:
self.add_field("WPRI3", 9, reg_field_access_t.WPRI)
self.add_field("UXL", 2, reg_field_access_t.WARL)
self.add_field("SXL", 2, reg_field_access_t.WARL)
self.add_field("WPRI4", rcs.XLEN - 37, reg_field_access_t.WPRI)
self.add_field("SD", 1, reg_field_access_t.WARL)
# Machine interrupt-enable register
elif(reg_name == privileged_reg_t.MIE):
self.privil_level = privileged_level_t.M_LEVEL
self.add_field("USIE", 1, reg_field_access_t.WARL)
self.add_field("SSIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI0", 1, reg_field_access_t.WPRI)
self.add_field("MSIE", 1, reg_field_access_t.WARL)
self.add_field("UTIE", 1, reg_field_access_t.WARL)
self.add_field("STIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI1", 1, reg_field_access_t.WPRI)
self.add_field("MTIE", 1, reg_field_access_t.WARL)
self.add_field("UEIE", 1, reg_field_access_t.WARL)
self.add_field("SEIE", 1, reg_field_access_t.WARL)
self.add_field("WPEI2", 1, reg_field_access_t.WPRI)
self.add_field("MEIE", 1, reg_field_access_t.WARL)
self.add_field("WPRI3", rcs.XLEN - 12, reg_field_access_t.WPRI)
else:
logging.error("reg %0s is not supported yet", reg_name.name)

View file

@ -0,0 +1,121 @@
"""
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 vsc
from importlib import import_module
from pygen_src.riscv_instr_pkg import pkg_ins, privileged_reg_t
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_privil_reg import riscv_privil_reg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
@vsc.randobj
class riscv_privileged_common_seq():
def __init___(self):
self.hart = 0
self.mstatus = vsc.attr(riscv_privil_reg)
self.mie = vsc.attr(riscv_privil_reg)
def enter_privileged_mode(self, mode, instrs):
label = pkg_ins.format_string("{}init_{}:"
.format(pkg_ins.hart_prefix(self.hart), mode),
pkg_ins.LABEL_STR_LEN)
ret_instr = ["mret"]
regs = vsc.list_t(vsc.attr(riscv_privil_reg()))
label = label.lower()
self.setup_mmode_reg(mode, regs)
if mode == "SUPERVISOR_MODE":
self.setup_smode_reg(mode, regs)
if mode == "USER_MODE":
self.setup_umode_reg(mode, regs)
if cfg.virtual_addr_translation_on:
self.setup_satp(instrs)
self.gen_csr_instr(regs, instrs)
# Use mret/sret to switch to the target privileged mode
instrs.append(ret_instr[0])
for i in range(len(instrs)):
instrs[i] = pkg_ins.indent + instrs[i]
instrs.insert(0, label)
# TODO
def setup_mmode_reg(self, mode, regs):
self.mstatus = riscv_privil_reg()
self.mstatus.init_reg(privileged_reg_t.MSTATUS)
if cfg.randomize_csr:
self.mstatus.set_val(cfg.mstatus)
self.mstatus.set_field("MPRV", cfg.mstatus_mprv)
self.mstatus.set_field("MXR", cfg.mstatus_mxr)
self.mstatus.set_field("SUM", cfg.mstatus_sum)
self.mstatus.set_field("TVM", cfg.mstatus_tvm)
self.mstatus.set_field("TW", cfg.set_mstatus_tw)
self.mstatus.set_field("FS", cfg.mstatus_fs)
self.mstatus.set_field("VS", cfg.mstatus_vs)
if (not("SUPERVISOR_MODE" in rcs.supported_privileged_mode) and (rcs.XLEN != 32)):
self.mstatus.set_field("SXL", 0)
elif rcs.XLEN == 64:
self.mstatus.set_field("SXL", 2)
if (not("USER_MODE" in rcs.supported_privileged_mode) and (rcs.XLEN != 32)):
self.mstatus.set_field("UXL", 0)
elif rcs.XLEN == 64:
self.mstatus.set_field("UXL", 2)
self.mstatus.set_field("XS", 0)
self.mstatus.set_field("SD", 0)
self.mstatus.set_field("UIE", 0)
# Set the previous privileged mode as the target mode
self.mstatus.set_field("MPP", 3) # TODO pass mode value as parameter
self.mstatus.set_field("SPP", 0)
# Enable Interrupt
self.mstatus.set_field("MPIE", cfg.enable_interrupt)
self.mstatus.set_field("MIE", cfg.enable_interrupt)
self.mstatus.set_field("SPIE", cfg.enable_interrupt)
self.mstatus.set_field("SIE", cfg.enable_interrupt)
self.mstatus.set_field("UPIE", cfg.enable_interrupt)
self.mstatus.set_field("UIE", rcs.support_umode_trap)
logging.info("self.mstatus_val: {}".format(hex(self.mstatus.get_val())))
regs.append(self.mstatus)
# Enable external and timer interrupt
if "MIE" in rcs.implemented_csr:
self.mie = riscv_privil_reg()
self.mie.init_reg(privileged_reg_t.MIE)
if cfg.randomize_csr:
self.mie.set_val(cfg.mie)
self.mie.set_field("UEIE", cfg.enable_interrupt)
self.mie.set_field("SEIE", cfg.enable_interrupt)
self.mie.set_field("MEIE", cfg.enable_interrupt)
self.mie.set_field("USIE", cfg.enable_interrupt)
self.mie.set_field("SSIE", cfg.enable_interrupt)
self.mie.set_field("MSIE", cfg.enable_interrupt)
self.mie.set_field("MTIE", cfg.enable_interrupt & cfg.enable_timer_irq)
self.mie.set_field("STIE", cfg.enable_interrupt & cfg.enable_timer_irq)
self.mie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq)
regs.append(self.mie)
# TODO
def setup_smode_reg(self, mode, regs):
pass
# TODO
def setup_umode_reg(self, mode, regs):
pass
# TODO
def setup_satp(self, instrs):
pass
def gen_csr_instr(self, regs, instrs):
for i in range(len(regs)):
instrs.append("li x{}, {}".format(cfg.gpr[0].value, hex(regs[i].get_val())))
instrs.append("csrw {}, x{} # {}".format(hex(regs[i].reg_name.value),
cfg.gpr[0], regs[i].reg_name.name))

View file

@ -0,0 +1,129 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import sys
import logging
import vsc
from importlib import import_module
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_instr_pkg import (
pkg_ins, privileged_reg_t, reg_field_access_t, privileged_level_t)
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
# Light weight RISC-V register class library
# Base class for RISC-V register field
@vsc.randobj
class riscv_reg_field:
def __init__(self):
self.bit_width = 0
self.reset_val = vsc.bit_t(rcs.XLEN)
self.val = vsc.rand_bit_t(rcs.XLEN)
self.access_type = vsc.enum_t(reg_field_access_t)
self.hard_wired = vsc.bit_t(1)
self.name = ""
@vsc.constraint
def zero_reserved_field_c(self):
with vsc.implies(self.access_type == reg_field_access_t.WPRI):
self.val == 0
@vsc.constraint
def hardwired_fld_c(self):
with vsc.implies(self.hard_wired == 1):
self.val == self.reset_val
def convert2string(self):
return pkg_ins.format_string("{} bit_width:{} val:{} type:{}".format(
self, self.bit_width, hex(self.val), self.access_type))
def post_randomize(self):
mask = vsc.bit_t(rcs.XLEN, 2**rcs.XLEN - 1)
mask = mask >> (rcs.XLEN - self.bit_width)
self.val = mask & self.val
# Base class for RISC-V register
@vsc.randobj
class riscv_reg:
def __init__(self):
self.reg_name = vsc.enum_t(privileged_reg_t)
self.offset = vsc.bit_t(12)
self.privil_level = vsc.enum_t(privileged_level_t)
self.val = vsc.bit_t(rcs.XLEN)
self.fld = vsc.rand_list_t(vsc.attr(riscv_reg_field()))
def init_reg(self, reg_name):
self.reg_name = reg_name
self.offset = reg_name.value
def get_val(self):
total_len = 0
for i in range((len(self.fld) - 1), -1, -1):
total_len += self.fld[i].bit_width
if total_len != rcs.XLEN:
for i in range((len(self.fld) - 1), -1, -1):
logging.info(self.fld[i].convert2string())
logging.critical("Total field length {} != XLEN {}".format(total_len, rcs.XLEN))
sys.exit(1)
self.val = 0
for i in range((len(self.fld) - 1), -1, -1):
self.val = (self.val << self.fld[i].bit_width) | self.fld[i].val
return self.val
def add_field(self, fld_name, bit_width, access_type, reset_val = 0):
new_fld = riscv_reg_field()
new_fld.bit_width = bit_width
new_fld.access_type = access_type
new_fld.reset_val = reset_val
new_fld.name = fld_name
self.fld.append(new_fld) # insert(index, value) is not supported in PyVSC
def set_field(self, fld_name, val, hard_wired = 0):
for i in range((len(self.fld) - 1), -1, -1):
if fld_name == self.fld[i].name:
self.fld[i].val = val
self.fld[i].hard_wired = hard_wired
if hard_wired:
self.fld[i].reset_val = val
return
logging.critical("Cannot match found field {}".format(fld_name))
sys.exit(1)
def get_field_by_name(self, fld_name):
for i in range((len(self.fld) - 1), -1, -1):
if fld_name == self.fld[i].name:
return self.fld[i]
logging.critical("Cannot match found field {}".format(fld_name))
sys.exit(1)
# TODO
def rand_field(self, fld_name):
pass
# TODO
def set_field_rand_mode(self, fld_name, rand_on):
pass
def reset(self):
for i in range((len(self.fld) - 1), -1, -1):
self.fld[i].val = self.fld[i].reset_val
def set_val(self, val):
for i in range((len(self.fld) - 1), -1, -1):
if not self.fld[i].hard_wired:
# Assign the valid msb to the field
self.fld[i].val = (val >> (rcs.XLEN - self.fld[i].bit_width))
logging.info("Assign field {}, bit_width:{}, reg_val 0x{}, fld_val:0x{}",
self.fld[i].name, self.fld[i].bit_width, val, self.fld[i].val)
self.val = val << self.fld[i].bit_width

View file

@ -15,9 +15,6 @@ import sys
import logging
import pandas as pd
from tabulate import tabulate
from pygen_src.isa import rv32i_instr
from pygen_src.isa import rv32m_instr
from pygen_src.isa import rv32c_instr
from pygen_src.riscv_instr_gen_config import cfg
from pygen_src.riscv_directed_instr_lib import (riscv_directed_instr_stream,
riscv_int_numeric_corner_stream,
@ -38,155 +35,18 @@ def factory(obj_of):
sys.exit(1)
def get_object(instr):
try:
instr_inst = eval("rv32i_instr.riscv_" + instr.name + "_instr()")
except Exception:
try:
instr_inst = eval("rv32m_instr.riscv_" + instr.name + "_instr()")
except Exception:
try:
instr_inst = eval("rv32c_instr.riscv_" + instr.name + "_instr()")
except Exception:
logging.critical("Failed to create instr: %0s", instr.name)
sys.exit(1)
return instr_inst
def gen_config_table():
data = []
data.append(['main_program_instr_cnt', type(cfg.main_program_instr_cnt),
sys.getsizeof(cfg.main_program_instr_cnt), cfg.main_program_instr_cnt])
data.append(['sub_program_instr_cnt', type(cfg.sub_program_instr_cnt),
sys.getsizeof(cfg.sub_program_instr_cnt), cfg.sub_program_instr_cnt])
data.append(['debug_program_instr_cnt', type(cfg.debug_program_instr_cnt),
sys.getsizeof(cfg.debug_program_instr_cnt), cfg.debug_program_instr_cnt])
data.append(['debug_sub_program_instr_cnt', type(cfg.debug_sub_program_instr_cnt),
sys.getsizeof(cfg.debug_sub_program_instr_cnt),
cfg.debug_sub_program_instr_cnt])
data.append(['max_directed_instr_stream_seq', type(cfg.max_directed_instr_stream_seq),
sys.getsizeof(cfg.max_directed_instr_stream_seq),
cfg.max_directed_instr_stream_seq])
data.append(['data_page_pattern', type(cfg.data_page_pattern),
sys.getsizeof(cfg.data_page_pattern), cfg.data_page_pattern])
data.append(['init_privileged_mode', type(cfg.init_privileged_mode),
sys.getsizeof(cfg.init_privileged_mode), cfg.init_privileged_mode])
data.append(['scratch_reg', type(cfg.scratch_reg),
sys.getsizeof(cfg.scratch_reg), cfg.scratch_reg])
data.append(['pmp_reg', type(cfg.pmp_reg), sys.getsizeof(cfg.pmp_reg), cfg.pmp_reg])
data.append(['reserved_regs', type(cfg.reserved_regs),
sys.getsizeof(cfg.reserved_regs), cfg.reserved_regs])
data.append(['sp', type(cfg.sp), sys.getsizeof(cfg.sp), cfg.sp])
data.append(['tp', type(cfg.tp), sys.getsizeof(cfg.tp), cfg.tp])
data.append(['ra', type(cfg.ra), sys.getsizeof(cfg.ra), cfg.ra])
data.append(['check_misa_init_val', type(cfg.check_misa_init_val),
sys.getsizeof(cfg.check_misa_init_val), cfg.check_misa_init_val])
data.append(['check_xstatus', type(cfg.check_xstatus),
sys.getsizeof(cfg.check_xstatus), cfg.check_xstatus])
data.append(['virtual_addr_translation_on', type(cfg.virtual_addr_translation_on),
sys.getsizeof(cfg.virtual_addr_translation_on),
cfg.virtual_addr_translation_on])
data.append(['kernel_stack_len', type(cfg.kernel_stack_len),
sys.getsizeof(cfg.kernel_stack_len), cfg.kernel_stack_len])
data.append(['kernel_program_instr_cnt', type(cfg.kernel_program_instr_cnt),
sys.getsizeof(cfg.kernel_program_instr_cnt), cfg.kernel_program_instr_cnt])
data.append(['num_of_sub_program', type(cfg.num_of_sub_program),
sys.getsizeof(cfg.num_of_sub_program), cfg.num_of_sub_program])
data.append(['instr_cnt', type(cfg.instr_cnt), sys.getsizeof(cfg.instr_cnt), cfg.instr_cnt])
data.append(['num_of_tests', type(cfg.num_of_tests),
sys.getsizeof(cfg.num_of_tests), cfg.num_of_tests])
data.append(['no_data_page', type(cfg.no_data_page),
sys.getsizeof(cfg.no_data_page), cfg.no_data_page])
data.append(['no_branch_jump', type(cfg.no_branch_jump),
sys.getsizeof(cfg.no_branch_jump), cfg.no_branch_jump])
data.append(['no_load_store', type(cfg.no_load_store),
sys.getsizeof(cfg.no_load_store), cfg.no_load_store])
data.append(['no_csr_instr', type(cfg.no_csr_instr),
sys.getsizeof(cfg.no_csr_instr), cfg.no_csr_instr])
data.append(['no_ebreak', type(cfg.no_ebreak), sys.getsizeof(cfg.no_ebreak), cfg.no_ebreak])
data.append(['no_dret', type(cfg.no_dret), sys.getsizeof(cfg.no_dret), cfg.no_dret])
data.append(['no_fence', type(cfg.no_fence), sys.getsizeof(cfg.no_fence), cfg.no_fence])
data.append(['no_wfi', type(cfg.no_wfi), sys.getsizeof(cfg.no_wfi), cfg.no_wfi])
data.append(['enable_unaligned_load_store', type(cfg.enable_unaligned_load_store),
sys.getsizeof(cfg.enable_unaligned_load_store),
cfg.enable_unaligned_load_store])
data.append(['illegal_instr_ratio', type(cfg.illegal_instr_ratio),
sys.getsizeof(cfg.illegal_instr_ratio), cfg.illegal_instr_ratio])
data.append(['hint_instr_ratio', type(cfg.hint_instr_ratio),
sys.getsizeof(cfg.hint_instr_ratio), cfg.hint_instr_ratio])
data.append(['num_of_harts', type(cfg.num_of_harts),
sys.getsizeof(cfg.num_of_harts), cfg.num_of_harts])
data.append(['fix_sp', type(cfg.fix_sp), sys.getsizeof(cfg.fix_sp), cfg.fix_sp])
data.append(['use_push_data_section', type(cfg.use_push_data_section),
sys.getsizeof(cfg.use_push_data_section), cfg.use_push_data_section])
data.append(['boot_mode_opts', type(cfg.boot_mode_opts),
sys.getsizeof(cfg.boot_mode_opts), cfg.boot_mode_opts])
data.append(['enable_page_table_exception', type(cfg.enable_page_table_exception),
sys.getsizeof(cfg.enable_page_table_exception),
cfg.enable_page_table_exception])
data.append(['no_directed_instr', type(cfg.no_directed_instr),
sys.getsizeof(cfg.no_directed_instr), cfg.no_directed_instr])
data.append(['asm_test_suffix', type(cfg.asm_test_suffix),
sys.getsizeof(cfg.asm_test_suffix), cfg.asm_test_suffix])
data.append(['enable_interrupt', type(cfg.enable_interrupt),
sys.getsizeof(cfg.enable_interrupt), cfg.enable_interrupt])
data.append(['enable_nested_interrupt', type(cfg.enable_nested_interrupt),
sys.getsizeof(cfg.enable_nested_interrupt), cfg.enable_nested_interrupt])
data.append(['enable_timer_irq', type(cfg.enable_timer_irq),
sys.getsizeof(cfg.enable_timer_irq), cfg.enable_timer_irq])
data.append(['bare_program_mode', type(cfg.bare_program_mode),
sys.getsizeof(cfg.bare_program_mode), cfg.bare_program_mode])
data.append(['enable_illegal_csr_instruction', type(cfg.enable_illegal_csr_instruction),
sys.getsizeof(cfg.enable_illegal_csr_instruction),
cfg.enable_illegal_csr_instruction])
data.append(['enable_access_invalid_csr_level', type(cfg.enable_access_invalid_csr_level),
sys.getsizeof(cfg.enable_access_invalid_csr_level),
cfg.enable_access_invalid_csr_level])
data.append(['enable_misaligned_instr', type(cfg.enable_misaligned_instr),
sys.getsizeof(cfg.enable_misaligned_instr), cfg.enable_misaligned_instr])
data.append(['enable_dummy_csr_write', type(cfg.enable_dummy_csr_write),
sys.getsizeof(cfg.enable_dummy_csr_write), cfg.enable_dummy_csr_write])
data.append(['randomize_csr', type(cfg.randomize_csr),
sys.getsizeof(cfg.randomize_csr), cfg.randomize_csr])
data.append(['allow_sfence_exception', type(cfg.allow_sfence_exception),
sys.getsizeof(cfg.allow_sfence_exception), cfg.allow_sfence_exception])
data.append(['no_delegation', type(cfg.no_delegation),
sys.getsizeof(cfg.no_delegation), cfg.no_delegation])
data.append(['force_m_delegation', type(cfg.force_m_delegation),
sys.getsizeof(cfg.force_m_delegation), cfg.force_m_delegation])
data.append(['force_s_delegation', type(cfg.force_s_delegation),
sys.getsizeof(cfg.force_s_delegation), cfg.force_s_delegation])
data.append(['support_supervisor_mode', type(cfg.support_supervisor_mode),
sys.getsizeof(cfg.support_supervisor_mode), cfg.support_supervisor_mode])
data.append(['disable_compressed_instr', type(cfg.disable_compressed_instr),
sys.getsizeof(cfg.disable_compressed_instr), cfg.disable_compressed_instr])
data.append(['require_signature_addr', type(cfg.require_signature_addr),
sys.getsizeof(cfg.require_signature_addr), cfg.require_signature_addr])
data.append(['signature_addr', type(cfg.signature_addr),
sys.getsizeof(cfg.signature_addr), cfg.signature_addr])
data.append(['gen_debug_section', type(cfg.gen_debug_section),
sys.getsizeof(cfg.gen_debug_section), cfg.force_s_delegation])
data.append(['enable_ebreak_in_debug_rom', type(cfg.enable_ebreak_in_debug_rom),
sys.getsizeof(cfg.enable_ebreak_in_debug_rom), cfg.enable_ebreak_in_debug_rom])
data.append(['set_dcsr_ebreak', type(cfg.set_dcsr_ebreak),
sys.getsizeof(cfg.set_dcsr_ebreak), cfg.set_dcsr_ebreak])
data.append(['num_debug_sub_program', type(cfg.num_debug_sub_program),
sys.getsizeof(cfg.num_debug_sub_program), cfg.num_debug_sub_program])
data.append(['enable_debug_single_step', type(cfg.enable_debug_single_step),
sys.getsizeof(cfg.enable_debug_single_step), cfg.enable_debug_single_step])
data.append(['single_step_iterations', type(cfg.single_step_iterations),
sys.getsizeof(cfg.single_step_iterations), cfg.single_step_iterations])
data.append(['set_mstatus_tw', type(cfg.set_mstatus_tw),
sys.getsizeof(cfg.set_mstatus_tw), cfg.set_mstatus_tw])
data.append(['set_mstatus_mprv', type(cfg.set_mstatus_mprv),
sys.getsizeof(cfg.set_mstatus_mprv), cfg.set_mstatus_mprv])
data.append(['enable_floating_point', type(cfg.enable_floating_point),
sys.getsizeof(cfg.enable_floating_point), cfg.enable_floating_point])
data.append(['enable_vector_extension', type(cfg.enable_vector_extension),
sys.getsizeof(cfg.enable_vector_extension), cfg.enable_vector_extension])
data.append(['enable_b_extension', type(cfg.enable_b_extension),
sys.getsizeof(cfg.enable_b_extension), cfg.enable_b_extension])
for key, value in cfg.__dict__.items():
# Ignoring the unneccesary attributes
if key in ["_ro_int", "_int_field_info", "argv", "mem_region",
"amo_region", "s_mem_region", "args_dict"]:
continue
else:
try: # Fields values for the pyvsc data types
data.append([key, type(key), sys.getsizeof(key), value.get_val()])
except Exception:
data.append([key, type(key), sys.getsizeof(key), value])
df = pd.DataFrame(data, columns=['Name', 'Type', 'Size', 'Value'])
df['Value'] = df['Value'].apply(str)
logging.info('\n' + tabulate(df, headers='keys', tablefmt='psql'))

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,63 @@
"""
Copyright 2020 Google LLC
Copyright 2020 PerfectVIPs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
XLEN = 32
implemented_csr = ['MVENDORID', 'MARCHID', 'MIMPID', 'MHARTID', 'MSTATUS', 'MISA', 'MIE',
'MTVEC', 'MCOUNTEREN', 'MSCRATCH', 'MEPC', 'MCAUSE', 'MTVAL', 'MIP']
SATP_MODE = 'BARE'
supported_isa = ['RV32I', 'RV32M', 'RV32C', 'RV32F', 'RV32FC', 'RV32D', 'RV32DC']
supported_privileged_mode = ['MACHINE_MODE']
supported_interrupt_mode = ['DIRECT', 'VECTORED']
max_interrupt_vector_num = 16
support_debug_mode = 0
NUM_HARTS = 1
support_pmp = 0
unsupported_instr = []
support_umode_trap = 0
support_sfence = 0
support_unaligned_load_store = 1
NUM_FLOAT_GPR = 32
NUM_GPR = 32
NUM_VEC_GPR = 32
VECTOR_EXTENSION_ENABLE = 0
VLEN = 512
ELEN = 32
SELEN = 0
MAX_MUL = 8
implemented_interrupt = ['M_SOFTWARE_INTR', 'M_TIMER_INTR', 'M_EXTERNAL_INTR']
implemented_exception = ['INSTRUCTION_ACCESS_FAULT', 'ILLEGAL_INSTRUCTION',
'BREAKPOINT', 'LOAD_ADDRESS_MISALIGNED',
'LOAD_ACCESS_FAULT', 'ECALL_MMODE']

View file

@ -15,12 +15,8 @@ import sys
sys.path.append("pygen/")
from pygen_src.riscv_instr_pkg import *
from pygen_src.riscv_instr_gen_config import cfg # NOQA
if cfg.argv.target == "rv32i":
from pygen_src.isa.rv32i_instr import * # NOQA
if cfg.argv.target == "rv32imc":
from pygen_src.isa.rv32i_instr import * # NOQA
from pygen_src.isa.rv32m_instr import * # NOQA
from pygen_src.isa.rv32c_instr import * # NOQA
for isa in rcs.supported_isa:
import_module("pygen_src.isa." + isa.lower() + "_instr")
from pygen_src.isa.riscv_instr import riscv_instr # NOQA
from pygen_src.riscv_asm_program_gen import riscv_asm_program_gen # NOQA
from pygen_src.riscv_utils import gen_config_table

View file

@ -756,7 +756,7 @@ def parse_args(cwd):
parser.add_argument("--target", type=str, default="rv32imc",
help="Run the generator with pre-defined targets: \
rv32imc, rv32i, rv64imc, rv64gc")
rv32imc, rv32i, rv32imfdc, rv64imc, rv64gc")
parser.add_argument("-o", "--output", type=str,
help="Output directory name", dest="o")
parser.add_argument("-tl", "--testlist", type=str, default="",
@ -918,6 +918,9 @@ def load_config(args, cwd):
if args.target == "rv32imc":
args.mabi = "ilp32"
args.isa = "rv32imc"
elif args.target == "rv32imfdc":
args.mabi = "ilp32"
args.isa = "rv32imfdc"
elif args.target == "rv32imc_sv32":
args.mabi = "ilp32"
args.isa = "rv32imc"

View file

@ -142,10 +142,6 @@ class riscv_compressed_instr extends riscv_instr;
end
has_imm = 1'b0;
end
CI_FORMAT : begin
has_rs2 = 1'b0;
has_rs1 = 1'b0;
end
CSS_FORMAT : begin
has_rs1 = 1'b0;
has_rd = 1'b0;
@ -160,7 +156,7 @@ class riscv_compressed_instr extends riscv_instr;
has_rs1 = 1'b0;
has_imm = 1'b0;
end
CIW_FORMAT: begin
CI_FORMAT, CIW_FORMAT: begin
has_rs1 = 1'b0;
has_rs2 = 1'b0;
end

View file

@ -1,3 +1,19 @@
/*
* 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.
*/
// Psuedo instructions are used to simplify assembly program writing
class riscv_pseudo_instr extends riscv_instr;

View file

@ -0,0 +1,146 @@
/*
* 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 = 32;
// Parameter for SATP mode, set to BARE if address translation is not supported
parameter satp_mode_t SATP_MODE = BARE;
// Supported Privileged mode
privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
// Unsupported instructions
riscv_instr_name_t unsupported_instr[];
// ISA supported by the processor
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32F, RV32FC};
// 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 = 0;
// Support unaligned load / store
bit support_unaligned_load_store = 1'b1;
// GPR setting
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 32;
// ----------------------------------------------------------------------------
// Vector extension configuration
// ----------------------------------------------------------------------------
// Parameter for vector extension
parameter int VECTOR_EXTENSION_ENABLE = 0;
parameter int VLEN = 512;
// 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 //
Machine mode mode CSR
MVENDORID, // Vendor ID
MARCHID, // Architecture ID
MIMPID, // Implementation ID
MHARTID, // Hardware thread ID
MSTATUS, // Machine status
MISA, // ISA and extensions
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
};
// 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
M_SOFTWARE_INTR,
M_TIMER_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,
ECALL_MMODE
};

View file

@ -0,0 +1,81 @@
# 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/rv32imc/testlist.yaml
- 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

View file

@ -12,6 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# The -CFLAGS option is required as some VCS DPI code contains smart quotes
# around some preprocessor macros, making G++ throw errors during compilation.
# As a result, passing -fno-extended-identifiers tells G++ to pretend that
# everything is ASCII, preventing strange compilation errors.
- tool: vcs
compile:
cmd:
@ -21,6 +25,7 @@
-f <cwd>/files.f -full64
-l <out>/compile.log
-LDFLAGS '-Wl,--no-as-needed'
-CFLAGS '--std=c99 -fno-extended-identifiers'
-Mdir=<out>/vcs_simv.csrc
-o <out>/vcs_simv <cmp_opts> <cov_opts> "
cov_opts: >