Skip to content

Commit

Permalink
Added command line control of coverage and added hooks for vector cov…
Browse files Browse the repository at this point in the history
…erage development (chipsalliance#317)

* fixed line widths (x2) and check error returns for any questa simalator

* added control of coverage from target/riscv_core-settings

* intermediate coverage of first 2 vector config instructions

* use comand line to control vectors and made vectors out in includes

* add all hooks to load (under development) remote vector coverage processing with options from command line to control vector and coverage

* added vector flaoting point registers to list

* renamed include files, alignment, removed comment on gen_dummy_csr_write, restored removed function
  • Loading branch information
simond-imperas authored and taoliug committed Nov 23, 2019
1 parent 7514074 commit bd78c57
Show file tree
Hide file tree
Showing 12 changed files with 473 additions and 221 deletions.
49 changes: 39 additions & 10 deletions cov.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@

LOGGER = logging.getLogger()


def collect_cov(log_dir, out, core, iss, testlist, batch_size, lsf_cmd, steps, \
opts, timeout, simulator, simulator_yaml, custom_target, \
isa, target, stop_on_first_error):
isa, target, stop_on_first_error,
dont_truncate_after_first_ecall,
vector_options, coverage_options):
"""Collect functional coverage from the instruction trace
Args:
log_dir : Trace log directory
out : Output directory
Expand All @@ -53,6 +55,8 @@ def collect_cov(log_dir, out, core, iss, testlist, batch_size, lsf_cmd, steps, \
isa : RISC-V ISA variant
target : Predefined target
stop_on_first_error : will end run on first error detected
vector_options : Enable Vectors and set vector config options
coverage_options : Set coverage config options
"""
cwd = os.path.dirname(os.path.realpath(__file__))
log_list = []
Expand Down Expand Up @@ -87,26 +91,39 @@ def collect_cov(log_dir, out, core, iss, testlist, batch_size, lsf_cmd, steps, \
if iss == "spike":
process_spike_sim_log(log, csv, 1)
elif iss == "ovpsim":
process_ovpsim_sim_log(log, csv, 1, stop_on_first_error)
process_ovpsim_sim_log(log, csv, 1, stop_on_first_error,
dont_truncate_after_first_ecall)
else:
logging.error("Full trace for %s is not supported yet" % iss)
sys.exit(1)
if steps == "all" or re.match("cov", steps):
opts_vec = ""
opts_cov = ""
if vector_options:
opts_vec = ("%0s" % vector_options)
if coverage_options:
opts_cov = ("%0s" % coverage_options)
build_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s "
" --co -o %s --cov -tl %s %s " %
(cwd, simulator, simulator_yaml, out, testlist, opts))
" --co -o %s --cov -tl %s %s --cmp_opts \"%s %s\" " %
(cwd, simulator, simulator_yaml, out, testlist, opts,
opts_vec, opts_cov))
base_sim_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s "
"--so -o %s --cov -tl %s %s "
"-tn riscv_instr_cov_test --steps gen --sim_opts \"<trace_csv_opts>\"" %
(cwd, simulator, simulator_yaml, out, testlist, opts))
"-tn riscv_instr_cov_test --steps gen --sim_opts \"<trace_csv_opts> %s %s\" " %
(cwd, simulator, simulator_yaml, out, testlist, opts,
opts_vec, opts_cov))
if target:
build_cmd += (" --target %s" % target)
if custom_target:
build_cmd += (" --custom_target %s" % custom_target)
if stop_on_first_error:
build_cmd += (" --stop_on_first_error")
if target:
base_sim_cmd += (" --target %s" % target)
if custom_target:
base_sim_cmd += (" --custom_target %s" % custom_target)
if stop_on_first_error:
base_sim_cmd += (" --stop_on_first_error")
logging.info("Building the coverage collection framework")
output = run_cmd(build_cmd)
file_idx = 0
Expand Down Expand Up @@ -256,11 +273,20 @@ def setup_parser():
help="Path for the riscv_core_setting.sv")
parser.add_argument("--stop_on_first_error", dest="stop_on_first_error",
action="store_true", help="Stop on detecting first error")
parser.add_argument("--dont_truncate_after_first_ecall", dest="dont_truncate_after_first_ecall",
action="store_true", help="Do not truncate log and csv file on first ecall")
parser.add_argument("--noclean", action="store_true",
help="Do not clean the output of the previous runs")
parser.add_argument("--vector_options", type=str, default="",
help="Enable Vectors and set options")
parser.add_argument("--coverage_options", type=str, default="",
help="Controlling coverage coverpoints")
parser.set_defaults(verbose=False)
parser.set_defaults(debug_mode=False)
parser.set_defaults(stop_on_first_error=False)
parser.add_argument("--noclean", action="store_true",
help="Do not clean the output of the previous runs")
parser.set_defaults(dont_truncate_after_first_ecall=False)
parser.set_defaults(vector_options="")
parser.set_defaults(coverage_options="")
return parser

