blob: 67452d5726275d5cbc799e60c4390ad5c3c92663 [file] [log] [blame]
"""
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.
Regression script for RISC-V random instruction generator
"""
import argparse
import os
import random
import re
import subprocess
import sys
sys.path.insert(0, "../../vendor/google_riscv-dv/scripts")
sys.path.insert(0, "./riscv_dv_extension")
from lib import *
from ibex_log_to_trace_csv import *
from spike_log_to_trace_csv import *
from ovpsim_log_to_trace_csv import *
from instr_trace_compare import *
def process_cmd(keyword, cmd, opts, enable):
""" Process the compile and simulation command
Args:
keyword : Keyword to search
cmd : Command to be processed
opts : Options to replace the keyword
enable : Option enable/disable
Returns:
Processed command
"""
if enable == "1":
return re.sub(keyword, opts, cmd)
else:
return re.sub(keyword, "", cmd)
def get_simulator_cmd(simulator, simulator_yaml, en_cov, en_wave):
""" Setup the compile and simulation command for the generator
Args:
simulator : RTL simulator used to run instruction generator
simulator_yaml : RTL simulator configuration file in YAML format
en_cov : Enable coverage dump
en_wave : Enable waveform
Returns:
compile_cmd : RTL simulator command to compile the instruction generator
sim_cmd : RTL simulator command to run the instruction generator
"""
print("Processing simulator setup file : %s" % simulator_yaml)
yaml_data = read_yaml(simulator_yaml)
# Search for matched simulator
for entry in yaml_data:
if entry['tool'] == simulator:
print("Found matching simulator: %s" % entry['tool'])
compile_cmd = entry['compile']['cmd']
for i in range(len(compile_cmd)):
compile_cmd[i] = process_cmd("<cov_opts>", compile_cmd[i],
entry['compile']['cov_opts'], en_cov)
compile_cmd[i] = process_cmd("<wave_opts>", compile_cmd[i],
entry['compile']['wave_opts'], en_wave)
sim_cmd = entry['sim']['cmd']
sim_cmd = process_cmd("<cov_opts>", sim_cmd, entry['sim']['cov_opts'], en_cov)
sim_cmd = process_cmd("<wave_opts>", sim_cmd, entry['sim']['wave_opts'], en_wave)
return compile_cmd, sim_cmd
print ("Cannot find RTL simulator %0s" % simulator)
sys.exit(1)
def run_cmd(cmd):
"""Run a command and return output
Args:
cmd : shell command to run
Returns:
command output
"""
try:
ps = subprocess.Popen(cmd,
shell=True,
universal_newlines=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
executable='/bin/bash')
except subprocess.CalledProcessError as exc:
print(ps.communicate()[0])
sys.exit(1)
return ps.communicate()[0]
def get_seed(seed):
"""Get the seed to run the generator
Args:
seed : input seed
Returns:
seed to run instruction generator
"""
if seed >= 0:
return seed
else:
return random.getrandbits(32)
def rtl_compile(compile_cmd, test_list, output_dir, lsf_cmd, opts, verbose):
"""Run the instruction generator
Args:
compile_cmd : Compile command
test_list : List of assembly programs to be compiled
output_dir : Output directory of the ELF files
lsf_cmd : LSF command to run compilation
opts : Compile options for the generator
verbose : Verbose logging
"""
# Compile the TB
print ("Compiling TB")
for cmd in compile_cmd:
cmd = re.sub("<out>", output_dir, cmd)
cmd = re.sub("<cmp_opts>", opts, cmd)
if verbose:
print("Compile command: %s" % cmd)
output = run_cmd(cmd)
if verbose:
print(output)
def rtl_sim(sim_cmd, test_list, output_dir, bin_dir, lsf_cmd, seed, opts, verbose):
"""Run the instruction generator
Args:
sim_cmd : Simulation command
test_list : List of assembly programs
output_dir : Simulation output directory
bin_dir : Directory of the ELF files
lsf_cmd : LSF command to run simulation
seed : Seed of RTL simulation
opts : Simulation options
verbose : Verbose logging
"""
# Run the RTL simulation
sim_cmd = re.sub("<out>", output_dir, sim_cmd)
sim_cmd = re.sub("<sim_opts>", opts, sim_cmd)
sim_cmd = re.sub("<cwd>", cwd, sim_cmd)
print ("Running RTL simulation...")
cmd_list = []
for test in test_list:
for i in range(test['iterations']):
rand_seed = get_seed(seed)
sim_dir = output_dir + ("/%s.%d" %(test['test'], i))
run_cmd(("mkdir -p %s" % sim_dir))
os.chdir(sim_dir)
if verbose:
print("Run dir: %s" % sim_dir)
binary = ("%s/%s.%d.bin" % (bin_dir, test['test'], i))
cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
(" +UVM_TESTNAME=%s " % test['rtl_test']) + \
(" +bin=%s " % binary) + \
(" +ntb_random_seed=%d " % rand_seed) + \
(" -l sim.log ")
print("Running %s with %s" % (test['rtl_test'], binary))
if verbose:
print(cmd)
try:
output = subprocess.check_output(cmd.split(),
timeout=1000,
universal_newlines=True)
except subprocess.CalledProcessError as exc:
print(output)
sys.exit(1)
if verbose:
print(output)
def compare(test_list, iss, output_dir, verbose):
"""Compare RTL & ISS simulation reult
Args:
test_list : List of assembly programs to be compiled
iss : List of instruction set simulators
output_dir : Output directory of the ELF files
verbose : Verbose logging
"""
report = ("%s/regr.log" % output_dir).rstrip()
for test in test_list:
for i in range(0, test['iterations']):
elf = ("%s/asm_tests/%s.%d.o" % (output_dir, test['test'], i))
print("Comparing %s/DUT sim result : %s" % (iss, elf))
run_cmd(("echo 'Test binary: %s' >> %s" % (elf, report)))
rtl_log = ("%s/rtl_sim/%s.%d/trace_core_00_0.log" % (output_dir, test['test'], i))
rtl_csv = ("%s/rtl_sim/%s.%d/trace_core_00_0.csv" % (output_dir, test['test'], i))
process_ibex_sim_log(rtl_log, rtl_csv)
iss_log = ("%s/instr_gen/%s_sim/%s.%d.log" % (output_dir, iss, test['test'], i))
iss_csv = ("%s/instr_gen/%s_sim/%s.%d.csv" % (output_dir, iss, test['test'], i))
if iss == "spike":
process_spike_sim_log(iss_log, iss_csv)
elif iss == "ovpsim":
process_ovpsim_sim_log(iss_log, iss_csv)
else:
print("Unsupported ISS" % iss)
sys.exit(1)
compare_trace_csv(rtl_csv, iss_csv, "ibex", iss, report)
passed_cnt = run_cmd("grep PASSED %s | wc -l" % report).strip()
failed_cnt = run_cmd("grep FAILED %s | wc -l" % report).strip()
summary = ("%s PASSED, %s FAILED" % (passed_cnt, failed_cnt))
print(summary)
run_cmd(("echo %s >> %s" % (summary, report)))
print("RTL & ISS regression report is saved to %s" % report)
# Parse input arguments
parser = argparse.ArgumentParser()
parser.add_argument("--o", type=str, default="./out",
help="Output directory name")
parser.add_argument("--testlist", type=str, default="riscv_dv_extension/testlist.yaml",
help="Regression testlist")
parser.add_argument("--test", type=str, default="all",
help="Test name, 'all' means all tests in the list")
parser.add_argument("--seed", type=int, default=-1,
help="Randomization seed, default -1 means random seed")
parser.add_argument("--iterations", type=int, default=0,
help="Override the iteration count in the test list")
parser.add_argument("--simulator", type=str, default="vcs",
help="Simulator used to run the generator, default VCS")
parser.add_argument("--simulator_yaml", type=str, default="yaml/rtl_simulation.yaml",
help="RTL simulator setting YAML")
parser.add_argument("--iss", type=str, default="spike",
help="Instruction set simulator")
parser.add_argument("--verbose", type=int, default=0,
help="Verbose logging")
parser.add_argument("--cmp_opts", type=str, default="",
help="Compile options for the generator")
parser.add_argument("--sim_opts", type=str, default="",
help="Simulation options for the generator")
parser.add_argument("--en_cov", type=str, default=0,
help="Enable coverage dump")
parser.add_argument("--en_wave", type=str, default=0,
help="Enable waveform dump")
parser.add_argument("--steps", type=str, default="all",
help="Run steps: compile,sim,compare")
parser.add_argument("--lsf_cmd", type=str, default="",
help="LSF command. Run in local sequentially if lsf \
command is not specified")
args = parser.parse_args()
cwd = os.path.dirname(os.path.realpath(__file__))
# Create the output directory
output_dir = ("%s/rtl_sim" % args.o)
bin_dir = ("%s/instr_gen/asm_tests" % args.o)
subprocess.run(["mkdir", "-p", output_dir])
# Process regression test list
matched_list = []
process_regression_list(args.testlist, args.test,
args.iterations, matched_list)
if len(matched_list) == 0:
sys.exit("Cannot find %s in %s" % (args.test, args.testlist))
compile_cmd = []
sim_cmd = ""
compile_cmd, sim_cmd = get_simulator_cmd(args.simulator, args.simulator_yaml,
args.en_cov, args.en_wave)
# Compile TB
if args.steps == "all" or re.match("compile", args.steps):
rtl_compile(compile_cmd, matched_list, output_dir,
args.lsf_cmd, args.cmp_opts, args.verbose)
# Run RTL simulation
if args.steps == "all" or re.match("sim", args.steps):
rtl_sim(sim_cmd, matched_list, output_dir, bin_dir, args.lsf_cmd,
args.seed, args.sim_opts, args.verbose)
# Compare RTL & ISS simulation result.;
if args.steps == "all" or re.match("compare", args.steps):
compare(matched_list, args.iss, args.o, args.verbose)