Commit 07f674c6 authored by aneels3's avatar aneels3
Browse files

Add support for RV32C coverage


Signed-off-by: default avataraneels3 <b150023ec@nitsikkim.ac.in>
parent 438ea995
......@@ -19,11 +19,11 @@ import vsc
import logging
from importlib import import_module
from enum import Enum, IntEnum, auto
from bitstring import BitArray
from pygen_src.riscv_instr_pkg import *
from pygen_src.riscv_instr_gen_config import cfg
rcs = import_module("pygen_src.target." + cfg.argv.target + ".riscv_core_setting")
class operand_sign_e(IntEnum):
POSITIVE = 0
NEGATIVE = auto()
......@@ -325,10 +325,11 @@ class riscv_cov_instr:
the result of the check_hazard_condition won't be accurate. Need to
explicitly extract the destination register from the operands '''
if pre_instr.has_rd:
if ((self.has_rs1 and self.rs1 == pre_instr.rd) or
(self.has_rs2 and self.rs1 == pre_instr.rd)):
if ((self.has_rs1 and (self.rs1 == pre_instr.rd)) or
(self.has_rs2 and (self.rs1 == pre_instr.rd))):
logging.info("pre_instr {}".format(pre_instr.instr.name))
self.gpr_hazard = hazard_e["RAW_HAZARD"]
elif self.has_rd and self.rd == pre_instr.rd:
elif self.has_rd and (self.rd == pre_instr.rd):
self.gpr_hazard = hazard_e["WAW_HAZARD"]
elif (self.has_rd and
((pre_instr.has_rs1 and (pre_instr.rs1 == self.rd)) or
......@@ -338,16 +339,16 @@ class riscv_cov_instr:
self.gpr_hazard = hazard_e["NO_HAZARD"]
if self.category == riscv_instr_category_t.LOAD:
if (pre_instr.category == riscv_instr_category_t.STORE and
pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
(pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["RAW_HAZARD"]
else:
self.lsu_hazard = hazard_e["NO_HAZARD"]
if self.category == riscv_instr_category_t.STORE:
if (pre_instr.category == riscv_instr_category_t.STORE and
pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
(pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["WAW_HAZARD"]
elif (pre_instr.category == riscv_instr_category_t.LOAD and
pre_instr.mem_addr.get_val() == self.mem_addr.get_val()):
(pre_instr.mem_addr.get_val() == self.mem_addr.get_val())):
self.lsu_hazard = hazard_e["WAR_HAZARD"]
else:
self.lsu_hazard = hazard_e["NO_HAZARD"]
......
......@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
import traceback
from pygen_src.isa.riscv_cov_instr import *
......@@ -1591,7 +1592,7 @@ class riscv_instr_cover_group:
super().__init__()
self.instr = None
self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[7:2],
self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[6:2],
bins={
"a": vsc.bin_array([], [0, 31])
}
......@@ -1619,11 +1620,340 @@ class riscv_instr_cover_group:
}
)
'''Compressed instructions'''
@vsc.covergroup
class compressed_opcode_cg(object):
# TODO issue with iff parameter
def __init__(self):
super().__init__()
self.instr = None
'''self.cp_opcode = vsc.coverpoint(lambda: self.instr.binary[15:0],
bins={
"a": vsc.bin_array([], [0, 31])
}
)'''
@vsc.covergroup
class c_lw_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
@vsc.covergroup
class c_lwsp_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
@vsc.covergroup
class c_sw_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
self.cp_lsu_hazard = vsc.coverpoint(lambda: self.instr.lsu_hazard,
cp_t=vsc.enum_t(store_lsu_hazard_e))
@vsc.covergroup
class c_swsp_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
@vsc.covergroup
class c_addi4spn_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(store_lsu_hazard_e))
@vsc.covergroup
class c_addi_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(store_lsu_hazard_e))
@vsc.covergroup
class c_addi16sp_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(store_lsu_hazard_e))
@vsc.covergroup
class c_li_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(store_lsu_hazard_e))
@vsc.covergroup
class c_lui_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_sp_t))
@vsc.covergroup
class c_sub_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_add_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
cp_t=vsc.enum_t(operand_sign_e))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_mv_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rs2_sign = vsc.coverpoint(lambda: self.instr.rs2_sign,
cp_t=vsc.enum_t(operand_sign_e))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_andi_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
@vsc.covergroup
class c_xor_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_or_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_and_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_rs2 = vsc.coverpoint(lambda: self.instr.rs2,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(hazard_e))
@vsc.covergroup
class c_beqz_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
@vsc.covergroup
class c_bnez_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
@vsc.covergroup
class c_srli_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
@vsc.covergroup
class c_srai_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(compressed_gpr))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
@vsc.covergroup
class c_slli_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rd = vsc.coverpoint(lambda: self.instr.rd,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_gpr_hazard = vsc.coverpoint(lambda: self.instr.gpr_hazard,
cp_t=vsc.enum_t(branch_hazard_e))
@vsc.covergroup
class c_j_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
@vsc.covergroup
class c_jal_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_imm_sign = vsc.coverpoint(lambda: self.instr.imm_sign,
cp_t=vsc.enum_t(operand_sign_e))
@vsc.covergroup
class c_jr_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],
bins={
"Zero" : vsc.bin(0),
"One" : vsc.bin(1),
"Two" : vsc.bin(2),
"Three": vsc.bin(3)
})
@vsc.covergroup
class c_jalr_cg(object):
def __init__(self):
super().__init__()
self.instr = None
self.cp_rs1 = vsc.coverpoint(lambda: self.instr.rs1,
cp_t=vsc.enum_t(riscv_reg_ex_zero_t))
self.cp_rs1_align = vsc.coverpoint(lambda: self.instr.rs1_value[1:0],
bins={
"Zero" : vsc.bin(0),
"One" : vsc.bin(1),
"Two" : vsc.bin(2),
"Three": vsc.bin(3)
})
self.cp_rd_align = vsc.coverpoint(lambda: self.instr.rd_value[1],
bins={
"Aligned" : vsc.bin(1),
"Not-aligned": vsc.bin(0)
})
def cg_instantiation(self):
self.opcode_cg_i = self.opcode_cg()
self.csrrw_cg_i = self.csrrw_cg()
self.rv32i_misc_cg_i = self.rv32i_misc_cg()
self.mepc_alignment_cg_i = self.mepc_alignment_cg()
# self.compressed_opcode_cg_i = self.compressed_opcode_cg()
self.beq_cg_i = self.beq_cg()
self.jal_cg_i = self.jal_cg()
self.lui_cg_i = self.lui_cg()
......@@ -1655,13 +1985,43 @@ class riscv_instr_cover_group:
self.divu_cg_i = self.divu_cg()
self.rem_cg_i = self.rem_cg()
self.remu_cg_i = self.remu_cg()
self.c_lw_cg_i = self.c_lw_cg()
self.c_lwsp_cg_i = self.c_lwsp_cg()
self.c_sw_cg_i = self.c_sw_cg()
self.c_swsp_cg_i = self.c_swsp_cg()
self.c_addi4spn_cg_i = self.c_addi4spn_cg()
self.c_addi_cg_i = self.c_addi_cg()
self.c_addi16sp_cg_i = self.c_addi16sp_cg()
self.c_li_cg_i = self.c_li_cg()
self.c_lui_cg_i = self.c_lui_cg()
self.c_sub_cg_i = self.c_sub_cg()
self.c_add_cg_i = self.c_add_cg()
self.c_mv_cg_i = self.c_mv_cg()
self.c_andi_cg_i = self.c_andi_cg()
self.c_xor_cg_i = self.c_xor_cg()
self.c_or_cg_i = self.c_or_cg()
self.c_and_cg_i = self.c_and_cg()
self.c_beqz_cg_i = self.c_beqz_cg()
self.c_bnez_cg_i = self.c_bnez_cg()
self.c_srli_cg_i = self.c_srli_cg()
self.c_srai_cg_i = self.c_srai_cg()
self.c_slli_cg_i = self.c_slli_cg()
self.c_j_cg_i = self.c_j_cg()
self.c_jal_cg_i = self.c_jal_cg()
self.c_jr_cg_i = self.c_jr_cg()
self.c_jalr_cg_i = self.c_jalr_cg()
def sample(self, instr):
self.instr_cnt += 1
if self.instr_cnt > 1:
instr.check_hazard_condition(self.pre_instr)
# TODO: sampling for hint, compressed, and illegal_compressed insts
if instr.binary[2:0] == 3:
if ((instr.binary[1:0] != 3) and (riscv_instr_group_t.RV32C in rcs.supported_isa)):
# self.compressed_opcode_cg_i.instr = instr
# self.compressed_opcode_cg_i.sample()
pass
if instr.binary[1:0] == 3:
self.opcode_cg_i.instr = instr
self.opcode_cg_i.sample()
try:
......@@ -1671,6 +2031,9 @@ class riscv_instr_cover_group:
except Exception:
logging.info("Covergroup for instr {} is not supported yet".format(
instr.instr.name))
# Trace the error if there is an Exception
logging.info("Traceback error log: {}".format(traceback.format_exc()))
if instr.group.name == "RV32I":
self.rv32i_misc_cg_i.instr = instr
self.rv32i_misc_cg_i.sample()
......
......@@ -1282,8 +1282,8 @@ class all_gpr(Enum):
T6 = auto()
class compressed_gpr(Enum):
S0 = 0
class compressed_gpr(IntEnum):
S0 = 8
S1 = auto()
A0 = auto()
A1 = auto()
......@@ -1293,7 +1293,7 @@ class compressed_gpr(Enum):
A5 = auto()
class all_categories(Enum):
class all_categories(IntEnum):
LOAD = 0
STORE = auto()
SHIFT = auto()
......@@ -1311,6 +1311,75 @@ class all_categories(Enum):
INTERRUPT = auto()
AMO = auto()
# Ignore ZERO and SP
class riscv_reg_ex_zero_sp_t(IntEnum):
RA = 1
GP = 3
TP = auto()
T0 = auto()
T1 = auto()
T2 = auto()
S0 = auto()
S1 = auto()
A0 = auto()
A1 = auto()
A2 = auto()
A3 = auto()
A4 = auto()
A5 = auto()
A6 = auto()
A7 = auto()
S2 = auto()
S3 = auto()
S4 = auto()
S5 = auto()
S6 = auto()
S7 = auto()
S8 = auto()
S9 = auto()
S10 = auto()
S11 = auto()
T3 = auto()
T4 = auto()
T5 = auto()
T6 = auto()
# Ignore ZERO only
class riscv_reg_ex_zero_t(IntEnum):
RA = 1
SP = auto()
GP = auto()
TP = auto()
T0 = auto()
T1 = auto()
T2 = auto()
S0 = auto()
S1 = auto()
A0 = auto()
A1 = auto()
A2 = auto()
A3 = auto()
A4 = auto()
A5 = auto()
A6 = auto()
A7 = auto()
S2 = auto()
S3 = auto()
S4 = auto()
S5 = auto()
S6 = auto()
S7 = auto()
S8 = auto()
S9 = auto()
S10 = auto()
S11 = auto()
T3 = auto()
T4 = auto()
T5 = auto()
T6 = auto()
# Currently PyVSC doesn't supports ignore bins
# riscv_reg_ex_zero_sp_t and riscv_reg_ex_zero_t is added as a WA and it can be removed later.
def get_val(in_string, hexa=0):
if len(in_string) > 2:
......@@ -1525,6 +1594,88 @@ def get_attr_list(instr_name):
riscv_instr_name_t.REMU: [riscv_instr_format_t.R_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32M],
# RV32C
riscv_instr_name_t.C_LW: [riscv_instr_format_t.CL_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_SW: [riscv_instr_format_t.CS_FORMAT,
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_LWSP: [riscv_instr_format_t.CI_FORMAT,
riscv_instr_category_t.LOAD,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_SWSP: [riscv_instr_format_t.CSS_FORMAT,
riscv_instr_category_t.STORE,
riscv_instr_group_t.RV32C, imm_t.UIMM],
riscv_instr_name_t.C_ADDI4SPN: [riscv_instr_format_t.CIW_FORMAT,
riscv_instr_category_t.ARITHMETIC,
riscv_instr_group_t.RV32C, imm_t.NZUIMM],