def main():
Expand Down Expand Up @@ -320,7 +346,10 @@ def main():
collect_cov(args.dir, output_dir, args.core, args.iss, args.testlist,
args.batch_size, args.lsf_cmd, args.steps, args.opts, args.timeout,
args.simulator, args.simulator_yaml, args.custom_target,
args.isa, args.target, args.stop_on_first_error)
args.isa, args.target, args.stop_on_first_error,
args.dont_truncate_after_first_ecall,
args.vector_options,
args.coverage_options)
logging.info("Coverage results are saved to %s" % output_dir)

if __name__ == "__main__":
Expand Down
42 changes: 25 additions & 17 deletions scripts/ovpsim_log_to_trace_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ def convert_mode(pri, line):
"a0","a1","a2","a3","a4","a5","a6","a7",
"s2","s3","s4","s5","s6","s7","s8","s9","s10","s11",
"t3","t4","t5","t6"]
FREGS = ["ft0","ft1","ft2","ft3","ft4","ft5","ft6","ft7","fs0","fs1","fa0",
"fa1","fa2","fa3","fa4","fa5","fa6","fa7","fs2","fs3","fs4","fs5",
"fs6","fs7","fs8","fs9","fs10","fs11","ft8","ft9","ft10","ft11"]

def process_jal(trace, operands, gpr):
""" correctly process jal """
Expand Down Expand Up @@ -156,14 +159,19 @@ def check_conversion(entry):
if stop_on_first_error:
sys.exit(-1)

operands_list = ["rd","rs1","rs2","vd","vs1","vs2","vs3","fd","fs1","fs2"]
def update_operands_values(trace, gpr):
""" ensure operands have been updated """
for op in operands_list:
exec("if trace.%0s in gpr: trace.%0s_val = gpr[trace.%0s]" % (op, op, op))

def show_line_instr(line, i):
""" show line """
if i.instr_str[0] in ['v']:
logging.debug("%s" % (line.strip()))
logging.debug(
" -->> instr_str(%s) binary(%s) addr(%s) mode(%s) instr(%s)"
% ( i.instr_str, i.binary, i.addr, i.privileged_mode,
i.instr))
% ( i.instr_str, i.binary, i.addr, i.privileged_mode,i.instr))

def check_num_operands(instr_str, num_operands, n):
""" ensure consistency """
Expand All @@ -173,8 +181,7 @@ def check_num_operands(instr_str, num_operands, n):

def is_csr(r):
""" see if r is a csr """

# add more as needed
# TODO add more as needed - could look in the enum privileged_reg_t or the cores settings: implemented_csr[]
if r in ["mtvec","pmpaddr0","pmpcfg0","mstatus","mepc","mscratch","mcause",
"mtval","vl","vtype"]:
return True
Expand Down Expand Up @@ -217,14 +224,16 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
os.system(cmd)

# storage and initial values of gpr and csr

gpr = {}
csr = {}

for g in REGS: # base base isa gprs
for g in REGS: # base isa gprs
gpr[g] = 0

for i in range(32): # add in v0-v31 gprs
gpr["v"+str(i)] = 0
for f in FREGS: # floating point gprs
gpr[f] = 0

csr["vl"] = 0
csr["vtype"] = 0
Expand All @@ -244,6 +253,7 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
# its instruction disassembly line
if prev_trace: # write out the previous one when find next one
check_conversion(prev_trace)
update_operands_values(prev_trace, gpr)
instr_cnt += 1
trace_csv.write_trace_entry(prev_trace)
if verbose2:
Expand All @@ -267,7 +277,7 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
#if prev_trace.instr in ["vsetvli"]:
#if prev_trace.instr in ["vlh.v"]:
#if prev_trace.instr in ["vmul.vx"]:
if prev_trace.instr in ["vmul.vx_XXX"]:
if prev_trace.instr in ["vsetvl"]:
logit = 1
verbose2 = True

Expand All @@ -282,8 +292,6 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
"flw" in line:
logging.debug ("Ignoring ins...(%s) " % (line))
continue
logging.debug("Processing [%s]: %s" %
(prev_trace.instr, prev_trace.instr_str))
process_if_compressed(prev_trace)
o = re.search (r"(?P<instr>[a-z]*?)\s(?P<operand>.*)",
prev_trace.instr_str)
Expand All @@ -296,7 +304,8 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
process_jal(prev_trace, operands, gpr)
else:
if 'v' in prev_trace.instr[0]:
assign_operand_vector(prev_trace, operands, gpr, stop_on_first_error)
assign_operand_vector(prev_trace, operands, gpr,
stop_on_first_error)
elif 'f' in prev_trace.instr[0] or "c.f" in prev_trace.instr[0:3]:
pass # ignore floating point. TODO include them
else:
Expand All @@ -308,8 +317,9 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
'bltz', 'blez', 'bgtz']:
process_branch_offset (1, operands, prev_trace)
if prev_trace.instr in ['j', 'c.j']:
operands[0] = "0x" + operands[0]
assign_operand(prev_trace, operands, gpr, stop_on_first_error)
operands[0] = "0x" + operands[0] # ovpsim has no '0x' so need to add it.
assign_operand(prev_trace, operands, gpr,
stop_on_first_error)
else:
# logging.debug("no operand for [%s] in [%s]" % (trace_instr,
# trace_instr_str))
Expand Down Expand Up @@ -340,9 +350,8 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
gpr[n.group("r")] = n.group("val")
else:
# backwards compatible
prev_trace.rd = n.group("r")
prev_trace.rd_val = n.group("val")
gpr[prev_trace.rd] = prev_trace.rd_val
prev_trace.rd_val = n.group("val")
gpr[prev_trace.rd] = prev_trace.rd_val
if 0:
print (
"write entry [[%d]]: rd[%s] val[%s] instr(%s) bin(%s) addr(%s)"
Expand All @@ -365,7 +374,7 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
logging.debug("Ignoring: [%d] [[%s]]" % (instr_cnt, line))
pass
elif "Warning (RISCV_" in line:
logging.debug("Skipping: [%d] (%s) [[%s]]" %
logging.debug("Skipping: [%d] (%s) [[%s]]" %
(instr_cnt, prev_trace.instr_str, line))
prev_trace.instr = "nop"
prev_trace.instr_str = "nop"
Expand All @@ -380,7 +389,6 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 1, stop = 0,
sys.exit(-1)
logging.info("CSV saved to : %s" % csv)


def main():
""" if used standalone set up for testing """
instr_trace = []
Expand Down
75 changes: 44 additions & 31 deletions scripts/riscv_trace_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ def __init__(self):
self.vs2_val = ""
self.vs3 = ""
self.vs3_val = ""
self.vtype_e = ""
self.vtype_m = ""
self.vtype_d = ""
self.vtype_vsew = ""
self.vtype_vmul = ""
self.vtype_vediv = ""
self.vm = ""
self.updated_csr = ""
self.updated_gpr = ""
self.fd = ""
self.fd_val = ""
self.fs1 = ""
self.fs1_val = ""
self.fs2 = ""
self.fs2_val = ""

def get_trace_string(self):
"""Return a short string of the trace entry"""
Expand All @@ -75,7 +81,8 @@ def start_new_trace(self):
"instr", "rd", "rd_val", "rs1", "rs1_val", "rs2", "rs2_val",
"imm", "str", "addr", "binary", "csr", "mode",
"vd", "vd_val", "vs1", "vs1_val","vs2", "vs2_val","vs3", "vs3_val",
"vtype_e", "vtype_m", "vtype_d", "vm", "updated_csr", "updated_gpr"]
"vtype_vsew", "vtype_vmul", "vtype_vediv", "vm", "updated_csr", "updated_gpr",
"fd", "fd_val", "fs1", "fs1_val","fs2", "fs2_val"]
self.csv_writer = csv.DictWriter(self.csv_fd, fieldnames=fields)
self.csv_writer.writeheader()

Expand All @@ -96,33 +103,39 @@ def read_trace(self, trace):
def write_trace_entry(self, entry):
"""Write a new trace entry to CSV"""
self.gpr[entry.rd] = entry.rd_val
self.csv_writer.writerow({'str' : entry.instr_str,
'rd' : entry.rd,
'rd_val' : entry.rd_val,
'rs1' : entry.rs1,
'rs1_val' : entry.rs1_val,
'rs2' : entry.rs2,
'rs2_val' : entry.rs2_val,
'addr' : entry.addr,
'instr' : entry.instr,
'imm' : entry.imm,
'csr' : entry.csr,
'binary' : entry.binary,
'mode' : entry.privileged_mode,
'vd' : entry.vd,
'vd_val' : entry.vd_val,
'vs1' : entry.vs1,
'vs1_val' : entry.vs1_val,
'vs2' : entry.vs2,
'vs2_val' : entry.vs2_val,
'vs3' : entry.vs3,
'vs3_val' : entry.vs3_val,
'vtype_e' : entry.vtype_e,
'vtype_m' : entry.vtype_m,
'vtype_d' : entry.vtype_d,
'vm' : entry.vm,
'updated_csr': entry.updated_csr,
'updated_gpr': entry.updated_gpr,
self.csv_writer.writerow({'str' : entry.instr_str,
'rd' : entry.rd,
'rd_val' : entry.rd_val,
'rs1' : entry.rs1,
'rs1_val' : entry.rs1_val,
'rs2' : entry.rs2,
'rs2_val' : entry.rs2_val,
'addr' : entry.addr,
'instr' : entry.instr,
'imm' : entry.imm,
'csr' : entry.csr,
'binary' : entry.binary,
'mode' : entry.privileged_mode,
'vd' : entry.vd,
'vd_val' : entry.vd_val,
'vs1' : entry.vs1,
'vs1_val' : entry.vs1_val,
'vs2' : entry.vs2,
'vs2_val' : entry.vs2_val,
'vs3' : entry.vs3,
'vs3_val' : entry.vs3_val,
'vtype_vsew' : entry.vtype_vsew,
'vtype_vmul' : entry.vtype_vmul,
'vtype_vediv' : entry.vtype_vediv,
'vm' : entry.vm,
'updated_csr' : entry.updated_csr,
'updated_gpr' : entry.updated_gpr,
'fd' : entry.fd,
'fd_val' : entry.fd_val,
'fs1' : entry.fs1,
'fs1_val' : entry.fs1_val,
'fs2' : entry.fs2,
'fs2_val' : entry.fs2_val,
})


Expand Down
8 changes: 8 additions & 0 deletions src/dv_defines.svh
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,11 @@
`define DV_CHECK_STD_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_,MSG_="Randomization failed!",ID_=`gfn) \
`DV_CHECK_FATAL(std::randomize(VAR_), MSG_, ID_, with { WITH_C_ })
`endif

// for vector processing
`ifndef VECTOR_INCLUDE
`define VECTOR_INCLUDE(VCE_INC) \
`ifdef ENABLE_VECTORS \
`include VCE_INC \
`endif
`endif
2 changes: 1 addition & 1 deletion src/riscv_asm_program_gen.sv
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ class riscv_asm_program_gen extends uvm_object;
init_floating_point_gpr();
end
core_is_initialized();
gen_dummy_csr_write();
gen_dummy_csr_write(); // TODO add a way to disable xStatus read
endfunction

// Setup MISA based on supported extensions
Expand Down
Loading

0 comments on commit bd78c57

Please sign in to comment.