diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a5a56ff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,53 @@
+*~
+*.nm
+*.elf
+*.hex
+*.itb
+*.map
+*.o
+*.so
+*.objdump
+*.readelf
+*.gtkw
+*.vcd
+*.vsif
+*.sve
+*.sdb
+test_build
+dsim.env
+dsim.log
+dsim_results
+metrics.db
+metrics_history.db
+xrun_results
+vsim_results
+vmgr_sessions
+__pycache__
+*.swp
+/.cproject
+/.project
+.dvt/
+dvt_build.log
+xrun.history
+xrun.log
+xrun.key
+xcelium.d/
+waves.shm/
+*.log
+stdout.txt
+.vscode
+riviera_results/
+*/vendor_lib/dpi_dasm_spike/
+*/vendor_lib/verilab/svlib/
+work*
+vsim.dbg
+*.wlf
+transcript
+.lib-rtl
+.opt-rtl
+tools/spike
+tools/verilator*
+*_results/
+*.signature_output
+ucli.key
+vcs.cmd
diff --git a/README.md b/README.md
index c47b99d..f00b75c 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,12 @@ SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
-->
# Verification Environment for the CV32E20 CORE-V processor core.
This directory hosts the CV32E20-specific SystemVerilog sources plus C and assembly test-program sources for the CV32E20 verification environment.
-Non-CV32E20-specific verification components (e.g. OBI Agent) used in this verification environment are in `../lib` and `../vendor_lib`.
+Non-CV32E20-specific verification components (e.g. OBI Agent) used in this verification environment are in `vendor_lib/openhwgroup_core-v-verif`.
## Directories:
- **bsp**: the "board support package" for test-programs compiled/assembled/linked for the CV32E20. This BSP is used by both the `core` testbench and the `uvmt_cv32` UVM verification environment.
- **env**: the UVM environment class and its associated infrastrucutre.
+- **mk**: Makefiles and related scriptware. You may find it useful to review the [Common Makefile README](https://github.com/openhwgroup/core-v-verif/blob/master/mk/README.md).
- **sim**: directory where you run the simulations.
- **tb**: the Testbench module that instanitates the core.
- **tests**: this is where all the testcases are.
@@ -18,5 +19,3 @@ There are README files in each directory with additional information.
## Getting Started
Check out the Quick Start Guide in the [CORE-V-VERIF Verification Strategy](https://docs.openhwgroup.org/projects/core-v-verif/en/latest/quick_start.html).
-
-You may also find it useful to review the [Common Makefile for the CORE-V-VERIF UVM Verification Environment](https://github.com/openhwgroup/core-v-verif/blob/master/mk/README.md).
diff --git a/bin/Makefile.uvmt b/bin/Makefile.uvmt
new file mode 100644
index 0000000..7dedb88
--- /dev/null
+++ b/bin/Makefile.uvmt
@@ -0,0 +1,43 @@
+#
+
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Redirection script to point to makefile under core with:
+# $(CV_CORE)/sim/uvmt/Makefile
+#
+###############################################################################
+
+# Validate CV_CORE
+ifndef CV_CORE
+$(error Must set CV_CORE to a valid core)
+endif
+
+# Variables
+MAKE = make
+MAKE_PATH := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
+CORE_V_VERIF = $(abspath $(MAKE_PATH)/..)
+CV_CORE_LC = $(shell echo $(CV_CORE) | tr A-Z a-z)
+
+# If no targets specified, run default target in CV_CORE
+all:
+ $(MAKE) -C $(CORE_V_VERIF)/$(CV_CORE_LC)/sim/uvmt
+
+# If specified recursively run each target in CV_CORE
+%:
+ $(MAKE) -C $(CORE_V_VERIF)/$(CV_CORE_LC)/sim/uvmt $@
diff --git a/bin/README.md b/bin/README.md
new file mode 100644
index 0000000..474ffbe
--- /dev/null
+++ b/bin/README.md
@@ -0,0 +1,121 @@
+Core-V-Verif Utilities
+==================================
+
+This directory contains various utilities for running tests and performing various verification-related
+activities in the core-v-verif repository.
+
+Unless otherwise noted all utilities in this directory should be agnostic to $CWD. Therefore a user
+should be able to run the utilities via a PATH from any directory. The utilities will be able to
+determine their own directory based on the implementation language hooks available.
+
+For example from a bash-type shell:
+> % export PATH=./core-v-verif/bin:$PATH
+
+Requirements
+============
+Much of the scriptware in CORE-V-VERIF is written in python and makes use of external packages that are not necessarily distributed with python itself.
+An easy way to get the Python plug-ins installed on your machine is:
+> % git clone https://github.com/openhwgroup/core-v-verif.git \
+> % cd \/bin
+> % pip3 install -r requirements.txt
+
+Utility Documentation
+=====================
+
+Documentation for each of the utilities are included below. Each utility should also support a help option
+on the command line for describing options and arguments available.
+
+## makeuvmt
+This is a simple wrapper to redirect a make call to any core's UVMT Makefile. This redirection script
+simply requires that you either:
+- specify CV_CORE in your environment -or-
+- specify CV_CORE on the maekeuvmt command line as an override
+
+The script will then invoke make in the following directory:
+> \/$(CV_CORE)/sim/uvmt
+
+This should enable simulations to be executed regardess of current shell directory. All common make flags
+and conventions should be passed to the underlying Makefile directory.
+
+*Examples:*
+> \# makeuvmt can be invoked from any directory
+> % makeuvmt test TEST=hello-world WAVES=1 SIMULATOR=vsim
+> \# Override the core to cv32e40x (regardless of CV_CORE environment setting)
+> % makeuvmt test TEST=hello-world WAVES=1 CV_CORE=cv32e40x
+
+## ci_check
+
+Continuous integration checker script. This script runs a quick sanity regression on the requested
+simulator for the purposes of ensuring a pull-request can be safely made. Note that *ci_check* should now
+be able to be executed in any directory where previously it required the user to *cd* to ci/. Please
+refer to *ci_check*'s help utility for more details on options
+
+If required, the step and compare ISS can be disabled for this regression by setting _--iss=0_
+
+*Examples:*
+> \# Run CI sanity regression on Xcelium
+% ci_check -s xrun
+> \# Run CI sanity regression on Xcelium with the ISS disabled
+% ci_check -s xrun --iss=0
+> \# Get help of all available options
+% ci_check --help
+
+## cv_regress
+
+Regression script generator utility. *cv_regress* will read in one or more regressions defined in a specific
+YAML format into an output format suitable for the specified regression platform or utility. The currently supported
+output platforms are:
+- Metrics JSON (--metrics)
+- Shell Script (--sh)
+- Vmanager VSIF (--vsif)
+
+The format of the YAML testlist file is given below. All YAML regression testslists should go in the following directory:
+> core-v-verif/\/regress
+
+where *\* is a core (cv32e40p or cva6)
+
+Note that the utility has the ability to combine multiple testlists to build larger regressions. Therefore the --file
+option may be specified multiple times.
+
+Please refer to the help utility of *cv_regress* for more details on the utility.
+
+*Examples:*
+> \# Read in *cv32e40p_ci_check* testlist with Questa and emit an executable shell script
+% cv_regress --file=cv32e40p_ci_check.yaml --simulator=vsim --outfile=vsim_ci_check.sh
+
+### Regression YAML Format
+
+The following describes the YAML format for regression testlists.
+
+>\<*Required*: the name of the testlist>
+name: \
+\<*Required*: human-readable description to specify the intent of the testlist>
+description: \
+>
+\# List of builds, this can include SystemVerilog compiles and riscv-dv compiles
+\# Multiple builds may be defined
+builds:
+ build_name0:
+ <*Required*: make command for the build>
+ cmd: make comp
+ <*Required*: make directory for the build>
+ dir: cv32/sim/uvmt_cv32
+>
+\# List of tests
+\# Multiple tests can be defined
+tests:
+ test_name0:
+ <*Required*: build dependencies, can be a list of single build_name>
+ build: \
+ <*Required*: human-readable test description>
+ description: \
+ <*Required*: make directory for the test>
+ dir: \
+ <*Optional*: A make command to run before running the test(s). This could be used for gen_* makes for corev-dv
+ precmd: \
+ <*Required*: make directory for the test>
+ cmd: \
+ <*Optional*: The number of test iterations to run. Note that all runs will receive a random seed>
+ num: \
+
+
diff --git a/bin/cfgyaml2make b/bin/cfgyaml2make
new file mode 100755
index 0000000..fdfd7a3
--- /dev/null
+++ b/bin/cfgyaml2make
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+# Copyright 2020 Silicon Labs, Inc.
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# cfgyaml2make
+# Converts a build configuration YAML to make variables
+#
+# Author: Steve Richmond
+# email: steve.richmond@silabs.com
+#
+# Written with Python 3.5.1 on RHEL 7.7. Your python mileage may vary.
+#
+################################################################################
+
+import argparse
+import os
+import sys
+import tempfile
+import re
+import pprint
+import logging
+import yaml
+
+logging.basicConfig()
+logger = logging.getLogger(os.path.basename(__file__))
+logger.setLevel(logging.INFO)
+
+TOPDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+REQUIRED_KEYS = ('name', 'description',)
+CFG_PATHS = (
+# '/tests/cfg',
+ 'tests/cfg',
+ )
+#try:
+ #DEFAULT_CORE=os.environ['CV_CORE']
+#except KeyError:
+ #DEFAULT_CORE=None
+DEFAULT_CORE='cv32e20'
+
+if (sys.version_info < (3,0,0)):
+ print ('Requires python 3')
+ exit(1)
+
+def read_file(file):
+ '''Read a YAML build specification'''
+
+ matches = [os.path.join(TOPDIR, p, file) for p in CFG_PATHS
+ if os.path.exists(os.path.join(TOPDIR, p, file))]
+
+ # It is a fatal error to find less than 1 or more than 1 match
+ if len(matches) == 0:
+ logger.fatal('Could not find {} in any cfg directories:'.format(file))
+ for p in CFG_PATHS:
+ logger.fatal(os.path.join(TOPDIR, p, file))
+ os.sys.exit(2)
+
+ if len(matches) >1 :
+ logger.fatal('Found multiple matches for {} in directories:'.format(yaml))
+ for p in CFG_PATHS:
+ logger.fatal(os.path.join(TOPDIR, p, file))
+ os.sys.exit(2)
+
+ stream = open(matches[0], 'r')
+ logger.debug('Reading cfg specification: {}'.format(matches[0]))
+ # Newer PyYAMLs must specify explicit loader (policy) or will issue warnings
+ # Older PyYAMLs will not support the Loader argument
+ # So try the new way first, then catch to the old way
+ try:
+ cfg_spec = yaml.load(stream, Loader=yaml.FullLoader)
+ except AttributeError:
+ cfg_spec = yaml.load(stream)
+ stream.close()
+
+ # Validation
+ for k in REQUIRED_KEYS:
+ if not k in cfg_spec:
+ logger.fatal('Key [{}] was not found in cfg specification YAML:'.format(k))
+ logger.fatal('-> : {}'.format(matches[0]))
+ os.sys.exit(2)
+
+ # Debug the YAML parsing
+ pp = pprint.PrettyPrinter()
+ logger.debug('Read YAML:')
+ logger.debug(pp.pformat(cfg_spec))
+
+ return cfg_spec
+
+def emit_make(cfg_spec, prefix):
+ '''Emit a hash from the YAML test specification into a makefile that can be included'''
+ fh = tempfile.NamedTemporaryFile(mode='w', delete=False)
+ for k,v in sorted(cfg_spec.items()):
+ # Handle empty value (allowed)
+ try:
+ v_rstrip = v.rstrip()
+ except AttributeError:
+ v_rstrip = ''
+ fh.write('{}{}={}\n'.format('' if not prefix else prefix.upper() + '_', k.upper(), v_rstrip))
+ fh.close()
+
+ return fh.name
+
+################################################################################
+# Command-line arguments
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-d', '--debug', action='store_true', help='Display debug messages')
+parser.add_argument('--yaml', help='Name of YAML build specification to find')
+parser.add_argument('--core', default=DEFAULT_CORE, help='Default core to test')
+parser.add_argument('--prefix', help='Prefix to add to make variables generated')
+args = parser.parse_args()
+
+if args.debug:
+ logger.setLevel(level=logging.DEBUG)
+
+# Validate
+if not args.core:
+ logger.fatal('Must specify core with CV_CORE envrionment variable or --core')
+ os.sys.exit(2)
+
+if not args.yaml:
+ logger.fatal('Must specify the YAML build specification with --yaml')
+ os.sys.exit(2)
+
+#CFG_PATHS = [p.replace('', args.core.lower()) for p in CFG_PATHS]
+
+cfg_spec = read_file(file=args.yaml)
+temp_file = emit_make(cfg_spec=cfg_spec, prefix=args.prefix)
+
+logger.debug('File written to {}'.format(temp_file))
+print(temp_file)
diff --git a/bin/ci_check b/bin/ci_check
new file mode 100755
index 0000000..42cf58c
--- /dev/null
+++ b/bin/ci_check
@@ -0,0 +1,434 @@
+#! /usr/bin/env python3
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# ci_check: python script to run a sanity regression. Intended to be used
+# to check updates prior to a pull-request. Uses the same
+# .metrics.json control script as the Metrics CI tool-chain.
+# Compiles and executes whatever is listed in the "regressions"
+# list-of-dictionaries.
+#
+# Author: Mike Thompson
+# email: mike@openhwgroup.org
+#
+# Written with Python 3.6.9 on Ubuntu 18.04. Your python mileage may vary.
+#
+# Restriction:
+# - Blindly uses .metrics.json with no ability for user over-ride.
+#
+# TODO:
+# 1. Check results using the "isPass" key.
+# 2. Handle Verilator a little more elegantly.
+# 3. Terminate if compile fails.
+################################################################################
+
+import json
+import sys
+import os
+import argparse
+import subprocess
+import pprint
+import yaml
+import re
+import shutil
+
+if (sys.version_info < (3,0,0)):
+ print ('Requires python 3')
+ exit(1)
+
+################################################################################
+# Globals....
+name_of_ci_check_regression = '_ci_check_dev' # must match the name of one regression list in .metrics.json
+core_tests = ['misalign', 'illegal', 'dhrystone', 'fibonacci', 'riscv_ebreak_test_0']
+try:
+ default_core = os.environ['CV_CORE']
+except KeyError:
+ default_core = 'None'
+
+# This script is run from the "bin" directory, but the paths used by simulator
+# commands assume we are at the root of the repo.
+topdir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+print('ci_check: topdir : {}'.format(topdir))
+
+################################################################################
+# Command-line arguments
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-s", "--simulator", help="SystemVerilog simulator", choices=['dsim', 'xrun', 'vsim', 'vcs', 'riviera'])
+parser.add_argument("--core", help="Set the core to test (default: {})".format(default_core), default=default_core)
+parser.add_argument("-d", "--debug", help="Display debug messages", action="store_true")
+parser.add_argument("-p", "--print_command", help="Print commands to stdout, do not run", action="store_true")
+parser.add_argument("-c", "--check_only", help="Check previosu results (do not run)", action="store_true")
+parser.add_argument("-k", "--keep", help="Keep previous cloned or generated files", action="store_true")
+parser.add_argument("-v", "--verilator", help="Run Verilator on the CORE testbench", action="store_true")
+parser.add_argument("-u", "--no_uvm", help="DO NOT run CI regression on the UVM testbench", action="store_true")
+parser.add_argument('--iss', help='Force USE_ISS flag to each test run (use 0 or 1), default: Enabled')
+parser.add_argument("--repo", help="Use this repo for the RTL, not one in Makefile", type=str)
+parser.add_argument("--branch", help="Use this branch for the RTL, not one in Makefile", type=str)
+parser.add_argument("--hash", help="Use this hash for the RTL, not one in Makefile", type=str)
+
+args = parser.parse_args()
+debug = 0 # warning, too much info!
+prcmd = 0 # prints cmds to stdout
+veril = 0 # run Verilator on CORE when set
+uvm = 1 # Run UVM CI regression by default
+################################################################################
+
+# Set correct simulator output path
+if 'CV_RESULTS' in os.environ:
+ uvm_results_dir = os.path.abspath(os.getenv('CV_RESULTS'))
+else:
+ uvm_results_dir = os.path.abspath(os.path.join(topdir, args.core.lower(), 'sim/uvmt'))
+
+sim_results_dir = os.path.abspath(os.path.join(uvm_results_dir, '{}_results'.format(args.simulator)))
+
+################################################################################
+# Methods....
+
+# Pretty (or at least, not so ugly) pass/fail summary
+def pr_result(line='/really/long/ugly/path/test.log: SIMULATION PASSED'):
+ rline = line.decode('utf-8').rstrip() # remove trailing whitespace
+ if not re.search('SIMULATION', rline):
+ print('!!! Unexpected test result: {}'.format(rline))
+ exit(1)
+ plist = rline.split('/') # build a list from path
+ res = plist[-1] # result we want is in last entry of list
+ iii = res.find(':') # ":" is delimiter between file name and pass-or-fail
+ rlist = [ res[0:iii], ':', res[-7:] ] # result list (works becaused " PASSED", " FAILED" and "ABORTED" all have 7 chars)
+ print('{: >40} {} {: >7}'.format(*rlist)) # pretty printing: produces "test.log: PASSED" using default value of arg
+
+
+# Check results and print something useful
+def check_uvm_results(check_only=0):
+ fail_count = 0
+ expct_fail = 0
+ pass_count = 0
+
+ if os.path.exists(sim_results_dir):
+ fails = subprocess.Popen('grep "SIMULATION FAILED" `find {} -name "*.log" -print`'.format(sim_results_dir),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell="TRUE")
+ passes = subprocess.Popen('grep "SIMULATION PASSED" `find {} -name "*.log" -print`'.format(sim_results_dir),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell="TRUE")
+
+ print ('\n\nCI Check results:')
+ for line in fails.stdout.readlines():
+ pr_result(line)
+ fail_count += 1
+ # TODO: make this a list of known failures (hopefully there won't be that many...)
+ if (
+ (re.search('riscv_compliance', line.decode('utf-8')))
+ # or (re.search('riscv_ebreak', line.decode('utf-8')))
+ ):
+ expct_fail += 1
+
+ for line in passes.stdout.readlines():
+ pr_result(line)
+ pass_count += 1
+
+ if (pass_count == 0):
+ print ('\nNo UVM logfiles found.\n')
+ elif ((not check_only) and ((pass_count+fail_count) != num_tests)):
+ print ('CI Check FAILED: Expected '+str(num_tests)+' tests to run but found only '+str(fail_count+pass_count)+' PASSED or FAILED messages');
+ elif ((fail_count == 0) and (pass_count >=3)):
+ print ('\nCI Check PASSED with no failures.')
+ print ('OK to issue a pull-request.\n')
+ elif (fail_count == expct_fail):
+ print ('\nCI Check PASSED with KNOWN failure(s).')
+ print ('OK to issue a pull-request.\n')
+ else:
+ print ('\nCI Check FAILED with unknown failures.')
+ print ('Please fix before issuing a pull-request.\n')
+ else:
+ print ('\nCI Check FAILED with non-existent sim directory: {}'.format(sim_results_dir))
+ print ('Please fix before issuing a pull-request.\n')
+
+
+def check_core_results(run_count):
+ core_runs = subprocess.Popen('grep "EXIT SUCCESS" -R -I ../{}/sim/core/simulation_results'.format(args.core.lower()),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell="TRUE")
+
+ if (run_count == 0):
+ print ('\nNo CORE logfiles found.\n')
+ else:
+ for line in core_runs.stdout.readlines():
+ #core_runs = line.decode('utf-8').rstrip()
+ print (line.decode('utf-8').rstrip())
+ run_count -= 1
+
+ if (run_count == 0):
+ print ('\nCI Check of CORE testbench PASSED.\nYou must also run the UVM CI regression before submitting a PR.')
+ else:
+ print ('\nCI Check of CORE testbench FAILED.')
+ print ('Please fix before issuing a pull-request.\n')
+
+
+# This script may do some unexpected things, so give the user an escape hatch.
+def ask_user():
+ txt = input("Is this what you want [Y/N]? ")
+ if not ((txt == 'Y') or (txt == 'y')):
+ exit(1)
+
+# Load regression YAML
+def load_regress_yaml(regression):
+ '''Load the regression yaml and return the dictionary'''
+ full_regression = os.path.join(topdir, '{}/regress'.format(args.core.lower()), regression + '.yaml')
+ fh = open(full_regression, 'r')
+ # Newer PyYAMLs must specify explicit loader (policy) or will issue warnings
+ # Older PyYAMLs will not support the Loader argument
+ # So try the new way first, then catch to the old way
+ try:
+ dict = yaml.load(fh, Loader=yaml.FullLoader)
+ except AttributeError:
+ dict = yaml.load(fh)
+ fh.close()
+
+ return dict
+
+################################################################################
+# Handle Command-line arguments
+
+if (args.debug):
+ debug = 1
+
+if (args.print_command):
+ prcmd = 1
+
+if (args.core == 'None'):
+ print('No default core specified in CV_CORE and no --core defined')
+ exit(1)
+
+if (not os.path.exists(os.path.join(topdir, args.core.lower(), 'sim/uvmt/Makefile'))):
+ print('Core directory for {} not found'.format(args.core))
+ exit(1)
+
+if (not args.verilator and args.no_uvm):
+ print ('Specifying --no_uvm without --verilator means I do nothing... Type `ci_check -h` for usage.')
+ exit(1)
+
+if (args.check_only):
+ if (args.verilator):
+ check_core_results(len(core_tests)+1) # +1 because 'make' runs hello-world
+ if not (args.no_uvm):
+ check_uvm_results(args.check_only)
+ exit(0)
+
+if (args.no_uvm):
+ uvm = 0
+
+if (args.verilator):
+ veril = 1
+elif (args.simulator == None):
+ print ('Must specify a simulator. Type `ci_check -h` to see how')
+ exit(0)
+elif (not(shutil.which(args.simulator))):
+ print ('ERROR: simulator='+args.simulator+' but executable not found')
+ exit(0)
+else:
+ svtool = args.simulator
+
+name_of_ci_check_regression = name_of_ci_check_regression.replace('', args.core.lower())
+print('ci_check: core : {}'.format(args.core))
+print('ci_check: name_of_ci_check_regression : {}'.format(name_of_ci_check_regression))
+os.environ['CV_CORE'] = args.core.upper()
+
+# --print_command is set: do not actually _do_ anything
+if not (prcmd):
+ if (args.keep):
+ print ('Keeping previously cloned version of the RTL plus any previously generated files')
+ ask_user()
+ else:
+ print ('This will delete your previously cloned RTL repo plus all previously generated files')
+ ask_user()
+ os.chdir(os.path.abspath(os.path.join(topdir, args.core.lower(), 'sim/uvmt')))
+ os.system('make clean_all')
+ os.chdir(os.path.join(topdir, '{}/sim/core'.format(args.core.lower())))
+ os.system('make clean_all')
+ os.chdir(os.path.join(topdir, 'bin'))
+
+################################################################################
+# script starts here
+
+
+
+
+# This script is run from the "ci" directory, but the paths used by simulator
+# commands assume we are at the root of the repo.
+os.chdir(topdir)
+
+#
+# Step 1: Run the User Regression for the UVM verification environment.
+#
+# .metrics.json is the CI regression config used by Metrics CI tools.
+if (uvm):
+ with open(os.path.join(topdir, '.metrics.json')) as f:
+ metrics_dict = json.load(f)
+
+ # Get the build command
+ for key in metrics_dict:
+ if (key == 'builds'):
+ builds_dict = metrics_dict['builds']
+ if (debug):
+ print (json.dumps(builds_dict, indent=2, sort_keys=True))
+ for key in builds_dict:
+ if (key == 'list'):
+ list_dict = builds_dict['list']
+ if (debug):
+ print (json.dumps(list_dict, indent=2, sort_keys=True))
+ for key in list_dict:
+ if (key['name'] != 'uvmt_{}'.format(args.core.lower())):
+ continue
+ build_cmd_list = (key['cmd']).split()
+ build_cmd = ' '.join(build_cmd_list[0:-1])
+ build_cmd = build_cmd.replace(' DSIM_WORK=/mux-flow/build/repo/dsim_work', '')
+ build_cmd = build_cmd.replace(' SIM_RESULTS=/mux-flow/build/results', '')
+ if (build_cmd != ''):
+ build_cmd = build_cmd.replace('dsim', svtool)
+ if (args.repo):
+ build_cmd = build_cmd + ' CV_CORE_REPO=' + args.repo
+ if (args.branch):
+ build_cmd = build_cmd + ' CV_CORE_BRANCH=' + args.branch
+ if (args.hash):
+ build_cmd = build_cmd + ' CV_CORE_HASH=' + args.hash
+ if (prcmd or debug):
+ print(build_cmd)
+ else:
+ os.system(build_cmd)
+ os.chdir(topdir) # cmd in .metrics.json assumes all cmds start from here
+ else:
+ print ('ERROR: cannot find build command in .metrics.json')
+ exit(0)
+
+ # Get the simulation command(s)
+ for key in metrics_dict:
+ if (key == 'regressions'):
+ regressions_dict = metrics_dict['regressions']
+ if (debug):
+ print (json.dumps(regressions_dict, indent=2))
+ for item in regressions_dict:
+ if (item['name'] != name_of_ci_check_regression):
+ continue
+ else:
+ if (debug):
+ print('Running', name_of_ci_check_regression)
+
+ # Load it in here!
+ m = re.search('\-\-file=(\w+)', item['tests']['listCmd'])
+ if not m:
+ print('Cannot parse listCmd: {}'.format(item['tests']['listCmd']))
+ exit(1)
+ lists_dict = load_regress_yaml(m.group(1))['tests']
+
+ if (debug):
+ pprint.pprint(lists_dict)
+
+ num_tests = 0
+ for key in lists_dict.values():
+ run_cmd = key['cmd']
+
+ if run_cmd == '':
+ print ('ERROR: cannot find run command in .metrics.json')
+ exit(1)
+
+ try:
+ if key['num'] > 1:
+ num = key['num']
+ except KeyError:
+ num = 1
+
+ # The iss command-line switch takes precedence,
+ # Otherwise use what is in the regression yaml if defined
+ # Otherwise set to 1
+ if args.iss != None:
+ iss = int(args.iss)
+ else:
+ try:
+ iss = key['iss']
+ except KeyError:
+ iss = 1
+
+ for n in range(num):
+ # Add directory
+ full_run_cmd = 'cd {}; {}'.format(key['dir'], run_cmd)
+ # Add SIMULATOR
+ full_run_cmd += ' SIMULATOR={}'.format(svtool)
+ # Add indices
+ full_run_cmd += ' GEN_START_INDEX={} RUN_INDEX={}'.format(n, n)
+ # Add ISS
+ full_run_cmd += ' USE_ISS={}'.format('YES' if iss else 'NO')
+
+ # Only DSIM can run corev-dv (riscv-dv) at present
+ if ( svtool == 'dsim' or svtool == 'xrun' or svtool == 'vsim' or svtool == 'riviera' or svtool == 'vcs'):
+ num_tests+=1
+ if (prcmd or debug):
+ print(full_run_cmd)
+ else:
+ os.system(full_run_cmd)
+ os.chdir(topdir) # cmd in .metrics.json assumes all cmds start from here
+ else:
+ num_tests+=1
+ if not ( re.search('corev_', full_run_cmd) ):
+ if (prcmd or debug):
+ print(full_run_cmd)
+ else:
+ os.system(full_run_cmd)
+ os.chdir(topdir) # cmd in .metrics.json assumes all cmds start from here
+
+else: # if(uvm):
+ print ('Not running UVM CI regression')
+
+#
+# Step 2: Optionally run a few testcases on the CORE testbench using verilator.
+# TODO: this is pretty brain-dead...
+#
+if (veril):
+ print ('Running Verilator tests on CORE testbench...')
+ if (debug):
+ print('{}/sim/core'.format(args.core.lower()))
+ os.chdir(os.path.join(topdir,'{}/sim/core'.format(args.core.lower())))
+
+ if (prcmd or debug):
+ print('make')
+ for core_test in core_tests:
+ print('make veri-test TEST=' + core_test)
+ if not (prcmd):
+ os.system('make')
+ for core_test in core_tests:
+ os.system('make veri-test TEST=' + core_test)
+
+os.chdir(topdir) # cmd in .metrics.json assumes all cmds start from here
+
+# Unless this is just a run to dump simulation commands (--print_commands),
+# grep results out of the logfiles and print to stdout
+os.chdir('bin')
+if not (prcmd):
+ if (veril):
+ check_core_results(len(core_tests)+1) # +1 because 'make' runs hello-world
+ if (uvm):
+ check_uvm_results()
+ else:
+ print ('UVM CI Regression not run. (Please do so before issuing a pull-request.)')
+
+## end ##
diff --git a/bin/cv_regress b/bin/cv_regress
new file mode 100755
index 0000000..a2cd8dd
--- /dev/null
+++ b/bin/cv_regress
@@ -0,0 +1,297 @@
+#!/usr/bin/env python3
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# cv_regress: python script to generate a tool-specific regression based
+# upon YAML specifications of regressions
+#
+# Author: Steve Richmond
+# email: steve.richmond@silabs.com
+#
+# Written with Python 3.5.1 on RHEL 7.7. Your python mileage may vary.
+#
+#
+# TODO:
+################################################################################
+
+import argparse
+import yaml
+import logging
+import sys
+import os
+import jinja2
+import pprint
+from collections import OrderedDict
+
+sys.path.append(os.path.join(os.path.dirname(__file__), 'lib'))
+
+import cv_regression
+
+logger = logging.getLogger(__name__)
+
+if (sys.version_info < (3,0,0)):
+ print ('Requires python 3')
+ exit(1)
+
+def get_project_path(project):
+ '''Fetch the project path based on path of this script'''
+ return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', project))
+
+def check_valid_test(project, name):
+ '''Validation step to determine if a testname in a regression is valid.
+ Some regression tools will fail if test name does not match make TEST variable.'''
+ test_dirs = (os.path.join(get_project_path(project), 'tests/programs/corev-dv'),
+ os.path.join(get_project_path(project), 'tests/programs/custom'),
+ os.path.join(get_project_path(project), 'tests/programs/embench'),
+ )
+
+ for t in test_dirs:
+ if os.path.isdir(os.path.join(t, name)):
+ return True
+
+ logger.fatal('Test name: {} is not valid'.format(name))
+ os.sys.exit(2)
+
+def get_filter_dir():
+ '''Fetch Vmanager filter path using project'''
+ return os.path.abspath(os.path.join(os.path.dirname(__file__), 'vmgr'))
+
+def get_regress_path(project):
+ '''Fetch regression path using project'''
+ return os.path.abspath(os.path.join(get_project_path(project), 'regress'))
+
+def get_results_path(project):
+ return os.path.abspath(os.path.join(get_project_path(project), 'sim', 'uvmt'))
+
+def read_file(args, file):
+ '''Read a YAML definition filelist'''
+ full_regress_file = os.path.join(get_regress_path(args.project), file)
+ stream = open(full_regress_file, 'r')
+ logger.info('Reading regression: {}'.format(full_regress_file))
+ # Newer PyYAMLs must specify explicit loader (policy) or will issue warnings
+ # Older PyYAMLs will not support the Loader argument
+ # So try the new way first, then catch to the old way
+ try:
+ testlist = yaml.load(stream, Loader=yaml.FullLoader)
+ except AttributeError:
+ testlist = yaml.load(stream)
+ stream.close()
+ pp = pprint.PrettyPrinter()
+ logger.debug('Read YAML:')
+ logger.debug(pp.pformat(testlist))
+
+ # Basic validation
+ assert 'name' in testlist, 'Must specify a testlist name in YAML header'
+ assert 'description' in testlist, 'Must specify a testlist description in YAML header'
+ assert 'tests' in testlist, 'A test section with at least one test must be defined'
+ for b, d in testlist['builds'].items():
+ assert 'cmd' in d, 'cmd must be specified in test: ' + b
+ assert 'dir' in d, 'dir must be specified in test: ' + b
+ for t, d in testlist['tests'].items():
+ try:
+ assert type(d['builds']) == list, 'builds must be a list in test: ' + t
+ except KeyError:
+ assert 'build' in d, 'builds or build must be specified in test: ' + t
+
+ assert 'cmd' in d, 'cmd must be specified in test: ' + t
+ assert 'dir' in d, 'dir must be specified in test: ' + t
+
+ # Construct a proper regression object
+ regression = cv_regression.Regression(name=testlist['name'],
+ description=testlist['description'])
+
+ # Create build objects
+ for k in testlist['builds']:
+ b = testlist['builds'][k]
+ build = cv_regression.Build(name=k, simulator=args.simulator, **b)
+ if args.cov:
+ build.set_cov()
+ if args.make:
+ build.sub_make(args.make)
+ if args.cfg:
+ build.cfg = args.cfg
+
+ regression.add_build(build)
+
+ # Create test objects
+ for k in testlist['tests']:
+ t = testlist['tests'][k]
+
+ try:
+ if args.simulator in t['skip_sim']:
+ continue
+ except KeyError:
+ pass
+ test = cv_regression.Test(name=k, simulator=args.simulator, **t)
+ if args.cov:
+ test.set_cov()
+ if args.make:
+ test.sub_make(args.make)
+ if args.iss != None:
+ test.iss = args.iss
+ if args.cfg:
+ test.cfg = args.cfg
+ if not test.builds and test.build:
+ test.builds = [ test.build ]
+
+ # Determine if a test is valid, skip for compliance tests
+ # Since it is not possible to determine apriori if a compliance test is valid
+ if not 'compliance' in test.cmd:
+ check_valid_test(args.project, test.name)
+
+ # Determine if a test is indexed for setting test iterations
+ if args.num:
+ test.num = int(args.num)
+
+ regression.add_test(test)
+
+ return regression
+
+# Defaults and globals
+VALID_SIMULATORS = ('dsim', 'vsim', 'vcs', 'xrun')
+DEFAULT_SIMULATOR = 'dsim'
+VALID_TOOLCHAINS = ('gnu','llvm','corev','pulp')
+DEFAULT_TOOLCHAIN = 'corev'
+
+VALID_PROJECTS = ('cv32e40p', 'cv32e40x', 'cv32e40s', 'cv64')
+try:
+ DEFAULT_PROJECT = os.environ['CV_CORE']
+except KeyError:
+ DEFAULT_PROJECT = 'cv32e40p'
+DEFAULT_CFG = 'default'
+DEFAULT_PARALLEL = '30'
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+parser.add_argument('-f', '--file', action='append', help='One or more input regression YAML lists to read')
+parser.add_argument('-p', '--project', '--core', default=DEFAULT_PROJECT, choices=VALID_PROJECTS, help='Select core for regression')
+parser.add_argument('-o', '--outfile', help='Output file')
+parser.add_argument('-d', '--debug', help='Emit debug messages from logger', action='store_true')
+parser.add_argument('--results', help='Set a non-standard results directory')
+parser.add_argument('-s', '--simulator', help='Select simulator', choices=VALID_SIMULATORS, default=DEFAULT_SIMULATOR)
+parser.add_argument('-c', '--cov', help='Enable coverage', action='store_true')
+parser.add_argument('--cfg', default=None, help='Override configuration for all builds and tests in regression')
+parser.add_argument('--iss', default=None, help='Force USE_ISS flag to each test run')
+parser.add_argument('--parallel', default=DEFAULT_PARALLEL, help='For VSIF only, set number of parallel jobs')
+parser.add_argument('-m', '--metrics', help='Select Metrics waves output', action='store_true')
+parser.add_argument('-n', '--num', help='Force number of iterations for tests with multiple iteration')
+parser.add_argument('--lsf', help='If applicable for output format, set LSF args to dispatch jobs')
+parser.add_argument('--make', help='Substitute for make command (to use short-cuts)')
+parser.add_argument('--makearg', action='append', help='Arguments to supply to each make command, can be specified multiple times')
+parser.add_argument('--sh', help='Select bash shell script output', action='store_true')
+parser.add_argument('--vsif', help='Select Vmanager VSIF output', action='store_true')
+parser.add_argument('--toolchain', help='Select toolchain to build with', choices=VALID_TOOLCHAINS, default=DEFAULT_TOOLCHAIN)
+args = parser.parse_args()
+
+if args.debug:
+ logger.setLevel(logging.DEBUG)
+
+# Validate arguments
+if not args.file:
+ logger.fatal('Must specify a regression definition YAML file with -f or --f')
+ os.sys.exit(2)
+
+# Supply defaults for outfile
+if not args.outfile:
+ args.outfile = os.path.splitext(args.file[0])[0]
+ if args.metrics:
+ args.outfile = args.outfile + '.json'
+ elif args.sh:
+ args.outfile = args.outfile + '.sh'
+ elif args.vsif:
+ args.outfile = args.outfile + '.vsif'
+
+regressions = []
+unique_builds = OrderedDict()
+for f in args.file:
+ # Add yaml extension if not supplied
+ if not os.path.splitext(f)[1] == 'yaml':
+ f = os.path.splitext(f)[0] + '.yaml'
+ r = read_file(args, f)
+ regressions.append(r)
+ for b in r.builds.values():
+ if not b.name in unique_builds:
+ unique_builds[b.name] = b
+
+# Generate output product
+env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__),
+ 'templates')), trim_blocks=True)
+
+# Output generation
+if args.sh:
+ # Generate shell script (--script)
+ template = env.get_template('regress_sh.j2')
+ logger.info('Rendering template: regress_sh.j2 into: {}'.format(args.outfile))
+ out_fh = open(args.outfile, 'w')
+ out_fh.write(template.render(regressions=regressions,
+ project=args.project,
+ cfg=args.cfg,
+ toolchain=args.toolchain,
+ results=args.results,
+ makeargs=' '.join(args.makearg) if args.makearg else '',
+ session=os.path.splitext(os.path.basename(args.outfile))[0],
+ unique_builds=unique_builds))
+ out_fh.close()
+ os.chmod(args.outfile, 0o775)
+
+if args.metrics:
+ # Generate a metrics-compatible JSON file (--metrics)
+ template = env.get_template('metrics.json.j2')
+ logger.info('Rendering template: metrics.json.j2 into: {}'.format(args.outfile))
+ out_fh = open(args.outfile, 'w')
+ out_fh.write(template.render(regressions=regressions,
+ project=args.project,
+ cfg=args.cfg,
+ toolchain=args.toolchain,
+ makeargs=' '.join(args.makearg) if args.makearg else '',
+ unique_builds=unique_builds))
+ out_fh.close()
+ os.chmod(args.outfile, 0o775)
+
+if args.vsif:
+ # Generate a Vmanager-compatible VSIF file (--vsif)
+ sve = os.path.splitext(args.outfile)[0] + '.sve'
+ template = env.get_template('regress_vsif.j2')
+ logger.info('Rendering template: regress_vsif.j2 into: {}'.format(args.outfile))
+ out_fh = open(args.outfile, 'w')
+ out_fh.write(template.render(session=os.path.splitext(os.path.basename(args.outfile))[0],
+ results_path=get_results_path(args.project),
+ project=args.project,
+ parallel=args.parallel,
+ regressions=regressions,
+ results=args.results,
+ makeargs=' '.join(args.makearg) if args.makearg else '',
+ lsf=args.lsf,
+ sve=os.path.abspath(sve),
+ toolchain=args.toolchain,
+ simulator=args.simulator,
+ filter_dir=get_filter_dir(),
+ unique_builds=unique_builds))
+ out_fh.close()
+
+ # Generate a Vmanager-compatible SVE
+ template = env.get_template('regress_sve.j2')
+ logger.info('Rendering template: regress_sve.j2 into: {}'.format(sve))
+ out_fh = open(sve, 'w')
+ out_fh.write(template.render(env=os.environ))
+ out_fh.close()
diff --git a/bin/diff_signatures.sh b/bin/diff_signatures.sh
new file mode 100755
index 0000000..0e563e0
--- /dev/null
+++ b/bin/diff_signatures.sh
@@ -0,0 +1,126 @@
+#!/bin/bash
+
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+# diff_signatures: script adopted from the riscv-compliance testsuite to
+# compare (diff) signature dumps. Will either compare the
+# reference and signature from a single test-program, or all
+# refs and sigs found in a regression.
+#
+# Usage:
+# diff_signatures ref sig : compare reference and signature
+# diff_signatures : (no arguments) iterates over all references
+# for a specific ISA (as defined by RISCV_ISA)
+# and compares to signatures.
+#
+# ENV: this script needs the following shell environment variables -
+# SUITEDIR : path to the compliance test-suite
+# SIG_ROOT : path to the signature files
+# REF : path to reference file (part of the compliance test-suite)
+# SIG : path to signature file (generated by running a sim)
+# COMPL_PROG : name of an individual compliance program, e.g. I-ADD-01
+# RISCV_TARGET : OpenHW
+# RISCV_DEVICE : cv32e40p
+# RISCV_ISA : one of rv32i|rv32im|rv32imc|rv32Zicsr|rv32Zifencei
+###############################################################################
+
+IGNORE=0
+ERROR=0
+MISCOMPARE=0
+RUN=0
+OK=0
+
+declare -i status=0
+
+diff_files() {
+ # Ensure both files exist
+ if [ ! -f $1 ]; then
+ ref_base=$(basename $1)
+ ref_stub=${sig_base//".reference_output"/}
+ echo "Reference file for ${ref_base} does not exist ... ERROR!"
+ ERROR=$((${ERROR} + 1))
+ else
+ if [ ! -f $2 ]; then
+ sig_base=$(basename $2)
+ sig_stub=${sig_base//".reference_output"/}
+ echo "Signature file for ${sig_stub} does not exist ... IGNORE"
+ IGNORE=$((${IGNORE} + 1))
+ else
+ sig_base=$(basename $2)
+ sig_stub=${sig_base//".reference_output"/}
+ echo -n "Check $(printf %24s ${sig_stub})"
+ RUN=$((${RUN} + 1))
+
+ diff --ignore-case --strip-trailing-cr $1 $2 #&> /dev/null
+
+ if [ $? == 0 ]; then
+ echo " ... OK"
+ OK=$((${OK} + 1))
+ else
+ echo " ... MISCOMPARE!"
+ MISCOMPARE=$((${MISCOMPARE} + 1))
+ fi
+ fi
+ fi
+}
+
+print_summary() {
+ if [ ${MISCOMPARE} == 0 ] && [ ${ERROR} == 0 ] && [ ${IGNORE} == 0 ]; then
+ echo "--------------------------------"
+ echo -n "OK: ${RUN}/${RUN} "
+ status=0
+ else
+ echo "--------------------------------"
+ echo "Summary for RISCV_TARGET=${RISCV_TARGET}; RISCV_DEVICE=${RISCV_DEVICE}; RISCV_ISA=${RISCV_ISA}"
+ echo " MISCOMPARE: ${MISCOMPARE}/${RUN} "
+ echo " IGNORE: ${IGNORE}/${RUN} "
+ echo " ERROR: ${ERROR}/${RUN} "
+ echo " OK: ${OK}/${RUN} "
+
+ if [ ${MISCOMPARE} != 0 ] || [ ${ERROR} != 0 ]; then
+ status=1
+ fi
+ fi
+ echo
+}
+
+# Script starts here
+if [[ $1 = "" ]]; then
+ diff_files ${REF} ${SIG}
+
+ print_summary
+else
+ for ref in ${SUITEDIR}/references/*.reference_output;
+ do
+ #echo "ref = ${ref}"
+ base=$(basename ${ref})
+ stub=${base//".reference_output"/}
+ sig=${SIG_ROOT}/${stub}/${RUN_INDEX}/${stub}.signature_output
+
+ diff_files ${ref} ${sig}
+ done
+
+ print_summary
+fi
+
+if [[ $status == "0" ]]; then
+ echo "All signatures passed"
+fi
+exit ${status}
diff --git a/bin/illegal_instr_generator_cv32e40p_v1.pl b/bin/illegal_instr_generator_cv32e40p_v1.pl
new file mode 100755
index 0000000..9988fff
--- /dev/null
+++ b/bin/illegal_instr_generator_cv32e40p_v1.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+# Copyright (C) 2024 EM Microelectronic US Inc.
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
+#
+# illegal_instr_generator_cv32e40p_v1.pl has usage “./illegal_instr_generator_cv32e40p_v1.pl ”
+# and produces a test approximately .09*int instructions long, where all the instructions are
+# illegal instructions that cannot compile or execute properly, and places the test in
+# ../application/exceptions.
+#
+# The script works by randomly generating a set of instruction encodings and then uses the
+# compiler to tell it if the instruction is decoded into something or assumed illegal.
+# This is why only about 9% of the randomly generated encodings are actually illegal.
+#
+# To use the script replace to the path of your compiler.
+#
+
+open OUT_FILE, '>', "illegal_instr_temp.S" or die "Can't open illegal_instr_temp.S";
+my @set = ('0' .. '9', 'a' .. 'f');
+for ($i = 0; $i<$ARGV[0]; $i++){
+ $str = join '' => map $set[rand @set], 1 .. 8;
+ $str = (".word(0x" . $str . ")");
+ print OUT_FILE ("$str\n");
+}
+close OUT_FILE;
+
+$cmd = ("-Os -g -D__riscv__=1 -D__LITTLE_ENDIAN__=1 -march=rv32imcxpulpv2 -Wa,-march=rv32imcxpulpv2 -fdata-sections -ffunction-sections -fdiagnostics-color=always");
+#print ("Compiling list of interrupted instructions (interrupted_instructions.S) into an object file (interrupted_instructions.o)\n");
+`/riscv32-unknown-elf-gcc ${cmd} -o illegal_instr_temp.o -c illegal_instr_temp.S`;
+#print ("Compiling list of objects (interrupted_instructions.o) into an objdump file (interrupted_instructions.objdump)\n");
+`/riscv32-unknown-elf-objdump -xd illegal_instr_temp.o > illegal_instr_temp.objdump`;
+
+open my $fh, '<', "illegal_instr_temp.objdump" or die "Can't open illegal_instr_temp.S";
+while(<$fh>){
+ chomp;
+ @fields = split(/\s+/);
+ #print("$fields[3]\n");
+ if($fields[3]=~/^0x[0-9a-f]{4,8}$/i){
+ #print("$fields[3] is an illegal instruction\n");
+ $str = (".word(0x" . $fields[2] . ")");
+ $illegal_instr{$str} = 1;
+ }
+}
+close $fh;
+
+open my $fh, '<', "illegal_instr_temp.S" or die "Can't open illegal_instr_temp.S for parsing";
+open OUT_FILE, '>', "illegal_instr_test.S" or die "Can't open illegal_instr_test.S";
+print OUT_FILE (".globl _start\n.globl main\n.globl exit\n.globl debug\n.section .text\n.global test_results\ndebug:\n j main\ntest_results:\n .word 123456789\nmain:\n li t0, (0x1 << 3)\n csrs mstatus, t0\n");
+while(<$fh>){
+ chomp;
+ $comp_string = $_;
+ if(exists($illegal_instr{$comp_string})){
+ print OUT_FILE "$comp_string\n";
+ }
+}
+close $fh;
+close OUT_FILE;
+`/riscv32-unknown-elf-gcc ${cmd} -o illegal_instr_test.o -c illegal_instr_test.S`;
+`/riscv32-unknown-elf-objdump -xd illegal_instr_test.o > illegal_instr_test.objdump`;
+`cp illegal_instr_test.S ../application/exception/illegal_instr_test.S`;
+`rm illegal_instr_temp.o illegal_instr_temp.objdump illegal_instr_temp.S illegal_instr_test.S illegal_instr_test.o`;
diff --git a/bin/lib/README.md b/bin/lib/README.md
new file mode 100644
index 0000000..0101b65
--- /dev/null
+++ b/bin/lib/README.md
@@ -0,0 +1,6 @@
+Core-V-Verif Library Modules
+==================================
+
+General library modules may be placed in this directory. Current Python modules are included here.
+
+- cv_regression.py - Python class implementations for *cv_regress* utility
diff --git a/bin/lib/cv_regression.py b/bin/lib/cv_regression.py
new file mode 100644
index 0000000..ae15523
--- /dev/null
+++ b/bin/lib/cv_regression.py
@@ -0,0 +1,171 @@
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+
+import os
+import re
+import sys
+import logging
+from collections import OrderedDict
+
+logger = logging.getLogger(__name__)
+
+DEFAULT_ISS = 'YES'
+DEFAULT_COV = 'NO'
+DEFAULT_CFG = 'default'
+DEFAULT_SIMULATION_PASSED = 'SIMULATION PASSED'
+DEFAULT_SIMULATION_FAILED = 'SIMULATION FAILED'
+DEFAULT_SKIP_SIM = []
+
+def get_proj_root():
+ '''Fetch absolute path of core-v-verif directory'''
+ return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
+
+class Build:
+ '''A regression build object'''
+ def __init__(self, **kwargs):
+
+ # Create defaults
+ self.iss = DEFAULT_ISS
+ self.cfg = DEFAULT_CFG
+
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ # Absolutize a directory if dir tag exists
+ self.abs_dir = os.path.abspath(os.path.join(get_proj_root(), self.dir))
+
+ def set_cov(self):
+ '''Set the coverage flag based on app setting.
+ If cov already defined (from testlist), then ignore'''
+ try:
+ getattr(self, 'cov')
+ except AttributeError:
+ self.cov = True
+
+ def sub_make(self, make_sub):
+ '''In the command substitute the make with the supplied substitution'''
+ self.cmd = re.sub('make', make_sub, self.cmd)
+
+ def __str__(self):
+ return '{} {} {}'.format(self.name, self.cmd, self.dir)
+
+class Test:
+ '''A regression test object'''
+ def __init__(self, **kwargs):
+ '''Create a test object'''
+
+ # Set defaults
+ self.skip_sim = DEFAULT_SKIP_SIM
+ self.simulation_passed = DEFAULT_SIMULATION_PASSED
+ self.simulation_failed = DEFAULT_SIMULATION_FAILED
+ self.iss = DEFAULT_ISS
+ self.num = 1
+ self.builds = []
+
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ # Absolutize a directory if exists
+ self.abs_dir = os.path.abspath(os.path.join(get_proj_root(), self.dir))
+
+ # Log equals the test name if does not exist
+ if not hasattr(self, 'log'):
+ self.log = self.name
+
+ def set_cov(self):
+ '''Set the coverage flag based on app setting.
+ If cov already defined (from testlist), then ignore'''
+ try:
+ getattr(self, 'cov')
+ except AttributeError:
+ self.cov = True
+
+ def sub_make(self, make_sub):
+ '''In the command substitute the make with the supplied substitution'''
+ self.cmd = re.sub('make', make_sub, self.cmd)
+ try:
+ self.precmd = re.sub('make', make_sub, self.precmd)
+ except AttributeError:
+ # precmd is optional
+ pass
+
+class Regression:
+ '''A full regression object'''
+ def __init__(self, **kwargs):
+ '''Constructor'''
+ self.builds = OrderedDict()
+ self.tests = OrderedDict()
+
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+
+ def add_build(self, build):
+ '''Add a new build object to this regression'''
+ if build.name in self.builds.keys():
+ logger.fatal('Build: {} was defined multiple times'.format(build['name']))
+ os.sys.exit(2)
+
+ self.builds[build.name] = build
+
+ def add_test(self, test):
+ '''Add a new test object to this regression'''
+ if test.name in self.tests.keys():
+ logger.fatal('Test: {} was defined multiple times'.format(test['name']))
+ os.sys.exit(2)
+
+ # Validate that builds exist
+ try:
+ for b in test.builds:
+ if not b in self.builds.keys():
+ logger.fatal('Test: {} references non-existent build: {}'.format(test.name, b))
+ os.sys.exit(2)
+ except TypeError:
+ logger.fatal('Test: {} did not specify a list of builds'.format(test.name))
+ os.sys.exit(2)
+
+ self.tests[test.name] = test
+
+ def get_builds(self):
+ '''Return all builds found in all tests'''
+
+ builds = {self.builds[build] for t in self.tests.values() for build in t.builds}
+ return list(builds)
+
+ def get_builds_with_no_tests(self):
+ '''Return all builds found in all tests'''
+
+ builds_with_no_tests = []
+
+ for b in self.builds.values():
+ found = False
+ for t in self.tests.values():
+ if b.name in t.builds:
+ found = True
+ if not found:
+ builds_with_no_tests.append(b)
+
+ return builds_with_no_tests
+
+ def get_tests_of_build(self, build):
+ '''Return all test objects that contain the given build'''
+
+ tests = [t for t in self.tests.values() if build in t.builds]
+ return tests
diff --git a/bin/makeuvmt b/bin/makeuvmt
new file mode 100755
index 0000000..8a2150c
--- /dev/null
+++ b/bin/makeuvmt
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Redirection script to point to makefile under core with:
+# $(CV_CORE)/sim/uvmt/Makefile
+#
+###############################################################################
+
+# Redirect to the Makefile.uvmt in bin direcotry which will redirect to the proper Makefile
+cd $(dirname $0) && make -f Makefile.uvmt "$@"
diff --git a/bin/metrics-regress b/bin/metrics-regress
new file mode 100755
index 0000000..613be71
--- /dev/null
+++ b/bin/metrics-regress
@@ -0,0 +1,145 @@
+#!/usr/bin/python3
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+# MetricsCI script launched by GitHub Actions.
+# See ../.github/workflows/metrics-regress.yml.
+# Not intended to be launched manually, but if you _have_ to here's an example:
+# ENV vars needed by metrics-regress:
+# $ export GITHUB_EVENT_NAME=push
+# $ export GITHUB_REF=master
+# You need to have saved METRICS_CI_TOKEN in a safe place.
+# $ export METRICS_CI_TOKEN=6Pcc5hQoIKEn8Pjz+lvjqG+C1SY=
+# $ ./metrics-regress cv32e40p_ci_check_regression main-core-v-verif-openhwgroup
+
+
+import json
+import http.client
+import argparse
+import os
+import time
+import math
+
+def make_http_request( req_type, endpoint, params=None ):
+ headers = { 'Content-Type': 'application/json',
+ 'Private-Token': str(os.environ['METRICS_CI_TOKEN'])
+ }
+
+ conn = http.client.HTTPSConnection(server)
+ conn.request(req_type, endpoint, params, headers)
+ response = conn.getresponse()
+ data = response.read()
+ regressionData = json.loads(data.decode('utf-8'))
+ conn.close()
+
+ return response, regressionData
+
+
+## Parse arguments to get regression name and project ID
+parser = argparse.ArgumentParser(prog='metrics-regress',
+ description='Launch a regression on the Metrics platform and query results')
+parser.add_argument('regressionName', help='The name of the regression to run')
+parser.add_argument('projectId', help='The ID of the Metrics project')
+args = parser.parse_args()
+
+## Server
+server = 'openhwgroup.metrics.ca:443'
+
+## API Endpoints
+postRegression = '/api/v1/projects/'+args.projectId+'/regressionRuns'
+getRegressionRunInfo = '/api/v1/projects/'+args.projectId+'/regressionRuns/'
+
+## Start regression
+reqParams = {}
+reqParams['regressionName'] = args.regressionName
+
+# Determine the git reference to pass to Metrics. For PRs, the reference
+# is of the format refs/pull//merge
+if str(os.environ['GITHUB_EVENT_NAME']) == 'pull_request_target':
+ reqParams['branch'] = 'refs/pull/' + str(os.environ['PR_NUMBER']) + '/merge'
+else:
+ reqParams['branch'] = str(os.environ['GITHUB_REF'])
+params = json.dumps(reqParams)
+
+response, regressionData = make_http_request('POST', postRegression, params)
+
+## Check response
+if response.status != 201:
+ print('Error, regression was not started. Response: ' + str(response.status) + ':' \
+ + str(response.reason) + ' ' + str(regressionData))
+ print('Exit with code 1')
+ exit(1)
+else:
+ print('Regression started. Id = ' + regressionData['id'])
+
+## Start polling regression status
+regressionRunId = regressionData['id']
+
+while True:
+ time.sleep(10)
+ response, regressionData = make_http_request('GET', getRegressionRunInfo+regressionRunId)
+ if response.status == 200:
+ if 'complete' in regressionData['status']:
+ print('Regression complete')
+ break
+ if 'buildFailed' in regressionData['status']:
+ print('A build has failed. No tests will be run')
+ print('Debug at: https://openhwgroup.metrics.ca/' + args.projectId + \
+ '/results/regressionRuns/' + regressionRunId)
+ exit(1)
+
+## Print test status
+print('\n')
+print('Regression results')
+print('==================')
+print('Total number of tests: ' + str(regressionData['testRuns']['total']))
+print('Passed tests: ' + str(regressionData['testRuns']['passed']))
+print('Failed tests: ' + str(regressionData['testRuns']['failed']))
+print('Incomplete tests: ' + str(regressionData['testRuns']['incomplete']))
+print('\n')
+
+## Poll for coverage data
+while True:
+ time.sleep(10)
+ response, regressionData = make_http_request('GET', getRegressionRunInfo+regressionRunId)
+ if response.status == 200:
+ if regressionData['functionalCoverage'] is not None :
+ break
+
+## Print functional coverage
+print('Coverage results')
+print('================')
+print('Functional: ' + str(math.trunc(regressionData['functionalCoverage']*100)/100))
+if regressionData['assertionCoverage'] is not None:
+ print('Assertion: ' + str(math.trunc(regressionData['assertionCoverage']*100) /100))
+if regressionData['lineCoverage'] is not None:
+ print('Code (block): ' + str(math.trunc(regressionData['lineCoverage']*100) /100))
+print('\n')
+
+print('Full results at: https://openhwgroup.metrics.ca/' + args.projectId + \
+ '/results/regressionRuns/' + regressionRunId)
+
+## Set the exit code to be used by github action
+if regressionData['testRuns']['failed'] > 0 or \
+ regressionData['testRuns']['incomplete'] > 0:
+ print('One or more tests has failed/is incomplete. Exit with code 1.')
+ exit(1)
+else:
+ print('All tests have passed. Exit with code 0.')
+ exit(0)
diff --git a/bin/objdump2itb b/bin/objdump2itb
new file mode 100755
index 0000000..072397e
--- /dev/null
+++ b/bin/objdump2itb
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+
+################################################################################
+#
+# Copyright 2021 OpenHW Group
+# Copyright 2021 Silicon Labs
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# dump2itb: python script to parse a GNU binutils objdump output file
+# into an instruction table format, which is a custom
+# text file more suitable for parsing using the standard IEEE 1800
+# text parsing functions
+#
+# The objdump should set the following flags to ensure that the regexps will
+# parse the expected text properly
+# % objdump -d -l -s program.elf > program.objdump
+#
+# The instruction table file format for a single instruction is:
+#
+# #
+# #
+# #
+# #...
+# #
+# <...>
+#
+# An esample: Note that the pound signs are part of the format
+# #6
+# # // Expect DCSR
+# # // 31:28 XDEBUGER Version = 4
+# # // 8:6 Cause = 2 Trigger
+# # // 1:0 Privelege = 3 Machine
+# # // TBD FIXME BUG documentation update needed
+# # li t1, 4<<28 | 2<<6 | 3<<0 | 1<<15
+# 437324064 _debugger_trigger_match_ebreak debugger.S 171 40008337 2 lui x6,0x40008
+#
+#
+# Author: Steve Richmond
+# email: steve.richmond@silabs.com
+#
+# Written with Python 3.5.1 on RHEL 7.7. Your python mileage may vary.
+#
+################################################################################
+
+import string
+import sys
+import re
+import argparse
+import logging
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+class CFunction:
+ def __init__(self, addr, name):
+ self.addr = addr
+ self.name = name
+
+# Regular expression to extract a function from objdump
+# Example:
+# 00000256 :
+FUNC_PATTERN = "(?P[0-9a-f]{8}) <(?P\S*)>:"
+FUNC_RE = re.compile(FUNC_PATTERN)
+
+# Regular expression to extract an individual instruction
+# Example:
+# 264: 00a31363 bne t1,a0,26a
+INST_PATTERN = "(?P[0-9a-f]{1,8}):\t*(?P[0-9a-f]{4}([0-9a-f]{4})?)\s{2,}(?P[a-z].*)$"
+INST_RE = re.compile(INST_PATTERN)
+
+# Regular expression to extract a source annotation for each instruction
+# Example:
+# /work/strichmo/core-v-verif/cv32e40x/tests/programs/custom/debug_test_trigger/debugger.S:47
+SRC_FILE_PATTERN = "^(?P/\S+)/(?P[^/\s]+):(?P[0-9]*)$"
+SRC_FILE_RE = re.compile(SRC_FILE_PATTERN)
+
+parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+parser.add_argument('objdump', help='Required objdump file for parsing. Use - to read STDIN')
+parser.add_argument('--debug', action='store_true', help='Enable more debug messages')
+
+# Main function
+def objdump2itb():
+ '''Parse an objdump file'''
+ args = parser.parse_args(sys.argv[1:])
+ if args.debug:
+ logger.setLevel(logging.DEBUG)
+
+ parse(args.objdump)
+
+def parse(objdump):
+ '''Parse the file'''
+
+ if objdump == '-':
+ fp = sys.stdin
+ else:
+ fp = open(objdump)
+
+ current_cfunction = None
+ current_src_file = None
+ current_src_line = 0
+ current_src_code = ""
+ used_src = 0
+
+ for line in fp:
+ line_orig = line.strip('\n')
+ line = line.strip()
+ if not line:
+ continue
+
+ # Parse function
+ func = FUNC_RE.match(line)
+ if func:
+ d = func.groupdict()
+ current_cfunction = CFunction(d["addr"], d["name"])
+ current_src_code = "" # reset the source code lines
+ used_src = 0
+ continue
+
+ # Parse source file
+ src_file = SRC_FILE_RE.match(line)
+ if src_file:
+ d = src_file.groupdict()
+ current_src_file = d["file"]
+ current_src_line = d["line"]
+ current_src_code = "" # reset the source code lines
+ used_src = 0
+ continue
+
+ # Parse instruction
+ inst = INST_RE.match(line)
+ if inst:
+ d = inst.groupdict()
+ addr = d["addr"]
+ mcode = d["mcode"]
+ asm = d["asm"]
+ mcode = mcode.replace(" ", "")
+ asm = asm.replace("\t", " ").strip()
+ addr = int("0x{}".format(addr), 0)
+ fname = current_cfunction.name
+ asm_len = len(asm.split())
+
+ used_src = 1
+ if current_src_code == "":
+ src_len = 0
+ print("#{}".format(src_len))
+ else:
+ src_len = len(current_src_code.split('\n'));
+ print("#{}\n{}".format(src_len, current_src_code))
+
+ print("{} {} {} {} {} {} {}".format(addr, fname, current_src_file, current_src_line, mcode, asm_len, asm))
+
+ logger.debug("Addr: '{:x}' Func: '{}' Source File: '{}' Source lineno: '{}' mcode: '{}' Asm: '{}'".format(
+ int(addr), fname, current_src_file, current_src_line, mcode, asm))
+ continue
+
+ # no match on filters
+ if current_src_code:
+ src_len = len(current_src_code.split('\n'));
+ if (src_len < 10): # keep src from getting too long, also good if filenames are missing
+ current_src_code += "\n#" + line_orig
+ else:
+ if current_src_file: # don't start adding source before first src file
+ # first src line no newline before
+ current_src_code = "#" + line_orig
+
+ logger.debug("Unmatched (treating as source line): '{}'".format(line))
+
+
+if __name__ == '__main__':
+ objdump2itb()
+
diff --git a/bin/requirements.txt b/bin/requirements.txt
new file mode 100644
index 0000000..4b85ff1
--- /dev/null
+++ b/bin/requirements.txt
@@ -0,0 +1,11 @@
+bitstring==3.1.9
+#constraint==0.4.1
+dv==1.0.10
+Jinja2==3
+junit_xml==1.9
+Pallets_Sphinx_Themes==2.0.2
+pandas==1.3.4
+pyvsc==0.6.3.1400856349
+setuptools==65.5.1
+sphinx_rtd_theme==1.0.0
+tabulate==0.8.9
diff --git a/bin/run_compliance.sh b/bin/run_compliance.sh
new file mode 100755
index 0000000..f0fb79a
--- /dev/null
+++ b/bin/run_compliance.sh
@@ -0,0 +1,145 @@
+#!/bin/bash
+
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+# run_compliance: runs all test-programs in a specific ISA.
+#
+# Usage:
+# run_compliance RISCV_ISA
+#
+# ENV: this script needs the following shell environment variables -
+# SIM_DIR : cwd from which to run sims
+###############################################################################
+
+cd ${SIM_DIR}
+
+# Script starts here
+if [ "$1" == "" ] ; then
+ echo "Please specify RISCV_ISA (rv32i|rv32im|rv32imc|rv32Zicsr|rv32Zifencei)"
+ exit 1
+fi
+
+if [ "$1" == "rv32i" ] || [ "$1" == "rv32im" ] || [ "$1" == "rv32imc" ] || [ "$1" == "rv32Zicsr" ] || [ "$1" == "rv32Zifencei" ] ; then
+ echo "nadda"
+else
+ echo "Unknown RISCV_ISA. Please specify one of rv32i|rv32im|rv32imc|rv32Zicsr|rv32Zifencei"
+ exit 1
+fi
+
+if [ "$1" == "rv32Zicsr" ] ; then
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRCI-01
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRW-01
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRSI-01
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRC-01
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRWI-01
+ make compliance RISCV_ISA=rv32Zicsr COMPLIANCE_PROG=I-CSRRS-01
+fi
+
+if [ "$1" == "rv32Zifencei" ]; then
+ make compliance RISCV_ISA=rv32Zifencei COMPLIANCE_PROG=I-FENCE.I-01
+fi
+
+if [ "$1" == "rv32im" ]; then
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=DIV
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=MULHU
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=REMU
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=MULH
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=MULHSU
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=DIVU
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=REM
+ make compliance RISCV_ISA=rv32im COMPLIANCE_PROG=MUL
+fi
+
+if [ "$1" == "rv32i" ]; then
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LB-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SUB-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SRAI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADDI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BEQ-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SW-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-RF_size-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LHU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLL-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLTU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-JALR-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SH-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BNE-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LW-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LH-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BGE-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLTI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BGEU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ANDI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SRL-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-XORI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ENDIANESS-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLT-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LBU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-RF_width-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ORI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-AND-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-LUI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BLT-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-NOP-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-XOR-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-AUIPC-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-RF_x0-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLTIU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-IO-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SRLI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SB-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SLLI-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-BLTU-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-SRA-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-JAL-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-DELAY_SLOTS-01
+ make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-OR-01
+fi
+
+if [ "$1" == "rv32imc" ]; then
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SUB
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-ADD
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SRLI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-BEQZ
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-J
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-JR
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SWSP
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-LW
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-ADDI4SPN
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-OR
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-BNEZ
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-LWSP
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-ADDI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-ADDI16SP
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SW
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-AND
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SRAI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-ANDI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-LI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-JALR
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-LUI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-SLLI
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-XOR
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-MV
+ make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=C-JAL
+fi
+
+exit 0
diff --git a/bin/run_embench.py b/bin/run_embench.py
new file mode 100755
index 0000000..95a8d1e
--- /dev/null
+++ b/bin/run_embench.py
@@ -0,0 +1,461 @@
+#!/usr/bin/env python3
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# run_embench : python script to fetch, set up, build and run EMBench
+# benchmarking suite on the present cores
+#
+# Author: Marton Teilgård
+# email: mateilga@silabs.com
+#
+# Written with Python 3.6.5 on RHEL 7.7. Your python mileage may vary.
+#
+# Restriction:
+#
+#
+################################################################################
+
+import argparse
+import logging
+import os
+import sys
+import subprocess
+import jinja2
+import glob
+import re
+
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger('run_embench')
+
+def main():
+
+ check_python_version(3,6)
+
+ parser = build_parser()
+ args = parser.parse_args()
+ paths = build_paths(args.core)
+
+ if args.debug == 'YES':
+ logger.setLevel(logging.DEBUG)
+
+ if args.core == 'notset':
+ logger.info('Must specify a core to benchmark')
+ sys.exit(1)
+
+ if args.ccomp == 'notset':
+ logger.info('Must specify a c compiler to benchmark')
+ sys.exit(1)
+
+ if args.type != 'speed' and args.type != 'size':
+ logger.info(f"Invalid type selected: {args.type}, must be 'speed' or 'size'")
+ sys.exit(1)
+
+ if args.parallel == 'YES':
+ parallel = True
+ elif args.parallel == 'NO':
+ parallel = False
+ else:
+ logger.info(f"Invalid 'parallel' option: {args.parallel}, must be 'YES' or 'NO'")
+ sys.exit(1)
+
+ if args.build_only == 'YES':
+ build_only = True
+ elif args.build_only == 'NO':
+ build_only = False
+ else:
+ logger.info(f"Invalid 'build_only' option: {args.build_only}, must be 'YES' or 'NO'")
+ sys.exit(1)
+
+ logger.info("Starting EMBench for core-v-verif")
+ logger.info(f"Benchmarking core: {args.core}")
+ logger.info(f"Type of benchmark to run: {args.type}\n\n")
+
+ # checking if there are existing configuration files
+ if os.path.exists(paths['emcfg']):
+ logger.info("EMBench repository checked out previously")
+ logger.info("Cleaning results and skipping cfg copy")
+ prebuilt = True
+ # deleting existing build results
+ try:
+ subprocess.run(
+ ['find', '.', '!', '-path', '.', '!', '-path', './README.md', '-delete'],
+ cwd=paths['testsem']
+ )
+ except:
+ logger.fatal('Failed to delete old build results')
+ else:
+ prebuilt = False
+
+ # ----------------------------------------------------------------------------------------------
+ # setup EMBench
+ # ----------------------------------------------------------------------------------------------
+ logger.info("Building Benchmark files")
+
+ if not prebuilt:
+ # copy core-native config
+ logger.info(f"Copying EMBench config from {paths['libcfg']} to {paths['emcfg']}")
+ try:
+ subprocess.run(
+ ['cp', '-R', paths['libcfg'], paths['emcfg']]
+ )
+ except:
+ logger.fatal('EMBench config copy failed')
+
+ # copy source files from bsp
+ # Only done when testing speed, size benchmark is built without support
+ # to matchEMBench baseline
+ if args.type == 'speed':
+ logger.info(f"Copying files from {paths['bsp']} to {paths['embrd']}")
+ for file in os.listdir(paths['bsp']):
+ if file.endswith('.S') or file.endswith('.c') or file.endswith('.h'):
+ logger.info(f"Copying {file}")
+ try:
+ subprocess.run(['cp', paths['bsp']+'/'+file, paths['embrd']])
+ except:
+ logger.fatal(f"EMBench bsp copy of file {file} failed")
+
+ # copy python module
+ logger.info(f"Symlinking {paths['libpy']}/run_corev32.py to {paths['empy']}/run_corev32.py")
+ try:
+ subprocess.run(
+ ['ln', '-s', f"{paths['libpy']}/run_corev32.py", f"{paths['empy']}/run_corev32.py"]
+ )
+ except:
+ logger.fatal('EMBench python module copy failed')
+
+ # ----------------------------------------------------------------------------------------------
+ # build benchmark object files (build_all.py)
+ # ----------------------------------------------------------------------------------------------
+ cmd = ['build_all.py',
+ '--arch=corev32',
+ '--board=corev32',
+ f'--cflags=-I{paths["bsp"]}',
+ f'--chip={args.type}',
+ f'--cc={args.ccomp}',
+ f'--warmup-heat=0',
+ f'--cpu-mhz={args.cpu_mhz}',
+ f'--ldflags=-T{paths["bsp"]}/link.ld',
+ '--clean']
+ logger.info(f"Calling build script: {' '.join(cmd)}")
+ try:
+ res = subprocess.run(
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd=paths['embench']
+ )
+ except:
+ logger.fatal('EMBench build failed')
+
+ log_file = get_log_file(args.core, paths, 'build')
+ fh = open(log_file, 'r')
+ for line in fh.readlines():
+ logger.info(line.rstrip())
+ fh.close()
+
+ if build_passed(res.stdout.decode('utf-8')):
+ logger.info(f"EMBench for {args.type} built successfully")
+ else:
+ logger.fatal('EMBench build failed')
+ sys.exit(1)
+
+ # build test directory, copy and rename the executable test files, and generate yaml files
+ # This is not done if the built files are for the size benchmark, as these are not able to run
+ if args.type == 'speed':
+ for folder in os.listdir(paths['emres']):
+ # create test directory
+ folder_ext = f"emb_{folder}"
+
+ logger.debug(f"Creating folder {paths['testsem']}/{folder_ext}")
+ try:
+ subprocess.run(['mkdir', f"{paths['testsem']}/{folder_ext}"])
+ except:
+ logger.fatal(f"Failed to generate folder {paths['testsem']}/{folder_ext}")
+ sys.exit(1)
+
+ # copy test files into the tests/programs/embench directories
+ for file in os.listdir(f"{paths['emres']}/{folder}"):
+ if not file.endswith('.o'):
+ logger.debug(f"Copying file {file}")
+ try:
+ subprocess.run(['cp', f"{paths['emres']}/{folder}/{file}", f"{paths['testsem']}/{folder_ext}/emb_{file}.elf"])
+ except:
+ logger.fatal(f"Copying file {file} to {paths['emres']}/{folder_ext}/ failed")
+ sys.exit(1)
+
+ break
+
+ # generate test.yaml
+ logger.debug(f"Rendering template: test.yaml.j2 for test: {folder_ext}")
+ generate_test_yaml(f"{paths['testsem']}/{folder_ext}", folder_ext)
+
+
+ if build_only:
+ logger.info("Build only selected, exiting")
+ sys.exit()
+
+ # ----------------------------------------------------------------------------------------------
+ # run benchmark script (benchmark_speed.py or benchmark_size.py)
+ # ----------------------------------------------------------------------------------------------
+ logger.info(f"Starting benchmarking of {args.type}")
+
+ if args.type == 'speed':
+ arglist = ['benchmark_speed.py', '--target-module=run_corev32',
+ f'--cpu-mhz={args.cpu_mhz}', f'--make-path={paths["make"]}',
+ f'--timeout={args.timeout}',
+ f'--simulator={args.simulator}']
+ if parallel:
+ arglist.append(f'--sim-parallel')
+ else:
+ arglist = ['benchmark_size.py']
+
+ try:
+ logger.info(f"Running: {' '.join(arglist)}")
+ res = subprocess.run(
+ arglist,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ cwd=paths['embench'],
+ )
+
+ except:
+ logger.fatal(f"EMBench script benchmark_{args.type}.py failed")
+ sys.exit(1)
+
+ logger.info('Complete with benchmark run')
+
+ # Check if benchmark run succeeded
+ if not run_passed(res.stdout.decode('utf-8'), args.type):
+ logger.fatal(f"EMBench benchmark run failed")
+ log_file = get_log_file(args.core, paths, args.type)
+ if log_file:
+ logger.info('For more debug check EMBench log: {}'.format(log_file))
+ sys.exit(1)
+
+ # Benchmark run succeeded, print logfile
+ log_file = get_log_file(args.core, paths, args.type)
+ fh = open(log_file, 'r')
+ for line in fh.readlines():
+ logger.info(line.rstrip())
+ fh.close()
+
+ # Check results if a target was applied
+ if check_result(res.stdout.decode('utf-8'), args.target, args.type) and args.target != 0:
+ logger.info(f"Benchmark run met target")
+ elif args.target != 0:
+ logger.info(f"Benchmark run failed to meet the target: {args.target}")
+
+
+###############################################################################
+# End of Main
+
+def build_parser():
+ """Build a parser for all the arguments"""
+ parser = argparse.ArgumentParser(description='Clone and run EMBench', formatter_class=argparse.RawTextHelpFormatter)
+
+ parser.add_argument(
+ '-c',
+ '--core',
+ default='notset',
+ help='Core to benchmark'
+ )
+
+ parser.add_argument(
+ '-cc',
+ '--ccomp',
+ default='notset',
+ help='C compiler for benchmark'
+ )
+
+ parser.add_argument(
+ '--parallel',
+ default='NO',
+ help=(
+ 'Set this option to "YES" to launch simulation in parallel\n'+
+ 'makefile alias: EMB_PARALLEL'
+ )
+ )
+
+ parser.add_argument(
+ '-t',
+ '--type',
+ default='speed',
+ help=(
+ 'What benchmark to run. Valid options: speed, size\n'+
+ 'Default option: speed \n'+
+ 'NOTE: type affects build configuration!\n'+
+ 'makefile alias: EMB_TYPE'
+ )
+ )
+
+ parser.add_argument(
+ '-b',
+ '--build-only',
+ default='NO',
+ help=(
+ 'Set this option to "YES" to only build the benchmarks.\n'+
+ 'Type option is still honored\n'+
+ 'makefile alias: EMB_BUILD_ONLY'
+ )
+ )
+
+ parser.add_argument(
+ '-tgt',
+ '--target',
+ type=float,
+ default=0,
+ help=(
+ 'Set a target for your EMBench score\n'+
+ 'Benchmark run will fail if target is not met\n'+
+ 'If no target is set, no checking is done\n'+
+ 'makefile alias: EMB_TARGET'
+ )
+ )
+
+ parser.add_argument(
+ '-f',
+ '--cpu-mhz',
+ default=1,
+ help=(
+ 'Set the core frequency in MHz.\n'+
+ 'Default is 1 MHz\n'+
+ 'makefile alias: EMB_CPU_MHZ'
+ )
+ )
+
+ parser.add_argument(
+ '--timeout',
+ default=3600,
+ help = (
+ 'Timeout for each simulation run in seconds\n'+
+ 'makefile alias: EMB_TIMEOUT',
+ )
+ )
+
+ parser.add_argument(
+ '-sim',
+ '--simulator',
+ default='xrun',
+ help=(
+ 'Simulator to run the benchmarks\n'+
+ 'makefile alias: SIMULATOR'
+ )
+ )
+
+ parser.add_argument(
+ '-d',
+ '--debug',
+ default='NO',
+ help=(
+ 'Set this option to "YES" to increase verbosity of the script\n'+
+ 'makefile alias: EMB_DEBUG'
+ )
+ )
+
+ return parser
+
+def build_paths(core):
+ """map out necessary paths"""
+ paths = dict()
+ paths['cver'] = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
+ paths['core'] = paths['cver'] + '/' + core
+ paths['libcfg'] = paths['core'] + '/tests/embench/config/corev32'
+ paths['libpy'] = paths['core'] + '/tests/embench/pylib'
+ paths['vlib'] = paths['core'] + '/vendor_lib'
+ paths['emb_logs'] = paths['core'] + '/vendor_lib/embench/logs'
+ paths['make'] = paths['core'] + '/sim/uvmt'
+ paths['embench'] = paths['vlib'] + '/embench'
+ paths['emcfg'] = paths['embench'] + '/config/corev32'
+ paths['empy'] = paths['embench'] + '/pylib'
+ paths['embrd'] = paths['emcfg'] + '/boards/corev32'
+ paths['emres'] = paths['embench'] + '/bd/src'
+ paths['bsp'] = paths['core'] + '/bsp'
+ paths['testsem'] = paths['core'] + '/tests/programs/embench'
+
+ return paths
+
+def generate_test_yaml(folder, test_name):
+ env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__),
+ 'templates')), trim_blocks=True)
+ template = env.get_template('embench_test.yaml.j2')
+
+ out = open(f"{folder}/test.yaml", 'w')
+ out.write(template.render(name=test_name))
+ out.close()
+
+def build_passed(stdout_str):
+ if re.search('All benchmarks built successfully', stdout_str, re.S):
+ return True
+ else:
+ return False
+
+def run_passed(stdout_str, type):
+ if type == 'speed':
+ if re.search('All benchmarks run successfully', stdout_str, re.S):
+ return True
+ else:
+ return False
+ else: #size
+ if re.search('All benchmarks sized successfully', stdout_str, re.S):
+ return True
+ else:
+ return False
+
+def check_result(stdout_str, tgt, type):
+ #find result in numeric value and compare to target
+ rcstr = re.search('Geometric mean *(\d+)[.](\d+)', stdout_str, re.S)
+ result = int(rcstr.group(1)) + (int(rcstr.group(2)) * 0.01)
+
+ if type == 'speed':
+ if (tgt == 0) or (result >= tgt):
+ return True
+ else:
+ return False
+ else:
+ if (tgt == 0) or (result <= tgt):
+ return True
+ else:
+ return False
+
+
+# Make sure we have new enough python
+def check_python_version(major, minor):
+ """Check the python version is at least {major}.{minor}."""
+ if ((sys.version_info[0] < major)
+ or ((sys.version_info[0] == major) and (sys.version_info[1] < minor))):
+ log.error('ERROR: Requires Python {mjr}.{mnr} or later'.format(mjr=major, mnr=minor))
+ sys.exit(1)
+
+def get_log_file(core, paths, log_type):
+ '''Find the log file from EMBench by looking for the latest touched file'''
+ last_mtime = 0
+ file = None
+ for f in glob.glob(os.path.join(paths['emb_logs'], '{}-*.log'.format(log_type))):
+ if last_mtime < os.stat(f).st_mtime:
+ last_mtime = os.stat(f).st_mtime
+ file = f
+
+ return file
+
+#run main
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/bin/templates/README.md b/bin/templates/README.md
new file mode 100644
index 0000000..019c93e
--- /dev/null
+++ b/bin/templates/README.md
@@ -0,0 +1,7 @@
+Core-V-Verif Templates
+==================================
+
+Templates for core-v-verif utilities are here. To render templates your Python installation should include the Jinja2 module. It can be installed via pip using:
+
+> pip install jinja2
+
diff --git a/bin/templates/embench_test.yaml.j2 b/bin/templates/embench_test.yaml.j2
new file mode 100644
index 0000000..0a6c9a5
--- /dev/null
+++ b/bin/templates/embench_test.yaml.j2
@@ -0,0 +1,33 @@
+{#
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+# test-yaml.j2: Jinja2 template for rendering test.yaml files for run_embench
+
+#}
+
+name: {{name}}
+uvm_test: uvmt_$(CV_CORE_LC)_firmware_test_c
+description: >
+ test is part of EMBench benchmarking suite
+plusargs: >
+ +rand_stall_obi_disable
+ +trn_log_disabled
+# This will inform the Common Makefile to copy out the elf there rather than build it
+fixed_elf: 1
diff --git a/bin/templates/metrics.json.j2 b/bin/templates/metrics.json.j2
new file mode 100644
index 0000000..83f9162
--- /dev/null
+++ b/bin/templates/metrics.json.j2
@@ -0,0 +1,60 @@
+{#
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+# metrics.json.j2: Jinja2 template for rendering metrics.json files for cv_regress
+
+#}
+
+{% import 'regress_macros.j2' as regress_macros %}
+
+{% set common_dsim_make_vars = "CV_CORE=" + project + " COMP=0 DSIM_WORK=/mux-flow/build/repo/dsim_work SIM_RESULTS=/mux-flow/build/results" %}
+{% set common_dsim_make_vars_waves = "CV_CORE=" + project + " COMP=0 DSIM_WORK=/mux-flow/build/repo/dsim_work SIM_RESULTS=/mux-flow/build/results WAVES=1" %}
+[
+{% for r in regressions %}
+{% for t in r.tests.values()|sort(attribute='name') %}
+{% set is_last_test = loop.last %}
+{# For Metrics, the name is description if available, otherwise use name, with index #}
+{% if t.description %}{% set test_name = t.description %}{% else %}{% set test_name = t.name %}{% endif %}
+{% for build in t.builds %}
+{% set is_last_build = loop.last %}
+{% set test_suffix = '/0' %}
+ {
+ "name": "{{test_name}}" ,
+ "build": "{{r.builds[build].name}}",
+ "cmd": "cd {{t.dir}}; {{t.cmd}} CV_CORE={{project}} CFG={{r.builds[build].cfg}} {{toolchain|upper}}=1 SIMULATOR={{t.simulator}} USE_ISS={{regress_macros.yesorno(t.iss)}} RNDSEED= {{common_dsim_make_vars}} {{makeargs}} {{t.makearg}}",
+ "wavesCmd": "cd {{t.dir}}; {{t.cmd}} CV_CORE={{project}} CFG={{r.builds[build].cfg}} {{toolchain|upper}}=1 SIMULATOR={{t.simulator}} USE_ISS={{regress_macros.yesorno(t.iss)}} RNDSEED= {{common_dsim_make_vars_waves}} {{makeargs}} {{t.makearg}}",
+{% if t.results %}
+ "metricsFile": "{{r.builds[build].cfg}}/{{t.results}}{{test_suffix}}/metrics.db",
+ "wavesFile": "{{r.builds[build].cfg}}/{{t.results}}{{test_suffix}}/dsim.vcd",
+{% else %}
+ "metricsFile": "{{r.builds[build].cfg}}/{{t.name}}{{test_suffix}}/metrics.db",
+ "wavesFile": "{{r.builds[build].cfg}}/{{t.name}}{{test_suffix}}/dsim.vcd",
+{% endif %}
+ "seed" : "random",
+ "iterations": {{t.num}},
+ "isPass": "{{t.simulation_passed}}",
+ "isFail": "{{t.simulation_failed}}"
+ }{% if not is_last_test or not is_last_build%},{% endif %}
+
+{% endfor %}
+{% endfor %}
+{% endfor %}
+]
+
diff --git a/bin/templates/regress_macros.j2 b/bin/templates/regress_macros.j2
new file mode 100644
index 0000000..dc05ab9
--- /dev/null
+++ b/bin/templates/regress_macros.j2
@@ -0,0 +1,7 @@
+{%- macro yesorno(val) -%}
+{%- if val == '0' -%}NO{%- elif val == '1' -%}YES{%- elif val == True-%}YES{%- else -%}{{val}}{%- endif -%}
+{%- endmacro -%}
+
+{%- macro cv_results(arg) -%}
+{%- if arg -%}CV_RESULTS={{arg}}{%- endif -%}
+{%- endmacro -%}
diff --git a/bin/templates/regress_sh.j2 b/bin/templates/regress_sh.j2
new file mode 100644
index 0000000..ff23cea
--- /dev/null
+++ b/bin/templates/regress_sh.j2
@@ -0,0 +1,141 @@
+{#
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+
+#}
+{% import 'regress_macros.j2' as regress_macros -%}
+
+#!/bin/bash
+
+# --------------------------------------------------------------------------------------
+# Variables
+# --------------------------------------------------------------------------------------
+pass_count=0
+fail_count=0
+failed=0
+
+# --------------------------------------------------------------------------------------
+# Functions
+# --------------------------------------------------------------------------------------
+check_log () {
+ log=$1
+ simulation_passed="$2"
+ test_name=$3
+
+ if grep -q "${simulation_passed}" ${log}; then
+ echo "{{session}}: Test PASSED: ${test_name} Log: ${log}"
+ else
+ echo "{{session}}: Test FAILED: ${test_name} Log: ${log}"
+ failed=1
+ fi
+}
+
+incr_test_counts () {
+ if [[ ${failed} == "0" ]]; then
+ ((pass_count+=1))
+ else
+ ((fail_count+=1))
+ fi
+}
+
+# --------------------------------------------------------------------------------------
+# Builds
+# --------------------------------------------------------------------------------------
+
+{% for b in unique_builds.values() %}
+# Build:{{b.name}} {{b.description}}
+{% set cmd = b.cmd + ' CV_CORE=' + project + ' CFG=' + b.cfg + ' SIMULATOR=' + b.simulator + ' COV=' + regress_macros.yesorno(b.cov) + ' ' + regress_macros.cv_results(results) + ' ' + makeargs %}
+echo "{{session}}: Running build: [cd {{b.abs_dir}} && {{cmd}}]"
+pushd {{b.abs_dir}} > /dev/null
+{{cmd}}
+popd > /dev/null
+
+{% endfor -%}
+
+# --------------------------------------------------------------------------------------
+# Tests
+# --------------------------------------------------------------------------------------
+
+{% for r in regressions %}
+{% for t in r.tests.values()|sort(attribute='name') %}
+{% for build in t.builds %}
+# --> Test: {{t.name}} : Build: {{build}} : {{t.description}}
+{% if t.precmd %}
+# Test (Precommand): {{t.name}} {{t.description}}
+{% set cmd = t.precmd + ' CV_CORE=' + project + 'CFG=' + r.builds[build].cfg + ' ' + toolchain|upper + '=1' + ' SIMULATOR=' + t.simulator + ' SEED=random GEN_NUM_TESTS=' + t.num + ' ' + regress_macros.cv_results(results) + ' ' + makeargs + ' ' + t.makearg %}
+echo "{{session}}: Running precmd: [cd {{t.abs_dir}} && {{cmd}}]
+pushd {{t.abs_dir}} > /dev/null
+{{cmd}} >& /dev/null;
+popd > /dev/null
+
+{% endif %}
+{% for run_index in range(t.num|int) %}
+{% set test_cmd = t.cmd %}
+{% set test_log = t.log %}
+# --> Test (Index: {{run_index}}): {{t.cmd}} : {{t.description}}
+{% set cmd = test_cmd + ' CV_CORE=' + project + ' CFG=' + r.builds[build].cfg + ' ' + toolchain|upper + '=1' + ' SIMULATOR=' + t.simulator + ' COMP=0 USE_ISS=' + regress_macros.yesorno(t.iss) + ' COV=' + regress_macros.yesorno(t.cov) + ' SEED=random GEN_START_INDEX=' + run_index|string + ' RUN_INDEX=' + run_index|string + ' ' + regress_macros.cv_results(results) + ' ' + makeargs %}
+echo "{{session}}: Running test [cd {{t.abs_dir}} && {{cmd}}]"
+pushd {{t.abs_dir}} > /dev/null
+{{cmd}} >& /dev/null;
+popd > /dev/null
+
+{# Determine results directory #}
+{% if results %}
+{% set results_dir = results + '/' + t.simulator + '_results' %}
+{% else %}
+{% set results_dir = t.simulator + '_results' %}
+{% endif %}
+
+{# Determine log location #}
+{% if t.results %}
+log={{t.abs_dir}}/{{results_dir}}/{{r.builds[build].cfg}}/{{t.results}}/{{run_index}}/{{t.simulator}}-{{test_log}}.log
+{% else %}
+log={{t.abs_dir}}/{{results_dir}}/{{r.builds[build].cfg}}/{{test_log}}/{{run_index}}/{{t.simulator}}-{{test_log}}.log
+{% endif %}
+
+{# Compliance signature check #}
+{% if 'compliance' in t.cmd %}
+{% if t.results %}
+compliance_diff_log={{t.abs_dir}}/{{results_dir}}/{{cfg}}/{{t.results}}/{{run_index}}/diff_signatures.log
+{% else %}
+compliance_diff_log={{t.abs_dir}}/{{results_dir}}/{{cfg}}/{{test_log}}_{{run_index}}/diff_signatures.log
+{% endif %}
+{% endif %}
+
+failed=0
+check_log ${log} "{{t.simulation_passed}}" {{test_log}}
+{% if 'compliance' in t.cmd %}
+check_log ${compliance_diff_log} "All signatures passed" {{test_log}}
+{% endif %}
+incr_test_counts
+{% endfor %}
+
+{% endfor %}
+{% endfor %}
+{% endfor %}
+
+echo "{{session}}: Passing tests: ${pass_count}"
+echo "{{session}}: Failing tests: ${fail_count}"
+
+if [ ${fail_count} -ne 0 ]; then
+ exit 1
+fi
+exit 0
diff --git a/bin/templates/regress_sve.j2 b/bin/templates/regress_sve.j2
new file mode 100644
index 0000000..266fdae
--- /dev/null
+++ b/bin/templates/regress_sve.j2
@@ -0,0 +1,30 @@
+{#
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+
+#}
+{% import 'regress_macros.j2' as regress_macros -%}
+
+#!/bin/sh -fx
+
+{% for k in env if not k=="PS1" %}
+export {{k}}="{{env[k]}}"
+{% endfor %}
diff --git a/bin/templates/regress_vsif.j2 b/bin/templates/regress_vsif.j2
new file mode 100644
index 0000000..5dce750
--- /dev/null
+++ b/bin/templates/regress_vsif.j2
@@ -0,0 +1,97 @@
+{#
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+
+#}
+{% import 'regress_macros.j2' as regress_macros -%}
+
+session {{session}} {
+ top_dir: {{results_path}}/vmgr_sessions;
+{% if lsf %}
+ drm: lsf;
+ max_runs_in_parallel: {{parallel}};
+ queuing_policy: round_robin;
+ default_dispatch_parameters: {{lsf}};
+{% endif %}
+}
+
+group {{project}} {
+{% if sve %}
+ // SVE Verification Environment definition
+ sve_name: {{sve}};
+
+{% endif %}
+
+{% for r in regressions %}
+{% for b in r.get_builds_with_no_tests() %}
+ // Build:{{b.name}} {{b.description}}
+ pre_group_script: 'cd {{b.abs_dir}} && {{b.cmd}} CV_CORE={{project}} CFG={{b.cfg}} CV_SIM_PREFIX= {{toolchain|upper}}=1 SIMULATOR={{b.simulator}} COV={{regress_macros.yesorno(b.cov)}} {{regress_macros.cv_results(results)}} {{makeargs}}';
+
+{% endfor %}
+{% for build in r.get_builds() %}
+ // --------------------------------------------------------------------------
+ // Build: {{build.name}}
+ // --------------------------------------------------------------------------
+ group {{build.name}} {
+
+ // Build:{{build.name}} {{build.description}}
+ pre_group_script: 'cd {{build.abs_dir}} && {{build.cmd}} CV_CORE={{project}} CFG={{build.cfg}} CV_SIM_PREFIX= {{toolchain|upper}}=1 SIMULATOR={{build.simulator}} COV={{regress_macros.yesorno(build.cov)}} {{regress_macros.cv_results(results)}} {{makeargs}}';
+
+{% for t in r.get_tests_of_build(build.name) %}
+{% set indent = ' '%}
+{% if t.precmd %}
+{% set indent = index + ' '%}
+ group {{t.name}}_precmd {
+ // Test (Precommand): {{t.name}} {{t.description}}
+ test precmd {
+ sv_seed: gen_random;
+ count: 1;
+ run_script: 'cd {{t.abs_dir}} && {{t.precmd}} CV_SIM_PREFIX= CV_CORE={{project}} CFG={{build.cfg}} {{toolchain|upper}}=1 SIMULATOR={{t.simulator}} RNDSEED=$RUN_ENV(BRUN_SV_SEED) NUM_TESTS={{t.num}} {{regress_macros.cv_results(results)}} {{makeargs}}';
+ };
+{% else %}
+{% endif %}
+{{indent}} // Cfg: {{cfg}} Test: {{t.name}} {{t.description}}
+{{indent}} group {{t.name}} {
+{% if t.precmd %}
+{{indent}} depends_on: ../precmd;
+{% endif %}
+{{indent}} timeout: 3600;
+{{indent}} test run {
+{{indent}} sv_seed: gen_random;
+{{indent}} count: {{t.num}};
+{{indent}} run_script: 'cd {{t.abs_dir}} && {{t.cmd}} COMP=0 CV_SIM_PREFIX= CV_CORE={{project}} {{toolchain|upper}}=1 CFG={{build.cfg}} SIMULATOR={{t.simulator}} USE_ISS={{regress_macros.yesorno(t.iss)}} COV={{regress_macros.yesorno(t.cov)}} RUN_INDEX=$RUN_ENV(BRUN_RUN_ID) GEN_START_INDEX=$RUN_ENV(BRUN_RUN_ID) RNDSEED=$RUN_ENV(BRUN_SV_SEED) {{regress_macros.cv_results(results)}} {{makeargs}} {{t.makearg}}';
+{% if simulator == 'vsim' %}
+{{indent}} scan_script: 'vm_scan.pl {{filter_dir}}/corev_uvm.flt {{filter_dir}}/vsim_run.flt';
+{% endif %}
+{% if simulator == 'xrun' %}
+{{indent}} scan_script: 'vm_scan.pl cdns_sim.flt {{filter_dir}}/corev_uvm.flt vm.flt shell.flt';
+{% endif %}
+{{indent}} };
+{{indent}} };
+{% if t.precmd %}
+ };
+{% endif %}
+{% endfor %}
+ };
+{% endfor %}
+{% endfor %}
+};
+
diff --git a/bin/vmgr/corev_uvm.flt b/bin/vmgr/corev_uvm.flt
new file mode 100644
index 0000000..df74fe7
--- /dev/null
+++ b/bin/vmgr/corev_uvm.flt
@@ -0,0 +1,107 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+###############################################################################
+#
+# Extensions and customizations to Vmanager UVM filter Perl script for Core-V
+# messages in the custom UVM report server
+#
+###############################################################################
+# -------------------------------------------------------------------------
+# File name : uvm.flt
+# Title : UVM SystemVerilog Class Library Filter for VManager
+# Project : UVM
+# Description : This file contains filters for Incisive Verification Manager,
+# to extract messages printed by the SystemVerilog UVM Class
+# Library.
+#
+# Notes : Use this filter file in environments based on the UVM
+# Class Library.
+# =============================================================================
+# Copyright (c) 2007 Cadence Design Systems, Inc. All rights reserved worldwide.
+# Please refer to the terms and conditions in $IPCM_HOME.
+# =============================================================================
+
+
+
+## Seed handling
+
+add_filter ("SV-Seed", 2,
+ '^SVSEED.*?:\s+(-?)([0-9]+)\n',
+ 'sv_seed: \"$1$2\" ; '
+ );
+
+
+## Detect signature miscompare
+add_filter ("compliance signature miscompare", 4,
+ '^\s*\.\.\. MISCOMPARE!',
+ failure (1,'compliance','signature miscompare','error', 'RISCV Compliance signature miscompare')
+ );
+
+
+## OVM and UVM Message filtering
+
+add_filter ("uvm_svcb_dut_critical", 4,
+ '\*{3} (OVM|UVM): DUT fatal at time (\d+).*?\n\S?\s*Checked at (.+?)\n(.+?)\n(.+?)\n',
+ failure (1,'$1','dut_error','critical','$5','$2','$3', '')
+ );
+
+add_filter ("uvm_svcb_dut_error", 4,
+ '\*{3} (OVM|UVM): DUT error at time (\d+).*?\n\S?\s*Checked at (.+?)\n(.+?)\n(.+?)\n',
+ failure (1,'$1','dut_error','error','$5','$2','$3', '')
+ );
+
+add_filter ("uvm_svcb_dut_warning", 2,
+ '\*{3} (OVM|UVM): DUT warning at time (\d+).*?\n\S?\s*Checked at (.+?)\n(.+?)\n(.+?)\n',
+ failure (1,'$1','dut_error','warning','$5','$2','$3', '')
+ );
+
+
+add_filter ("uvm_critical", 4,
+ '(OVM|UVM)_FATAL\s@\s(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*([^\s]*?)\s+(?:\[(.+?)\])?\s+(.+?)\n',
+ failure (1,'$1','$5','critical','$6','$2','$4','$3')
+ );
+
+
+add_filter ("uvm_error", 4,
+ '(OVM|UVM)_ERROR\s@\s(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*([^\s]*?)\s+(?:\[(.+?)\])?\s+(.+?)\n',
+ failure (1,'$1','$5','error','$6','$2','$4','$3')
+ );
+
+
+add_filter ("uvm_warning_error", 2,
+ '(OVM|UVM)_WARNING\s@\s(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*([^\s]*?)\s+(?:\[(.+?)\])?\s+(.+?)\n',
+ failure (1,'$1','$5','warning','$6','$2','$4','$3')
+ );
+
+
+add_generic_failure_filter ("uvm_critical_general",
+ '(OVM|UVM)_FATAL@\s*(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*(.+?)\n',
+ failure (1,'$1','','critical','$4','$2','','$3')
+ );
+
+
+add_generic_failure_filter ("uvm_error_general",
+ '(OVM|UVM)_ERROR@\s*(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*(.+?)\n',
+ failure (1,'$1','','error','$4','$2','','$3')
+ );
+
+
+add_generic_failure_filter ("uvm_warning_general",
+ '(OVM|UVM)_WARNING@\s*(\d+)(?:\.\d+)?(?:.*?:)?\s*([^\n]*?)\s*(.+?)\n',
+ failure (1,'$1','','warning','$4','$2','','$3')
+ );
+
diff --git a/bin/vmgr/vsim_run.flt b/bin/vmgr/vsim_run.flt
new file mode 100644
index 0000000..c2c9697
--- /dev/null
+++ b/bin/vmgr/vsim_run.flt
@@ -0,0 +1,60 @@
+### scan script filter file for Questa-specific errors and warnings
+
+### syntax
+#
+# add_filter(attr-name, priority, match-regexp, replacement, else-replacement)
+#
+# failure(ref, tool, kind, severity, description, time, module, context)
+
+## Seed handling
+
+add_filter ("questa_svseed", 2,
+ '-sv_seed\s+(-?)([0-9]+)',
+ 'sv_seed: \"$1$2\" ; '
+ );
+
+
+## Questa Errors
+# ** Error: (vlog|vopt-num) .* File(line): (descr)
+add_filter("questa_vsim_early_error", 2,
+ '\*\*\s+Error\s+(?:\(suppressible\))?\:\s+\(([\w\-]+)\)\s+(.*?)\n',
+ failure(1, # ref
+ 'questa', # tool
+ '$1', # kind
+ 'error', # severity
+ '$2', # description
+ undef, # time
+ undef, # module
+ undef, # context
+ )
+ );
+
+add_filter("questa_error", 1,
+ '\*\*\s+Error:\s+\(([\w\-]+)\)\s+([\w\/\.\(\)]+):\s+(.*?)\n',
+ failure(1, # ref
+ 'questa', # tool
+ '$1', # kind
+ 'error', # severity
+ '$3', # description
+ undef, # time
+ undef, # module
+ '$2', # context
+ )
+ );
+
+# Assertion
+# ** Error: Assertion error.
+# Time: 1817903696 ps Started: 1817803696 ps Scope: tb.dut.gen_ramif_array_0[0].u_arbiter.u_arb_core.a_grant_priority_next File: /work/strichmo/ip_mcu_32bit/mdx_sbox_mpahbram/modules/dig_mpahbram/views/rtl/dig_mpahbram_arbiter_core.sv Line: 619
+add_filter("questa_assert", 2,
+ '\*\*\s+Error:\s+Assertion error.\s*\n'.
+ '\s+Time:\s+(\d+)\s+\w+\s+\w+:\s+\d+\s+\w+\s+Scope\:\s+(\S+)\s+File:\s+(\S+)\s+Line:\s+(\d+)',
+ failure(1,
+ 'questa',
+ 'assertion',
+ 'error',
+ '$2',
+ '$1',
+ '',
+ '$3'.','.'$4')
+ );
+
diff --git a/bin/yaml2make b/bin/yaml2make
new file mode 100755
index 0000000..da3ce2d
--- /dev/null
+++ b/bin/yaml2make
@@ -0,0 +1,177 @@
+#!/usr/bin/env python3
+
+################################################################################
+#
+# Copyright 2020 OpenHW Group
+# Copyright 2020 Silicon Labs, Inc.
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier:Apache-2.0 WITH SHL-2.0
+#
+################################################################################
+#
+# test_yaml
+#
+# Author: Steve Richmond
+# email: steve.richmond@silabs.com
+#
+# Written with Python 3.5.1 on RHEL 7.7. Your python mileage may vary.
+#
+################################################################################
+
+import argparse
+import os
+import sys
+import tempfile
+import re
+import pprint
+import logging
+import yaml
+
+logging.basicConfig()
+logger = logging.getLogger(os.path.basename(__file__))
+logger.setLevel(logging.INFO)
+
+# Constants
+TOPDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
+VALID_YAMLS = ('corev-dv.yaml', 'test.yaml')
+REQUIRED_KEYS = ('name', 'uvm_test', 'description',)
+CFG_PATH = (
+# '/tests/cfg',
+ 'tests/cfg',
+ )
+TEST_PATHS = (
+# '/tests/programs/corev-dv/',
+# '/tests/programs/embench/',
+# '/tests/programs/custom',
+ 'tests/programs/corev-dv/',
+ 'tests/programs/embench/',
+ 'tests/programs/custom',
+ )
+#try:
+# DEFAULT_CORE=os.environ['CV_CORE']
+#except KeyError:
+# DEFAULT_CORE=None
+DEFAULT_CORE='cv32e20'
+
+if (sys.version_info < (3,0,0)):
+ print ('Requires python 3')
+ exit(1)
+
+def read_file(test, type, run_index):
+ '''Read a YAML test specification'''
+
+ matches = [os.path.join(TOPDIR, p, test, type) for p in TEST_PATHS
+ if os.path.exists(os.path.join(TOPDIR, p, test, type))]
+
+ # It is a fatal error to find less than 1 or more than 1 match
+ if len(matches) == 0:
+ logger.fatal('Could not find [{}] in any directories:'.format(type))
+ for p in TEST_PATHS:
+ logger.fatal(os.path.join(TOPDIR, p, test, type))
+ os.sys.exit(2)
+
+ if len(matches) >1 :
+ logger.fatal('Found multiple matches for {}:{} in directories:'.format(test, type))
+ for p in TEST_PATHS:
+ logger.fatal(os.path.join(TOPDIR, p, test, type))
+ os.sys.exit(2)
+
+ stream = open(matches[0], 'r')
+ logger.debug('Reading test specification: {}'.format(matches[0]))
+ # Newer PyYAMLs must specify explicit loader (policy) or will issue warnings
+ # Older PyYAMLs will not support the Loader argument
+ # So try the new way first, then catch to the old way
+ try:
+ test_spec = yaml.load(stream, Loader=yaml.FullLoader)
+ except AttributeError:
+ test_spec = yaml.load(stream)
+ stream.close()
+ test_spec['test_dir'] = os.path.dirname(matches[0])
+
+ # Debug the YAML parsing
+ pp = pprint.PrettyPrinter()
+ logger.debug('Read YAML:')
+ logger.debug(pp.pformat(test_spec))
+
+ # Substitute
+ for k in test_spec:
+ if k == 'disable_csr_check':
+ test_spec[k] = '+'.join(test_spec[k])
+ test_spec[k] = str(test_spec[k])
+ test_spec[k] = re.sub('', run_index, test_spec[k])
+
+ # Validation
+ for k in REQUIRED_KEYS:
+ if not k in test_spec:
+ logger.fatal('Key [{}] was not found in test specification YAML:'.format(k))
+ logger.fatal('-> : {}'.format(matches[0]))
+ os.sys.exit(2)
+
+ if not 'program' in test_spec:
+ test_spec['program'] = test_spec['name']
+
+ # Debug the YAML parsing
+ pp = pprint.PrettyPrinter()
+ logger.debug('Read YAML:')
+ logger.debug(pp.pformat(test_spec))
+
+ return test_spec
+
+def emit_make(test_spec, prefix):
+ '''Emit a hash from the YAML test specification into a makefile that can be included'''
+ fh = tempfile.NamedTemporaryFile(mode='w', delete=False)
+ for k,v in sorted(test_spec.items()):
+ fh.write('{}{}={}\n'.format('' if not prefix else prefix.upper() + '_', k.upper(), v.rstrip()))
+ fh.close()
+
+ return fh.name
+
+################################################################################
+# Command-line arguments
+
+parser = argparse.ArgumentParser()
+parser.add_argument('-t', '--test', help='Required: Test to look for')
+parser.add_argument('--yaml', choices=VALID_YAMLS, help='Required: Name of YAML test specification to find')
+parser.add_argument('--core', default=DEFAULT_CORE, help='Default core to test')
+parser.add_argument('--prefix', help='Prefix to add to make variables generated')
+parser.add_argument('--run-index', default='0', help='Add a run index to append to test specifications')
+parser.add_argument('-d', '--debug', action='store_true', help='Display debug messages')
+args = parser.parse_args()
+
+if args.debug:
+ logger.setLevel(level=logging.DEBUG)
+
+#if not args.core:
+# logger.fatal('Must specify core with CV_CORE envrionment variable or --core')
+# os.sys.exit(2)
+
+# Validate
+if not args.yaml:
+ logger.fatal('Must specify the YAML type with --yaml')
+ logger.fatal('Valid choices: {}'.format(VALID_YAMLS))
+ os.sys.exit(2)
+
+if not args.test:
+ logger.fatal('Must specify a test with -t or --test')
+ os.sys.exit(2)
+
+#CFG_PATH = [p.replace('', args.core.lower()) for p in CFG_PATH]
+#TEST_PATHS = [p.replace('', args.core.lower()) for p in TEST_PATHS]
+
+test_spec = read_file(test=args.test, type=args.yaml, run_index=args.run_index)
+temp_file = emit_make(test_spec=test_spec, prefix=args.prefix)
+
+logger.debug('File written to {}'.format(temp_file))
+print(temp_file)
diff --git a/bsp/Makefile b/bsp/Makefile
index 71028d6..08159f3 100644
--- a/bsp/Makefile
+++ b/bsp/Makefile
@@ -10,34 +10,30 @@ RISCV ?= $(CV_SW_TOOLCHAIN)
RISCV_EXE_PREFIX ?= $(RISCV)/bin/riscv32-unknown-elf-
RISCV_GCC = $(RISCV_EXE_PREFIX)gcc
RISCV_AR = $(RISCV_EXE_PREFIX)ar
-C_FILES = syscalls_kernel.c csr.c syscalls.c syscalls.h rand.c
-SRC = crt0.S handlers.S syscalls.c syscalls_kernel.c vectors.S csr.c rand.c
-OBJ = crt0.o handlers.o syscalls.o syscalls_kernel.o vectors.o csr.o rand.o
-LIBCV-VERIF = libcv-verif.a
-CFLAGS ?= -Os -g -static -mabi=ilp32 -march=$(RISCV_MARCH) -Wall -pedantic
+SRC = crt0.S handlers.S syscalls.c vectors.S
+OBJ = crt0.o handlers.o syscalls.o vectors.o
+LIBCV-VERIF = libcv-verif.a
+CFLAGS ?= -Os -g -static -mabi=ilp32 -march=$(CV_SW_MARCH) -Wall -pedantic
all: $(LIBCV-VERIF)
-$(LIBCV-VERIF): $(OBJ)
+$(LIBCV-VERIF): $(OBJ)
$(RISCV_AR) rcs $@ $(OBJ)
%.o : %.c
$(RISCV_GCC) $(CFLAGS) -c $< -o $@
-
+
%.o : %.S
$(RISCV_GCC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJ) $(LIBCV-VERIF)
-format:
- clang-format -i --style=llvm $(C_FILES)
-
vars:
@echo "make bsp variables:"
- @echo " CV_SW_TOOLCHAIN = $(RISCV)"
- @echo " CV_SW_MARCH = $(RISCV_MARCH)"
+ @echo " CV_SW_TOOLCHAIN = $(CV_SW_TOOLCHAIN)"
+ @echo " CV_SW_MARCH = $(CV_SW_MARCH)"
@echo " RISCV = $(RISCV)"
@echo " RISCV_EXE_PREFIX = $(RISCV_EXE_PREFIX)"
@echo " RISCV_GCC = $(RISCV_GCC)"
diff --git a/bsp/crt0.S b/bsp/crt0.S
index 043fd3f..3422360 100644
--- a/bsp/crt0.S
+++ b/bsp/crt0.S
@@ -20,35 +20,42 @@ _start:
/* initialize global pointer */
.option push
.option norelax
-1: auipc gp, %pcrel_hi(__global_pointer$)
- addi gp, gp, %pcrel_lo(1b)
+1: auipc gp, %pcrel_hi(__global_pointer$)
+ addi gp, gp, %pcrel_lo(1b)
.option pop
/* initialize stack pointer */
- la sp, __stack_end
+ la sp, __stack_end
/* set vector table address */
- la a0, __vector_start // TODO: why is this __vector_start and not vector_table?
- ori a0, a0, 1 // vector mode is always 'vectored' for CV32E20
- csrw mtvec, a0
+ la a0, __vector_start // TODO: why is this __vector_start and not vector_table?
+ ori a0, a0, 1 // vector mode is always 'vectored' for CV32E20
+ csrw mtvec, a0
+
+/* clear the bss segment */
+ la a0, _edata
+ la a2, _end
+ sub a2, a2, a0
+ li a1, 0
+ call memset
/* new-style constructors and destructors */
- la a0, __libc_fini_array
- call atexit
- call __libc_init_array
+ la a0, __libc_fini_array
+ call atexit
+ call __libc_init_array
/* call main */
-// lw a0, 0(sp) /* a0 = argc */
-// addi a1, sp, __SIZEOF_POINTER__ /* a1 = argv */
-// li a2, 0 /* a2 = envp = NULL */
+// lw a0, 0(sp) /* a0 = argc */
+// addi a1, sp, __SIZEOF_POINTER__ /* a1 = argv */
+// li a2, 0 /* a2 = envp = NULL */
// Initialize these variables to 0. Cannot use argc or argv
// since the stack is not initialized
- li a0, 0
- li a1, 0
- li a2, 0
+ li a0, 0
+ li a1, 0
+ li a2, 0
- call main
- tail _exit
+ call main
+ tail exit
.size _start, .-_start
@@ -60,6 +67,6 @@ _init:
_fini:
/* These don't have to do anything since we use init_array/fini_array. Prevent
missing symbol error */
- ret
+ ret
.size _init, .-_init
.size _fini, .-_fini
diff --git a/bsp/csr.c b/bsp/csr.c
deleted file mode 100644
index 38b4e09..0000000
--- a/bsp/csr.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "csr.h"
-
-void return_to_machine() {
- char *argv[] = {"return_to_machine"};
- execve("return_to_machine", argv, NULL);
-}
-
-inline void set_status_pp(priv_e new_mode) {
-
- csr_set_mask(mstatus, CSR_MSTATUS_MPP, new_mode);
- asm volatile("la t0, 1f;"
- "csrrw t0, mepc, t0;"
- "mret;"
- "1:");
-}
-
-void test_fail() { exit(1); }
-
-void test_pass() { exit(0); }
-
-void _test_pass() { _exit(0); }
-
-void _test_fail() { _exit(1); }
diff --git a/bsp/csr.h b/bsp/csr.h
deleted file mode 100644
index 3ccf978..0000000
--- a/bsp/csr.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef CSR_H
-#define CSR_H
-
-#include "csr_encoding.h"
-#include "syscalls.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#undef errno
-#ifndef __ASSEMBLER__
-
-extern int errno;
-
-typedef enum priv_enum { PRIV_M = 0x3, PRIV_S = 0x1, PRIV_U = 0x0 } priv_e;
-
-inline const char *priv_to_string(priv_e val) {
- switch (val) {
- case PRIV_M:
- return "PRIV_M";
- case PRIV_S:
- return "PRIV_S";
- case PRIV_U:
- return "PRIV_U";
- default:
- return "PRIV";
- }
-}
-
-void set_status_pp(priv_e new_mode);
-
-void return_to_machine();
-
-inline void __attribute__ ((naked)) test_fail();
-
-inline void __attribute__ ((naked)) test_pass();
-
-inline void __attribute__ ((naked)) _test_fail();
-
-inline void __attribute__ ((naked)) _test_pass();
-
-#define BITS2SHIFT(mask) (mask & -mask)
-
-#define csr_read(reg) \
- ({ \
- unsigned long __tmp; \
- asm volatile("csrr %0, " #reg : "=r"(__tmp)); \
- __tmp; \
- })
-
-#define csr_write(reg, val) ({ asm volatile("csrw " #reg ", %0" ::"rK"(val)); })
-
-#define csr_swap(reg, val) \
- ({ \
- unsigned long __tmp; \
- asm volatile("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "rK"(val)); \
- __tmp; \
- })
-
-#define csr_set(reg, bit) \
- ({ \
- unsigned long __tmp; \
- asm volatile("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
- __tmp; \
- })
-
-#define csr_clear(reg, bit) \
- { \
- unsigned long __tmp; \
- asm volatile("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
- __tmp; \
- }
-
-#define csr_clear_mask(reg, mask) csr_clear(reg, BITS2SHIFT(mask))
-
-#define csr_set_mask(reg, mask, value) \
- { \
- unsigned long __tmp = csr_read(reg); \
- __tmp = __tmp & mask; \
- __tmp |= (value << BITS2SHIFT(mask)); \
- csr_write(reg, __tmp); \
- __tmp; \
- }
-
-#define rdtime() csr_read(time)
-#define rdcycle() csr_read(cycle)
-#define rdinstret() csr_read(instret)
-
-#endif
-
-#endif
diff --git a/bsp/csr_encoding.h b/bsp/csr_encoding.h
deleted file mode 100644
index 0e5ccdd..0000000
--- a/bsp/csr_encoding.h
+++ /dev/null
@@ -1,759 +0,0 @@
-#ifndef RISCV_CSR_ENCODING_H
-#define RISCV_CSR_ENCODING_H
-
-#define CSR_FFLAGS 0x1
-#define CSR_FRM 0x2
-#define CSR_FCSR 0x3
-#define CSR_VSTART 0x8
-#define CSR_VXSAT 0x9
-#define CSR_VXRM 0xa
-#define CSR_VCSR 0xf
-#define CSR_SEED 0x15
-#define CSR_JVT 0x17
-#define CSR_CYCLE 0xc00
-#define CSR_TIME 0xc01
-#define CSR_INSTRET 0xc02
-#define CSR_HPMCOUNTER3 0xc03
-#define CSR_HPMCOUNTER4 0xc04
-#define CSR_HPMCOUNTER5 0xc05
-#define CSR_HPMCOUNTER6 0xc06
-#define CSR_HPMCOUNTER7 0xc07
-#define CSR_HPMCOUNTER8 0xc08
-#define CSR_HPMCOUNTER9 0xc09
-#define CSR_HPMCOUNTER10 0xc0a
-#define CSR_HPMCOUNTER11 0xc0b
-#define CSR_HPMCOUNTER12 0xc0c
-#define CSR_HPMCOUNTER13 0xc0d
-#define CSR_HPMCOUNTER14 0xc0e
-#define CSR_HPMCOUNTER15 0xc0f
-#define CSR_HPMCOUNTER16 0xc10
-#define CSR_HPMCOUNTER17 0xc11
-#define CSR_HPMCOUNTER18 0xc12
-#define CSR_HPMCOUNTER19 0xc13
-#define CSR_HPMCOUNTER20 0xc14
-#define CSR_HPMCOUNTER21 0xc15
-#define CSR_HPMCOUNTER22 0xc16
-#define CSR_HPMCOUNTER23 0xc17
-#define CSR_HPMCOUNTER24 0xc18
-#define CSR_HPMCOUNTER25 0xc19
-#define CSR_HPMCOUNTER26 0xc1a
-#define CSR_HPMCOUNTER27 0xc1b
-#define CSR_HPMCOUNTER28 0xc1c
-#define CSR_HPMCOUNTER29 0xc1d
-#define CSR_HPMCOUNTER30 0xc1e
-#define CSR_HPMCOUNTER31 0xc1f
-#define CSR_VL 0xc20
-#define CSR_VTYPE 0xc21
-#define CSR_VLENB 0xc22
-#define CSR_SSTATUS 0x100
-#define CSR_SEDELEG 0x102
-#define CSR_SIDELEG 0x103
-#define CSR_SIE 0x104
-#define CSR_STVEC 0x105
-#define CSR_SCOUNTEREN 0x106
-#define CSR_SENVCFG 0x10a
-#define CSR_SSTATEEN0 0x10c
-#define CSR_SSTATEEN1 0x10d
-#define CSR_SSTATEEN2 0x10e
-#define CSR_SSTATEEN3 0x10f
-#define CSR_SSCRATCH 0x140
-#define CSR_SEPC 0x141
-#define CSR_SCAUSE 0x142
-#define CSR_STVAL 0x143
-#define CSR_SIP 0x144
-#define CSR_STIMECMP 0x14d
-#define CSR_SISELECT 0x150
-#define CSR_SIREG 0x151
-#define CSR_STOPEI 0x15c
-#define CSR_SATP 0x180
-#define CSR_SCONTEXT 0x5a8
-#define CSR_VSSTATUS 0x200
-#define CSR_VSIE 0x204
-#define CSR_VSTVEC 0x205
-#define CSR_VSSCRATCH 0x240
-#define CSR_VSEPC 0x241
-#define CSR_VSCAUSE 0x242
-#define CSR_VSTVAL 0x243
-#define CSR_VSIP 0x244
-#define CSR_VSTIMECMP 0x24d
-#define CSR_VSISELECT 0x250
-#define CSR_VSIREG 0x251
-#define CSR_VSTOPEI 0x25c
-#define CSR_VSATP 0x280
-#define CSR_HSTATUS 0x600
-#define CSR_HEDELEG 0x602
-#define CSR_HIDELEG 0x603
-#define CSR_HIE 0x604
-#define CSR_HTIMEDELTA 0x605
-#define CSR_HCOUNTEREN 0x606
-#define CSR_HGEIE 0x607
-#define CSR_HVIEN 0x608
-#define CSR_HVICTL 0x609
-#define CSR_HENVCFG 0x60a
-#define CSR_HSTATEEN0 0x60c
-#define CSR_HSTATEEN1 0x60d
-#define CSR_HSTATEEN2 0x60e
-#define CSR_HSTATEEN3 0x60f
-#define CSR_HTVAL 0x643
-#define CSR_HIP 0x644
-#define CSR_HVIP 0x645
-#define CSR_HVIPRIO1 0x646
-#define CSR_HVIPRIO2 0x647
-#define CSR_HTINST 0x64a
-#define CSR_HGATP 0x680
-#define CSR_HCONTEXT 0x6a8
-#define CSR_HGEIP 0xe12
-#define CSR_VSTOPI 0xeb0
-#define CSR_SCOUNTOVF 0xda0
-#define CSR_STOPI 0xdb0
-#define CSR_UTVT 0x7
-#define CSR_UNXTI 0x45
-#define CSR_UINTSTATUS 0x46
-#define CSR_USCRATCHCSW 0x48
-#define CSR_USCRATCHCSWL 0x49
-#define CSR_STVT 0x107
-#define CSR_SNXTI 0x145
-#define CSR_SINTSTATUS 0x146
-#define CSR_SSCRATCHCSW 0x148
-#define CSR_SSCRATCHCSWL 0x149
-#define CSR_MTVT 0x307
-#define CSR_MNXTI 0x345
-#define CSR_MINTSTATUS 0x346
-#define CSR_MSCRATCHCSW 0x348
-#define CSR_MSCRATCHCSWL 0x349
-#define CSR_MSTATUS 0x300
-#define CSR_MISA 0x301
-#define CSR_MEDELEG 0x302
-#define CSR_MIDELEG 0x303
-#define CSR_MIE 0x304
-#define CSR_MTVEC 0x305
-#define CSR_MCOUNTEREN 0x306
-#define CSR_MVIEN 0x308
-#define CSR_MVIP 0x309
-#define CSR_MENVCFG 0x30a
-#define CSR_MSTATEEN0 0x30c
-#define CSR_MSTATEEN1 0x30d
-#define CSR_MSTATEEN2 0x30e
-#define CSR_MSTATEEN3 0x30f
-#define CSR_MCOUNTINHIBIT 0x320
-#define CSR_MSCRATCH 0x340
-#define CSR_MEPC 0x341
-#define CSR_MCAUSE 0x342
-#define CSR_MTVAL 0x343
-#define CSR_MIP 0x344
-#define CSR_MTINST 0x34a
-#define CSR_MTVAL2 0x34b
-#define CSR_MISELECT 0x350
-#define CSR_MIREG 0x351
-#define CSR_MTOPEI 0x35c
-#define CSR_PMPCFG0 0x3a0
-#define CSR_PMPCFG1 0x3a1
-#define CSR_PMPCFG2 0x3a2
-#define CSR_PMPCFG3 0x3a3
-#define CSR_PMPCFG4 0x3a4
-#define CSR_PMPCFG5 0x3a5
-#define CSR_PMPCFG6 0x3a6
-#define CSR_PMPCFG7 0x3a7
-#define CSR_PMPCFG8 0x3a8
-#define CSR_PMPCFG9 0x3a9
-#define CSR_PMPCFG10 0x3aa
-#define CSR_PMPCFG11 0x3ab
-#define CSR_PMPCFG12 0x3ac
-#define CSR_PMPCFG13 0x3ad
-#define CSR_PMPCFG14 0x3ae
-#define CSR_PMPCFG15 0x3af
-#define CSR_PMPADDR0 0x3b0
-#define CSR_PMPADDR1 0x3b1
-#define CSR_PMPADDR2 0x3b2
-#define CSR_PMPADDR3 0x3b3
-#define CSR_PMPADDR4 0x3b4
-#define CSR_PMPADDR5 0x3b5
-#define CSR_PMPADDR6 0x3b6
-#define CSR_PMPADDR7 0x3b7
-#define CSR_PMPADDR8 0x3b8
-#define CSR_PMPADDR9 0x3b9
-#define CSR_PMPADDR10 0x3ba
-#define CSR_PMPADDR11 0x3bb
-#define CSR_PMPADDR12 0x3bc
-#define CSR_PMPADDR13 0x3bd
-#define CSR_PMPADDR14 0x3be
-#define CSR_PMPADDR15 0x3bf
-#define CSR_PMPADDR16 0x3c0
-#define CSR_PMPADDR17 0x3c1
-#define CSR_PMPADDR18 0x3c2
-#define CSR_PMPADDR19 0x3c3
-#define CSR_PMPADDR20 0x3c4
-#define CSR_PMPADDR21 0x3c5
-#define CSR_PMPADDR22 0x3c6
-#define CSR_PMPADDR23 0x3c7
-#define CSR_PMPADDR24 0x3c8
-#define CSR_PMPADDR25 0x3c9
-#define CSR_PMPADDR26 0x3ca
-#define CSR_PMPADDR27 0x3cb
-#define CSR_PMPADDR28 0x3cc
-#define CSR_PMPADDR29 0x3cd
-#define CSR_PMPADDR30 0x3ce
-#define CSR_PMPADDR31 0x3cf
-#define CSR_PMPADDR32 0x3d0
-#define CSR_PMPADDR33 0x3d1
-#define CSR_PMPADDR34 0x3d2
-#define CSR_PMPADDR35 0x3d3
-#define CSR_PMPADDR36 0x3d4
-#define CSR_PMPADDR37 0x3d5
-#define CSR_PMPADDR38 0x3d6
-#define CSR_PMPADDR39 0x3d7
-#define CSR_PMPADDR40 0x3d8
-#define CSR_PMPADDR41 0x3d9
-#define CSR_PMPADDR42 0x3da
-#define CSR_PMPADDR43 0x3db
-#define CSR_PMPADDR44 0x3dc
-#define CSR_PMPADDR45 0x3dd
-#define CSR_PMPADDR46 0x3de
-#define CSR_PMPADDR47 0x3df
-#define CSR_PMPADDR48 0x3e0
-#define CSR_PMPADDR49 0x3e1
-#define CSR_PMPADDR50 0x3e2
-#define CSR_PMPADDR51 0x3e3
-#define CSR_PMPADDR52 0x3e4
-#define CSR_PMPADDR53 0x3e5
-#define CSR_PMPADDR54 0x3e6
-#define CSR_PMPADDR55 0x3e7
-#define CSR_PMPADDR56 0x3e8
-#define CSR_PMPADDR57 0x3e9
-#define CSR_PMPADDR58 0x3ea
-#define CSR_PMPADDR59 0x3eb
-#define CSR_PMPADDR60 0x3ec
-#define CSR_PMPADDR61 0x3ed
-#define CSR_PMPADDR62 0x3ee
-#define CSR_PMPADDR63 0x3ef
-#define CSR_MSECCFG 0x747
-#define CSR_TSELECT 0x7a0
-#define CSR_TDATA1 0x7a1
-#define CSR_TDATA2 0x7a2
-#define CSR_TDATA3 0x7a3
-#define CSR_TINFO 0x7a4
-#define CSR_TCONTROL 0x7a5
-#define CSR_MCONTEXT 0x7a8
-#define CSR_MSCONTEXT 0x7aa
-#define CSR_DCSR 0x7b0
-#define CSR_DPC 0x7b1
-#define CSR_DSCRATCH0 0x7b2
-#define CSR_DSCRATCH1 0x7b3
-#define CSR_MCYCLE 0xb00
-#define CSR_MINSTRET 0xb02
-#define CSR_MHPMCOUNTER3 0xb03
-#define CSR_MHPMCOUNTER4 0xb04
-#define CSR_MHPMCOUNTER5 0xb05
-#define CSR_MHPMCOUNTER6 0xb06
-#define CSR_MHPMCOUNTER7 0xb07
-#define CSR_MHPMCOUNTER8 0xb08
-#define CSR_MHPMCOUNTER9 0xb09
-#define CSR_MHPMCOUNTER10 0xb0a
-#define CSR_MHPMCOUNTER11 0xb0b
-#define CSR_MHPMCOUNTER12 0xb0c
-#define CSR_MHPMCOUNTER13 0xb0d
-#define CSR_MHPMCOUNTER14 0xb0e
-#define CSR_MHPMCOUNTER15 0xb0f
-#define CSR_MHPMCOUNTER16 0xb10
-#define CSR_MHPMCOUNTER17 0xb11
-#define CSR_MHPMCOUNTER18 0xb12
-#define CSR_MHPMCOUNTER19 0xb13
-#define CSR_MHPMCOUNTER20 0xb14
-#define CSR_MHPMCOUNTER21 0xb15
-#define CSR_MHPMCOUNTER22 0xb16
-#define CSR_MHPMCOUNTER23 0xb17
-#define CSR_MHPMCOUNTER24 0xb18
-#define CSR_MHPMCOUNTER25 0xb19
-#define CSR_MHPMCOUNTER26 0xb1a
-#define CSR_MHPMCOUNTER27 0xb1b
-#define CSR_MHPMCOUNTER28 0xb1c
-#define CSR_MHPMCOUNTER29 0xb1d
-#define CSR_MHPMCOUNTER30 0xb1e
-#define CSR_MHPMCOUNTER31 0xb1f
-#define CSR_MHPMEVENT3 0x323
-#define CSR_MHPMEVENT4 0x324
-#define CSR_MHPMEVENT5 0x325
-#define CSR_MHPMEVENT6 0x326
-#define CSR_MHPMEVENT7 0x327
-#define CSR_MHPMEVENT8 0x328
-#define CSR_MHPMEVENT9 0x329
-#define CSR_MHPMEVENT10 0x32a
-#define CSR_MHPMEVENT11 0x32b
-#define CSR_MHPMEVENT12 0x32c
-#define CSR_MHPMEVENT13 0x32d
-#define CSR_MHPMEVENT14 0x32e
-#define CSR_MHPMEVENT15 0x32f
-#define CSR_MHPMEVENT16 0x330
-#define CSR_MHPMEVENT17 0x331
-#define CSR_MHPMEVENT18 0x332
-#define CSR_MHPMEVENT19 0x333
-#define CSR_MHPMEVENT20 0x334
-#define CSR_MHPMEVENT21 0x335
-#define CSR_MHPMEVENT22 0x336
-#define CSR_MHPMEVENT23 0x337
-#define CSR_MHPMEVENT24 0x338
-#define CSR_MHPMEVENT25 0x339
-#define CSR_MHPMEVENT26 0x33a
-#define CSR_MHPMEVENT27 0x33b
-#define CSR_MHPMEVENT28 0x33c
-#define CSR_MHPMEVENT29 0x33d
-#define CSR_MHPMEVENT30 0x33e
-#define CSR_MHPMEVENT31 0x33f
-#define CSR_MVENDORID 0xf11
-#define CSR_MARCHID 0xf12
-#define CSR_MIMPID 0xf13
-#define CSR_MHARTID 0xf14
-#define CSR_MCONFIGPTR 0xf15
-#define CSR_MTOPI 0xfb0
-#define CSR_SIEH 0x114
-#define CSR_SIPH 0x154
-#define CSR_STIMECMPH 0x15d
-#define CSR_VSIEH 0x214
-#define CSR_VSIPH 0x254
-#define CSR_VSTIMECMPH 0x25d
-#define CSR_HTIMEDELTAH 0x615
-#define CSR_HIDELEGH 0x613
-#define CSR_HVIENH 0x618
-#define CSR_HENVCFGH 0x61a
-#define CSR_HVIPH 0x655
-#define CSR_HVIPRIO1H 0x656
-#define CSR_HVIPRIO2H 0x657
-#define CSR_HSTATEEN0H 0x61c
-#define CSR_HSTATEEN1H 0x61d
-#define CSR_HSTATEEN2H 0x61e
-#define CSR_HSTATEEN3H 0x61f
-#define CSR_CYCLEH 0xc80
-#define CSR_TIMEH 0xc81
-#define CSR_INSTRETH 0xc82
-#define CSR_HPMCOUNTER3H 0xc83
-#define CSR_HPMCOUNTER4H 0xc84
-#define CSR_HPMCOUNTER5H 0xc85
-#define CSR_HPMCOUNTER6H 0xc86
-#define CSR_HPMCOUNTER7H 0xc87
-#define CSR_HPMCOUNTER8H 0xc88
-#define CSR_HPMCOUNTER9H 0xc89
-#define CSR_HPMCOUNTER10H 0xc8a
-#define CSR_HPMCOUNTER11H 0xc8b
-#define CSR_HPMCOUNTER12H 0xc8c
-#define CSR_HPMCOUNTER13H 0xc8d
-#define CSR_HPMCOUNTER14H 0xc8e
-#define CSR_HPMCOUNTER15H 0xc8f
-#define CSR_HPMCOUNTER16H 0xc90
-#define CSR_HPMCOUNTER17H 0xc91
-#define CSR_HPMCOUNTER18H 0xc92
-#define CSR_HPMCOUNTER19H 0xc93
-#define CSR_HPMCOUNTER20H 0xc94
-#define CSR_HPMCOUNTER21H 0xc95
-#define CSR_HPMCOUNTER22H 0xc96
-#define CSR_HPMCOUNTER23H 0xc97
-#define CSR_HPMCOUNTER24H 0xc98
-#define CSR_HPMCOUNTER25H 0xc99
-#define CSR_HPMCOUNTER26H 0xc9a
-#define CSR_HPMCOUNTER27H 0xc9b
-#define CSR_HPMCOUNTER28H 0xc9c
-#define CSR_HPMCOUNTER29H 0xc9d
-#define CSR_HPMCOUNTER30H 0xc9e
-#define CSR_HPMCOUNTER31H 0xc9f
-#define CSR_MSTATUSH 0x310
-#define CSR_MIDELEGH 0x313
-#define CSR_MIEH 0x314
-#define CSR_MVIENH 0x318
-#define CSR_MVIPH 0x319
-#define CSR_MENVCFGH 0x31a
-#define CSR_MSTATEEN0H 0x31c
-#define CSR_MSTATEEN1H 0x31d
-#define CSR_MSTATEEN2H 0x31e
-#define CSR_MSTATEEN3H 0x31f
-#define CSR_MIPH 0x354
-#define CSR_MHPMEVENT3H 0x723
-#define CSR_MHPMEVENT4H 0x724
-#define CSR_MHPMEVENT5H 0x725
-#define CSR_MHPMEVENT6H 0x726
-#define CSR_MHPMEVENT7H 0x727
-#define CSR_MHPMEVENT8H 0x728
-#define CSR_MHPMEVENT9H 0x729
-#define CSR_MHPMEVENT10H 0x72a
-#define CSR_MHPMEVENT11H 0x72b
-#define CSR_MHPMEVENT12H 0x72c
-#define CSR_MHPMEVENT13H 0x72d
-#define CSR_MHPMEVENT14H 0x72e
-#define CSR_MHPMEVENT15H 0x72f
-#define CSR_MHPMEVENT16H 0x730
-#define CSR_MHPMEVENT17H 0x731
-#define CSR_MHPMEVENT18H 0x732
-#define CSR_MHPMEVENT19H 0x733
-#define CSR_MHPMEVENT20H 0x734
-#define CSR_MHPMEVENT21H 0x735
-#define CSR_MHPMEVENT22H 0x736
-#define CSR_MHPMEVENT23H 0x737
-#define CSR_MHPMEVENT24H 0x738
-#define CSR_MHPMEVENT25H 0x739
-#define CSR_MHPMEVENT26H 0x73a
-#define CSR_MHPMEVENT27H 0x73b
-#define CSR_MHPMEVENT28H 0x73c
-#define CSR_MHPMEVENT29H 0x73d
-#define CSR_MHPMEVENT30H 0x73e
-#define CSR_MHPMEVENT31H 0x73f
-#define CSR_MNSCRATCH 0x740
-#define CSR_MNEPC 0x741
-#define CSR_MNCAUSE 0x742
-#define CSR_MNSTATUS 0x744
-#define CSR_MSECCFGH 0x757
-#define CSR_MCYCLEH 0xb80
-#define CSR_MINSTRETH 0xb82
-#define CSR_MHPMCOUNTER3H 0xb83
-#define CSR_MHPMCOUNTER4H 0xb84
-#define CSR_MHPMCOUNTER5H 0xb85
-#define CSR_MHPMCOUNTER6H 0xb86
-#define CSR_MHPMCOUNTER7H 0xb87
-#define CSR_MHPMCOUNTER8H 0xb88
-#define CSR_MHPMCOUNTER9H 0xb89
-#define CSR_MHPMCOUNTER10H 0xb8a
-#define CSR_MHPMCOUNTER11H 0xb8b
-#define CSR_MHPMCOUNTER12H 0xb8c
-#define CSR_MHPMCOUNTER13H 0xb8d
-#define CSR_MHPMCOUNTER14H 0xb8e
-#define CSR_MHPMCOUNTER15H 0xb8f
-#define CSR_MHPMCOUNTER16H 0xb90
-#define CSR_MHPMCOUNTER17H 0xb91
-#define CSR_MHPMCOUNTER18H 0xb92
-#define CSR_MHPMCOUNTER19H 0xb93
-#define CSR_MHPMCOUNTER20H 0xb94
-#define CSR_MHPMCOUNTER21H 0xb95
-#define CSR_MHPMCOUNTER22H 0xb96
-#define CSR_MHPMCOUNTER23H 0xb97
-#define CSR_MHPMCOUNTER24H 0xb98
-#define CSR_MHPMCOUNTER25H 0xb99
-#define CSR_MHPMCOUNTER26H 0xb9a
-#define CSR_MHPMCOUNTER27H 0xb9b
-#define CSR_MHPMCOUNTER28H 0xb9c
-#define CSR_MHPMCOUNTER29H 0xb9d
-#define CSR_MHPMCOUNTER30H 0xb9e
-#define CSR_MHPMCOUNTER31H 0xb9f
-
-
-#define CSR_MSTATUS_UIE 0x00000001
-#define CSR_MSTATUS_SIE 0x00000002
-#define CSR_MSTATUS_HIE 0x00000004
-#define CSR_MSTATUS_MIE 0x00000008
-#define CSR_MSTATUS_UPIE 0x00000010
-#define CSR_MSTATUS_SPIE 0x00000020
-#define CSR_MSTATUS_UBE 0x00000040
-#define CSR_MSTATUS_MPIE 0x00000080
-#define CSR_MSTATUS_SPP 0x00000100
-#define CSR_MSTATUS_VS 0x00000600
-#define CSR_MSTATUS_MPP 0x00001800
-#define CSR_MSTATUS_FS 0x00006000
-#define CSR_MSTATUS_XS 0x00018000
-#define CSR_MSTATUS_MPRV 0x00020000
-#define CSR_MSTATUS_SUM 0x00040000
-#define CSR_MSTATUS_MXR 0x00080000
-#define CSR_MSTATUS_TVM 0x00100000
-#define CSR_MSTATUS_TW 0x00200000
-#define CSR_MSTATUS_TSR 0x00400000
-#define CSR_MSTATUS32_SD 0x80000000
-#define CSR_MSTATUS_UXL 0x0000000300000000
-#define CSR_MSTATUS_SXL 0x0000000C00000000
-#define CSR_MSTATUS_SBE 0x0000001000000000
-#define CSR_MSTATUS_MBE 0x0000002000000000
-#define CSR_MSTATUS_GVA 0x0000004000000000
-#define CSR_MSTATUS_MPV 0x0000008000000000
-#define CSR_MSTATUS64_SD 0x8000000000000000
-
-#define CSR_MSTATUSH_SBE 0x00000010
-#define CSR_MSTATUSH_MBE 0x00000020
-#define CSR_MSTATUSH_GVA 0x00000040
-#define CSR_MSTATUSH_MPV 0x00000080
-
-#define CSR_SSTATUS_UIE 0x00000001
-#define CSR_SSTATUS_SIE 0x00000002
-#define CSR_SSTATUS_UPIE 0x00000010
-#define CSR_SSTATUS_SPIE 0x00000020
-#define CSR_SSTATUS_UBE 0x00000040
-#define CSR_SSTATUS_SPP 0x00000100
-#define CSR_SSTATUS_VS 0x00000600
-#define CSR_SSTATUS_FS 0x00006000
-#define CSR_SSTATUS_XS 0x00018000
-#define CSR_SSTATUS_SUM 0x00040000
-#define CSR_SSTATUS_MXR 0x00080000
-#define CSR_SSTATUS32_SD 0x80000000
-#define CSR_SSTATUS_UXL 0x0000000300000000
-#define CSR_SSTATUS64_SD 0x8000000000000000
-
-#define CSR_HSTATUS_VSXL 0x300000000
-#define CSR_HSTATUS_VTSR 0x00400000
-#define CSR_HSTATUS_VTW 0x00200000
-#define CSR_HSTATUS_VTVM 0x00100000
-#define CSR_HSTATUS_VGEIN 0x0003f000
-#define CSR_HSTATUS_HU 0x00000200
-#define CSR_HSTATUS_SPVP 0x00000100
-#define CSR_HSTATUS_SPV 0x00000080
-#define CSR_HSTATUS_GVA 0x00000040
-#define CSR_HSTATUS_VSBE 0x00000020
-
-#define CSR_USTATUS_UIE 0x00000001
-#define CSR_USTATUS_UPIE 0x00000010
-
-#define CSR_MNSTATUS_NMIE 0x00000008
-#define CSR_MNSTATUS_MNPP 0x00001800
-#define CSR_MNSTATUS_MNPV 0x00000080
-
-#define CSR_DCSR_XDEBUGVER (3U<<30)
-#define CSR_DCSR_NDRESET (1<<29)
-#define CSR_DCSR_FULLRESET (1<<28)
-#define CSR_DCSR_EBREAKM (1<<15)
-#define CSR_DCSR_EBREAKH (1<<14)
-#define CSR_DCSR_EBREAKS (1<<13)
-#define CSR_DCSR_EBREAKU (1<<12)
-#define CSR_DCSR_STOPCYCLE (1<<10)
-#define CSR_DCSR_STOPTIME (1<<9)
-#define CSR_DCSR_CAUSE (7<<6)
-#define CSR_DCSR_DEBUGINT (1<<5)
-#define CSR_DCSR_HALT (1<<3)
-#define CSR_DCSR_STEP (1<<2)
-#define CSR_DCSR_PRV (3<<0)
-
-#define CSR_DCSR_CAUSE_NONE 0
-#define CSR_DCSR_CAUSE_SWBP 1
-#define CSR_DCSR_CAUSE_HWBP 2
-#define CSR_DCSR_CAUSE_DEBUGINT 3
-#define CSR_DCSR_CAUSE_STEP 4
-#define CSR_DCSR_CAUSE_HALT 5
-#define CSR_DCSR_CAUSE_GROUP 6
-
-#define CSR_MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4))
-#define CSR_MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5))
-#define CSR_MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11))
-
-#define CSR_MCONTROL_SELECT (1<<19)
-#define CSR_MCONTROL_TIMING (1<<18)
-#define CSR_MCONTROL_ACTION (0x3f<<12)
-#define CSR_MCONTROL_CHAIN (1<<11)
-#define CSR_MCONTROL_MATCH (0xf<<7)
-#define CSR_MCONTROL_M (1<<6)
-#define CSR_MCONTROL_H (1<<5)
-#define CSR_MCONTROL_S (1<<4)
-#define CSR_MCONTROL_U (1<<3)
-#define CSR_MCONTROL_EXECUTE (1<<2)
-#define CSR_MCONTROL_STORE (1<<1)
-#define CSR_MCONTROL_LOAD (1<<0)
-
-#define CSR_MCONTROL_TYPE_NONE 0
-#define CSR_MCONTROL_TYPE_MATCH 2
-
-#define CSR_MCONTROL_ACTION_DEBUG_EXCEPTION 0
-#define CSR_MCONTROL_ACTION_DEBUG_MODE 1
-#define CSR_MCONTROL_ACTION_TRACE_START 2
-#define CSR_MCONTROL_ACTION_TRACE_STOP 3
-#define CSR_MCONTROL_ACTION_TRACE_EMIT 4
-
-#define CSR_MCONTROL_MATCH_EQUAL 0
-#define CSR_MCONTROL_MATCH_NAPOT 1
-#define CSR_MCONTROL_MATCH_GE 2
-#define CSR_MCONTROL_MATCH_LT 3
-#define CSR_MCONTROL_MATCH_MASK_LOW 4
-#define CSR_MCONTROL_MATCH_MASK_HIGH 5
-
-#define CSR_MIP_USIP (1 << IRQ_U_SOFT)
-#define CSR_MIP_SSIP (1 << IRQ_S_SOFT)
-#define CSR_MIP_VSSIP (1 << IRQ_VS_SOFT)
-#define CSR_MIP_MSIP (1 << IRQ_M_SOFT)
-#define CSR_MIP_UTIP (1 << IRQ_U_TIMER)
-#define CSR_MIP_STIP (1 << IRQ_S_TIMER)
-#define CSR_MIP_VSTIP (1 << IRQ_VS_TIMER)
-#define CSR_MIP_MTIP (1 << IRQ_M_TIMER)
-#define CSR_MIP_UEIP (1 << IRQ_U_EXT)
-#define CSR_MIP_SEIP (1 << IRQ_S_EXT)
-#define CSR_MIP_VSEIP (1 << IRQ_VS_EXT)
-#define CSR_MIP_MEIP (1 << IRQ_M_EXT)
-#define CSR_MIP_SGEIP (1 << IRQ_S_GEXT)
-#define CSR_MIP_LCOFIP (1 << IRQ_LCOF)
-
-#define CSR_MIP_S_MASK (MIP_SSIP | MIP_STIP | MIP_SEIP)
-#define CSR_MIP_VS_MASK (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)
-#define CSR_MIP_HS_MASK (MIP_VS_MASK | MIP_SGEIP)
-
-#define CSR_MIDELEG_FORCED_MASK MIP_HS_MASK
-
-#define CSR_SIP_SSIP MIP_SSIP
-#define CSR_SIP_STIP MIP_STIP
-
-#define CSR_MENVCFG_FIOM 0x00000001
-#define CSR_MENVCFG_CBIE 0x00000030
-#define CSR_MENVCFG_CBCFE 0x00000040
-#define CSR_MENVCFG_CBZE 0x00000080
-#define CSR_MENVCFG_HADE 0x2000000000000000
-#define CSR_MENVCFG_PBMTE 0x4000000000000000
-#define CSR_MENVCFG_STCE 0x8000000000000000
-
-#define CSR_MENVCFGH_HADE 0x20000000
-#define CSR_MENVCFGH_PBMTE 0x40000000
-#define CSR_MENVCFGH_STCE 0x80000000
-
-#define CSR_MSTATEEN0_CS 0x00000001
-#define CSR_MSTATEEN0_FCSR 0x00000002
-#define CSR_MSTATEEN0_JVT 0x00000004
-#define CSR_MSTATEEN0_HCONTEXT 0x0200000000000000
-#define CSR_MSTATEEN0_HENVCFG 0x4000000000000000
-#define CSR_MSTATEEN_HSTATEEN 0x8000000000000000
-
-#define CSR_MSTATEEN0H_HCONTEXT 0x02000000
-#define CSR_MSTATEEN0H_HENVCFG 0x40000000
-#define CSR_MSTATEENH_HSTATEEN 0x80000000
-
-#define CSR_MHPMEVENT_VUINH 0x0400000000000000
-#define CSR_MHPMEVENT_VSINH 0x0800000000000000
-#define CSR_MHPMEVENT_UINH 0x1000000000000000
-#define CSR_MHPMEVENT_SINH 0x2000000000000000
-#define CSR_MHPMEVENT_MINH 0x4000000000000000
-#define CSR_MHPMEVENT_OF 0x8000000000000000
-
-#define CSR_MHPMEVENTH_VUINH 0x04000000
-#define CSR_MHPMEVENTH_VSINH 0x08000000
-#define CSR_MHPMEVENTH_UINH 0x10000000
-#define CSR_MHPMEVENTH_SINH 0x20000000
-#define CSR_MHPMEVENTH_MINH 0x40000000
-#define CSR_MHPMEVENTH_OF 0x80000000
-
-#define CSR_HENVCFG_FIOM 0x00000001
-#define CSR_HENVCFG_CBIE 0x00000030
-#define CSR_HENVCFG_CBCFE 0x00000040
-#define CSR_HENVCFG_CBZE 0x00000080
-#define CSR_HENVCFG_HADE 0x2000000000000000
-#define CSR_HENVCFG_PBMTE 0x4000000000000000
-#define CSR_HENVCFG_STCE 0x8000000000000000
-
-#define CSR_HENVCFGH_HADE 0x20000000
-#define CSR_HENVCFGH_PBMTE 0x40000000
-#define CSR_HENVCFGH_STCE 0x80000000
-
-#define CSR_HSTATEEN0_CS 0x00000001
-#define CSR_HSTATEEN0_FCSR 0x00000002
-#define CSR_HSTATEEN0_JVT 0x00000004
-#define CSR_HSTATEEN0_SCONTEXT 0x0200000000000000
-#define CSR_HSTATEEN0_SENVCFG 0x4000000000000000
-#define CSR_HSTATEEN_SSTATEEN 0x8000000000000000
-
-#define CSR_HSTATEEN0H_SCONTEXT 0x02000000
-#define CSR_HSTATEEN0H_SENVCFG 0x40000000
-#define CSR_HSTATEENH_SSTATEEN 0x80000000
-
-#define CSR_SENVCFG_FIOM 0x00000001
-#define CSR_SENVCFG_CBIE 0x00000030
-#define CSR_SENVCFG_CBCFE 0x00000040
-#define CSR_SENVCFG_CBZE 0x00000080
-
-#define CSR_SSTATEEN0_CS 0x00000001
-#define CSR_SSTATEEN0_FCSR 0x00000002
-#define CSR_SSTATEEN0_JVT 0x00000004
-
-#define CSR_MSECCFG_MML 0x00000001
-#define CSR_MSECCFG_MMWP 0x00000002
-#define CSR_MSECCFG_RLB 0x00000004
-#define CSR_MSECCFG_USEED 0x00000100
-#define CSR_MSECCFG_SSEED 0x00000200
-
-/* jvt fields */
-#define CSR_JVT_MODE 0x3F
-#define CSR_JVT_BASE (~0x3F)
-
-#define CSR_PRV_U 0
-#define CSR_PRV_S 1
-#define CSR_PRV_M 3
-
-#define CSR_PRV_HS (PRV_S + 1)
-
-#define CSR_SATP32_MODE 0x80000000
-#define CSR_SATP32_ASID 0x7FC00000
-#define CSR_SATP32_PPN 0x003FFFFF
-#define CSR_SATP64_MODE 0xF000000000000000
-#define CSR_SATP64_ASID 0x0FFFF00000000000
-#define CSR_SATP64_PPN 0x00000FFFFFFFFFFF
-
-#define CSR_SATP_MODE_OFF 0
-#define CSR_SATP_MODE_SV32 1
-#define CSR_SATP_MODE_SV39 8
-#define CSR_SATP_MODE_SV48 9
-#define CSR_SATP_MODE_SV57 10
-#define CSR_SATP_MODE_SV64 11
-
-#define CSR_HGATP32_MODE 0x80000000
-#define CSR_HGATP32_VMID 0x1FC00000
-#define CSR_HGATP32_PPN 0x003FFFFF
-
-#define CSR_HGATP64_MODE 0xF000000000000000
-#define CSR_HGATP64_VMID 0x03FFF00000000000
-#define CSR_HGATP64_PPN 0x00000FFFFFFFFFFF
-
-#define CSR_HGATP_MODE_OFF 0
-#define CSR_HGATP_MODE_SV32X4 1
-#define CSR_HGATP_MODE_SV39X4 8
-#define CSR_HGATP_MODE_SV48X4 9
-#define CSR_HGATP_MODE_SV57X4 10
-
-#define CSR_PMP_R 0x01
-#define CSR_PMP_W 0x02
-#define CSR_PMP_X 0x04
-#define CSR_PMP_A 0x18
-#define CSR_PMP_L 0x80
-#define CSR_PMP_SHIFT 2
-
-#define CSR_PMP_TOR 0x08
-#define CSR_PMP_NA4 0x10
-#define CSR_PMP_NAPOT 0x18
-
-#define CSR_IRQ_U_SOFT 0
-#define CSR_IRQ_S_SOFT 1
-#define CSR_IRQ_VS_SOFT 2
-#define CSR_IRQ_M_SOFT 3
-#define CSR_IRQ_U_TIMER 4
-#define CSR_IRQ_S_TIMER 5
-#define CSR_IRQ_VS_TIMER 6
-#define CSR_IRQ_M_TIMER 7
-#define CSR_IRQ_U_EXT 8
-#define CSR_IRQ_S_EXT 9
-#define CSR_IRQ_VS_EXT 10
-#define CSR_IRQ_M_EXT 11
-#define CSR_IRQ_S_GEXT 12
-#define CSR_IRQ_COP 12
-#define CSR_IRQ_LCOF 13
-
-/* page table entry (PTE) fields */
-#define CSR_PTE_V 0x001 /* Valid */
-#define CSR_PTE_R 0x002 /* Read */
-#define CSR_PTE_W 0x004 /* Write */
-#define CSR_PTE_X 0x008 /* Execute */
-#define CSR_PTE_U 0x010 /* User */
-#define CSR_PTE_G 0x020 /* Global */
-#define CSR_PTE_A 0x040 /* Accessed */
-#define CSR_PTE_D 0x080 /* Dirty */
-#define CSR_PTE_SOFT 0x300 /* Reserved for Software */
-#define CSR_PTE_RSVD 0x1FC0000000000000 /* Reserved for future standard use */
-#define CSR_PTE_PBMT 0x6000000000000000 /* Svpbmt: Page-based memory types */
-#define CSR_PTE_N 0x8000000000000000 /* Svnapot: NAPOT translation contiguity */
-#define CSR_PTE_ATTR 0xFFC0000000000000 /* All attributes and reserved bits */
-
-#define CSR_PTE_PPN_SHIFT 10
-
-#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
-
-#ifdef __riscv
-
-#if __riscv_xlen == 64
-# define MSTATUS_SD MSTATUS64_SD
-# define SSTATUS_SD SSTATUS64_SD
-# define RISCV_PGLEVEL_BITS 9
-# define SATP_MODE SATP64_MODE
-#else
-# define MSTATUS_SD MSTATUS32_SD
-# define SSTATUS_SD SSTATUS32_SD
-# define RISCV_PGLEVEL_BITS 10
-# define SATP_MODE SATP32_MODE
-#endif
-#define RISCV_PGSHIFT 12
-#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
-
-
-#endif
-
-#endif
diff --git a/bsp/link.ld b/bsp/link.ld
index df72b02..bac16cd 100644
--- a/bsp/link.ld
+++ b/bsp/link.ld
@@ -1,26 +1,35 @@
-ENTRY(_start)
+/* Script for -z combreloc */
+/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
+ Copyright (C) 2019 ETH Zürich and University of Bologna
+ Copyright (C) 2020 OpenHW Group
+ SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+
+/* This linker script is adapted from the default linker script for upstream
+ RISC-V GCC. It has been modified for use in verification of CORE-V cores.
+*/
-/*----------------------------------------------------------------------*/
-/* Sections */
-/*----------------------------------------------------------------------*/
+OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
+ "elf32-littleriscv")
+OUTPUT_ARCH(riscv)
+ENTRY(_start)
/* CORE-V */
MEMORY
{
- ram (rwxai) : ORIGIN = 0x80000000, LENGTH = 0x400000 /* 4 MB RAM */
- dbg (rwxai) : ORIGIN = 0x1A110800, LENGTH = 0x50000
-}
-
-ENTRY(_start)
+ /* Our testbench is a bit weird in that we initialize the RAM (thus
+ allowing initialized sections to be placed there). Infact we dump all
+ sections to ram. */
-/* Configurable sizes for the heap, stack, and debugger stack */
-_heap_size = DEFINED(_heap_size) ? _heap_size : 0x100000; /* Default heap size 1MB */
-_stack_size = DEFINED(_stack_size) ? _stack_size : 0x40000; /* Default stack size 256KB */
-_debugger_stack_size = DEFINED(_debugger_stack_size) ? _debugger_stack_size : 0x10000; /* Default debugger stack size 64KB */
+ ram (rwxai) : ORIGIN = 0x00000000, LENGTH = 0x400000
+ dbg (rwxai) : ORIGIN = 0x1A110800, LENGTH = 0x50000
+}
SECTIONS
{
-/* CORE-V Debugger Code: This section address must be the same as the
+ /* CORE-V Debugger Code: This section address must be the same as the
DM_HaltAddress parameter in the RTL */
.debugger (ORIGIN(dbg)):
{
@@ -31,75 +40,275 @@ SECTIONS
KEEP(*(.debugger_exception));
} >dbg
/* Debugger Stack*/
- .debugger_stack ORIGIN(dbg) + LENGTH(dbg) - _debugger_stack_size : ALIGN(16)
+ .debugger_stack : ALIGN(16)
{
PROVIDE(__debugger_stack_start = .);
- . += _debugger_stack_size;
- PROVIDE(__debugger_stack_end = .);
+ . = 0x80;
} >dbg
+ /* CORE-V: we want a fixed entry point */
+ PROVIDE(__boot_address = 0x000);
+ PROVIDE(_debugger_exception_start = 0x1A140000);
- /* text: test code section */
- . = 0x80000000;
- .text.start : { *(.text.start) }
- . = ALIGN(0x1000);
- .tohost : { *(.tohost) }
+ /* CORE-V: crt0 init code */
+ .init (ORIGIN(ram)):
+ {
+ KEEP (*(SORT_NONE(.init)))
+ KEEP (*(.text.start))
+ } >ram
- /* CORE-V: interrupt vectors */
+/* CORE-V: interrupt vectors */
.vectors : ALIGN(256)
{
PROVIDE(__vector_start = .);
KEEP(*(.vectors));
- }
-
- . = ALIGN(0x1000);
- .text : { *(.text) }
+ } >ram
- /* data segment */
- .data : { *(.data) }
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
+ .interp : { *(.interp) } >ram
+ .note.gnu.build-id : { *(.note.gnu.build-id) } >ram
+ .hash : { *(.hash) } >ram
+ .gnu.hash : { *(.gnu.hash) } >ram
+ .dynsym : { *(.dynsym) } >ram
+ .dynstr : { *(.dynstr) } >ram
+ .gnu.version : { *(.gnu.version) } >ram
+ .gnu.version_d : { *(.gnu.version_d) } >ram
+ .gnu.version_r : { *(.gnu.version_r) } >ram
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+ *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+ *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+ *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
+ } >ram
+ .rela.plt :
+ {
+ *(.rela.plt)
+ } >ram
- .sdata : {
- __global_pointer$ = . + 0x800;
- *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata*)
+ .plt : { *(.plt) }
+ .iplt : { *(.iplt) }
+ .text :
+ {
+ *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+ *(.text.exit .text.exit.*)
+ *(.text.startup .text.startup.*)
+ *(.text.hot .text.hot.*)
+ *(SORT(.text.sorted.*))
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf.em. */
+ *(.gnu.warning)
+ } >ram
+ .fini :
+ {
+ KEEP (*(SORT_NONE(.fini)))
+ } >ram
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } >ram
+ .rodata1 : { *(.rodata1) } >ram
+ .sdata2 :
+ {
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ } >ram
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } >ram
+ .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } >ram
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >ram
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >ram
+ .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >ram
+ /* These sections are generated by the Sun/Oracle C++ compiler. */
+ .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >ram
+ .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } >ram
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >ram
+ .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) } >ram
+ /* Thread Local Storage sections */
+ .tdata :
+ {
+ PROVIDE_HIDDEN (__tdata_start = .);
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ } >ram
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } >ram
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ } >ram
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ } >ram
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ } >ram
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ } >ram
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ } >ram
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ . = DATA_SEGMENT_RELRO_END (0, .);
+ .data :
+ {
+ __DATA_BEGIN__ = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ } >ram
+ .data1 : { *(.data1) } >ram
+ .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ __SDATA_BEGIN__ = .;
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
- }
- . = ALIGN(0x1000);
-
- /* bss segment */
- .sbss : {
+ } >ram
+ _edata = .; PROVIDE (edata = .);
+ . = .;
+ __bss_start = .;
+ .sbss :
+ {
+ *(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
- }
- .bss : { *(.bss) }
-
- .tdata :
- {
- _tdata_begin = .;
- *(.tdata)
- _tdata_end = .;
- }
- .tbss :
+ } >ram
+ .bss :
{
- *(.tbss)
- _tbss_end = .;
- }
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we do not
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ } >ram
+ . = ALIGN(32 / 8);
+ . = SEGMENT_START("ldata-segment", .);
+ . = ALIGN(32 / 8);
+ __bss_end = .;
+ __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
+ MAX(__DATA_BEGIN__ + 0x800, __bss_end - 0x800));
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
- .heap : ALIGN(16)
+ /* Heap grows upward towards end of ram */
+ .heap : ALIGN(16)
{
- PROVIDE(__heap_start = ORIGIN(ram) + LENGTH(ram) - _stack_size - _debugger_stack_size - _heap_size);
- . += _heap_size;
- PROVIDE(__heap_end = .);
- }
+ PROVIDE(__heap_start = .);
+ /* If end of ram is not 16-byte aligned, align to previous 16-byte
+ boundary */
+ PROVIDE(__heap_end = ALIGN(ORIGIN(ram) + LENGTH(ram) - __heap_start - 15, 16));
+ . = __heap_end;
+ } >ram
- .stack (__stack_start) : ALIGN(16)
+ /* Stack grows downward from end of ram */
+ .stack (__heap_start) : ALIGN(16) /* this is a requirement of the ABI(?) */
{
- PROVIDE(__stack_start = ORIGIN(ram) + LENGTH(ram) - _stack_size);
- . += _stack_size;
+ PROVIDE(__stack_start = __heap_start);
+ . = __heap_end;
PROVIDE(__stack_end = .);
- }
+ } >ram
- /* End of uninitialized data segment */
- _end = .;
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF Extension. */
+ .debug_macro 0 : { *(.debug_macro) }
+ .debug_addr 0 : { *(.debug_addr) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
diff --git a/bsp/rand.c b/bsp/rand.c
deleted file mode 100644
index 7894a9a..0000000
--- a/bsp/rand.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "rand.h"
-
-// Function to generate a pseudo-random number
-uint32_t custom_rand() {
- static unsigned int seed = 0; // Initialize the seed with a default value
- seed = (RAND_A * seed + RAND_C) % RAND_M;
- return seed;
-}
-
-uint32_t random_num(uint32_t upper_bound, uint32_t lower_bound) {
- uint32_t random_num = random_num32();
- uint32_t num = (random_num % (upper_bound - lower_bound + 1)) + lower_bound;
- return num;
-}
-
-uint32_t random_num32() {
- return (uint32_t) custom_rand() ;
-}
diff --git a/bsp/rand.h b/bsp/rand.h
deleted file mode 100644
index f9a24e2..0000000
--- a/bsp/rand.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include
-
-// Define constants for the LCG algorithm
-#define RAND_A 1103515245
-#define RAND_C 12345
-#define RAND_M 2147483648 // 2^31
-
-// Function to generate a pseudo-random number
-uint32_t custom_rand();
-
-uint32_t random_num(uint32_t upper_bound, uint32_t lower_bound);
-
-uint32_t random_num32();
diff --git a/bsp/syscalls.c b/bsp/syscalls.c
index df4824c..23e7ad5 100644
--- a/bsp/syscalls.c
+++ b/bsp/syscalls.c
@@ -19,26 +19,361 @@
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include "syscalls.h"
-
-void exit(int value) {
- asm inline(" \
- mv a7, %0; \
- mv t0, %0; \
- mv a0, %1; \
- ecall;"
- :
- : "r"(SYS_exit), "r"(value));
-}
-
-int execve(const char *name, char *const argv[], char *const env[]) {
- asm inline(" \
- mv a7, %0; \
- mv t0, %0; \
- mv a0, %1; \
- mv a1, %2; \
- mv a2, %3; \
- ecall;"
- :
- : "r"(SYS_execve), "r"(name), "r"(argv), "r"(env));
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#undef errno
+extern int errno;
+
+/* write to this reg for outputting strings */
+#define STDOUT_REG 0x10000000
+/* write test result of program to this reg */
+#define RESULT_REG 0x20000000
+/* write exit value of program to this reg */
+#define EXIT_REG 0x20000000
+
+#define STDOUT_FILENO 1
+
+/* It turns out that older newlib versions use different symbol names which goes
+ * against newlib recommendations. Anyway this is fixed in later version.
+ */
+#if __NEWLIB__ <= 2 && __NEWLIB_MINOR__ <= 5
+#define _sbrk sbrk
+#define _write write
+#define _close close
+#define _lseek lseek
+#define _read read
+#define _fstat fstat
+#define _isatty isatty
+#endif
+/* Upstream newlib now defines this in libgloss/riscv/internal_syscall.h. */
+long
+__syscall_error(long a0)
+{
+ errno = -a0;
+ return -1;
+}
+
+void unimplemented_syscall()
+{
+ const char *p = "BSP: Unimplemented system call called!\n";
+ while (*p)
+ *(volatile int *)STDOUT_REG = *(p++);
+}
+
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _access(const char *file, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _chdir(const char *path)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _chmod(const char *path, mode_t mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _chown(const char *path, uid_t owner, gid_t group)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _close(int file)
+{
+ return -1;
+}
+
+int _execve(const char *name, char *const argv[], char *const env[])
+{
+ errno = ENOMEM;
+ return -1;
+}
+
+void _exit(int exit_status)
+{
+ *(volatile int *)EXIT_REG = exit_status;
+ asm volatile("wfi");
+ /* _exit should not return */
+ while (1) {};
+}
+
+int _faccessat(int dirfd, const char *file, int mode, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _fork(void)
+{
+ errno = EAGAIN;
+ return -1;
+}
+
+int _fstat(int file, struct stat *st)
+{
+ st->st_mode = S_IFCHR;
+ return 0;
+ // errno = -ENOSYS;
+ // return -1;
+}
+
+int _fstatat(int dirfd, const char *file, struct stat *st, int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _ftime(struct timeb *tp)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+char *_getcwd(char *buf, size_t size)
+{
+ errno = -ENOSYS;
+ return NULL;
+}
+
+int _getpid()
+{
+ return 1;
+}
+
+int _gettimeofday(struct timeval *tp, void *tzp)
+{
+ errno = -ENOSYS;
+ return -1;
+}
+
+int _isatty(int file)
+{
+ return (file == STDOUT_FILENO);
+}
+
+int _kill(int pid, int sig)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+int _link(const char *old_name, const char *new_name)
+{
+ errno = EMLINK;
+ return -1;
+}
+
+off_t _lseek(int file, off_t ptr, int dir)
+{
+ return 0;
+}
+
+int _lstat(const char *file, struct stat *st)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _open(const char *name, int flags, int mode)
+{
+ return -1;
+}
+
+int _openat(int dirfd, const char *name, int flags, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+ssize_t _read(int file, void *ptr, size_t len)
+{
+ return 0;
+}
+
+int _stat(const char *file, struct stat *st)
+{
+ st->st_mode = S_IFCHR;
+ return 0;
+ // errno = ENOSYS;
+ // return -1;
+}
+
+long _sysconf(int name)
+{
+
+ return -1;
+}
+
+clock_t _times(struct tms *buf)
+{
+ return -1;
+}
+
+int _unlink(const char *name)
+{
+ errno = ENOENT;
+ return -1;
+}
+
+int _utime(const char *path, const struct utimbuf *times)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int _wait(int *status)
+{
+ errno = ECHILD;
+ return -1;
+}
+
+ssize_t _write(int file, const void *ptr, size_t len)
+{
+ const char *cptr = (char *)ptr;
+ if (file != STDOUT_FILENO)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ const void *eptr = cptr + len;
+ while (cptr != eptr)
+ *(volatile int *)STDOUT_REG = *cptr++;
+ return len;
+}
+
+extern char __heap_start[];
+extern char __heap_end[];
+static char *brk = __heap_start;
+
+int _brk(void *addr)
+{
+ brk = addr;
+ return 0;
+}
+
+void *_sbrk(ptrdiff_t incr)
+{
+ char *old_brk = brk;
+ register long sp asm("sp");
+
+ char *new_brk = brk += incr;
+ if (new_brk < (char *) sp && new_brk < __heap_end)
+ {
+ brk = new_brk;
+
+ return old_brk;
+ }
+ else
+ {
+ errno = ENOMEM;
+ return (void *) -1;
+ }
+}
+
+void handle_syscall (long a0,
+ long a1,
+ long a2,
+ long a3,
+ __attribute__((unused)) long a4,
+ __attribute__((unused)) long a5,
+ __attribute__((unused)) long a6,
+ long a7) {
+ #ifdef __riscv_32e
+ register long syscall_id asm("t0");
+ #else
+ long syscall_id = a7;
+ #endif
+
+ switch (syscall_id) {
+ case SYS_exit:
+ _exit (a0);
+ break;
+ case SYS_read:
+ _read (a0, (void *) a1, a2);
+ break;
+ case SYS_write:
+ _write (a0, (const void *) a1, a2);
+ break;
+ case SYS_getpid:
+ _getpid ();
+ break;
+ case SYS_kill:
+ _kill (a0, a1);
+ break;
+ case SYS_open:
+ _open ((const char *) a0, a1, a2);
+ break;
+ case SYS_openat:
+ _openat (a0, (const char *) a1, a2, a3);
+ break;
+ case SYS_close:
+ _close (a0);
+ break;
+ case SYS_lseek:
+ _lseek (a0, a1, a2);
+ break;
+ case SYS_brk:
+ _brk ((void *) a0);
+ break;
+ case SYS_link:
+ _link ((const char *) a0, (const char *) a1);
+ break;
+ case SYS_unlink:
+ _unlink ((const char *) a0);
+ break;
+ case SYS_chdir:
+ _chdir ((const char *) a0);
+ break;
+ case SYS_getcwd:
+ _getcwd ((char *) a0, a1);
+ break;
+ case SYS_stat:
+ _stat ((const char *) a0, (struct stat *) a1);
+ break;
+ case SYS_fstat:
+ _fstat (a0, (struct stat *) a1);
+ break;
+ case SYS_lstat:
+ _lstat ((const char *) a0, (struct stat *) a1);
+ break;
+ case SYS_fstatat:
+ _fstatat (a0, (const char *) a1, (struct stat *) a2, a3);
+ break;
+ case SYS_access:
+ _access ((const char *) a0, a1);
+ break;
+ case SYS_faccessat:
+ _faccessat (a0, (const char *) a1, a2, a3);
+ break;
+ case SYS_gettimeofday:
+ _gettimeofday ((struct timeval *) a0, (void *) a1);
+ break;
+ case SYS_times:
+ _times ((struct tms *) a0);
+ break;
+ default:
+ unimplemented_syscall ();
+ break;
+ }
}
diff --git a/bsp/syscalls.h b/bsp/syscalls.h
deleted file mode 100644
index 82157bc..0000000
--- a/bsp/syscalls.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef SYSCALLS_H
-#define SYSCALLS_H
-#include "csr.h"
-#include "csr_encoding.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#undef errno
-
-extern int errno;
-extern volatile uint64_t tohost;
-extern volatile uint64_t fromhost;
-
-extern volatile uint64_t stdout_reg;
-
-#define STDOUT_FILENO 1
-
-/* It turns out that older newlib versions use different symbol names which goes
- * against newlib recommendations. Anyway this is fixed in later version.
- */
-#if __NEWLIB__ <= 2 && __NEWLIB_MINOR__ <= 5
-#define _sbrk sbrk
-#define _write write
-#define _close close
-#define _lseek lseek
-#define _read read
-#define _fstat fstat
-#define _isatty isatty
-#endif
-
-#ifndef SYS_execve
-#define SYS_execve 59
-#endif
-
-void exit(int value);
-
-#endif
diff --git a/bsp/syscalls_kernel.c b/bsp/syscalls_kernel.c
deleted file mode 100644
index 5aa7a58..0000000
--- a/bsp/syscalls_kernel.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2021 OpenHW Group
-// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
-
-/* An extremely minimalist syscalls.c for newlib
- * Based on riscv newlib libgloss/riscv/sys_*.c
- *
- * Copyright 2019 Claire Wolf
- * Copyright 2019 ETH Zürich and University of Bologna
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-#include "syscalls.h"
-
-volatile uint64_t tohost __attribute__((section(".tohost"))) = 0;
-volatile uint64_t fromhost __attribute__((section(".tohost"))) = 0;
-volatile uint64_t stdout_reg __attribute__((section(".stdout_reg"))) = 0;
-
-/* Upstream newlib now defines this in libgloss/riscv/internal_syscall.h. */
-long __syscall_error(long a0) {
- errno = -a0;
- return -1;
-}
-
-void unimplemented_syscall() {
- const char *p = "BSP: Unimplemented system call called!\n";
- while (*p)
- stdout_reg = *(p++);
-}
-
-int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) {
- errno = ENOSYS;
- return -1;
-}
-
-int _access(const char *file, int mode) {
- errno = ENOSYS;
- return -1;
-}
-
-int _chdir(const char *path) {
- errno = ENOSYS;
- return -1;
-}
-
-int _chmod(const char *path, mode_t mode) {
- errno = ENOSYS;
- return -1;
-}
-
-int _chown(const char *path, uid_t owner, gid_t group) {
- errno = ENOSYS;
- return -1;
-}
-
-int _close(int file) { return -1; }
-
-int _execve(const char *name, char *const argv[], char *const env[]) {
- if (name == "return_to_machine") {
- {
- printf("Returning to Machine");
- csr_set_mask(mstatus, CSR_MSTATUS_MPP, PRIV_M);
- }
- }
- return 0;
-}
-
-void __attribute__ ((naked)) _exit(int exit_status) {
- tohost = (exit_status << 1) | 1;
-
- asm volatile("wfi");
- /* _exit should not return */
- while (1) {
- };
-}
-
-int _faccessat(int dirfd, const char *file, int mode, int flags) {
- errno = ENOSYS;
- return -1;
-}
-
-int _fork(void) {
- errno = EAGAIN;
- return -1;
-}
-
-int _fstat(int file, struct stat *st) {
- st->st_mode = S_IFCHR;
- return 0;
- // errno = -ENOSYS;
- // return -1;
-}
-
-int _fstatat(int dirfd, const char *file, struct stat *st, int flags) {
- errno = ENOSYS;
- return -1;
-}
-
-int _ftime(struct timeb *tp) {
- errno = ENOSYS;
- return -1;
-}
-
-char *_getcwd(char *buf, size_t size) {
- errno = -ENOSYS;
- return NULL;
-}
-
-int _getpid() { return 1; }
-
-int _gettimeofday(struct timeval *tp, void *tzp) {
- errno = -ENOSYS;
- return -1;
-}
-
-int _isatty(int file) { return (file == STDOUT_FILENO); }
-
-int _kill(int pid, int sig) {
- errno = EINVAL;
- return -1;
-}
-
-int _link(const char *old_name, const char *new_name) {
- errno = EMLINK;
- return -1;
-}
-
-off_t _lseek(int file, off_t ptr, int dir) { return 0; }
-
-int _lstat(const char *file, struct stat *st) {
- errno = ENOSYS;
- return -1;
-}
-
-int _open(const char *name, int flags, int mode) { return -1; }
-
-int _openat(int dirfd, const char *name, int flags, int mode) {
- errno = ENOSYS;
- return -1;
-}
-
-ssize_t _read(int file, void *ptr, size_t len) { return 0; }
-
-int _stat(const char *file, struct stat *st) {
- st->st_mode = S_IFCHR;
- return 0;
- // errno = ENOSYS;
- // return -1;
-}
-
-long _sysconf(int name) { return -1; }
-
-clock_t _times(struct tms *buf) { return -1; }
-
-int _unlink(const char *name) {
- errno = ENOENT;
- return -1;
-}
-
-int _utime(const char *path, const struct utimbuf *times) {
- errno = ENOSYS;
- return -1;
-}
-
-int _wait(int *status) {
- errno = ECHILD;
- return -1;
-}
-
-ssize_t _write(int file, const void *ptr, size_t len) {
- const char *cptr = (char *)ptr;
- if (file != STDOUT_FILENO) {
- errno = ENOSYS;
- return -1;
- }
-
- const void *eptr = cptr + len;
- while (cptr != eptr)
- stdout_reg = *cptr++;
- return len;
-}
-
-extern char __heap_start[];
-extern char __heap_end[];
-static char *brk = __heap_start;
-
-int _brk(void *addr) {
- brk = addr;
- return 0;
-}
-
-void *_sbrk(ptrdiff_t incr) {
- char *old_brk = brk;
- register long sp asm("sp");
-
- char *new_brk = brk += incr;
- if (new_brk < (char *)sp && new_brk < __heap_end) {
- brk = new_brk;
-
- return old_brk;
- } else {
- errno = ENOMEM;
- return (void *)-1;
- }
-}
-
-void handle_syscall(long a0, long a1, long a2, long a3,
- __attribute__((unused)) long a4,
- __attribute__((unused)) long a5,
- __attribute__((unused)) long a6, long a7) {
-#ifdef __riscv_32e
- register long syscall_id asm("t0");
-#else
- long syscall_id = a7;
-#endif
-
- switch (syscall_id) {
- case SYS_exit:
- _exit(a0);
- break;
- case SYS_read:
- _read(a0, (void *)a1, a2);
- break;
- case SYS_write:
- _write(a0, (const void *)a1, a2);
- break;
- case SYS_getpid:
- _getpid();
- break;
- case SYS_kill:
- _kill(a0, a1);
- break;
- case SYS_open:
- _open((const char *)a0, a1, a2);
- break;
- case SYS_openat:
- _openat(a0, (const char *)a1, a2, a3);
- break;
- case SYS_close:
- _close(a0);
- break;
- case SYS_lseek:
- _lseek(a0, a1, a2);
- break;
- case SYS_brk:
- _brk((void *)a0);
- break;
- case SYS_link:
- _link((const char *)a0, (const char *)a1);
- break;
- case SYS_unlink:
- _unlink((const char *)a0);
- break;
- case SYS_chdir:
- _chdir((const char *)a0);
- break;
- case SYS_getcwd:
- _getcwd((char *)a0, a1);
- break;
- case SYS_stat:
- _stat((const char *)a0, (struct stat *)a1);
- break;
- case SYS_fstat:
- _fstat(a0, (struct stat *)a1);
- break;
- case SYS_lstat:
- _lstat((const char *)a0, (struct stat *)a1);
- break;
- case SYS_fstatat:
- _fstatat(a0, (const char *)a1, (struct stat *)a2, a3);
- break;
- case SYS_access:
- _access((const char *)a0, a1);
- break;
- case SYS_faccessat:
- _faccessat(a0, (const char *)a1, a2, a3);
- break;
- case SYS_gettimeofday:
- _gettimeofday((struct timeval *)a0, (void *)a1);
- break;
- case SYS_times:
- _times((struct tms *)a0);
- break;
- case SYS_execve:
- _execve((const char *)a0, (char *const)a1, (char *const)a2);
- break;
- default:
- unimplemented_syscall();
- break;
- }
-}
diff --git a/core-v-cores/.gitignore b/core-v-cores/.gitignore
new file mode 100644
index 0000000..b10cef5
--- /dev/null
+++ b/core-v-cores/.gitignore
@@ -0,0 +1 @@
+cv32e20/
diff --git a/env/uvme/uvme_cv32e20_cfg.sv b/env/uvme/uvme_cv32e20_cfg.sv
index 54cffda..d7b36a6 100644
--- a/env/uvme/uvme_cv32e20_cfg.sv
+++ b/env/uvme/uvme_cv32e20_cfg.sv
@@ -282,6 +282,8 @@ endfunction : new
function void uvme_cv32e20_cfg_c::pre_randomize();
+ `uvm_info("CFG", "Executing pre_randomize() of env cfg.", UVM_DEBUG)
+
if ($test$plusargs("rand_stall_obi_disable")) begin
int retval;
diff --git a/env/uvme/uvme_cv32e20_env.sv b/env/uvme/uvme_cv32e20_env.sv
index 24afaa7..7b03383 100644
--- a/env/uvme/uvme_cv32e20_env.sv
+++ b/env/uvme/uvme_cv32e20_env.sv
@@ -27,7 +27,7 @@ typedef class uvme_cv32e20_vp_status_flags_seq_c;
typedef class uvme_cv32e20_vp_rand_num_seq_c;
import "DPI-C" function longint read_symbol(input string symbol, output longint unsigned address);
-import "DPI-C" function read_elf(input string filename);
+import "DPI-C" function void read_elf(input string filename);
/**
* Top-level component that encapsulates, builds and connects all other
* CV32E20 environment components.
@@ -196,7 +196,9 @@ function void uvme_cv32e20_env_c::build_phase(uvm_phase phase);
create_env_components();
if (cfg.is_active) begin
- load_binary();
+ if ($test$plusargs("USE_ISS")) begin
+ load_binary();
+ end
create_vsequencer();
end
@@ -502,8 +504,8 @@ function void uvme_cv32e20_env_c::load_binary();
$value$plusargs("vp_interrupt_timer=%0h",cfg.vp_interrupt_timer);
$value$plusargs("vp_debug_control=%0h", cfg.vp_debug_control);
- if ($value$plusargs("elf_file=%s", binary))
- begin
+ if ($value$plusargs("elf_file=%s", binary)) begin
+ `uvm_info("cv32e20_env", $sformatf("\n\t\t\tReading ELF: %s", binary) , UVM_NONE)
read_elf(binary);
vp_status_flags_symbol_present = ! read_symbol("tohost", cfg.vp_status_flags_symbol);
if (vp_status_flags_symbol_present) begin
diff --git a/env/uvme/vseq/uvme_cv32e20_vp_status_flags_seq.sv b/env/uvme/vseq/uvme_cv32e20_vp_status_flags_seq.sv
index 447e2c3..429642f 100644
--- a/env/uvme/vseq/uvme_cv32e20_vp_status_flags_seq.sv
+++ b/env/uvme/vseq/uvme_cv32e20_vp_status_flags_seq.sv
@@ -87,17 +87,36 @@ task uvme_cv32e20_vp_status_flags_seq_c::vp_body(uvma_obi_memory_mon_trn_c mon_t
if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin
`uvm_info("VP_VSEQ", $sformatf("Call to virtual peripheral 'vp_status_flags':\n%s", mon_trn.sprint()), UVM_DEBUG)
+ // get_vp_index() returns the "register number" from a given virtual peripheral.
+ // For example, this virtual peripheral (status flags) has two registers:
+ // 0 : assert pass/fail
+ // 1 : return exit_value
case (get_vp_index(mon_trn))
0: begin
- if (mon_trn.data[0] == 1) begin
- cv32e20_cntxt.vp_status_vif.exit_value = mon_trn.data >> 1;
- cv32e20_cntxt.vp_status_vif.exit_valid = 1;
- `uvm_info("VP_VSEQ", $sformatf("virtual peripheral: TEST PASSED WITH CODE %h", cv32e20_cntxt.vp_status_vif.exit_value), UVM_LOW)
+ // Register (IDX) 0: assert pass/fail
+ cv32e20_cntxt.vp_status_vif.exit_value = mon_trn.data[0];
+ cv32e20_cntxt.vp_status_vif.exit_valid = 1;
+ if (mon_trn.data[0] == 0) begin
+ `uvm_info("VP_IDX_0", $sformatf("VP Status Flags: TEST PASSED WITH CODE %h", cv32e20_cntxt.vp_status_vif.exit_value), UVM_NONE)
end
+ else begin
+ `uvm_error("VP_IDX_0", $sformatf("VP Status Flags: TEST FAILED WITH CODE %h", cv32e20_cntxt.vp_status_vif.exit_value))
+ end
+ end
+ 1: begin
+ // Register (IDX) 1: exit_value
+ cv32e20_cntxt.vp_status_vif.exit_value = mon_trn.data[0];
+ cv32e20_cntxt.vp_status_vif.exit_valid = 1;
+ `uvm_info("VP_IDX_1", $sformatf("VP Status Flags: TEST PASSED WITH CODE %h", cv32e20_cntxt.vp_status_vif.exit_value), UVM_NONE)
+ end
+ default: begin
+ // No VP Status Flags Registers beyond this point.
+ `uvm_fatal("VP_IDX_X", $sformatf("VP Status Flags: Unknown VP Register (idx), get_vp_index(mon_trn)"))
end
endcase
end
else if (mon_trn.access_type == UVMA_OBI_MEMORY_ACCESS_READ) begin
+ // Reading the VP Status Flags returns zero
slv_rsp.rdata = 0;
end
diff --git a/mk/Common.mk b/mk/Common.mk
new file mode 100644
index 0000000..b9d80ca
--- /dev/null
+++ b/mk/Common.mk
@@ -0,0 +1,765 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Common code for simulation Makefiles.
+#
+###############################################################################
+#
+# Copyright 2019 Claire Wolf
+# Copyright 2019 Robert Balas
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+# Original Author: Robert Balas (balasr@iis.ee.ethz.ch)
+#
+###############################################################################
+
+###############################################################################
+# Common functions
+
+# Map multiple flag values to "YES" or NO
+# Use like this, to test variable MYVAR
+# ifeq ($(call IS_YES($(MYVAR)),YES)
+YES_VALS=Y YES 1 y yes TRUE true
+IS_YES=$(if $(filter $(YES_VALS),$(1)),YES,NO)
+NO_VALS=N NO 0 n no FALSE false
+IS_NO=$(if $(filter $(NO_VALS),$(1)),NO,YES)
+
+# Resolve flags for tool options in precdence order
+# Call as: MY_FLAG=$(call RESOLVE_FLAG3,$(FIRST),$(SECOND))
+# The first resolved variable in order of FIRST,SECOND will be assigned to MY_FLAG
+RESOLVE_FLAG2=$(if $(1),$(1),$(2))
+
+###############################################################################
+# Common variables
+BANNER=*******************************************************************************************
+
+###############################################################################
+# Fetch commands
+ifndef CV_CORE_REPO
+$(error Must define a CV_CORE_REPO to use the common makefile)
+endif
+
+ifndef RISCVDV_REPO
+$(error Must define a RISCVDV_REPO to use the common makefile)
+endif
+
+ifndef EMBENCH_REPO
+$(warning Must define a EMBENCH_REPO to use the common makefile)
+endif
+
+ifndef COMPLIANCE_REPO
+$(error Must define a COMPLIANCE_REPO to use the common makefile)
+endif
+
+ifndef DPI_DASM_SPIKE_REPO
+$(warning Must define a DPI_DASM_SPIKE_REPO to use the common makefile)
+endif
+
+###############################################################################
+# Generate command to clone or symlink the core RTL
+ifeq ($(CV_CORE_PATH),)
+ ifeq ($(CV_CORE_BRANCH), master)
+ TMP = git clone $(CV_CORE_REPO) $(CV_CORE_PKG)
+ else
+ TMP = git clone -b $(CV_CORE_BRANCH) --single-branch $(CV_CORE_REPO) $(CV_CORE_PKG)
+ endif
+
+ # If head is not specified, get a specific hash
+ ifeq ($(CV_CORE_HASH), head)
+ CLONE_CV_CORE_CMD = $(TMP)
+ else
+ CLONE_CV_CORE_CMD = $(TMP); cd $(CV_CORE_PKG); git checkout $(CV_CORE_HASH)
+ endif
+else
+ CLONE_CV_CORE_CMD = ln -s $(CV_CORE_PATH) $(CV_CORE_PKG)
+endif
+
+###############################################################################
+# Generate command to clone RISCV-DV (Google's random instruction generator)
+ifeq ($(RISCVDV_BRANCH), master)
+ TMP3 = git clone $(RISCVDV_REPO) --recurse $(RISCVDV_PKG)
+else
+ TMP3 = git clone -b $(RISCVDV_BRANCH) --single-branch $(RISCVDV_REPO) --recurse $(RISCVDV_PKG)
+endif
+
+ifeq ($(RISCVDV_HASH), head)
+ CLONE_RISCVDV_CMD = $(TMP3)
+else
+ CLONE_RISCVDV_CMD = $(TMP3); cd $(RISCVDV_PKG); git checkout $(RISCVDV_HASH)
+endif
+# RISCV-DV repo var end
+
+###############################################################################
+# Generate command to clone the RISCV Compliance Test-suite
+ifeq ($(COMPLIANCE_BRANCH), master)
+ TMP4 = git clone $(COMPLIANCE_REPO) --recurse $(COMPLIANCE_PKG)
+else
+ TMP4 = git clone -b $(COMPLIANCE_BRANCH) --single-branch $(COMPLIANCE_REPO) --recurse $(COMPLIANCE_PKG)
+endif
+
+ifeq ($(COMPLIANCE_HASH), head)
+ CLONE_COMPLIANCE_CMD = $(TMP4)
+else
+ CLONE_COMPLIANCE_CMD = $(TMP4); cd $(COMPLIANCE_PKG); sleep 2; git checkout $(COMPLIANCE_HASH)
+endif
+# RISCV Compliance repo var end
+
+###############################################################################
+# Generate command to clone EMBench (Embedded Benchmarking suite)
+ifeq ($(EMBENCH_BRANCH), master)
+ TMP5 = git clone $(EMBENCH_REPO) --recurse $(EMBENCH_PKG)
+else
+ TMP5 = git clone -b $(EMBENCH_BRANCH) --single-branch $(EMBENCH_REPO) --recurse $(EMBENCH_PKG)
+endif
+
+ifeq ($(EMBENCH_HASH), head)
+ CLONE_EMBENCH_CMD = $(TMP5)
+else
+ CLONE_EMBENCH_CMD = $(TMP5); cd $(EMBENCH_PKG); git checkout $(EMBENCH_HASH)
+endif
+# EMBench repo var end
+
+###############################################################################
+# Generate command to clone Spike for the Disassembler DPI (used in the isacov model)
+ifeq ($(DPI_DASM_SPIKE_BRANCH), master)
+ TMP7 = git clone $(DPI_DASM_SPIKE_REPO) --recurse $(DPI_DASM_SPIKE_PKG)
+else
+ TMP7 = git clone -b $(DPI_DASM_SPIKE_BRANCH) --single-branch $(DPI_DASM_SPIKE_REPO) --recurse $(DPI_DASM_SPIKE_PKG)
+endif
+
+ifeq ($(DPI_DASM_SPIKE_HASH), head)
+ CLONE_DPI_DASM_SPIKE_CMD = $(TMP7)
+else
+ CLONE_DPI_DASM_SPIKE_CMD = $(TMP7); cd $(DPI_DASM_SPIKE_PKG); git checkout $(DPI_DASM_SPIKE_HASH)
+endif
+# DPI_DASM Spike repo var end
+
+###############################################################################
+# Generate command to clone Verilab SVLIB
+ifeq ($(SVLIB_BRANCH), master)
+ TMP8 = git clone $(SVLIB_REPO) --recurse $(SVLIB_PKG)
+else
+ TMP8 = git clone -b $(SVLIB_BRANCH) --single-branch $(SVLIB_REPO) --recurse $(SVLIB_PKG)
+endif
+
+ifeq ($(SVLIB_HASH), head)
+ CLONE_SVLIB_CMD = $(TMP8)
+else
+ CLONE_SVLIB_CMD = $(TMP8); cd $(SVLIB_PKG); git checkout $(SVLIB_HASH)
+endif
+# SVLIB repo var end
+
+###############################################################################
+# Generate command to clone CORE-V-VERIF (OpenHW's UVM Verification Library)
+ifeq ($(CV_VERIF_BRANCH), master)
+ TMP9 = git clone $(CV_VERIF_REPO) --recurse $(CV_VERIF_PKG)
+else
+ TMP9 = git clone -b $(CV_VERIF_BRANCH) --single-branch $(CV_VERIF_REPO) --recurse $(CV_VERIF_PKG)
+endif
+
+ifeq ($(CV_VERIF_HASH), head)
+ CLONE_CV_VERIF_CMD = $(TMP9)
+else
+ CLONE_CV_VERIF_CMD = $(TMP9); cd $(CV_VERIF_PKG); git checkout $(CV_VERIF_HASH)
+endif
+# CORE-V-VERIF repo var end
+
+###############################################################################
+# Imperas Instruction Set Simulator
+
+DV_OVPM_HOME = $(CORE_V_VERIF)/vendor_lib/imperas
+DV_OVPM_MODEL = $(DV_OVPM_HOME)/imperas_DV_COREV
+DV_OVPM_DESIGN = $(DV_OVPM_HOME)/design
+OVP_MODEL_DPI = $(DV_OVPM_MODEL)/bin/Linux64/imperas_CV32.dpi.so
+#OVP_CTRL_FILE = $(DV_OVPM_DESIGN)/riscv_CV32E40P.ic
+
+###############################################################################
+# Run the yaml2make scripts
+
+ifeq ($(VERBOSE),1)
+YAML2MAKE_DEBUG = --debug
+else
+YAML2MAKE_DEBUG =
+endif
+
+# If the gen_corev-dv target is defined then read in a test defintions file
+YAML2MAKE = $(CORE_V_VERIF)/bin/yaml2make
+ifneq ($(filter gen_corev-dv,$(MAKECMDGOALS)),)
+ifeq ($(TEST),)
+$(error ERROR must specify a TEST variable with gen_corev-dv target)
+endif
+GEN_FLAGS_MAKE := $(shell $(YAML2MAKE) --test=$(TEST) --yaml=corev-dv.yaml $(YAML2MAKE_DEBUG) --prefix=GEN --core=$(CV_CORE))
+ifeq ($(GEN_FLAGS_MAKE),)
+$(error ERROR Could not find corev-dv.yaml for test: $(TEST))
+endif
+include $(GEN_FLAGS_MAKE)
+endif
+
+# If the test target is defined then read in a test defintions file
+TEST_YAML_PARSE_TARGETS=test waves cov hex clean_hex veri-test dsim-test xrun-test bsp
+ifneq ($(filter $(TEST_YAML_PARSE_TARGETS),$(MAKECMDGOALS)),)
+ifeq ($(TEST),)
+$(error ERROR! must specify a TEST variable)
+endif
+TEST_FLAGS_MAKE := $(shell $(YAML2MAKE) --test=$(TEST) --yaml=test.yaml $(YAML2MAKE_DEBUG) --run-index=$(u) --prefix=TEST --core=$(CV_CORE))
+ifeq ($(TEST_FLAGS_MAKE),)
+$(error ERROR Could not find test.yaml for test: $(TEST))
+endif
+include $(TEST_FLAGS_MAKE)
+endif
+
+###############################################################################
+# cfg
+CFGYAML2MAKE = $(CORE_V_VERIF)/bin/cfgyaml2make
+CFG_YAML_PARSE_TARGETS=comp ldgen comp_corev-dv gen_corev-dv test hex clean_hex corev-dv sanity-veri-run bsp
+ifneq ($(filter $(CFG_YAML_PARSE_TARGETS),$(MAKECMDGOALS)),)
+ifneq ($(CFG),)
+CFG_FLAGS_MAKE := $(shell $(CFGYAML2MAKE) --yaml=$(CFG).yaml $(YAML2MAKE_DEBUG) --prefix=CFG --core=$(CV_CORE))
+ifeq ($(CFG_FLAGS_MAKE),)
+$(error ERROR Error finding or parsing configuration: $(CFG).yaml)
+endif
+include $(CFG_FLAGS_MAKE)
+endif
+endif
+
+###############################################################################
+# Determine the values of the CV_SW_ variables.
+# The priority order is ENV > TEST > CFG.
+
+ifndef CV_SW_TOOLCHAIN
+ifdef TEST_CV_SW_TOOLCHAIN
+CV_SW_TOOLCHAIN = $(TEST_CV_SW_TOOLCHAIN)
+else
+ifdef CFG_CV_SW_TOOLCHAIN
+CV_SW_TOOLCHAIN = $(CFG_CV_SW_TOOLCHAIN)
+else
+$(error CV_SW_TOOLCHAIN not defined in either the shell environment, test.yaml or cfg.yaml)
+endif
+endif
+endif
+
+ifndef CV_SW_PREFIX
+ifdef TEST_CV_SW_PREFIX
+CV_SW_PREFIX = $(TEST_CV_SW_PREFIX)
+else
+ifdef CFG_CV_SW_PREFIX
+CV_SW_PREFIX = $(CFG_CV_SW_PREFIX)
+else
+$(error CV_SW_PREFIX not defined in either the shell environment, test.yaml or cfg.yaml)
+endif
+endif
+endif
+
+ifndef CV_SW_MARCH
+ifdef TEST_CV_SW_MARCH
+CV_SW_MARCH = $(TEST_CV_SW_MARCH)
+else
+ifdef CFG_CV_SW_MARCH
+CV_SW_MARCH = $(CFG_CV_SW_MARCH)
+else
+CV_SW_MARCH = rv32imc
+$(warning CV_SW_MARCH not defined in either the shell environment, test.yaml or cfg.yaml)
+endif
+endif
+endif
+
+ifndef CV_SW_CC
+ifdef TEST_CV_SW_CC
+CV_SW_CC = $(TEST_CV_SW_CC)
+else
+ifdef CFG_CV_SW_CC
+CV_SW_CC = $(CFG_CV_SW_CC)
+else
+CV_SW_CC = gcc
+$(warning CV_SW_CC not defined in either the shell environment, test.yaml or cfg.yaml)
+endif
+endif
+endif
+
+ifndef CV_SW_CFLAGS
+ifdef TEST_CV_SW_CFLAGS
+CV_SW_CFLAGS = $(TEST_CV_SW_CFLAGS)
+else
+ifdef CFG_CV_SW_CFLAGS
+CV_SW_CFLAGS = $(CFG_CV_SW_CFLAGS)
+else
+$(warning CV_SW_CFLAGS not defined in either the shell environment, test.yaml or cfg.yaml)
+endif
+endif
+endif
+
+RISCV = $(CV_SW_TOOLCHAIN)
+RISCV_PREFIX = $(CV_SW_PREFIX)
+RISCV_EXE_PREFIX = $(RISCV)/bin/$(RISCV_PREFIX)
+
+RISCV_MARCH = $(CV_SW_MARCH)
+RISCV_CC = $(CV_SW_CC)
+RISCV_CFLAGS = $(CV_SW_CFLAGS)
+
+CFLAGS ?= -Os -g -static -mabi=ilp32 -march=$(RISCV_MARCH) -Wall -pedantic $(RISCV_CFLAGS)
+
+$(warning RISCV set to $(RISCV))
+$(warning RISCV_PREFIX set to $(RISCV_PREFIX))
+$(warning RISCV_EXE_PREFIX set to $(RISCV_EXE_PREFIX))
+$(warning RISCV_MARCH set to $(RISCV_MARCH))
+$(warning RISCV_CC set to $(RISCV_CC))
+$(warning RISCV_CFLAGS set to $(RISCV_CFLAGS))
+#$(error STOP IT!)
+
+# Keeping this around just in case it is needed again
+#ifeq ($(firstword $(subst _, ,$(TEST))),pulp)
+# CFLAGS = -Os -g -D__riscv__=1 -D__LITTLE_ENDIAN__=1 -march=rv32imcxpulpv2 -Wa,-march=rv32imcxpulpv2 -fdata-sections -ffunction-sections -fdiagnostics-color=always
+#endif
+
+ASM ?= ../../tests/asm
+ASM_DIR ?= $(ASM)
+
+# CORE FIRMWARE vars. The C and assembler test-programs
+# were once collectively known as "Core Firmware".
+#
+# Note that the DSIM targets allow for writing the log-files to arbitrary
+# locations, so all of these paths are absolute, except those used by Verilator.
+#CORE_TEST_DIR = $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs
+#BSP = $(CORE_V_VERIF)/$(CV_CORE_LC)/bsp
+CORE_TEST_DIR = $(CORE_V_VERIF)/tests/programs
+BSP = $(CORE_V_VERIF)/bsp
+FIRMWARE = $(CORE_TEST_DIR)/firmware
+VERI_FIRMWARE = ../../tests/core/firmware
+ASM_PROG ?= my_hello_world
+CV32_RISCV_TESTS_FIRMWARE = $(CORE_TEST_DIR)/cv32_riscv_tests_firmware
+CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE = $(CORE_TEST_DIR)/cv32_riscv_compliance_tests_firmware
+RISCV_TESTS = $(CORE_TEST_DIR)/riscv_tests
+RISCV_COMPLIANCE_TESTS = $(CORE_TEST_DIR)/riscv_compliance_tests
+RISCV_TEST_INCLUDES = -I$(CORE_TEST_DIR)/riscv_tests/ \
+ -I$(CORE_TEST_DIR)/riscv_tests/macros/scalar \
+ -I$(CORE_TEST_DIR)/riscv_tests/rv64ui \
+ -I$(CORE_TEST_DIR)/riscv_tests/rv64um
+CV32_RISCV_TESTS_FIRMWARE_OBJS = $(addprefix $(CV32_RISCV_TESTS_FIRMWARE)/, \
+ start.o print.o sieve.o multest.o stats.o)
+CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE_OBJS = $(addprefix $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/, \
+ start.o print.o sieve.o multest.o stats.o)
+RISCV_TESTS_OBJS = $(addsuffix .o, \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32ui/*.S)) \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32um/*.S)) \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32uc/*.S)))
+FIRMWARE_OBJS = $(addprefix $(FIRMWARE)/, \
+ start.o print.o sieve.o multest.o stats.o)
+FIRMWARE_TEST_OBJS = $(addsuffix .o, \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32ui/*.S)) \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32um/*.S)) \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32uc/*.S)))
+FIRMWARE_SHORT_TEST_OBJS = $(addsuffix .o, \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32ui/*.S)) \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32um/*.S)))
+COMPLIANCE_TEST_OBJS = $(addsuffix .o, \
+ $(basename $(wildcard $(RISCV_COMPLIANCE_TESTS)/*.S)))
+
+
+# Thales verilator testbench compilation start
+
+SUPPORTED_COMMANDS := vsim-firmware-unit-test questa-unit-test questa-unit-test-gui dsim-unit-test vcs-unit-test
+SUPPORTS_MAKE_ARGS := $(filter $(firstword $(MAKECMDGOALS)), $(SUPPORTED_COMMANDS))
+
+ifneq "$(SUPPORTS_MAKE_ARGS)" ""
+ UNIT_TEST := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
+ $(eval $(UNIT_TEST):;@:)
+ UNIT_TEST_CMD := 1
+else
+ UNIT_TEST_CMD := 0
+endif
+
+COMPLIANCE_UNIT_TEST = $(subst _,-,$(UNIT_TEST))
+
+FIRMWARE_UNIT_TEST_OBJS = $(addsuffix .o, \
+ $(basename $(wildcard $(RISCV_TESTS)/rv32*/$(UNIT_TEST).S)) \
+ $(basename $(wildcard $(RISCV_COMPLIANCE_TESTS)*/$(COMPLIANCE_UNIT_TEST).S)))
+
+# Thales verilator testbench compilation end
+
+###############################################################################
+# The sanity rule runs whatever is currently deemed to be the minimal test that
+# must be able to run (and pass!) prior to generating a pull-request.
+sanity: hello-world
+
+
+###############################################################################
+# Code generators
+# New agent is pulled from moore.io temp site
+new-agent:
+ mkdir -p $(CORE_V_VERIF)/temp
+ wget --no-check-certificate -q https://mooreio.com/packages/uvm_gen.tgz -P $(CORE_V_VERIF)/temp
+ tar xzf $(CORE_V_VERIF)/temp/uvm_gen.tgz -C $(CORE_V_VERIF)/temp
+ cd $(CORE_V_VERIF)/temp && ./src/new_agent_basic.py $(CORE_V_VERIF)/lib/uvm_agents "OpenHW Group"
+ rm -rf $(CORE_V_VERIF)/temp
+
+
+
+# corev-dv tests needs an added run_index_suffix, blank for other tests
+ifeq ($(shell echo $(TEST) | head -c 6),corev_)
+export OPT_RUN_INDEX_SUFFIX=_$(RUN_INDEX)
+endif
+
+###############################################################################
+# Rule to generate hex (loadable by simulators) from elf
+# $@ is the file being generated.
+# $< is first prerequiste.
+# $^ is all prerequistes.
+# $* is file_name (w/o extension) of target
+%.hex: %.elf
+ @echo "$(BANNER)"
+ @echo "* Generating hexfile, readelf and objdump files"
+ @echo "$(BANNER)"
+ $(RISCV_EXE_PREFIX)objcopy -O verilog \
+ $< \
+ $@
+ $(RISCV_EXE_PREFIX)readelf -a $< > $*.readelf
+ $(RISCV_EXE_PREFIX)objdump \
+ -d \
+ -M no-aliases \
+ -M numeric \
+ -S \
+ $*.elf > $*.objdump
+ $(RISCV_EXE_PREFIX)objdump \
+ -d \
+ -S \
+ -M no-aliases \
+ -M numeric \
+ -l \
+ $*.elf | ${CORE_V_VERIF}/bin/objdump2itb - > $*.itb
+
+# Patterned targets to generate ELF. Used only if explicit targets do not match.
+#
+.PRECIOUS : %.elf
+
+# Single rule for compiling test source into an ELF file
+# For directed tests, TEST_FILES gathers all of the .S and .c files in a test directory
+# For corev_ tests, TEST_FILES will only point to the specific .S for the RUN_INDEX and TEST_NAME provided to make
+ifeq ($(shell echo $(TEST) | head -c 6),corev_)
+TEST_FILES = $(filter %.c %.S,$(wildcard $(SIM_TEST_PROGRAM_RESULTS)/$(TEST_NAME)$(OPT_RUN_INDEX_SUFFIX).S))
+else
+TEST_FILES = $(filter %.c %.S,$(wildcard $(TEST_TEST_DIR)/*))
+endif
+
+# If a test defines "default_cflags" in its yaml, then it is responsible to define ALL flags
+# Otherwise add the default cflags in the variable CFLAGS defined above
+ifneq ($(TEST_DEFAULT_CFLAGS),)
+TEST_CFLAGS += $(TEST_DEFAULT_CFLAGS)
+else
+TEST_CFLAGS += $(CFLAGS)
+endif
+
+# Optionally use linker script provided in test directory
+# this must be evaluated at access time, so ifeq/ifneq does
+# not get parsed correctly
+TEST_RESULTS_LD = $(addprefix $(SIM_TEST_PROGRAM_RESULTS)/, link.ld)
+TEST_LD = $(addprefix $(TEST_TEST_DIR)/, link.ld)
+
+LD_LIBRARY = $(if $(wildcard $(TEST_RESULTS_LD)),-L $(SIM_TEST_PROGRAM_RESULTS),$(if $(wildcard $(TEST_LD)),-L $(TEST_TEST_DIR),))
+LD_FILE = $(if $(wildcard $(TEST_RESULTS_LD)),$(TEST_RESULTS_LD),$(if $(wildcard $(TEST_LD)),$(TEST_LD),$(BSP)/link.ld))
+LD_LIBRARY += -L $(SIM_BSP_RESULTS)
+
+ifeq ($(TEST_FIXED_ELF),1)
+%.elf:
+ @echo "$(BANNER)"
+ @echo "* Copying fixed ELF test program to $(@)"
+ @echo "$(BANNER)"
+ mkdir -p $(SIM_TEST_PROGRAM_RESULTS)
+ cp $(TEST_TEST_DIR)/$(TEST).elf $@
+else
+%.elf: $(TEST_FILES)
+ mkdir -p $(SIM_TEST_PROGRAM_RESULTS)
+ make bsp
+ @echo "$(BANNER)"
+ @echo "* Compiling test-program $@"
+ @echo "$(BANNER)"
+ $(RISCV_EXE_PREFIX)$(RISCV_CC) \
+ $(CFG_CFLAGS) \
+ $(TEST_CFLAGS) \
+ $(RISCV_CFLAGS) \
+ -I $(ASM) \
+ -I $(BSP) \
+ -o $@ \
+ -nostartfiles \
+ $(TEST_FILES) \
+ -T $(LD_FILE) \
+ $(LD_LIBRARY) \
+ -lcv-verif
+endif
+
+.PHONY: hex
+
+# Shorthand target to only build the firmware using the hex and elf suffix rules above
+hex: $(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex
+
+bsp:
+ @echo "$(BANNER)"
+ @echo "* Compiling the BSP"
+ @echo "$(BANNER)"
+ mkdir -p $(SIM_BSP_RESULTS)
+ cp $(BSP)/Makefile $(SIM_BSP_RESULTS)
+ make -C $(SIM_BSP_RESULTS) \
+ VPATH=$(BSP) \
+ RISCV=$(RISCV) \
+ RISCV_PREFIX=$(RISCV_PREFIX) \
+ RISCV_EXE_PREFIX=$(RISCV_EXE_PREFIX) \
+ RISCV_MARCH=$(RISCV_MARCH) \
+ RISCV_CC=$(RISCV_CC) \
+ RISCV_CFLAGS="$(RISCV_CFLAGS)" \
+ all
+
+vars_bsp:
+ make vars -C $(BSP) RISCV=$(RISCV) RISCV_PREFIX=$(RISCV_PREFIX) RISCV_EXE_PREFIX=$(RISCV_EXE_PREFIX) RISCV_MARCH=$(RISCV_MARCH)
+
+clean_bsp:
+ make -C $(BSP) clean
+ rm -rf $(SIM_BSP_RESULTS)
+
+
+# compile and dump RISCV_TESTS only
+#$(CV32_RISCV_TESTS_FIRMWARE)/cv32_riscv_tests_firmware.elf: $(CV32_RISCV_TESTS_FIRMWARE_OBJS) $(RISCV_TESTS_OBJS) \
+# $(CV32_RISCV_TESTS_FIRMWARE)/link.ld
+# $(RISCV_EXE_PREFIX)gcc -g -Os -mabi=ilp32 -march=rv32imc -ffreestanding -nostdlib -o $@ \
+# $(RISCV_TEST_INCLUDES) \
+# -Wl,-Bstatic,-T,$(CV32_RISCV_TESTS_FIRMWARE)/link.ld,-Map,$(CV32_RISCV_TESTS_FIRMWARE)/cv32_riscv_tests_firmware.map,--strip-debug \
+# $(CV32_RISCV_TESTS_FIRMWARE_OBJS) $(RISCV_TESTS_OBJS) -lgcc
+
+#$(CV32_RISCV_TESTS_FIRMWARE)/cv32_riscv_tests_firmware.elf: $(CV32_RISCV_TESTS_FIRMWARE_OBJS) $(RISCV_TESTS_OBJS) \
+# $(CV32_RISCV_TESTS_FIRMWARE)/link.ld
+../../tests/core/cv32_riscv_tests_firmware/cv32_riscv_tests_firmware.elf: $(CV32_RISCV_TESTS_FIRMWARE_OBJS) $(RISCV_TESTS_OBJS)
+ $(RISCV_EXE_PREFIX)gcc $(CFLAGS) -ffreestanding -nostdlib -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -Wl,-Bstatic,-T,$(CV32_RISCV_TESTS_FIRMWARE)/link.ld,-Map,$(CV32_RISCV_TESTS_FIRMWARE)/cv32_riscv_tests_firmware.map,--strip-debug \
+ $(CV32_RISCV_TESTS_FIRMWARE_OBJS) $(RISCV_TESTS_OBJS) -lgcc
+
+$(CV32_RISCV_TESTS_FIRMWARE)/start.o: $(CV32_RISCV_TESTS_FIRMWARE)/start.S
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -o $@ $<
+
+$(CV32_RISCV_TESTS_FIRMWARE)/%.o: $(CV32_RISCV_TESTS_FIRMWARE)/%.c
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) --std=c99 -Wall \
+ $(RISCV_TEST_INCLUDES) \
+ -ffreestanding -nostdlib -o $@ $<
+
+# compile and dump RISCV_COMPLIANCE_TESTS only
+$(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/cv32_riscv_compliance_tests_firmware.elf: $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE_OBJS) $(COMPLIANCE_TEST_OBJS) \
+ $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/link.ld
+ $(RISCV_EXE_PREFIX)gcc $(CFLAGS) -ffreestanding -nostdlib -o $@ \
+ -D RUN_COMPLIANCE \
+ $(RISCV_TEST_INCLUDES) \
+ -Wl,-Bstatic,-T,$(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/link.ld,-Map,$(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/cv32_riscv_compliance_tests_firmware.map,--strip-debug \
+ $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE_OBJS) $(COMPLIANCE_TEST_OBJS) -lgcc
+
+$(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/start.o: $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/start.S
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -D RUN_COMPLIANCE -o $@ $<
+
+$(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/%.o: $(CV32_RISCV_COMPLIANCE_TESTS_FIRMWARE)/%.c
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) --std=c99 -Wall \
+ $(RISCV_TEST_INCLUDES) \
+ -ffreestanding -nostdlib -o $@ $<
+
+# compile and dump picorv firmware
+
+# Thales start
+$(FIRMWARE)/firmware_unit_test.elf: $(FIRMWARE_OBJS) $(FIRMWARE_UNIT_TEST_OBJS) $(FIRMWARE)/link.ld
+ $(RISCV_EXE_PREFIX)gcc $(CFLAGS) -ffreestanding -nostdlib -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -D RUN_COMPLIANCE \
+ -Wl,-Bstatic,-T,$(FIRMWARE)/link.ld,-Map,$(FIRMWARE)/firmware.map,--strip-debug \
+ $(FIRMWARE_OBJS) $(FIRMWARE_UNIT_TEST_OBJS) -lgcc
+# Thales end
+
+$(FIRMWARE)/firmware.elf: $(FIRMWARE_OBJS) $(FIRMWARE_TEST_OBJS) $(COMPLIANCE_TEST_OBJS) $(FIRMWARE)/link.ld
+ $(RISCV_EXE_PREFIX)gcc $(CFLAGS) -ffreestanding -nostdlib -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -D RUN_COMPLIANCE \
+ -Wl,-Bstatic,-T,$(FIRMWARE)/link.ld,-Map,$(FIRMWARE)/firmware.map,--strip-debug \
+ $(FIRMWARE_OBJS) $(FIRMWARE_TEST_OBJS) $(COMPLIANCE_TEST_OBJS) -lgcc
+
+#$(FIRMWARE)/start.o: $(FIRMWARE)/start.S
+# $(RISCV_EXE_PREFIX)gcc -c -march=rv32imc -g -D RUN_COMPLIANCE -o $@ $<
+
+# Thales start
+$(FIRMWARE)/start.o: $(FIRMWARE)/start.S
+ifeq ($(UNIT_TEST_CMD),1)
+ifeq ($(FIRMWARE_UNIT_TEST_OBJS),)
+$(error no existing unit test in argument )
+else
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -D RUN_COMPLIANCE -DUNIT_TEST_CMD=$(UNIT_TEST_CMD) -DUNIT_TEST=$(UNIT_TEST) -DUNIT_TEST_RET=$(UNIT_TEST)_ret -o $@ $<
+endif
+else
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -D RUN_COMPLIANCE -DUNIT_TEST_CMD=$(UNIT_TEST_CMD) -o $@ $<
+endif
+# Thales end
+
+$(FIRMWARE)/%.o: $(FIRMWARE)/%.c
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) --std=c99 \
+ $(RISCV_TEST_INCLUDES) \
+ -ffreestanding -nostdlib -o $@ $<
+
+$(RISCV_TESTS)/rv32ui/%.o: $(RISCV_TESTS)/rv32ui/%.S $(RISCV_TESTS)/riscv_test.h \
+ $(RISCV_TESTS)/macros/scalar/test_macros.h
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
+ -DTEST_FUNC_TXT='"$(notdir $(basename $<))"' \
+ -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
+
+$(RISCV_TESTS)/rv32um/%.o: $(RISCV_TESTS)/rv32um/%.S $(RISCV_TESTS)/riscv_test.h \
+ $(RISCV_TESTS)/macros/scalar/test_macros.h
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
+ -DTEST_FUNC_TXT='"$(notdir $(basename $<))"' \
+ -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
+
+$(RISCV_TESTS)/rv32uc/%.o: $(RISCV_TESTS)/rv32uc/%.S $(RISCV_TESTS)/riscv_test.h \
+ $(RISCV_TESTS)/macros/scalar/test_macros.h
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -o $@ \
+ $(RISCV_TEST_INCLUDES) \
+ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
+ -DTEST_FUNC_TXT='"$(notdir $(basename $<))"' \
+ -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
+
+# Build riscv_compliance_test. Make sure to escape dashes to underscores
+$(RISCV_COMPLIANCE_TESTS)/%.o: $(RISCV_COMPLIANCE_TESTS)/%.S $(RISCV_COMPLIANCE_TESTS)/riscv_test.h \
+ $(RISCV_COMPLIANCE_TESTS)/test_macros.h $(RISCV_COMPLIANCE_TESTS)/compliance_io.h \
+ $(RISCV_COMPLIANCE_TESTS)/compliance_test.h
+ $(RISCV_EXE_PREFIX)gcc -c $(CFLAGS) -o $@ \
+ -DTEST_FUNC_NAME=$(notdir $(subst -,_,$(basename $<))) \
+ -DTEST_FUNC_TXT='"$(notdir $(subst -,_,$(basename $<)))"' \
+ -DTEST_FUNC_RET=$(notdir $(subst -,_,$(basename $<)))_ret $<
+
+# in dsim
+.PHONY: dsim-unit-test
+dsim-unit-test: firmware-unit-test-clean
+dsim-unit-test: $(FIRMWARE)/firmware_unit_test.hex
+dsim-unit-test: ALL_VSIM_FLAGS += "+firmware=$(FIRMWARE)/firmware_unit_test.hex +elf_file=$(FIRMWARE)/firmware_unit_test.elf"
+dsim-unit-test: dsim-firmware-unit-test
+
+# in vcs
+.PHONY: firmware-vcs-run
+firmware-vcs-run: vcsify $(FIRMWARE)/firmware.hex
+ ./simv $(SIMV_FLAGS) "+firmware=$(FIRMWARE)/firmware.hex"
+
+.PHONY: firmware-vcs-run-gui
+firmware-vcs-run-gui: VCS_FLAGS+=-debug_all
+firmware-vcs-run-gui: vcsify $(FIRMWARE)/firmware.hex
+ ./simv $(SIMV_FLAGS) -gui "+firmware=$(FIRMWARE)/firmware.hex"
+
+.PHONY: vcs-unit-test
+vcs-unit-test: firmware-unit-test-clean
+vcs-unit-test: $(FIRMWARE)/firmware_unit_test.hex
+vcs-unit-test: vcsify $(FIRMWARE)/firmware_unit_test.hex
+vcs-unit-test: vcs-run
+
+###############################################################################
+# Clone CORE-V-VERIF
+
+core-v-verif:
+ $(CLONE_CV_VERIF_CMD)
+
+###############################################################################
+# Build disassembler
+
+DPI_DASM_SRC = $(DPI_DASM_PKG)/dpi_dasm.cxx $(DPI_DASM_PKG)/spike/disasm.cc $(DPI_DASM_SPIKE_PKG)/disasm/regnames.cc
+DPI_DASM_ARCH = $(shell uname)$(shell getconf LONG_BIT)
+DPI_DASM_LIB ?= $(DPI_DASM_PKG)/lib/$(DPI_DASM_ARCH)/libdpi_dasm.so
+DPI_DASM_CFLAGS = -shared -fPIC -std=c++11
+DPI_DASM_INC = -I$(DPI_DASM_PKG) -I$(DPI_INCLUDE) -I$(DPI_DASM_SPIKE_PKG)/riscv -I$(DPI_DASM_SPIKE_PKG)/softfloat
+DPI_DASM_CXX = g++
+
+dpi_dasm: $(DPI_DASM_SPIKE_PKG)
+ $(CLONE_DPI_DASM_SPIKE_CMD)
+ $(DPI_DASM_CXX) $(DPI_DASM_CFLAGS) $(DPI_DASM_INC) $(DPI_DASM_SRC) -o $(DPI_DASM_LIB)
+
+###############################################################################
+# Build vendor/riscv-isa-sim into tools/
+
+export SPIKE_PATH = $(CORE_V_VERIF)/vendor/riscv/riscv-isa-sim
+export SPIKE_INSTALL_DIR = $(CORE_V_VERIF)/tools/spike/
+SPIKE_LIBS_DIR = $(SPIKE_INSTALL_DIR)/lib/
+SPIKE_FESVR_LIB = $(SPIKE_LIBS_DIR)/libfesvr
+SPIKE_RISCV_LIB = $(SPIKE_LIBS_DIR)/libriscv
+SPIKE_DISASM_LIB = $(SPIKE_LIBS_DIR)/libdisasm
+SPIKE_CUSTOMEXT_LIB = $(SPIKE_LIBS_DIR)/libcustomext
+SPIKE_YAML_LIB = $(SPIKE_LIBS_DIR)/libyaml-cpp
+
+NUM_JOBS ?= 8
+
+$(SPIKE_FESVR_LIB).so $(SPIKE_RISCV_LIB).so:
+ mkdir -p $(SPIKE_PATH)/build;
+ [ ! -f $(SPIKE_PATH)/build/config.log ] && cd $(SPIKE_PATH)/build && ../configure --prefix=$(SPIKE_INSTALL_DIR) || true
+ make -C $(SPIKE_PATH)/build/ -j $(NUM_JOBS) yaml-cpp-static;
+ make -C $(SPIKE_PATH)/build/ -j $(NUM_JOBS) yaml-cpp;
+ make -C $(SPIKE_PATH)/build/ -j $(NUM_JOBS) install;
+
+spike_lib: $(SPIKE_FESVR_LIB).so $(SPIKE_RISCV_LIB).so
+
+###############################################################################
+# Build SVLIB DPI
+
+SVLIB_SRC = $(SVLIB_PKG)/svlib/src/dpi/svlib_dpi.c
+SVLIB_CFLAGS = -shared -fPIC
+SVLIB_LIB = $(SVLIB_PKG)/../svlib_dpi.so
+SVLIB_CXX = gcc
+
+svlib: $(SVLIB_PKG)
+ @echo "$(BANNER)"
+ @echo "Building $(SVLIB_PKG)"
+ @echo "$(BANNER)"
+ $(SVLIB_CXX) $(SVLIB_CFLAGS) $(SVLIB_SRC) -I$(DPI_INCLUDE) -o $(SVLIB_LIB)
+
+###############################################################################
+# Build Stub for RVVI-API (in the case where ImperasDV is not available)
+RVVI_STUB_SRC = $(RVVI_STUB)/rvviApiStubs.c
+RVVI_STUB_CFLAGS = -shared -fPIC
+RVVI_STUB_LIB = $(RVVI_STUB)/rvviApi.so
+RVVI_STUB_CXX = gcc
+
+rvvi_stub:
+ @echo "$(BANNER)"
+ @echo "Building $(RVVI_STUB)"
+ @echo "$(BANNER)"
+ $(RVVI_STUB_CXX) $(RVVI_STUB_CFLAGS) $(RVVI_STUB_SRC) -I$(DPI_INCLUDE) -o $(RVVI_STUB_LIB)
+
+###############################################################################
+.PHONY: firmware-clean
+firmware-clean:
+ rm -vrf $(addprefix $(FIRMWARE)/firmware., elf bin hex map) \
+ $(FIRMWARE_OBJS) $(FIRMWARE_TEST_OBJS) $(COMPLIANCE_TEST_OBJS)
+
+.PHONY: firmware-unit-test-clean
+firmware-unit-test-clean:
+ rm -vrf $(addprefix $(FIRMWARE)/firmware_unit_test., elf bin hex map) \
+ $(FIRMWARE_OBJS) $(FIRMWARE_UNIT_TEST_OBJS)
+
+#endend
+
+
diff --git a/mk/README.md b/mk/README.md
new file mode 100644
index 0000000..a5a1081
--- /dev/null
+++ b/mk/README.md
@@ -0,0 +1,475 @@
+Common Makefile for the CORE-V-VERIF UVM Verification Environment
+==================================
+This directory contains the _Common_ makefiles for the UVM and Core testbenches to perform common functionality:
+- Cloning third party repositories (Core RTL, libraries, ISGs, RISC-V compliance library, etc.)
+- Invoking the toolchain to compile directed and/or random test programs into machine code for simulation
+- Invoking the toolchain to compile compliance test programs for simulation
+- Importing the source code in DVT Eclipse IDE (https://dvteclipse.com/)
+
+In the core-v-verif UVM environment, the distinction between a **_testcases_** and **_test-program_** is important.
+* **testcase**: a SystemVerilog class extended from uvm_test that instantiates and controls the UVM environment.
+A testcase will control things like whether or not, and when, an interrupt is asserted and randomization of cycle timing on the external memory interfaces.
+* **test-program**: a C or assembler program that is executed by the core RTL model.
+
+There may be only one testcase, but typically there are many test-programs.
+For more information please refer to the [Verification Strategy](https://core-v-docs-verif-strat.readthedocs.io/en/latest/intro.html)
+
+The testcases are at located at `CV_CORE/tests/uvmt`.
+Test-programs can be found in `CV_CORE/tests/program`.
+See the README in those directories for more information.
+
+To run the UVM environment you will need:
+- a run-time license for the Imperas OVPsim Instruction Set Simulator
+- a SystemVerilog simulator,
+- the UVM-1.2 library,
+- the RISC-V GCC compiler, and
+- at least some familiarity with [Make](https://www.gnu.org/software/make/manual/) and Makefiles.
+
+Required COREV Environment Variables
+------------------------------------
+The Makefile use a set of common shell environment variables to control individual simulations and/or regressions.
+The following variables **must** be set for any `make` invocation to run tests in core-v-verif.
+These can be set on the command line (e.g. `make CV_SIMULATOR=xrun`) or set in the user's shell environment.
+Note that `CV_CORE` is infered by the Makefiles if you launch a test from a `uvmt` directory.
+
+| Environment Variable | Description |
+|----------------------|--------------|
+| CV_SIMULATOR | The default simulator to use for all tools (dsim, vcs, xrun, vsim, riviera). Can be overridden on any make invocation. |
+| CV_CORE | The core to simulate by default. Can be overridden on any make command line. |
+| CV_SW_TOOLCHAIN | Points to SW toolchain installation for compiling, assembling, and/or linking test programs. |
+| CV_SW_PREFIX | Prefix of the SW toolchain installation. |
+
+**Notes:**
+1. A toolchain is required for running any tests in the core-v-verif environments, see below for more detail.
+2. If CV_CORE is not set, running a simulation from the `/sim/uvmt` directory will automatically set it to "core".
+
+A toolchain is comprised of a set of executables (e.g. gcc, objcopy, etc.) each of which typically has a path of the form `$(CV_SW_TOOLCHAIN)/bin/$(CV_SW_PREFIX)`.
+For example, if your toolchain executables are at `/opt/riscv/bin/riscv32-unknown-elf-`, then you would set `CV_SW_TOOLCHAIN` to **_/opt/riscv_** and `CV_SW_PREFIX` to **_riscv32-unknown-elf-_**.
+
+Optional COREV Environment Variables
+----------------------------------------
+The Makefile use a set of common shell environment variables to control individual simulations and/or regressions.
+The following environment variables may be set for any `make` invocation to run tests or set in the user's environment to customize setting.
+
+| Environment Variable | Description |
+|----------------------|--------------|
+| CV_SIM_PREFIX | Prepended to all simulation compile and/or execution invocations. Can be used to invoke job-scheduling tool (e.g. LSF). |
+| CV_TOOL_PREFIX | Prepended to all standalone tool (i.e. non-interacitive) simulation tool invocations such as coverage tools and waveform viewers. Can be used to invoke job-scheduling tool (e.g. LSF). |
+| CV_RESULTS | Optional simulator output redirection path. Defaults to blank, i.e. simulation outputs will be located in <core>/mk/uvmt/<simulator>\_results if a relative path is given. Optionally an absolute path can be used as well and simulation outputs will be located in $(CV\_RESULTS)/<simulator>\_results |
+| CV_SW_MARCH | Architecture of tool chain to invoke. The default is `rv32imc`. |
+| CV_SW_CFLAGS | Optional command-line arguments (flags) passed to $(CV_SW_CC). |
+| CV_SW_CC | Postfix name of the C compiler used to compile the test-program. The default is `gcc`. If you are using an LLVM toolchain, this would typically be set to `cc`. |
+
+Imperas Reference Models
+------------------------
+Many CORE-V cores verified in CORE-V-VERIF use a reference model from [Imperas](https://www.imperas.com/).
+Earlier generations of CORE-V-VERIF used the **_OVPsim Instruction Set Simulator_**, and as of March, 2023 we have transitioned to **_ImperasDV_**.
+To purchase a run-time license for ImperasDV, please contact Imperas at the link above.
+
+To run CORE-V-VERIF without the reference model, set the `USE_ISS` make variable to "NO":
+```
+$ make test TEST=hello-world SIMULATOR= USE_ISS=NO
+```
+The above works for all tests, but be aware that most test-programs in CORE-V-VERIF are not self-checking,
+so without a running reference model, passing simulations are vacuous.
+
+SystemVerilog Simulators
+----------------------------------
+Any SystemVerilog simulator that implements complete support for [IEEE-1800-2017](https://ieeexplore.ieee.org/document/8299595)
+will be able to compile and run this verification environment. Metrics **_dsim_**, Cadence **_Xcelium_**, Mentor's **_Questa_**,
+Aldec's **_Riviera-PRO_** and Synopsys **_VCS_** simulators are supported by the Makefiles. If you have access to a SystemVerilog
+simulator not listed here and would like to add support to the Makefiles, your pull-request will be graciously accepted!
+
+UVM-1.2 Libraries
+-------------
+The UVM environments in core-v-verif require the use of version 1.2 of the UVM library (1.1 will not suffice). Typically,
+the UVM library comes with the distribution of your SystemVerilog simulator. Point your shell environment
+variable `UVM_HOME` to your simulator's UVM library. For example Metrics dsim users will have something
+like this:
`export UVM_HOME=/tools/Metrics/dsim/20191112.8.0/uvm-1.2`.
+
+Alternately, you can download the source code from
+[Accellera](https://www.accellera.org/downloads/standards/uvm). The UVM LRM (IEEE-1800.2) can be obtained
+from the [IEEE Standards Association](https://standards.ieee.org/).
+
+Toolchains
+----------
+Compiling the test-programs requires a RISC-V cross-compiler, often refered to as the "toolchain".
+See [TOOLCHAIN](./TOOLCHAIN.md) for detailed installation instructions.
+
+Makefiles
+-----------
+`Make` is used to generate the command-lines that compile and run simulations.
+- `CV_CORE/sim/uvmt/Makefile` is the 'root' Makefile from which users can invoke simulations.
+This Makefile is largely empty and include:
+- `CV_CORE/sim/ExternalRepos.mk` should be used to define variables to point to third-party libraries.
+This include the RTL repo to simulate; Google riscv-dv; RISCV compliance suite and other external repositories.
+- `CORE-V-VERIF/mk/uvmt/uvmt.mk`, which implements simulation execution targets and:
+- `CORE-V-VERIF/mk/Common.mk` supports all common variables, rules and targets, including specific targets to clone the RTL.
+
+Simulator-specific Makefiles are used to build the command-line to run a specific test with a specific
+simulator. These files are organized as shown below:
+```
+CORE-V-VERIF/
+ |
+ +--- mk/
+ | +--- Common.mk # Common variables and targets
+ | +--- uvmt/
+ | +--- uvmt.mk # Simulation makefile (includes ../Common.mk and simulator-specific mk)
+ | +--- vcs.mk # Synopsys VCS
+ | +--- vsim.mk # Mentor Questa
+ | +--- dsim.mk # Metrics dsim
+ | +--- xrun.mk # Cadance Xcelium
+ | +--- riviera.mk # Aldec Riviera-PRO
+ | +--- .mk
+ +--- CV_CORE/
+ +--- sim/
+ +--- ExternalRepos.mk # URLs, hashes to external repos (RTL, riscv-dv, etc.)
+ +--- uvmt/
+ +--- Makefile # "root" Makefile
+ # includes ../ExternalRepos.mk and CORE-V-VERIF/mk/uvmt/uvmt.mk
+```
+The goal of this structure is to minimize the amount of redundant code in the
+Makefiles, maintain common look-and-feel across all cores and ease the maintance of a given simulator's specific variables,
+rules and targets.
+
+The basic usage is: `make SIMULATOR= ` where `sim` is vsim, dsim,
+ xrun, vcs or riviera and `target` selects one or more activities (e.g. 'clean', 'test', 'gen_corev-dv')
+
+**Hint**: define shell ENV variable "SIMULATOR" to match one of the supported
+simulator-specific Makefiles (e.g. vsim) to save yourself a lot of typing.
+
+The basic format to run a test is `make test SIMULATOR= TEST=` where `test-program`
+is the name of a [test-program](https://core-v-docs-verif-strat.readthedocs.io/en/latest/sim_tests.html#test-program)
+(either C or RISC-V assembler) located in /tests/programs/custom/.
+
+Importing the source code in DVT Eclipse IDE [dvt](https://www.dvteclipse.com/products/dvt-eclipse-ide)
+----------------------
+Alongside the simulator-specific Makefiles, there is also a makefile called `dvt.mk`.
+The command `make SIMULATOR= open_in_dvt_ide` will import the core-v-verif testbench and RTL source code
+in the DVT Eclipse IDE.
+
+**Note:** `CV_CORE/sim/uvmt/Makefile` is the 'root' Makefile from which users can invoke DVT.
+
+
+Running the envrionment with Metrics [dsim](https://metrics.ca)
+----------------------
+The command **make SIMULATOR=dsim sanity** will run the sanity testcase using _dsim_.
+
+Setting a shell environment variable `CV_SIMULATOR` to "dsim" will also define the
+Makefile variable SIMULATOR to `dsim` and you can save yourself a lot of typing. For
+example, in a bash shell:
+
**export CV_SIMULATOR=dsim**
+
**make sanity**
+
+The Makefile for dsim also supports variables to control wave dumping. For example:
+
**make sanity WAVES=1**
+
Have a look at `dsim.mk` to see additional variables to control the filename
+of the dumpfile, etc.
+
+The Makefile variable DSIM_RUN_FLAGS can be used to pass user define arguments
+to dsim at run-time. For example:
+
**make sanity DSIM\_RUN\_FLAGS=+print\_uvm\_runflow\_banner=1**
+
+Running the environment with Cadence [Xcelium](https://www.cadence.com/en_US/home/tools/system-design-and-verification/simulation-and-testbench-verification/xcelium-parallel-simulator.html) (xrun)
+----------------------
+The command **make SIMULATOR=xrun sanity** will run the sanity testcase
+using _xrun_. Set the shell variable SIMULATOR to `xrun` to simply run **`make `**.
+
+**Note for Cadence users:** This testbench is known to require Xcelium 19.09 or
+later. See [Issue 11](https://github.com/openhwgroup/core-v-verif/issues/11)
+for more info.
+
+
+Running the environment with Mentor Graphics [Questa](https://www.mentor.com/products/fv/questa/) (vsim)
+----------------------
+The command **make SIMULATOR=vsim sanity** will run the sanity testcase using _vsim_.
+Set the shell variable SIMULATOR to `vsim` to simply run **`make `**.
+
+**Note for Mentor users:** This testbench is known to require Questa 2019.2 or later.
+
+
+Running the environment with Synopsys VCS [VCS](https://www.synopsys.com/verification/simulation/vcs.html) (vcs)
+----------------------
+The command **make SIMULATOR=vcs sanity** will run the sanity testcase using _vsim_.
+Set the shell variable SIMULATOR to `vcs` to simply run **`make `**.
+
+**Note for Synopsys users:** This testbench has not been compiled/run
+with _vcs_ in several weeks. If you need to update the Makefiles, please do
+so and issue a Pull Request.
+
+Running the environment with Aldec [Riviera-PRO](https://www.aldec.com/en/products/functional_verification/riviera-pro) (riviera)
+----------------------
+The command **make SIMULATOR=riviera sanity** will run the sanity testcase using _riviera_.
+Set the shell variable SIMULATOR to `riviera` to simply run **`make `**.
+
+Sanity Tests
+---------------
+The `make` commands here assume you have set your shell SIMULATION
+environment variable to your specific simulator (see above).
+
+Before making changes to the code in your local branch, it is a good idea to run the sanity
+test to ensure you are starting from a stable code-base. The code (both RTL
+and verification) should _always_ pass sanity, so if it does not, please
+raise an issue and assign it to @mikeopenhwgroup. The definition of "sanity"
+may change over time as the ability of the verification environment to
+stress the RTL improves. Running sanity is trivial:
+```
+make sanity
+```
+
+CI Mini-regression
+------------------
+OpenHW uses the [Metrics CI platform]() for regressions. The control script for this is `.metrics.json`
+located at the top-level of this repository. A pythin script `ci/ci_check` can be used to run the
+"cv32 CI check regression" specified in the control script. Before issuing a pull-request for either
+the RTL or verification code, please run `ci_check`. Your pull-request will be rejected if `ci_check`
+does not compile and run successfully. Usage is simple:
+```
+./ci_check --core cv32e40p -s xrun
+```
+will run the CI sanity regression on the cv32e40p using Xcelium.
+
+Complete user information is obtained in the usual way:
+```
+./ci_check -h
+```
+
+Available Test Programs
+-----------------------
+The `make` commands here assume you have set your shell SIMULATION
+environment variable to your specific simulator (see above).
+
+The general form to run a test is `make test TEST=`, where _test-program_ is the filename
+of a test-program (without the file extension) of a test program located at /tests/programs/custom.
+Each test-program (either C or assembler) has its own directory, which contains the program itself (either
+C or assembler) plus `test.yaml`, the test-program configuration file (see Build Configurations, below).
+
+Here are a few examples
+* **make test TEST=hello-world**:
run the hello_world program found at `/tests/programs/custom`.
+* **make test TEST=dhrystone**:
run the dhrystone program found at `/tests/programs/custom`.
+* **make test TEST=riscv_arithmetic_basic_test**:
run the riscv_arithmetic_basic_test program found at `/tests/programs/custom`.
+
+There are also a few targets that do something other than run a test. The most popular is:
+```
+**make clean_all**
+```
+which deletes all SIMULATOR generated intermediates, waves and logs **plus** the cloned RTL code.
+
+### CoreMark
+
+There is a port of the [CoreMark](https://www.eembc.org/coremark/)
+benchmark runnable with the following make command.
+
+* **make test TEST=coremark USE_ISS=NO**
+
+This will run the benchmark and print out the results.
+The numbers "Total ticks" and "Iterations" can be used to compute the CoreMak/MHz score with
+the following equation `CoreMark/MHz = iterations / (totalticks / 1e6)`.
+
+COREV-DV Generated Tests
+---------------
+The CV32 UVM environment uses the [Google riscv-dv](https://github.com/google/riscv-dv)
+generator to automate the generation of test-programs. The generator
+is cloned by the Makefiles to `$(CV_CORE)/vendor_lib/google` as needed. Specific
+classes ar extended to create a `corev-dv` generator that is specific to this environment.
+Note that riscv-dv is not modified, merely extended, allowing core-v-verif to stay
+up-to-date with the latest release of riscv-dv.
+
+Riscv-dv uses test templates such as "riscv_arithmetic_basic_test" and "riscv_rand_jump_test".
+Corev-dv has a set of templates for corev-dv generated test-programs at `/tests/programs/corev-dv`.
+Running these is a two-step process. The first step is to clone riscv-dv and compile corev-dv:
+```
+make corev-dv
+```
+Note that the `corev-dv` target need only be run once. The next step is to generate, compile
+and run a test. For example:
+```
+make gen_corev-dv test TEST=corev_rand_jump_stress_test
+```
+
+RISC-V Compliance Test-suite and Regressions
+---------------
+The CV32 UVM environment is able to run the [RISC-V compliance](https://github.com/riscv/riscv-compliance)
+test-suite in step-and-compare mode with the ISS Reference Model, and can optionally dump and check a signature
+file against a reference signature. As with riscv-dv, the compliance test-suite
+is cloned by the Makefiles to `$(CV_CORE)/vendor_lib/riscv` as needed. The form of the target to run a single test-program
+from the compliance test suite is as follows:
+```
+make compliance RISCV_ISA= COMPLIANCE_PROG=
+```
+To have the signature dumped and checked:
+```
+make compliance_check_sig RISCV_ISA= COMPLIANCE_PROG=
+```
+Note that running either of these targets will invoke the `all_compliance` target which clones riscv-compliance
+and compiles all the test-programs. Below is an example of running a specific test-program from the suite:
+```
+make compliance RISCV_ISA=rv32Zifencei COMPLIANCE_PROG=I-FENCE.I-01
+```
+**Note:** There is a dependancy between RISCV_ISA and COMPLIANCE_PROG. For example, because the I-ADD-01 test-program is part of the rv32i testsuite this works:
+```
+make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+```
+But this does not:
+```
+make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+```
+The `compliance_check_sig` target can be used in the same way as above to run the simulation plus perform a post-simulation
+check of the signature file and the reference signature provided as part of the compliance test-suite.
+
+Per-extension compliance regressions can be run using the `compliance_regression` target. For example:
+```
+make compliance_regression RISCV_ISA=rv32imc
+```
+will run all compressed instruction tests in the compliance test-suite, diff the signature files and produce a summary report. Note that four of the test-programs
+in the rv32i compliance suite are deliberately ignored. See [issue #412](https://github.com/openhwgroup/core-v-verif/issues/412).
+
+The _cv_regress_ utility can also be used to run the compliance regression tests found in the [cv32_compliance](https://github.com/openhwgroup/core-v-verif/blob/master/cv32e40p/regress/cv32_compliance.yaml) YAML regression
+specification. This is supported for Metrics JSON (--metrics), shell script (--sh), and Cadence Vmanager VSIF (--vsif) output formats. Use the following example:
+```
+# Shell script output
+% cv_regress --file=cv32e40p_compliance --sim=xrun --sh
+% ./cv32e40p_compliance.sh
+```
+
+Build Configurations
+--------------------
+The `uvmt` environment supports adding compile flags to the testbench to support a specialized configuration of the core. The testbench
+flow supports a single compilation object at any point in time so it is recommended that any testbench options be supported as run-time
+options (see the Test Specification documentation for setting run-time plusargs). However if, for instance, parameters to the DUT need to be
+changed then this flow needs to be used.
+
+All build configurations are in the files:
+
+```
+/tests/cfg/.yaml
+```
+
+The contents of the YAML file support the following tags:
+| YAML Tag | Required | Description |
+|---------------|----------|---------------------|
+| name | Yes | The name of the configuration |
+| description | Yes | Brief description of the intent of the build configuration |
+| compile_flags | No | Compile flags passed to the simulator compile-step |
+| ovpsim | No | Flags for the IC file for the OVPSim ISS |
+
+
+The following is an example build configuration:
+
+```
+name: no_pulp
+description: Sets all PULP-related flags to 0
+compile_flags: >
+ +define+NO_PULP
+ +define+HAHAHA
+ovpsim: >
+ --override root/cpu0/misa_Extensions=0x1104
+ --showoverrides
+```
+To facilitate multiple simultaneous runs with different configurations, simulation databases and output files are located in the <simulator_results/<CFG>-subdirectories, where CFG is the name of the current yaml configuration. If not overriden, the default configuration is chosen and the subdirectory named accordingly.
+
+Common Makefile Flags
+---------------
+For all tests in the uvmt directory the following flags and targets are supported for common operations with the simulators. For all flags and targets described in this section it is assumed that the user will supply a SIMULATOR setting on the make command line or populate the CV_SIMULATOR environment variable.
+
+| SIMULATOR | Supported |
+|--------------|-----------|
+|dsim | Yes |
+|xrun | Yes |
+|vsim(questa) | Yes |
+|vcs | Yes |
+|Riviera-PRO | Yes |
+
+For certain simulators multiple debug tools are available that enable advanced debug capabilities but generally require respective licenses from the vendor. By default all debug-related commands in this section will support a standard debug tool with the simulator. However support is provided for advanced debug tools when avaiable. The advanced debug tool is selected with each make command by setting the **ADV_DEBUG=YES** flag.
+
+| SIMULATOR | Standard Debug Tool | Advanced Debug Tool |
+|-------------|---------------------|---------------------|
+| dsim | gtkwave | N/A |
+| xrun | SimVision | Indago |
+| questa | Questa Tk GUI | Visualizer |
+| vcs | DVE | Verdi |
+| Riviera-PRO | Riviera-PRO | Riviera-PRO |
+
+### Interactive Simulation
+
+To run a simulation in interactive mode (to enable single-stepping, breakpoints, restarting), use the GUI=1 command when running a test.
+
+If applicable for a simulator, line debugging will be enabled in the compile to enable single-stepping.
+
+**make test TEST=hello-world GUI=1**
+
+### Passing run-time arguments to the simulator
+
+The Makefiles support a user controllable variable **USER_RUN_FLAGS** which can be used to pass run-time arguments. Two typical use-cases for this are provided below:
+
+#### Set the UVM quit count
+
+All error signaling and handling is routed through the standard UVM report server for all OpenHW testbenches. By default the UVM is configured
+to allow up to 5 errors to be signaled before aborting the test. There is a run-time plusarg to configure this that should work for all
+tests. Use the USER_RUN_FLAGS make variable with the standard UVM_MAX_QUIT_COUNT plusarg as below. Please note that the NO is required
+and signals that you want UVM to use your plusarg over any internally configured quit count values.
+
+**make test TEST=hello-world USER_RUN_FLAGS=+UVM_MAX_QUIT_COUNT=10,NO**
+
+#### UVM verbosity control
+
+The following will increase the verbosity level to DEBUG.
+
+**make test TEST=hello-world USER_RUN_FLAGS=+UVM_VERBOSITY=UVM_DEBUG**
+
+### Post-process Waveform Debug
+
+There are flags and targets defined to support generating waveforms during simulation and viewing those waveforms in a post-process debug tool specific to the respective simulator used.
+
+To create waves during simulation, set the **WAVES=YES** flag.
+
+The waveform dump will include all signals in the uvmt_tb32 testbench and recursively throughout the hierarchy.
+
+**make test TEST=hello-world WAVES=1**
+
+If applicable for a simulator, dumping waves for an advanced debug tool is available.
+
+**make hello-world WAVES=1 ADV_DEBUG=1**
+
+To invoke the debug tool itself use the **make waves** target. Note that the test must be provided. Additionally the advanced debug tool flag must match the setting used during waveform generation.
+
+Invoke debug tool on hello-world test using the standard debug tool.
+
+**make waves TEST=hello-world**
+
+Invoke debug tool on hello-world test using the advanced debug tool.
+
+**make waves TEST=hello-world ADV_DEBUG=1**
+
+### Coverage
+
+The makefile supports the generation of coverage databases during simulation and invoking simulator-specific coverage reporting and browsing tools.
+
+By default coverage information is not generated during a simulation for xrun, questa, and vcs. Therefore a flag was added to the makefiles to enable generation of a coverage database during simulation. The coverage database will include line, expression, toggle, functional and assertion coverage in the generated database.
+
+To generate coverage database, set **COV=1**.
+
+**make test TEST=hello-world COV=1**
+
+To view coverage results a new target **cov** was added to the makefiles. By default the target will generate a coverage report in the same directory as the output log files and the coverage database.
+
+The user can invoke the GUI coverage browsing tool specific to the simulator by setting **GUI=1** on the **make cov** command line.
+
+Generate coverage report for the hello-world test
+
+**make cov TEST=hello-world**
+
+Invoke GUI coverage browser for the hello-world test:
+
+**make cov TEST=hello-world GUI=1**
+
+An additional option to the **make cov** target exists to merge coverage. To merge coverage the makefiles will look in **all** existing test results directories for the selected simulator and configuration, and generate a merged coverage report in <simulator>_results/<cfg>/merged_cov. The respective coverage report of GUI invocation will use that directory as the coverage database. Coverage merging is selected by setting the MERGE=1 flag.
+
+Generate coverage report for all executed tests with coverage databases.
+
+**make cov MERGE=1**
+
+Invoke GUI coverage browser for all executed tests with coverage databases.
+
+**make cov MERGE=1 GUI=1**
+
diff --git a/mk/TOOLCHAIN.md b/mk/TOOLCHAIN.md
new file mode 100644
index 0000000..5f080ab
--- /dev/null
+++ b/mk/TOOLCHAIN.md
@@ -0,0 +1,164 @@
+## Toolchain Installation Instructions
+
+The following are instructions for obtaining and installing a toolchain on your system.
+Please refer to the [README](./README.md) in this directory for instructions on setting up the core-v-verif to use your Toolchain.
+[Toolchain Parameters Example](#toolchain-parameters-example), below, provides an explainer on how to select from multiple toolchain parameters on a per-test-program basis.
+
+### CORE-V Toolchain
+The recommended toolchain for all CORE-V cores is available from Embecosm
+[here](https://www.embecosm.com/resources/tool-chain-downloads/#corev).
+It is recommended that you install this at `/opt/corev`.
+As detailed in [README](./README.md#required-corev-environment-variables), you will need to define a shell variable to point to it:
+```
+$ export CV_SW_TOOLCHAIN="/opt/riscv"
+```
+
+### RISC-V Toolchain
+For many CORE-V cores, the standard RISC-V toolchain will work. You can obtain pre-built version for various platforms from Embecosm
+[here](https://www.embecosm.com/resources/tool-chain-downloads/#riscv).
+It is recommended that you install this at `/opt/riscv` and define a shell variable to point to it:
+```
+$ export CV_SW_TOOLCHAIN="/opt/riscv"
+```
+
+### LLVM Toolchain
+The core-v-verif testbench also supports usage of an LLVM/Clang toolchain.
+An LLVM toolchain with RISCV32 support built for various Linux binary platforms is available [here](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable).
+
+All tests and regressions for the CV32E40X and CV32E40S should be buildable and runnable with LLVM/Clang.
+
+To use LLVM it is recommended that you install it at `/opt/llvm` and define a shell variable to point to it:
+```
+$ export CV_SW_TOOLCHAIN="/opt/llvm"
+```
+
+#### Known caveats with LLVM
+* When using a non-standard extension, the test should set the cflag `-menable-experimental-extensions`
+* The clang integrated assembler cannot properly convert conditional branches to jump sequences when the branch distance is too large
+(i.e. beyond +-2KB). Set the cflag `-fno-integrated-as` to use a GNU system assembler with this ability.
+
+### PULP Toolchain
+If you are using the PULP instruction extensions, you will need access to the PULP toolchain. **Note** that this toolchain is
+out-of-date and cannot compile all test-programs for the CV32E40P, so it is recommended to use the COREV toolchain by
+default and the PULP toolchain as needed. The see the comment header in `Common.mk` (in this directory) to
+see how to set this up.
+
+#### Pre-built PULP Toolchain
+The PULP toolchain for CV32E40P is available [here](https://www.embecosm.com/resources/tool-chain-downloads/#pulp).
+It is recommended that you install this at /opt/pulp.
+
+#### Building the PULP Toolchain from source
+What follows is a set of commands that can be used to install the Toolchain from the PULP-Platform team.
+If you use these commands verbatim you should not encounter any issues. If you do, please open an issue and assign it to @MikeOpenHWGroup.
+
+The process takes about two hours
+
+Please note that the OpenHW Group expects to update the recommended Toolchain in the near future.
+```
+# Create directory for the toolchain
+$ sudo mkdir /opt/pulp
+# Create shell ENV variables to point to it (put this in .bashrc)
+$ PATH="/opt/pulp/bin:$PATH"
+$ export PULP="YES"
+# Get prerequists
+$ sudo apt-get update
+$ sudo apt-get install autoconf automake autotools-dev curl libmpc-dev \
+ libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf \
+ libtool patchutils bc zlib1g-dev
+# Clone the toolchain repo (assumes you are placing the cloned code in
+# ~GitHubRepos/pulp-platform/pulp-riscv-gnu-toolchain/master).
+$ cd ~GitHubRepos/pulp-platform/pulp-riscv-gnu-toolchain
+$ git clone --recursive \
+ https://github.com/pulp-platform/pulp-riscv-gnu-toolchain \
+ master
+$ cd master
+# Build the toolchain
+$ ./configure --prefix=/opt/pulp --with-arch=rv32imc \
+ --with-cmodel=medlow --enable-multilib
+$ sudo make
+# Wait about 2 hours (seriously, it takes that long)
+```
+
+## Test-Program Definitions
+
+Events such as generating a test-program, compiling the test-program
+and compiling/simulating the SystemVerilog testbench are all controlled by
+a the set of environment variables described in the [README](./README.md), plus
+a set of YAML files collectively known as the _test-program definitions_.
+
+The YAML files allow for fine-grained control of the
+[required](./README.md#required-corev-environment-variables) and
+[optional](./README.md#optional-corev-environment-variables) CORE-V-VERIF environment variables,
+plus a host of other variables such as SystemVerilog "plusargs".
+Each test-program will have its own test-program defintion, _test.yaml_,
+which resides in the same directory as the test-program sources,
+plus a configuration-level test-program defintion that resides in `tests/cfg`.
+If a configuration-level test-program defintion is not specfied then _default.yaml_ is used.
+
+The following describes how this works in core-v-verif.
+
+In core-v-verif each test-program has its own directory and the test-program defintion, _test.yaml_ is required to exist in that directory.
+This test-program defintion contains variables used by the software toolchain and SystemVerilog simulator.
+For an example see:
+`$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/programs/custom/hello-world/test.yaml`
+
+
+The test-program defintion can overload the defintion of the CV_SW_TOOLCHAIN and CV_SW_PREXFIX, if required.
+For example:
+```
+cv_sw_toolchain: /opt/llvm
+cv_sw_prefix: riscv-openhw-elf-
+```
+
+Similarily, each pseudo-random (corev-dv) test-program is required to have two YAML files:
+1. _corev-dv.yaml_ is the test-program defintion for the corev-dv instruction generator.
+2. _test.yaml_ is the test-program defintion for the toolchain and SystemVerilog simulator. This test.yaml serves the same function as for manually written test-programs.
+
+For examples see:
+`$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/programs/corev-dv/corev_rand_arithmetic_base_test/corev-dv.yaml` and
+`$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/programs/corev-dv/corev_rand_arithmetic_base_test/test.yaml`.
+
+The script [YAML2MAKE](../bin/yaml2make) will parse test.yaml and create a set of Makefile variables that are used by the Makefile to:
+* Compile the test-program.
+* Compile UVM environment.
+* Pass run-time arguments to the SystemVerilog simulator.
+These variables all have a "TEST\_" prefix.
+
+Similarily, [YAML2MAKE](../bin/yaml2make) also parses corev-dv.yaml and create a set of
+variables that are used by the corev-dv to pass run-time arguments to the
+SystemVerilog simulator, typically as plusargs to control how corev-dv
+generates the pseudo-random test-program. These variables all have a "GEN\_"
+prefix. NOTE: defining toolchain parameters in corev-dv is not required
+as the Makefile does not use variables prefixed with "GEN\_" to access or control the toolchain.
+
+Lastly, if the "CFG" variable is set, [CFGYAML2MAKE](../bin/cfgyaml2make) parses a specific YAML file in `$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/cfg`.
+The variables generated by this script all have a "CFG\_" prefix.
+The "CFG" variable must be set to the filename (no extension) of a yaml file in the cfg directory.
+Note that "CFG" can be a shell environment variable or passed to "make" on the comand line:
+ make test TEST=my_test_program CFG=my_cfg
+
+Note: if "CFG" is not defined, then `$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/cfg/default.yaml` is used.
+
+The common Makefile, ([Common.mk](./Common.mk)), will launch the yaml2make and cfgyaml2make scripts to generate the TEST\*, GEN\* and CFG\* variables.
+These are then used to set the appropriate parameters for generating the test-program, compiling the test-program, compiling and simulating the SystemVerilog testbench.
+
+### Toolchain Parameter Example
+
+Let's take, as an example, setting of the `march` argument for gcc.
+This is determined by the value of CV_SW_MARCH.
+This could be determined by defining a shell environment variable CV_SW_MARCH, as discussed at the top of this document.
+If the test-program definition and default configuration definitions do not define this variable, then the value of `march` used is determined by the shell variable.
+However, if _either_ the test-program definition or default configuration definition set this variable, that will override the environment variable.
+Suppose the default configuration test-program defintion,`$(CORE_V_VERIF)/$(CORE_V_CORE)/tests/cfg/default.yaml`, contains the following line:
+```
+cv_sw_march: rv32imc_zba1p00_zbb1p00_zbc1p00_zbs1p00
+```
+This would set CV_SW_MARCH for all tests that use cfg/default.yaml.
+The priority order for controlling variables is ENV > TEST > CFG.
+
+### Non-defaults
+
+Recall that the toolchain selection variables, CV_SW_TOOLCHAIN and CV_SW_PREFIX are not optional.
+These shell environment variables must be set, or the Makefiles will fatal-out and terminate execution immediately.
+Due to the priority ordering of toolchain selection variables discussed above,
+this means that the value of CV_SW_TOOLCHAIN and CV_SW_PREFIX cannot be set in either the test-program definition or the default configuration definition.
diff --git a/mk/core/core.mk b/mk/core/core.mk
new file mode 100644
index 0000000..48d6267
--- /dev/null
+++ b/mk/core/core.mk
@@ -0,0 +1,242 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Makefile for the CORE testbench for multiple OpenHW-verified cores.
+#
+###############################################################################
+
+# Variable checks
+ifndef CV_CORE
+$(error Must set CV_CORE to a valid core)
+endif
+
+# "Constants"
+DATE = $(shell date +%F)
+CV_CORE_LC = $(shell echo $(CV_CORE) | tr A-Z a-z)
+CV_CORE_UC = $(shell echo $(CV_CORE) | tr a-z A-Z)
+export CV_CORE_LC
+export CV_CORE_UC
+.DEFAULT_GOAL := no_rule
+
+# Useful commands
+MKDIR_P = mkdir -p
+
+# Compile compile flags for all simulators (careful!)
+WAVES ?= 0
+SV_CMP_FLAGS ?= "+define+$(CV_CORE_UC)_ASSERT_ON"
+TIMESCALE ?= -timescale 1ns/1ps
+UVM_PLUSARGS ?=
+
+# User selectable SystemVerilog simulator targets/rules
+CV_SIMULATOR ?= unsim
+SIMULATOR ?= $(CV_SIMULATOR)
+
+# Optionally exclude the OVPsim (not recommended)
+USE_ISS ?= YES
+
+# Common configuration variables
+CFG ?= default
+
+# Common Generation variables
+GEN_START_INDEX ?= 0
+GEN_NUM_TESTS ?= 1
+
+# Commont test variables
+RUN_INDEX ?= 0
+
+# UVM Environment
+export DV_UVMT_PATH = $(CORE_V_VERIF)/$(CV_CORE_LC)/tb/uvmt
+export DV_UVME_PATH = $(CORE_V_VERIF)/$(CV_CORE_LC)/env/uvme
+export DV_UVML_HRTBT_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_hrtbt
+export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov
+export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst
+export DV_UVMA_INTERRUPT_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_interrupt
+export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug
+export DV_UVML_TRN_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_trn
+export DV_UVML_LOGS_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_logs
+export DV_UVML_SB_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_sb
+
+export DV_OVPM_HOME = $(CORE_V_VERIF)/vendor_lib/imperas
+export DV_OVPM_MODEL = $(DV_OVPM_HOME)/imperas_DV_COREV
+export DV_OVPM_DESIGN = $(DV_OVPM_HOME)/design
+
+DV_UVMT_SRCS = $(wildcard $(DV_UVMT_PATH)/*.sv))
+
+# Testcase name: must be the CLASS name of the testcase (not the filename).
+# Look in ../../tests/uvmt
+UVM_TESTNAME ?= uvmt_$(CV_CORE_LC)_firmware_test_c
+
+# Google's random instruction generator
+RISCVDV_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/google/riscv-dv
+COREVDV_PKG := $(CORE_V_VERIF)/lib/corev-dv
+CV_CORE_COREVDV_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/env/corev-dv
+export RISCV_DV_ROOT = $(RISCVDV_PKG)
+export COREV_DV_ROOT = $(COREVDV_PKG)
+export CV_CORE_COREV_DV_ROOT = $(CV_CORE_COREVDV_PKG)
+
+# RISC-V Foundation's RISC-V Compliance Test-suite
+COMPLIANCE_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance
+
+# TB source files for the CV32E core
+TBSRC_TOP := $(TBSRC_HOME)/uvmt/uvmt_$(CV_CORE_LC)_tb.sv
+TBSRC_HOME := $(CORE_V_VERIF)/$(CV_CORE_LC)/tb
+export TBSRC_HOME = $(CORE_V_VERIF)/$(CV_CORE_LC)/tb
+
+SIM_LIBS := $(CORE_V_VERIF)/lib/sim_libs
+
+RTLSRC_VLOG_TB_TOP := $(basename $(notdir $(TBSRC_TOP)))
+RTLSRC_VOPT_TB_TOP := $(addsuffix _vopt, $(RTLSRC_VLOG_TB_TOP))
+
+# RTL source files for the CV32E core
+# DESIGN_RTL_DIR is used by CV32E40P_MANIFEST file
+CV_CORE_PKG := $(CORE_V_VERIF)/core-v-cores/$(CV_CORE_LC)
+CV_CORE_MANIFEST := $(CV_CORE_PKG)/$(CV_CORE_LC)_manifest.flist
+export DESIGN_RTL_DIR = $(CV_CORE_PKG)/rtl
+
+RTLSRC_HOME := $(CV_CORE_PKG)/rtl
+RTLSRC_INCDIR := $(RTLSRC_HOME)/include
+
+###############################################################################
+# Seed management for constrained-random sims
+SEED ?= 1
+RNDSEED ?=
+
+ifeq ($(SEED),random)
+RNDSEED = $(shell date +%N)
+else
+ifeq ($(SEED),)
+# Empty SEED variable selects 1
+RNDSEED = 1
+else
+RNDSEED = $(SEED)
+endif
+endif
+
+###############################################################################
+# Common Makefile:
+# - Core Firmware and the RISCV GCC Toolchain (SDK)
+# - Variables for RTL dependencies
+include $(CORE_V_VERIF)/mk/Common.mk
+###############################################################################
+# Clone core RTL and DV dependencies
+clone_cv_core_rtl:
+ $(CLONE_CV_CORE_CMD)
+
+clone_riscv-dv:
+ $(CLONE_RISCVDV_CMD)
+
+$(CV_CORE_PKG):
+ echo "Cloning"
+ $(CLONE_CV_CORE_CMD)
+
+$(COMPLIANCE_PKG):
+ $(CLONE_COMPLIANCE_CMD)
+
+###############################################################################
+# RISC-V Compliance Test-suite
+# As much as possible, the test suite is used "out-of-the-box". The
+# "build_compliance" target below uses the Makefile supplied by the suite
+# to compile all the individual test-programs in the suite to generate the
+# elf and hex files used in simulation. Each .mk is assumed to have a
+# target to run the compiled test-program.
+
+# RISCV_ISA='rv32i|rv32im|rv32imc|rv32Zicsr|rv32Zifencei'
+RISCV_ISA ?= rv32i
+RISCV_TARGET ?= OpenHW
+RISCV_DEVICE ?= $(CV_CORE_LC)
+
+clone_compliance:
+ $(CLONE_COMPLIANCE_CMD)
+
+clr_compliance:
+ make clean -C $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance
+
+build_compliance: $(COMPLIANCE_PKG)
+ make simulate -i -C $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance \
+ RISCV_TARGET=${RISCV_TARGET} \
+ RISCV_DEVICE=${RISCV_DEVICE} \
+ PATH=$(RISCV)/bin:$(PATH) \
+ RISCV_PREFIX=$(RISCV_PREFIX) \
+ NOTRAPS=1 \
+ RISCV_ISA=$(RISCV_ISA)
+# VERBOSE=1
+
+all_compliance: $(COMPLIANCE_PKG)
+ make build_compliance RISCV_ISA=rv32i && \
+ make build_compliance RISCV_ISA=rv32im && \
+ make build_compliance RISCV_ISA=rv32imc && \
+ make build_compliance RISCV_ISA=rv32Zicsr && \
+ make build_compliance RISCV_ISA=rv32Zifencei
+
+# "compliance" is a simulator-specific target defined in .mk
+
+compliance_check_sig: compliance
+ @echo "Checking Compliance Signature for $(RISCV_ISA)/$(COMPLIANCE_PROG)"
+ @echo "Reference: $(REF)"
+ @echo "Signature: $(SIG)"
+ @export SUITEDIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance/riscv-test-suite/$(RISCV_ISA) && \
+ export REF=$(REF) && export SIG=$(SIG) && export COMPL_PROG=$(COMPLIANCE_PROG) && \
+ export RISCV_TARGET=${RISCV_TARGET} && export RISCV_DEVICE=${RISCV_DEVICE} && \
+ export RISCV_ISA=${RISCV_ISA} export SIG_ROOT=${SIG_ROOT} && \
+ $(CORE_V_VERIF)/bin/diff_signatures.sh | tee $(SIMULATOR)_results/$(COMPLIANCE_PROG)/diff_signatures.log
+
+compliance_check_all_sigs:
+ @$(MKDIR_P) $(SIMULATOR)_results/$(RISCV_ISA)
+ @echo "Checking Compliance Signature for all tests in $(RISCV_ISA)"
+ @export SUITEDIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance/riscv-test-suite/$(RISCV_ISA) && \
+ export RISCV_TARGET=${RISCV_TARGET} && export RISCV_DEVICE=${RISCV_DEVICE} && \
+ export RISCV_ISA=${RISCV_ISA} export SIG_ROOT=${SIG_ROOT} && \
+ $(CORE_V_VERIF)/bin/diff_signatures.sh $(RISCV_ISA) | tee $(SIMULATOR)_results/$(RISCV_ISA)/diff_signatures.log
+
+# export REF=$(REF) && export SIG=$(SIG) && export COMPL_PROG=$(COMPLIANCE_PROG) && \
+
+compliance_regression:
+ make build_compliance RISCV_ISA=$(RISCV_ISA)
+ @export SIM_DIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/sim/uvmt && \
+ $(CORE_V_VERIF)/bin/run_compliance.sh $(RISCV_ISA)
+ make compliance_check_all_sigs RISCV_ISA=$(RISCV_ISA)
+
+dah:
+ @export SIM_DIR=$(CORE_V_VERIF)/cv32/sim/uvmt && \
+ $(CORE_V_VERIF)/bin/run_compliance.sh $(RISCV_ISA)
+
+###############################################################################
+# Clean up your mess!
+# 1. Clean all generated files of the C and assembler tests
+# 2. Simulator-specific clean targets are in ./.mk
+# 3. clean-bsp target is specified in ../Common.mk
+clean_test_programs: clean-bsp
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.o -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.hex -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.elf -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.map -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.readelf -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/uvmt/test-programs -name *.objdump -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.o -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.hex -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.elf -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.map -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.itb -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.readelf -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name *.objdump -exec rm {} \;
+ find $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs -name corev_*.S -exec rm {} \;
+
+clean_compliance:
+ rm -rf $(COMPLIANCE_PKG)
diff --git a/mk/toolchain_check.sh b/mk/toolchain_check.sh
new file mode 100755
index 0000000..a7af0d9
--- /dev/null
+++ b/mk/toolchain_check.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+###############################################################################
+#
+# Copyright 2021 OpenHW Group
+# Copyright 2021 Silicon Labs, Inc.
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Helper bash script to determine when multiple build toolchains are configured
+# to diagnose toolchain test configuration issues with the COREV verification
+# testbench environment
+#
+###############################################################################
+
+GNU_YES=$1
+PULP_YES=$2
+COREV_YES=$3
+LLVM_YES=$4
+
+# Logic to return 1 if any two toolchains are enabled
+if [ ${GNU_YES} = "YES" -a ${PULP_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+if [ ${GNU_YES} = "YES" -a ${COREV_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+if [ ${GNU_YES} = "YES" -a ${LLVM_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+if [ ${PULP_YES} = "YES" -a ${COREV_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+if [ ${PULP_YES} = "YES" -a ${LLVM_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+if [ ${COREV_YES} = "YES" -a ${LLVM_YES} = "YES" ]; then
+ echo "1"
+ exit 0
+fi
+
+echo "0"
+
diff --git a/mk/uvmt/README.md b/mk/uvmt/README.md
new file mode 100644
index 0000000..12a0d41
--- /dev/null
+++ b/mk/uvmt/README.md
@@ -0,0 +1,5 @@
+Tool-specific Makefiles for the CORE-V-VERIF UVM Verification Environment
+==================================
+This directory contains a set of simulator-specific Makefiles.
+The Makefile selected is controlled by the `CV_SIMULATOR` shell environment variable.
+For more information see Makefiles in [../README](../README.md#makefiles).
diff --git a/mk/uvmt/dsim.mk b/mk/uvmt/dsim.mk
new file mode 100644
index 0000000..4eb219d
--- /dev/null
+++ b/mk/uvmt/dsim.mk
@@ -0,0 +1,383 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# DSIM-specific Makefile.
+# DSIM is the Metrics Technologies SystemVerilog simulator (https://metrics.ca/)
+#
+###############################################################################
+
+DSIM = dsim
+DSIM_HOME ?= /tools/Metrics/dsim
+DSIM_CMP_FLAGS ?= $(TIMESCALE) $(SV_CMP_FLAGS) -top uvmt_$(CV_CORE_LC)_tb
+DSIM_ERR_SUPPRESS ?= MultiBlockWrite:ReadingOutputModport:IneffectiveDynamicCast:IndexOOB:PortWidthMismatch:UninstVif:LatchInferred:AlwaysFFNba
+DSIM_UVM_ARGS ?= +incdir+$(UVM_HOME)/src $(UVM_HOME)/src/uvm_pkg.sv
+DSIM_WORK ?= $(SIM_CFG_RESULTS)/dsim_work
+DSIM_IMAGE ?= dsim.out
+DSIM_RUN_FLAGS ?=
+DSIM_CODE_COV_SCOPE ?= $(MAKE_PATH)/../tools/dsim/ccov_scopes.txt
+#DSIM_USE_ISS ?= YES
+
+DSIM_FILE_LIST ?= -f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist
+DSIM_COMPILE_ARGS += +define+$(CV_CORE_UC)_TRACE_EXECUTION+RVFI
+DSIM_USER_COMPILE_ARGS ?=
+
+#################################
+# Reference Model selection start
+ifeq ($(USE_ISS),YES)
+ DSIM_RUN_FLAGS += +USE_ISS
+else
+ DSIM_RUN_FLAGS += +DISABLE_OVPSIM
+endif
+
+ifeq ($(call IS_YES,$(SPIKE)),YES)
+ DSIM_RUN_FLAGS += +SPIKE
+endif
+
+ifeq ($(call IS_YES,$(IMPERAS)),YES)
+ DSIM_RUN_FLAGS += +IMPERAS
+endif
+
+ifeq ($(call IS_YES,$(BOTH)),YES)
+ DSIM_RUN_FLAGS += +BOTH
+endif
+# Reference Model selection end
+#################################
+
+ifeq ($(call IS_YES,$(TEST_DISABLE_ALL_CSR_CHECKS)),YES)
+ DSIM_RUN_FLAGS +="+DISABLE_ALL_CSR_CHECKS"
+endif
+ifneq ($(TEST_DISABLE_CSR_CHECK),)
+ DSIM_RUN_FLAGS += +DISABLE_CSR_CHECK=$(TEST_DISABLE_CSR_CHECK)
+endif
+
+DSIM_PMA_INC += +incdir+$(TBSRC_HOME)/uvmt \
+ +incdir+$(CV_CORE_PKG)/rtl/include \
+ +incdir+$(CV_CORE_COREVDV_PKG)/ldgen \
+ +incdir+$(abspath $(MAKE_PATH)/../../../lib/mem_region_gen)
+
+# Seed management for constrained-random sims. This is an intentional repeat
+# of the root Makefile: dsim regressions use random seeds by default.
+DSIM_SEED ?= random
+DSIM_RNDSEED ?=
+
+ifeq ($(DSIM_SEED),random)
+DSIM_RNDSEED = $(shell date +%N)
+else
+ifeq ($(DSIM_SEED),)
+# Empty DSIM_SEED variable selects a random value
+DSIM_RNDSEED = 1
+else
+DSIM_RNDSEED = $(DSIM_SEED)
+endif
+endif
+
+DSIM_RUN_FLAGS += $(USER_RUN_FLAGS)
+DSIM_RUN_FLAGS += -sv_seed $(DSIM_RNDSEED)
+
+# Enable profiling (off by default)
+PROFILE ?= 0
+ifneq ($(PROFILE), 0)
+ DSIM_CMP_FLAGS += -gen-profile
+ DSIM_RUN_FLAGS += -profile $(PROFILE)
+endif
+
+# Variables to control wave dumping from command the line
+# Humans _always_ forget the "S", so you can have it both ways...
+WAVES ?= 0
+WAVE ?= 0
+DUMP_WAVES := 0
+# Code Coverage collected by default
+CCOV ?= 1
+
+ifneq ($(WAVES), 0)
+DUMP_WAVES = 1
+endif
+
+ifneq ($(WAVE), 0)
+DUMP_WAVES = 1
+endif
+
+ifneq ($(DUMP_WAVES), 0)
+DSIM_ACC_FLAGS ?= +acc
+DSIM_DMP_FILE ?= dsim.vcd
+DSIM_DMP_FLAGS ?= -waves $(DSIM_DMP_FILE)
+endif
+
+ifneq ($(CCOV), 0)
+ DSIM_COMPILE_ARGS += -code-cov block -code-cov-scope-specs $(DSIM_CODE_COV_SCOPE)
+ DSIM_RUN_FLAGS += -code-cov block -code-cov-scope-specs $(DSIM_CODE_COV_SCOPE)
+endif
+
+# Special var to point to tool and installation dependent path of DPI headers.
+# Used to recompile dpi_dasm_spike if needed (by default, not needed).
+DPI_INCLUDE ?= $(shell dirname $(shell which dsim))/../include
+
+no_rule:
+ @echo 'makefile: SIMULATOR is set to $(SIMULATOR), but no rule/target specified.'
+ @echo 'try "make SIMULATOR=dsim sanity" (or just "make sanity" if shell ENV variable SIMULATOR is already set).'
+# @echo 'DUMP_WAVES=$(DUMP_WAVES) DSIM_ACC_FLAGS=$(DSIM_ACC_FLAGS) DSIM_DMP_FLAGS=$(DSIM_DMP_FLAGS)'
+
+all: clean_all hello-world
+
+# This special target is to support the special sanity target in the Common Makefile
+hello-world:
+ $(MAKE) test TEST=hello-world
+
+help:
+ dsim -help
+
+mk_results:
+ $(MKDIR_P) $(SIM_CFG_RESULTS)
+ $(MKDIR_P) $(DSIM_WORK)
+
+################################################################################
+# DSIM compile target
+comp: mk_results clone_cv_core_rtl $(SVLIB_PKG) $(CV_VERIF_PKG) rvvi_stub
+ @echo "$(BANNER)"
+ @echo "Compiling with DSim..."
+ @echo "$(BANNER)"
+ $(DSIM) \
+ $(DSIM_CMP_FLAGS) \
+ -suppress $(DSIM_ERR_SUPPRESS) \
+ $(DSIM_UVM_ARGS) \
+ $(DSIM_ACC_FLAGS) \
+ $(CFG_COMPILE_FLAGS) \
+ $(DSIM_COMPILE_ARGS) \
+ $(DSIM_USER_COMPILE_ARGS) \
+ +incdir+$(DV_UVME_PATH) \
+ +incdir+$(DV_UVMT_PATH) \
+ +incdir+$(DPI_DASM_PKG) \
+ -f $(CV_CORE_MANIFEST) \
+ $(DSIM_FILE_LIST) \
+ -work $(DSIM_WORK) \
+ +$(UVM_PLUSARGS) \
+ -genimage $(DSIM_IMAGE)
+
+
+################################################################################
+# General test execution target "test"
+#
+
+################################################################################
+# If the configuration specified OVPSIM arguments, generate an ovpsim.ic file and
+# set IMPERAS_TOOLS to point to it
+gen_ovpsim_ic:
+ @rm -f $(SIM_RUN_RESULTS)/ovpsim.ic
+ @mkdir -p $(SIM_RUN_RESULTS)
+ @touch $(SIM_RUN_RESULTS)/ovpsim.ic
+ @if [ ! -z "$(CFG_OVPSIM)" ]; then \
+ echo "$(CFG_OVPSIM)" > $(SIM_RUN_RESULTS)/ovpsim.ic; \
+ fi
+export IMPERAS_TOOLS=$(SIM_RUN_RESULTS)/ovpsim.ic
+
+# Skip compile if COMP is specified and negative
+ifneq ($(call IS_NO,$(COMP)),NO)
+DSIM_SIM_PREREQ = comp
+endif
+
+test: $(DSIM_SIM_PREREQ) hex gen_ovpsim_ic
+ @echo "$(BANNER)"
+ @echo "Simulating with DSim..."
+ @echo "$(BANNER)"
+ mkdir -p $(SIM_RUN_RESULTS) && \
+ cd $(SIM_RUN_RESULTS) && \
+ $(DSIM) \
+ -l dsim-$(TEST_NAME).log \
+ -image $(DSIM_IMAGE) \
+ -work $(DSIM_WORK) \
+ $(DSIM_RUN_FLAGS) \
+ $(DSIM_DMP_FLAGS) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ -sv_lib $(DPI_DASM_LIB) \
+ -sv_lib $(abspath $(SVLIB_LIB)) \
+ -sv_lib $(OVP_MODEL_DPI) \
+ -sv_lib $(RVVI_STUB_LIB) \
+ +UVM_TESTNAME=$(TEST_UVM_TEST) \
+ +firmware=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex \
+ +elf_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).elf \
+ +itb_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).itb
+
+# Similar to above, but for the ASM directory.
+asm: comp $(ASM_DIR)/$(ASM_PROG).hex $(ASM_DIR)/$(ASM_PROG).elf
+ mkdir -p $(SIM_RESULTS)/$(CFG)/$(ASM_PROG)_$(RUN_INDEX) && cd $(SIM_RESULTS)/$(CFG)/$(ASM_PROG)_$(RUN_INDEX) && \
+ $(DSIM) -l dsim-$(ASM_PROG).log -image $(DSIM_IMAGE) \
+ -work $(DSIM_WORK) $(DSIM_RUN_FLAGS) $(DSIM_DMP_FLAGS) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ -sv_lib $(DPI_DASM_LIB) \
+ -sv_lib $(OVP_MODEL_DPI) \
+ +UVM_TESTNAME=$(UVM_TESTNAME) \
+ +firmware=$(ASM_DIR)/$(ASM_PROG).hex \
+ +elf_file=$(ASM_DIR)/$(ASM_PROG).elf
+
+###############################################################################
+# Run a single test-program from the RISC-V Compliance Test-suite. The parent
+# Makefile of this .mk implements "all_compliance", the target that
+# compiles the test-programs.
+#
+# There is a dependancy between RISCV_ISA and COMPLIANCE_PROG which *you* are
+# required to know. For example, the I-ADD-01 test-program is part of the rv32i
+# testsuite.
+# So this works:
+# make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+# But this does not:
+# make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+#
+RISCV_ISA ?= rv32i
+COMPLIANCE_PROG ?= I-ADD-01
+
+SIG_ROOT ?= $(SIM_RESULTS)/$(CFG)/$(RISCV_ISA)
+SIG ?= $(SIM_RESULTS)/$(CFG)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)/$(COMPLIANCE_PROG).signature_output
+REF ?= $(COMPLIANCE_PKG)/riscv-test-suite/$(RISCV_ISA)/references/$(COMPLIANCE_PROG).reference_output
+TEST_PLUSARGS ?= +signature=$(COMPLIANCE_PROG).signature_output
+
+compliance: comp build_compliance
+ mkdir -p $(SIM_RESULTS)/$(CFG)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)
+ cd $(SIM_RESULTS)/$(CFG)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX) && \
+ export IMPERAS_TOOLS=$(CORE_V_VERIF)/$(CV_CORE_LC)/tests/cfg/ovpsim_no_pulp.ic && \
+ $(DSIM) -l dsim-$(COMPLIANCE_PROG).log -image $(DSIM_IMAGE) \
+ -work $(DSIM_WORK) $(DSIM_RUN_FLAGS) $(DSIM_DMP_FLAGS) $(TEST_PLUSARGS) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ -sv_lib $(DPI_DASM_LIB) \
+ -sv_lib $(OVP_MODEL_DPI) \
+ +UVM_TESTNAME=$(UVM_TESTNAME) \
+ +firmware=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).hex \
+ +elf_file=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).elf
+
+################################################################################
+# Commonly used targets:
+# Here for historical reasons - mostly (completely?) superceeded by the
+# custom target.
+#
+
+# Mythical no-test-program testcase. Might never be used. Not known tow work
+no-test-program: comp
+ mkdir -p $(SIM_RESULTS)/$(CFG)/hello-world_$(RUN_INDEX) && cd $(SIM_RESULTS)/$(CFG)/hello-world_$(RUN_INDEX) && \
+ $(DSIM) -l dsim-$(UVM_TESTNAME).log -image $(DSIM_IMAGE) \
+ -work $(DSIM_WORK) $(DSIM_RUN_FLAGS) $(DSIM_DMP_FLAGS) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ -sv_lib $(DPI_DASM_LIB) \
+ -sv_lib $(OVP_MODEL_DPI) \
+ +UVM_TESTNAME=$(UVM_TESTNAME)
+
+################################################################################
+# DSIM UNIT TESTS: run each test individually.
+# Example: to run the ADDI test `make dsim-unit-test addi`
+# DO NOT INVOKE rule "dsim-firmware-unit-test" directly. It is a support
+# rule for rule "dsim-unit-test" (in included ../Firmware.mk).
+dsim-firmware-unit-test: comp
+ mkdir -p $(SIM_RESULTS)/firmware_$(RUN_INDEX) && cd $(SIM_RESULTS)/firmware_$(RUN_INDEX) && \
+ $(DSIM) -l dsim-$(UNIT_TEST).log -image $(DSIM_IMAGE) \
+ -work $(DSIM_WORK) $(DSIM_RUN_FLAGS) $(DSIM_DMP_FLAGS) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ -sv_lib $(DPI_DASM_LIB) \
+ -sv_lib $(OVP_MODEL_DPI) \
+ +UVM_TESTNAME=uvmt_$(CV_CORE_LC)_firmware_test_c \
+ +firmware=$(FIRMWARE)/firmware_unit_test.hex \
+ +elf_file=$(FIRMWARE)/firmware_unit_test.elf
+
+# Aliases for 'dsim-unit-test' (defined in ../Common.mk)
+.PHONY: unit-test
+unit-test: dsim-unit-test
+
+###############################################################################
+# Use Google instruction stream generator (RISCV-DV) to create new test-programs
+#riscv-dv: clone_riscv-dv
+comp_corev-dv: $(CV_CORE_PKG)
+ mkdir -p $(SIM_COREVDV_RESULTS)
+ dsim -sv \
+ -work $(SIM_COREVDV_RESULTS)/dsim \
+ -genimage image \
+ +incdir+$(UVM_HOME)/src \
+ $(UVM_HOME)/src/uvm_pkg.sv \
+ +define+DSIM \
+ -top $(CV_CORE_LC)_instr_gen_tb_top \
+ -suppress EnumMustBePositive \
+ -suppress SliceOOB \
+ -f $(CV_CORE_MANIFEST) \
+ +incdir+$(CV_CORE_COREVDV_PKG)/target/$(CV_CORE_LC) \
+ +incdir+$(RISCVDV_PKG)/user_extension \
+ +incdir+$(COREVDV_PKG) \
+ +incdir+$(CV_CORE_COREVDV_PKG) \
+ $(DSIM_PMA_INC) \
+ $(CFG_COMPILE_FLAGS) \
+ -f $(COREVDV_PKG)/manifest.f \
+ -l $(SIM_COREVDV_RESULTS)/compile.log
+
+#riscv-test: riscv-dv
+# +asm_file_name=$(RISCVDV_PKG)/out_2020-06-24/asm_tests/riscv_arithmetic_basic_test \
+
+gen_corev-dv:
+ mkdir -p $(SIM_COREVDV_RESULTS)/$(TEST)
+ # Clean old assembler generated tests in results
+ idx=$(GEN_START_INDEX); sum=$$(($(GEN_START_INDEX) + $(GEN_NUM_TESTS))); \
+ while [ $$idx -lt $${sum} ]; do \
+ mkdir -p $(SIM_CFG_RESULTS)/$(TEST)/$$idx/test_program; \
+ echo "idx = $$idx"; \
+ idx=$$((idx + 1)); \
+ done
+ cd $(SIM_COREVDV_RESULTS)/$(TEST) && \
+ dsim -sv_seed $(DSIM_RNDSEED) \
+ -sv_lib $(UVM_HOME)/src/dpi/libuvm_dpi.so \
+ +acc+rwb \
+ -image image \
+ -work $(SIM_COREVDV_RESULTS)/dsim \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ +start_idx=$(GEN_START_INDEX) \
+ +asm_file_name_opts=$(TEST) \
+ +ldgen_cp_test_path=$(SIM_CFG_RESULTS)/$(TEST) \
+ -l $(TEST)_$(GEN_START_INDEX)_$(GEN_NUM_TESTS).log \
+ $(CFG_PLUSARGS) \
+ $(GEN_PLUSARGS)
+ # Copy out final assembler files to test directory
+ idx=$(GEN_START_INDEX); sum=$$(($(GEN_START_INDEX) + $(GEN_NUM_TESTS))); \
+ while [ $$idx -lt $${sum} ]; do \
+ cp ${BSP}/link_corev-dv.ld ${SIM_TEST_RESULTS}/$$idx/test_program/link.ld; \
+ cp ${SIM_COREVDV_RESULTS}/${TEST}/${TEST}_$$idx.S ${SIM_TEST_RESULTS}/$$idx/test_program; \
+ idx=$$((idx + 1)); \
+ done
+
+corev-dv: clean_riscv-dv \
+ clone_riscv-dv \
+ comp_corev-dv
+
+###############################################################################
+# Clean up your mess!
+
+# Metrics dsim cleanup
+clean:
+ rm -f dsim.log
+ rm -f dsim-*.log
+ rm -f metrics_history.db
+ rm -f metrics.db
+ rm -f metrics.xml
+ rm -f trace_core_00_0.log
+ rm -rf dsim_work
+ rm -f dsim.env
+ rm -f $(DSIM_IMAGE)
+ rm -rf $(SIM_RESULTS)
+
+# All generated files plus the clone of the RTL
+# TODO: fix the 'clean_embench' targets
+clean_all: clean clean_rtl clean_riscv-dv clean_test_programs clean_bsp clean_compliance clean_dpi_dasm_spike clean_svlib clean_rvvi_stub
+ rm -rf $(CV_CORE_PKG)
+
diff --git a/mk/uvmt/dvt.mk b/mk/uvmt/dvt.mk
new file mode 100644
index 0000000..563d62d
--- /dev/null
+++ b/mk/uvmt/dvt.mk
@@ -0,0 +1,67 @@
+###############################################################################
+#
+# Copyright 2020 AMIQ EDA s.r.l.
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Bring up the project inside the AMIQ DVT Eclipse IDE (https://dvteclipse.com/)
+#
+# Usage: make SIMULATOR= open_in_dvt_ide
+###############################################################################
+
+DVT_COMMAND=$(DVT_HOME)/bin/dvt_cli.sh createProject $(CORE_V_VERIF) -force -lang vlog -build default $(DVT_CLI_ARGS)
+
+ifeq ($(SIMULATOR), xrun)
+ DVT_BUILD_FILE_CONTENT="+dvt_init+xcelium.xrun\n$(XRUN_COMP)\n-top $(RTLSRC_VLOG_TB_TOP)"
+else
+ifeq ($(SIMULATOR), vcs)
+ DVT_BUILD_FILE_CONTENT="+dvt_init+vcs.vlogan\n$(VCS_COMP)\n-top $(RTLSRC_VLOG_TB_TOP)"
+else
+ifeq ($(SIMULATOR), vsim)
+ DVT_BUILD_FILE_CONTENT="+dvt_init+questa.vlog\n-work $(VWORK) $(VLOG_FLAGS) +incdir+$(DV_UVME_PATH) +incdir+$(DV_UVMT_PATH) +incdir+$(UVM_HOME) $(UVM_HOME)/uvm_pkg.sv -f $(CV_CORE_MANIFEST) $(VLOG_FILE_LIST) $(TBSRC_PKG) -top $(RTLSRC_VLOG_TB_TOP)"
+else
+ DVT_BUILD_FILE_CONTENT="+dvt_init+dvt\n-uvm\n+define+CV32E40P_ASSERT_ON\n+define+ISS+CV32E40P_TRACE_EXECUTION\n+incdir+$(DV_UVME_PATH)\n+incdir+$(DV_UVMT_PATH)\n-f $(CV_CORE_MANIFEST)\n-f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist\n-f $(DV_UVMT_PATH)/imperas_iss.flist\n-top $(RTLSRC_VLOG_TB_TOP)"
+endif
+endif
+endif
+
+.PHONY: open_in_dvt_ide check_dvt_home create_dvt_build_dir create_dvt_build_file dvt_dump_env_vars
+
+create_dvt_build_dir:
+ @ mkdir -p $(CORE_V_VERIF)/.dvt
+
+create_dvt_build_file: create_dvt_build_dir $(CV_CORE_PKG) $(SVLIB_PKG)
+ @ printf $(DVT_BUILD_FILE_CONTENT) > $(CORE_V_VERIF)/.dvt/default.build
+
+open_in_dvt_ide: check_dvt_home create_dvt_build_file
+ $(DVT_COMMAND)
+
+define NEWLINE
+
+
+endef
+
+ENV_VARS := $(foreach v, $(.VARIABLES), $(if $(filter file,$(origin $(v))), $(if $(filter-out .% NEWLINE%, $(v)), export $(v)='$($(v))' $(NEWLINE) )))
+dvt_dump_env_vars:
+ $(ENV_VARS)
+
+check_dvt_home:
+ifndef DVT_HOME
+ @ echo "DVT_HOME env var is not set!"; \
+ exit 1; \
+endif
+endif
diff --git a/mk/uvmt/riviera.mk b/mk/uvmt/riviera.mk
new file mode 100644
index 0000000..345e9d3
--- /dev/null
+++ b/mk/uvmt/riviera.mk
@@ -0,0 +1,336 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Riviera-PRO-specific Makefile for the Core-V-Verif "uvmt" testbench.
+# Riviera-PRO is the Aldec SystemVerilog simulator.
+#
+###############################################################################
+
+# Executables
+VLIB = vlib
+VMAP = vmap
+VLOG = $(CV_SIM_PREFIX) vlog
+VSIM = $(CV_SIM_PREFIX) vsim
+VWORK = work
+
+# Paths
+VSIM_RESULTS ?= $(if $(CV_RESULTS),$(abspath $(CV_RESULTS))/riviera_results,$(MAKE_PATH)/riviera_results)
+VSIM_COREVDV_RESULTS ?= $(VSIM_RESULTS)/corev-dv
+VSIM_COV_MERGE_DIR ?= $(VSIM_RESULTS)/merged
+UVM_HOME ?= ${ALDEC_PATH}/vlib/uvm-1.2/src/
+USES_DPI = 1
+
+# Default flags
+VLOG_COV ?= -coverage sbecam
+VSIM_USER_FLAGS ?=
+VSIM_COV ?= -acdb -acdb_cov sbfectapm -acdb_file $(VSIM_TEST).acdb
+VSIM_WAVES_ADV_DEBUG ?=
+VSIM_WAVES_DO ?=
+
+# Common QUIET flag defaults to -quiet unless VERBOSE is set
+ifeq ($(call IS_YES,$(VERBOSE)),YES)
+QUIET=
+else
+QUIET=-quiet
+endif
+
+ifeq ($(USES_DPI),1)
+ DPILIB_VLOG_OPT =
+ DPILIB_VSIM_OPT = -sv_lib "$(ALDEC_PATH)/bin/uvm_1_2_dpi"
+ DPILIB_TARGET = dpi_lib$(BITS)
+else
+ DPILIB_VLOG_OPT = +define+UVM_NO_DPI
+ DPILIB_VSIM_OPT =
+ DPILIB_TARGET =
+endif
+
+LIBDIR = $(UVM_HOME)/lib
+LIBNAME = uvm_dpi
+
+###############################################################################
+# VLOG (Compilation)
+VLOG_FLAGS ?= \
+ -timescale "1ns/1ps" \
+ -err VCP2694 W1 #for riscv dv
+
+VLOG_FILE_LIST = -f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist
+
+VLOG_DEBUG_FLAGS ?= -dbg
+VLOG_FLAGS += $(DPILIB_VLOG_OPT)
+
+# Add the ISS to compilation
+VLOG_FILE_LIST += -f $(DV_UVMT_PATH)/imperas_iss.flist
+VLOG_FLAGS += "+define+$(CV_CORE_UC)_TRACE_EXECUTION"
+VLOG_FLAGS += -dpilib
+
+###############################################################################
+# VSIM (Simulaion)
+VSIM_FLAGS += $(VSIM_USER_FLAGS) +access +r+w
+VSIM_DEBUG_FLAGS ?= -dbg
+VSIM_GUI_FLAGS ?= -gui
+VSIM_SCRIPT_DIR = $(abspath $(MAKE_PATH)/../tools/riviera)
+
+VSIM_UVM_ARGS =
+
+VSIM_FLAGS += -sv_lib $(basename $(OVP_MODEL_DPI))
+
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+VSIM_FLAGS += +USE_ISS
+else
+VSIM_FLAGS += +DISABLE_OVPSIM
+endif
+
+VSIM_FLAGS += -sv_lib $(basename $(DPI_DASM_LIB))
+VSIM_FLAGS += -sv_lib $(basename $(abspath $(SVLIB_LIB)))
+
+# Skip compile if requested (COMP=NO)
+ifneq ($(call IS_NO,$(COMP)),NO)
+VSIM_RUN_PREREQ = comp
+endif
+
+VSIM_PMA_INC += +incdir+$(TBSRC_HOME)/uvmt \
+ +incdir+$(CV_CORE_PKG)/rtl/include \
+ +incdir+$(CV_CORE_COREVDV_PKG)/ldgen \
+ +incdir+$(abspath $(MAKE_PATH)/../../../lib/mem_region_gen)
+
+################################################################################
+# Coverage database generation
+#TODO
+ifeq ($(call IS_YES,$(COV)),YES)
+VLOG_FLAGS += $(VLOG_COV)
+VSIM_FLAGS += $(VSIM_COV)
+endif
+
+################################################################################
+# Waveform generation
+#TODO
+
+################################################################################
+# Interactive simulation
+ifeq ($(call IS_YES,$(GUI)),YES)
+VRUN_FLAGS += run -all
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+VLOG_FLAGS += $(VLOG_DEBUG_FLAGS)
+VSIM_FLAGS += $(VSIM_GUI_FLAGS) $(VSIM_DEBUG_FLAGS)
+else
+VSIM_FLAGS += $(VSIM_GUI_FLAGS)
+endif
+else
+VSIM_FLAGS += -c
+VRUN_FLAGS += run -all; endsim; quit -force
+endif
+
+################################################################################
+# Coverage command
+#TODO
+
+################################################################################
+# Waveform (post-process) command line
+#TODO
+
+################################################################################
+# Targets
+
+.PHONY: no_rule help mk_vsim_dir lib comp run
+
+no_rule:
+ @echo 'makefile: SIMULATOR is set to $(SIMULATOR), but no rule/target specified.'
+ @echo 'try "make SIMULATOR=vsim sanity" (or just "make sanity" if shell ENV variable SIMULATOR is already set).'
+
+help:
+ vsim -help
+
+################################################################################
+# corev-dv generation targets
+
+vlog_corev-dv:
+ $(MKDIR_P) $(VSIM_COREVDV_RESULTS)
+ $(MKDIR_P) $(COREVDV_PKG)/out_$(DATE)/run
+ cd $(VSIM_COREVDV_RESULTS) && \
+ $(VLIB) $(VWORK)
+ cd $(VSIM_COREVDV_RESULTS) && \
+ $(VLOG) \
+ $(VLOG_FLAGS) \
+ $(VSIM_PMA_INC) \
+ -uvmver 1.2 \
+ +incdir+$(CV_CORE_COREVDV_PKG)/target/$(CV_CORE_LC) \
+ +incdir+$(RISCVDV_PKG)/user_extension \
+ +incdir+$(COREVDV_PKG) \
+ +incdir+$(CV_CORE_COREVDV_PKG) \
+ $(CFG_COMPILE_FLAGS) \
+ -f $(CV_CORE_MANIFEST) \
+ -f $(COREVDV_PKG)/manifest.f
+
+gen_corev-dv:
+ mkdir -p $(VSIM_COREVDV_RESULTS)/$(TEST)
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ mkdir -p $(GEN_TEST_DIR)/test_build/$(CFG)/$$idx; \
+ done
+ cd $(VSIM_COREVDV_RESULTS)/$(TEST) && \
+ $(VSIM) \
+ $(VSIM_FLAGS) \
+ $(CV_CORE_LC)_instr_gen_tb_top \
+ $(DPILIB_VSIM_OPT) \
+ -lib $(VSIM_COREVDV_RESULTS)/work \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ -l $(TEST)_$(GEN_START_INDEX)_$(GEN_NUM_TESTS).log \
+ +start_idx=$(GEN_START_INDEX) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ +asm_file_name_opts=$(TEST) \
+ +ldgen_cp_test_path=$(GEN_TEST_DIR)/test_build/$(CFG) \
+ $(CFG_PLUSARGS) \
+ $(GEN_PLUSARGS) \
+ -do '$(VRUN_FLAGS)'
+ # Copy out final assembler files to test directory
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ cp -f ${BSP}/link_pma.ld ${GEN_TEST_DIR}/test_build/${CFG}/$$idx/link.ld; \
+ cp ${VSIM_COREVDV_RESULTS}/${TEST}/${TEST}_$$idx.S ${GEN_TEST_DIR}/test_build/$(CFG)/$$idx; \
+ done
+
+comp_corev-dv: $(RISCVDV_PKG) $(CV_CORE_PKG) vlog_corev-dv
+
+corev-dv: clean_riscv-dv \
+ clone_riscv-dv \
+ comp_corev-dv
+
+################################################################################
+# Riviera-PRO simulation targets
+
+mk_vsim_dir:
+ $(MKDIR_P) $(VSIM_RESULTS)
+
+###############################################################################
+# Run a single test-program from the RISC-V Compliance Test-suite. The parent
+# Makefile of this .mk implements "all_compliance", the target that
+# compiles the test-programs.
+#
+# There is a dependancy between RISCV_ISA and COMPLIANCE_PROG which *you* are
+# required to know. For example, the I-ADD-01 test-program is part of the rv32i
+# testsuite.
+# So this works:
+# make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+# But this does not:
+# make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+#
+RISCV_ISA ?= rv32i
+COMPLIANCE_PROG ?= I-ADD-01
+
+SIG_ROOT ?= $(VSIM_RESULTS)/$(CFG)/$(RISCV_ISA)
+SIG ?= $(VSIM_RESULTS)/$(CFG)/$(RISCV_ISA)/$(COMPLIANCE_PROG)_$(RUN_INDEX)/$(COMPLIANCE_PROG).signature_output
+REF ?= $(COMPLIANCE_PKG)/riscv-test-suite/$(RISCV_ISA)/references/$(COMPLIANCE_PROG).reference_output
+TEST_PLUSARGS ?= +signature=$(COMPLIANCE_PROG).signature_output
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+VSIM_COMPLIANCE_PREREQ = build_compliance
+endif
+
+compliance: VSIM_TEST=$(COMPLIANCE_PROG)
+compliance: OPT_SUBDIR=$(RISCV_ISA)
+compliance: VSIM_FLAGS+=+firmware=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).hex
+compliance: VSIM_FLAGS+=+elf_file=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).elf
+compliance: TEST_UVM_TEST=uvmt_$(CV_CORE_LC)_firmware_test_c
+compliance: $(VSIM_COMPLIANCE_PREREQ) run
+compliance: export IMPERAS_TOOLS=$(CORE_V_VERIF)/$(CV_CORE_LC)/tests/cfg/ovpsim_no_pulp.ic
+
+################################################################################
+# If the configuration specified OVPSIM arguments, generate an ovpsim.ic file and
+# set IMPERAS_TOOLS to point to it
+gen_ovpsim_ic:
+ @rm -f $(VSIM_RESULTS)/$(CFG)/$(TEST_NAME)_$(RUN_INDEX)/ovpsim.ic
+ @mkdir -p $(VSIM_RESULTS)/$(CFG)/$(TEST_NAME)_$(RUN_INDEX)
+ @touch $(VSIM_RESULTS)/$(CFG)/$(TEST_NAME)_$(RUN_INDEX)/ovpsim.ic
+ @if [ ! -z "$(CFG_OVPSIM)" ]; then \
+ echo "$(CFG_OVPSIM)" > $(VSIM_RESULTS)/$(CFG)/$(TEST_NAME)_$(RUN_INDEX)/ovpsim.ic; \
+ fi
+export IMPERAS_TOOLS=$(VSIM_RESULTS)/$(CFG)/$(TEST_NAME)_$(RUN_INDEX)/ovpsim.ic
+
+# Target to create work directory in $(VSIM_RESULTS)/
+lib: mk_vsim_dir $(CV_CORE_PKG) $(SVLIB_PKG) $(TBSRC_PKG) $(TBSRC)
+ if [ ! -d "$(VSIM_RESULTS)/$(CFG)/$(VWORK)" ]; then \
+ $(VLIB) "$(VSIM_RESULTS)/$(CFG)/$(VWORK)"; \
+ fi
+
+# Target to run vlog over SystemVerilog source in $(VSIM_RESULTS)/
+comp: lib
+ @echo "$(BANNER)"
+ @echo "* Running vlog in $(VSIM_RESULTS)/$(CFG)"
+ @echo "* Log: $(VSIM_RESULTS)/$(CFG)/vlog.log"
+ @echo "$(BANNER)"
+ cd $(VSIM_RESULTS)/$(CFG) && \
+ $(VLOG) \
+ $(VLOG_FLAGS) \
+ $(CFG_COMPILE_FLAGS) \
+ +incdir+$(DV_UVME_PATH) \
+ +incdir+$(DV_UVMT_PATH) \
+ -uvmver 1.2 \
+ -f $(CV_CORE_MANIFEST) \
+ $(VLOG_FILE_LIST) \
+ $(TBSRC_PKG)
+
+RUN_DIR = $(abspath $(VSIM_RESULTS)/$(CFG)/$(OPT_SUBDIR)/$(VSIM_TEST)_$(RUN_INDEX))
+
+# Target to run VSIM (i.e. run the simulation)
+run: $(VSIM_RUN_PREREQ) gen_ovpsim_ic
+ @echo "$(BANNER)"
+ @echo "* Running vsim in $(RUN_DIR)"
+ @echo "* Log: $(RUN_DIR)/vsim-$(VSIM_TEST).log"
+ @echo "$(BANNER)"
+ mkdir -p $(RUN_DIR) && \
+ cd $(RUN_DIR) && \
+ $(VSIM) \
+ $(VSIM_FLAGS) \
+ ${DPILIB_VSIM_OPT} \
+ -l vsim-$(VSIM_TEST).log \
+ -lib $(VSIM_RESULTS)/$(CFG)/work \
+ +UVM_TESTNAME=$(TEST_UVM_TEST)\
+ $(RTLSRC_VLOG_TB_TOP) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS) \
+ -do '$(VRUN_FLAGS)'
+
+################################################################################
+# Test targets
+
+################################################################################
+# The new general test target
+
+test: VSIM_TEST=$(TEST_PROGRAM)
+test: VSIM_FLAGS += +firmware=$(TEST_TEST_DIR)/test_build/$(CFG)/$(RUN_INDEX)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex
+test: VSIM_FLAGS += +elf_file=$(TEST_TEST_DIR)/test_build/$(CFG)/$(RUN_INDEX)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).elf
+test: VSIM_FLAGS += +itb_file=$(TEST_TEST_DIR)/test_build/$(CFG)/$(RUN_INDEX)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).itb
+test: $(TEST_TEST_DIR)/test_build/$(CFG)/$(RUN_INDEX)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex run
+
+################################################################################
+# Invoke post-process waveform viewer
+#TODO
+
+################################################################################
+# Invoke coverage
+#TODO
+
+###############################################################################
+# Clean up your mess!
+
+clean:
+ rm -rf $(VSIM_RESULTS) library.cfg $(VWORK)
+
+# All generated files plus the clone of the RTL
+clean_all: clean clean_riscv-dv clean_test_programs clean-bsp clean_compliance clean_embench clean_dpi_dasm_spike clean_gen_linker_files clean_svlib
+ rm -rf $(CV_CORE_PKG)
diff --git a/mk/uvmt/unsim.mk b/mk/uvmt/unsim.mk
new file mode 100644
index 0000000..a8b227a
--- /dev/null
+++ b/mk/uvmt/unsim.mk
@@ -0,0 +1,31 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+###############################################################################
+#
+# Makefile for the "unknown simulator".
+#
+###############################################################################
+
+no_rule:
+ @echo 'no SIMULATOR and rule/target specified.'
+ @echo 'Usage: make SIMULATOR= '
+ @echo 'e.g: make SIMULATOR=xrun hello-world'
+ @exit 1
+
+%::
+ @echo '$(SIMULATOR): unknown simulator'
+ @exit 1
\ No newline at end of file
diff --git a/mk/uvmt/uvmt.mk b/mk/uvmt/uvmt.mk
new file mode 100644
index 0000000..8096e25
--- /dev/null
+++ b/mk/uvmt/uvmt.mk
@@ -0,0 +1,542 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# Makefile for the UVMT testbench for multiple OpenHW-verified cores. Substantially modified
+# from the original Makefile for the RI5CY testbench.
+#
+###############################################################################
+#
+# Copyright 2019 Claire Wolf
+# Copyright 2019 Robert Balas
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+#
+# Original Author: Robert Balas (balasr@iis.ee.ethz.ch)
+#
+###############################################################################
+
+# Variable checks
+ifndef CV_CORE
+$(error Must set CV_CORE to a valid core)
+endif
+
+# "Constants"
+DATE = $(shell date +%F)
+CV_CORE_LC = $(shell echo $(CV_CORE) | tr A-Z a-z)
+CV_CORE_UC = $(shell echo $(CV_CORE) | tr a-z A-Z)
+SIMULATOR_UC = $(shell echo $(SIMULATOR) | tr a-z A-Z)
+export CV_CORE_LC
+export CV_CORE_UC
+.DEFAULT_GOAL := no_rule
+
+# Useful commands
+MKDIR_P = mkdir -p
+
+
+# Compile compile flags for all simulators (careful!)
+WAVES ?= 0
+SV_CMP_FLAGS ?= "+define+$(CV_CORE_UC)_ASSERT_ON"
+TIMESCALE ?= -timescale 1ns/1ps
+UVM_PLUSARGS ?=
+
+# User selectable SystemVerilog simulator targets/rules
+CV_SIMULATOR ?= unsim
+SIMULATOR ?= $(CV_SIMULATOR)
+
+# Optionally exclude the OVPsim (not recommended)
+USE_ISS ?= YES
+ISS ?= IMPERAS
+
+# Common configuration variables
+CFG ?= default
+
+# Common Generation variables
+GEN_START_INDEX ?= 0
+GEN_NUM_TESTS ?= 1
+export RUN_INDEX ?= 0
+
+# Common output directories
+SIM_RESULTS ?= $(if $(CV_RESULTS),$(abspath $(CV_RESULTS))/$(SIMULATOR)_results,$(MAKE_PATH)/$(SIMULATOR)_results)
+SIM_CFG_RESULTS = $(SIM_RESULTS)/$(CFG)
+SIM_COREVDV_RESULTS = $(SIM_CFG_RESULTS)/corev-dv
+SIM_LDGEN_RESULTS = $(SIM_CFG_RESULTS)/$(LDGEN)
+SIM_TEST_RESULTS = $(SIM_CFG_RESULTS)/$(TEST)
+SIM_RUN_RESULTS = $(SIM_TEST_RESULTS)/$(RUN_INDEX)
+SIM_TEST_PROGRAM_RESULTS = $(SIM_RUN_RESULTS)/test_program
+SIM_BSP_RESULTS = $(SIM_TEST_PROGRAM_RESULTS)/bsp
+
+# EMBench options
+EMB_TYPE ?= speed
+EMB_TARGET ?= 0
+EMB_CPU_MHZ ?= 1
+EMB_TIMEOUT ?= 3600
+EMB_PARALLEL_ARG = $(if $(filter $(YES_VALS),$(EMB_PARALLEL)),YES,NO)
+EMB_BUILD_ONLY_ARG = $(if $(filter $(YES_VALS),$(EMB_BUILD_ONLY)),YES,NO)
+EMB_DEBUG_ARG = $(if $(filter $(YES_VALS),$(EMB_DEBUG)),YES,NO)
+
+# UVM Environment
+# OLD
+#export DV_UVMT_PATH = $(CORE_V_VERIF)/$(CV_CORE_LC)/tb/uvmt
+#export DV_UVME_PATH = $(CORE_V_VERIF)/$(CV_CORE_LC)/env/uvme
+#export DV_UVML_HRTBT_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_hrtbt
+#export DV_UVMA_CORE_CNTRL_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_core_cntrl
+#export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov
+#export DV_UVMA_RVFI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvfi
+#export DV_UVMA_RVVI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvvi
+#export DV_UVMA_RVVI_OVPSIM_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_rvvi_ovpsim
+#export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst
+#export DV_UVMA_INTERRUPT_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_interrupt
+#export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug
+#export DV_UVMA_PMA_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_pma
+#export DV_UVMA_OBI_MEMORY_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi_memory
+#export DV_UVMA_FENCEI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_fencei
+#export DV_UVML_TRN_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_trn
+#export DV_UVML_LOGS_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_logs
+#export DV_UVML_SB_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_sb
+#export DV_UVML_MEM_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_mem
+#
+#export DV_UVMC_RVFI_SCOREBOARD_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_scoreboard/
+#export DV_UVMC_RVFI_REFERENCE_MODEL_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_reference_model/
+#
+#export DV_OVPM_HOME = $(CORE_V_VERIF)/vendor_lib/imperas
+#export DV_OVPM_MODEL = $(DV_OVPM_HOME)/imperas_DV_COREV
+#
+#export DV_OVPM_DESIGN = $(DV_OVPM_HOME)/design
+#
+#export DV_SVLIB_PATH = $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/verilab
+#
+#DV_UVMT_SRCS = $(wildcard $(DV_UVMT_PATH)/*.sv))
+
+# NEW NEW NEW!!!
+export DV_UVMT_PATH = $(CORE_V_VERIF)/tb/uvmt
+export DV_UVME_PATH = $(CORE_V_VERIF)/env/uvme
+export DV_UVML_HRTBT_PATH = $(CV_VERIF_PKG)/lib/uvm_libs/uvml_hrtbt
+export DV_UVMA_CORE_CNTRL_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_core_cntrl
+export DV_UVMA_ISACOV_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_isacov
+export DV_UVMA_RVFI_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_rvfi
+export DV_UVMA_RVVI_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_rvvi
+export DV_UVMA_RVVI_OVPSIM_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_rvvi_ovpsim
+export DV_UVMA_CLKNRST_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_clknrst
+export DV_UVMA_INTERRUPT_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_interrupt
+export DV_UVMA_DEBUG_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_debug
+export DV_UVMA_PMA_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_pma
+export DV_UVMA_OBI_MEMORY_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_obi_memory
+export DV_UVMA_FENCEI_PATH = $(CV_VERIF_PKG)/lib/uvm_agents/uvma_fencei
+export DV_UVML_TRN_PATH = $(CV_VERIF_PKG)/lib/uvm_libs/uvml_trn
+export DV_UVML_LOGS_PATH = $(CV_VERIF_PKG)/lib/uvm_libs/uvml_logs
+export DV_UVML_SB_PATH = $(CV_VERIF_PKG)/lib/uvm_libs/uvml_sb
+export DV_UVML_MEM_PATH = $(CV_VERIF_PKG)/lib/uvm_libs/uvml_mem
+
+export DV_UVMC_RVFI_SCOREBOARD_PATH = $(CV_VERIF_PKG)/lib/uvm_components/uvmc_rvfi_scoreboard/
+export DV_UVMC_RVFI_REFERENCE_MODEL_PATH = $(CV_VERIF_PKG)/lib/uvm_components/uvmc_rvfi_reference_model/
+
+export DV_OVPM_HOME = $(CV_VERIF_PKG)/vendor_lib/imperas
+export DV_OVPM_MODEL = $(DV_OVPM_HOME)/imperas_DV_COREV
+
+export DV_OVPM_DESIGN = $(DV_OVPM_HOME)/design
+
+export DV_SVLIB_PATH = $(CORE_V_VERIF)/vendor_lib/verilab
+
+DV_UVMT_SRCS = $(wildcard $(DV_UVMT_PATH)/*.sv))
+
+# Testcase name: must be the CLASS name of the testcase (not the filename).
+# Look in ../../tests/uvmt
+UVM_TESTNAME ?= uvmt_$(CV_CORE_LC)_firmware_test_c
+
+# Google's random instruction generator
+RISCVDV_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/google/riscv-dv
+COREVDV_PKG := $(CORE_V_VERIF)/lib/corev-dv
+CV_CORE_COREVDV_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/env/corev-dv
+export RISCV_DV_ROOT = $(RISCVDV_PKG)
+export COREV_DV_ROOT = $(COREVDV_PKG)
+export CV_CORE_COREV_DV_ROOT = $(CV_CORE_COREVDV_PKG)
+
+# RISC-V Foundation's RISC-V Compliance Test-suite
+COMPLIANCE_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance
+
+# EMBench benchmarking suite
+EMBENCH_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/embench
+EMBENCH_TESTS := $(CORE_V_VERIF)/$(CV_CORE_LC)/tests/programs/embench
+
+# Disassembler
+#DPI_DASM_PKG := $(CORE_V_VERIF)/lib/dpi_dasm
+#DPI_DASM_SPIKE_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/dpi_dasm_spike
+DPI_DASM_PKG := $(CV_VERIF_PKG)/lib/dpi_dasm
+DPI_DASM_SPIKE_PKG := $(CV_VERIF_PKG)/vendor_lib/dpi_dasm_spike
+export DPI_DASM_PKG = $(CV_VERIF_PKG)/lib/dpi_dasm
+export DPI_DASM_ROOT = $(DPI_DASM_PKG)
+export DPI_DASM_SPIKE_ROOT = $(DPI_DASM_SPIKE_PKG)
+
+# TB source files for the CV32E core
+#TBSRC_HOME := $(CORE_V_VERIF)/$(CV_CORE_LC)/tb
+TBSRC_HOME := $(CORE_V_VERIF)/tb
+TBSRC_TOP := $(TBSRC_HOME)/uvmt/uvmt_$(CV_CORE_LC)_tb.sv
+#export TBSRC_HOME = $(CORE_V_VERIF)/$(CV_CORE_LC)/tb
+export TBSRC_HOME = $(CORE_V_VERIF)/tb
+
+SIM_LIBS := $(CORE_V_VERIF)/lib/sim_libs
+
+RTLSRC_VLOG_TB_TOP := $(basename $(notdir $(TBSRC_TOP)))
+RTLSRC_VOPT_TB_TOP := $(addsuffix _vopt, $(RTLSRC_VLOG_TB_TOP))
+
+# RTL source files for the CV32E core
+# DESIGN_RTL_DIR is used by CV32E40P_MANIFEST file
+CV_CORE_PKG := $(CORE_V_VERIF)/core-v-cores/$(CV_CORE_LC)
+CV_CORE_MANIFEST := $(CV_CORE_PKG)/$(CV_CORE_LC)_manifest.flist
+export DESIGN_RTL_DIR = $(CV_CORE_PKG)/rtl
+
+RTLSRC_HOME := $(CV_CORE_PKG)/rtl
+RTLSRC_INCDIR := $(RTLSRC_HOME)/include
+
+# SVLIB
+#SVLIB_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/verilab/svlib
+#export SVLIB_PKG = $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/verilab/svlib
+SVLIB_PKG := $(CORE_V_VERIF)/vendor_lib/verilab/svlib
+export SVLIB_PKG = $(CORE_V_VERIF)/vendor_lib/verilab/svlib
+
+# CORE-V-VERIF
+#CV_VERIF_PKG := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/openhwgroup_core-v-verif
+#export CV_VERIF_PKG = $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/openhwgroup_core-v-verif
+CV_VERIF_PKG := $(CORE_V_VERIF)/vendor_lib/openhwgroup_core-v-verif
+export CV_VERIF_PKG = $(CORE_V_VERIF)/vendor_lib/openhwgroup_core-v-verif
+
+# RVVI
+#RVVI_HOME := $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv-verification/RVVI
+#export RVVI_HOME = $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv-verification/RVVI
+RVVI_HOME := $(CORE_V_VERIF)/vendor_lib/riscv-verification/RVVI
+export RVVI_HOME = $(CORE_V_VERIF)/vendor_lib/riscv-verification/RVVI
+RVVI_STUB := $(RVVI_HOME)/../stubs
+export RVVI_STUB = $(RVVI_HOME)/../stubs
+RVVI_IMPERASDV := $(RVVI_HOME)/source/host/rvvi
+export RVVI_IMPERASDV = $(RVVI_HOME)/source/host/rvvi
+
+###############################################################################
+# Seed management for constrained-random sims
+SEED ?= 1
+RNDSEED ?=
+
+ifeq ($(SEED),random)
+RNDSEED = $(shell date +%N)
+else
+ifeq ($(SEED),)
+# Empty SEED variable selects 1
+RNDSEED = 1
+else
+RNDSEED = $(SEED)
+endif
+endif
+
+###############################################################################
+# Common Makefile:
+# - Core Firmware and the RISCV GCC Toolchain (SDK)
+# - Variables for RTL dependencies
+include $(CORE_V_VERIF)/mk/Common.mk
+###############################################################################
+# Clone core RTL and DV dependencies
+clone_cv_core_rtl: $(CV_CORE_PKG)
+
+clone_riscv-dv: $(RISCVDV_PKG)
+
+clone_embench: $(EMBENCH_PKG)
+
+clone_compliance: $(COMPLIANCE_PKG)
+
+clone_dpi_dasm_spike:
+ $(CLONE_DPI_DASM_SPIKE_CMD)
+
+clone_svlib: $(SVLIB_PKG)
+
+$(CV_CORE_PKG):
+ $(CLONE_CV_CORE_CMD)
+
+$(RISCVDV_PKG):
+ $(CLONE_RISCVDV_CMD)
+
+$(COMPLIANCE_PKG):
+ $(CLONE_COMPLIANCE_CMD)
+
+$(EMBENCH_PKG):
+ $(CLONE_EMBENCH_CMD)
+
+$(DPI_DASM_SPIKE_PKG):
+ $(CLONE_DPI_DASM_SPIKE_CMD)
+
+$(SVLIB_PKG):
+ $(CLONE_SVLIB_CMD)
+
+$(CV_VERIF_PKG):
+ $(CLONE_CV_VERIF_CMD)
+
+###############################################################################
+# RISC-V Compliance Test-suite
+# As much as possible, the test suite is used "out-of-the-box". The
+# "build_compliance" target below uses the Makefile supplied by the suite
+# to compile all the individual test-programs in the suite to generate the
+# elf and hex files used in simulation. Each .mk is assumed to have a
+# target to run the compiled test-program.
+
+# RISCV_ISA='rv32i|rv32im|rv32imc|rv32Zicsr|rv32Zifencei'
+RISCV_ISA ?= rv32i
+RISCV_TARGET ?= OpenHW
+RISCV_DEVICE ?= $(CV_CORE_LC)
+
+clone_compliance:
+ $(CLONE_COMPLIANCE_CMD)
+
+clr_compliance:
+ make clean -C $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance
+
+build_compliance: $(COMPLIANCE_PKG)
+ make simulate -i -C $(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance \
+ RISCV_TARGET=${RISCV_TARGET} \
+ RISCV_DEVICE=${RISCV_DEVICE} \
+ PATH=$(RISCV)/bin:$(PATH) \
+ RISCV_PREFIX=$(RISCV_PREFIX) \
+ NOTRAPS=1 \
+ RISCV_ISA=$(RISCV_ISA)
+# VERBOSE=1
+
+all_compliance: $(COMPLIANCE_PKG)
+ make build_compliance RISCV_ISA=rv32i && \
+ make build_compliance RISCV_ISA=rv32im && \
+ make build_compliance RISCV_ISA=rv32imc && \
+ make build_compliance RISCV_ISA=rv32Zicsr && \
+ make build_compliance RISCV_ISA=rv32Zifencei
+
+# "compliance" is a simulator-specific target defined in .mk
+COMPLIANCE_RESULTS = $(SIM_RESULTS)
+
+compliance_check_sig: compliance
+ @echo "Checking Compliance Signature for $(RISCV_ISA)/$(COMPLIANCE_PROG)"
+ @echo "Reference: $(REF)"
+ @echo "Signature: $(SIG)"
+ @export SUITEDIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance/riscv-test-suite/$(RISCV_ISA) && \
+ export REF=$(REF) && export SIG=$(SIG) && export COMPL_PROG=$(COMPLIANCE_PROG) && \
+ export RISCV_TARGET=${RISCV_TARGET} && export RISCV_DEVICE=${RISCV_DEVICE} && \
+ export RISCV_ISA=${RISCV_ISA} export SIG_ROOT=${SIG_ROOT} && \
+ $(CORE_V_VERIF)/bin/diff_signatures.sh | tee $(COMPLIANCE_RESULTS)/$(CFG)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)/diff_signatures.log
+
+compliance_check_all_sigs:
+ @$(MKDIR_P) $(COMPLIANCE_RESULTS)/$(CFG)/$(RISCV_ISA)
+ @echo "Checking Compliance Signature for all tests in $(CFG)/$(RISCV_ISA)"
+ @export SUITEDIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/vendor_lib/riscv/riscv-compliance/riscv-test-suite/$(RISCV_ISA) && \
+ export RISCV_TARGET=${RISCV_TARGET} && export RISCV_DEVICE=${RISCV_DEVICE} && \
+ export RISCV_ISA=${RISCV_ISA} export SIG_ROOT=${SIG_ROOT} && \
+ $(CORE_V_VERIF)/bin/diff_signatures.sh $(RISCV_ISA) | tee $(COMPLIANCE_RESULTS)/$(CFG)/$(RISCV_ISA)/diff_signatures.log
+
+compliance_regression:
+ make build_compliance RISCV_ISA=$(RISCV_ISA)
+ @export SIM_DIR=$(CORE_V_VERIF)/$(CV_CORE_LC)/sim/uvmt && \
+ $(CORE_V_VERIF)/bin/run_compliance.sh $(RISCV_ISA)
+ make compliance_check_all_sigs RISCV_ISA=$(RISCV_ISA)
+
+dah:
+ @export SIM_DIR=$(CORE_V_VERIF)/cv32/sim/uvmt && \
+ $(CORE_V_VERIF)/bin/run_compliance.sh $(RISCV_ISA)
+
+###############################################################################
+# EMBench benchmark
+# target to check out and run the EMBench suite for code size and speed
+#
+
+embench: $(EMBENCH_PKG)
+ $(CORE_V_VERIF)/bin/run_embench.py \
+ -c $(CV_CORE) \
+ -cc $(RISCV_EXE_PREFIX)$(RISCV_CC) \
+ -sim $(SIMULATOR) \
+ -t $(EMB_TYPE) \
+ --timeout $(EMB_TIMEOUT) \
+ --parallel $(EMB_PARALLEL_ARG) \
+ -b $(EMB_BUILD_ONLY_ARG) \
+ -tgt $(EMB_TARGET) \
+ -f $(EMB_CPU_MHZ) \
+ -d $(EMB_DEBUG_ARG)
+
+###############################################################################
+# ISACOV (ISA coverage)
+# Compare the log against the tracer log.
+# This checks that sampling went correctly without false positives/negatives.
+
+ISACOV_LOGDIR = $(SIM_CFG_RESULTS)/$(TEST)/$(RUN_INDEX)
+ISACOV_RVFILOG = $(ISACOV_LOGDIR)/uvm_test_top.env.rvfi_agent.trn.log
+ISACOV_COVERAGELOG = $(ISACOV_LOGDIR)/uvm_test_top.env.isacov_agent.trn.log
+
+isacov_logdiff:
+ @echo isacov_logdiff:
+ @echo checking that env/dirs/files are as expected...
+ @printenv TEST > /dev/null || (echo specify TEST; false)
+ @ls $(ISACOV_LOGDIR) > /dev/null
+ @ls $(ISACOV_RVFILOG) > /dev/null
+ @ls $(ISACOV_COVERAGELOG) > /dev/null
+ @echo extracting assembly code from logs...
+ @cat $(ISACOV_RVFILOG) \
+ | awk -F ' - ' '{print $$2}' `#discard everything but the assembly` \
+ | sed 's/ *#.*//' `#discard comments` \
+ | sed 's/ *<.*//' `#discard symbol information` \
+ | sed 's/,/, /g' `#add space after commas` \
+ | tail -n +4 > trace.tmp `#don't include banner`
+ @cat $(ISACOV_COVERAGELOG) \
+ | awk -F '\t' '{print $$3}' `#discard everything but the assembly` \
+ | sed 's/_/./' `#convert "c_addi" to "c.addi" etc` \
+ | tail -n +2 > agent.tmp `#don't include banner`
+ @echo diffing the instruction sequences...
+ @echo saving to $(ISACOV_LOGDIR)/isacov_logdiff
+ @rm -rf $(ISACOV_LOGDIR)/isacov_logdiff
+ @diff trace.tmp agent.tmp > $(ISACOV_LOGDIR)/isacov_logdiff; true
+ @rm -rf trace.tmp agent.tmp
+ @(test ! -s $(ISACOV_LOGDIR)/isacov_logdiff && echo OK) || (echo FAIL; false)
+
+###############################################################################
+# Include the targets/rules for the selected SystemVerilog simulator
+#ifeq ($(SIMULATOR), unsim)
+#include unsim.mk
+#else
+ifeq ($(SIMULATOR), dsim)
+include $(CORE_V_VERIF)/mk/uvmt/dsim.mk
+else
+ifeq ($(SIMULATOR), xrun)
+include $(CORE_V_VERIF)/mk/uvmt/xrun.mk
+else
+ifeq ($(SIMULATOR), vsim)
+include $(CORE_V_VERIF)/mk/uvmt/vsim.mk
+else
+ifeq ($(SIMULATOR), vcs)
+include $(CORE_V_VERIF)/mk/uvmt/vcs.mk
+else
+ifeq ($(SIMULATOR), riviera)
+include $(CORE_V_VERIF)/mk/uvmt/riviera.mk
+else
+include $(CORE_V_VERIF)/mk/uvmt/unsim.mk
+endif
+endif
+endif
+endif
+endif
+#endif
+
+################################################################################
+# Open a DVT Eclipse IDE instance with the project imported automatically
+ifeq ($(MAKECMDGOALS), open_in_dvt_ide)
+include $(CORE_V_VERIF)/mk/uvmt/dvt.mk
+else
+ifeq ($(MAKECMDGOALS), create_dvt_build_file)
+include $(CORE_V_VERIF)/mk/uvmt/dvt.mk
+else
+ifeq ($(MAKECMDGOALS), dvt_dump_env_vars)
+include $(CORE_V_VERIF)/mk/uvmt/dvt.mk
+endif
+endif
+endif
+
+################################################################################
+# Display all the shell env vars defined here (handy debug tool).
+echo_env:
+ @echo "ENV vars set in uvmt.mk:"
+ @echo " CV_CORE_LC = $(CV_CORE_LC)"
+ @echo " CV_CORE_UC = $(CV_CORE_UC)"
+ @echo " DV_UVMT_PATH = $(DV_UVMT_PATH)"
+ @echo " DV_UVME_PATH = $(DV_UVME_PATH)"
+ @echo " DV_UVML_HRTBT_PATH = $(DV_UVML_HRTBT_PATH)"
+ @echo " DV_UVMA_CORE_CNTRL_PATH = $(DV_UVMA_CORE_CNTRL_PATH)"
+ @echo " DV_UVMA_ISACOV_PATH = $(DV_UVMA_ISACOV_PATH)"
+ @echo " DV_UVMA_RVFI_PATH = $(DV_UVMA_RVFI_PATH)"
+ @echo " DV_UVMA_RVVI_PATH = $(DV_UVMA_RVVI_PATH)"
+ @echo " DV_UVMA_RVVI_OVPSIM_PATH = $(DV_UVMA_RVVI_OVPSIM_PATH)"
+ @echo " DV_UVMA_CLKNRST_PATH = $(DV_UVMA_CLKNRST_PATH)"
+ @echo " DV_UVMA_INTERRUPT_PATH = $(DV_UVMA_INTERRUPT_PATH)"
+ @echo " DV_UVMA_DEBUG_PATH = $(DV_UVMA_DEBUG_PATH)"
+ @echo " DV_UVMA_PMA_PATH = $(DV_UVMA_PMA_PATH)"
+ @echo " DV_UVMA_OBI_MEMORY_PATH = $(DV_UVMA_OBI_MEMORY_PATH)"
+ @echo " DV_UVMA_FENCEI_PATH = $(DV_UVMA_FENCEI_PATH)"
+ @echo " DV_UVML_TRN_PATH = $(DV_UVML_TRN_PATH)"
+ @echo " DV_UVML_LOGS_PATH = $(DV_UVML_LOGS_PATH)"
+ @echo " DV_UVML_SB_PATH = $(DV_UVML_SB_PATH)"
+ @echo " DV_UVML_MEM_PATH = $(DV_UVML_MEM_PATH)"
+ @echo " DV_UVMC_RVFI_SCOREBOARD_PATH = $(DV_UVMC_RVFI_SCOREBOARD_PATH)"
+ @echo " DV_UVMC_RVFI_REFERENCE_MODEL_PATH = $(DV_UVMC_RVFI_REFERENCE_MODEL_PATH)"
+ @echo " DV_OVPM_HOME = $(DV_OVPM_HOME)"
+ @echo " DV_OVPM_MODEL = $(DV_OVPM_MODEL)"
+ @echo " DV_OVPM_DESIGN = $(DV_OVPM_DESIGN)"
+ @echo " DV_SVLIB_PATH = $(DV_SVLIB_PATH)"
+ @echo " SVLIB_PKG = $(SVLIB_PKG)"
+ @echo " CV_VERIF_PKG = $(CV_VERIF_PKG)"
+ @echo " RISCV_DV_ROOT = $(RISCV_DV_ROOT)"
+ @echo " COREV_DV_ROOT = $(COREV_DV_ROOT)"
+ @echo " CV_CORE_COREV_DV_ROOT = $(CV_CORE_COREV_DV_ROOT)"
+ @echo " DPI_DASM_ROOT = $(DPI_DASM_ROOT)"
+ @echo " DPI_DASM_SPIKE_ROOT = $(DPI_DASM_SPIKE_ROOT)"
+ @echo " TBSRC_HOME = $(TBSRC_HOME)"
+ @echo " RVVI_HOME = $(RVVI_HOME)"
+ @echo " RVVI_STUB = $(RVVI_STUB)"
+ @echo " RVVI_IMPERASDV = $(RVVI_IMPERASDV)"
+ @echo " DESIGN_RTL_DIR = $(DESIGN_RTL_DIR)"
+
+###############################################################################
+# Clean up your mess!
+# 1. Clean all generated files of the C and assembler tests
+# 2. Simulator-specific clean targets are in ./.mk
+# 3. clean_bsp target is specified in ../Common.mk
+clean_rtl:
+ rm -rf $(CV_CORE_PKG)
+
+clean_hex:
+ rm -rf $(SIM_TEST_PROGRAM_RESULTS)
+
+clean_test_programs: clean_bsp
+ if [ -d "$(SIM_RESULTS)" ]; then \
+ find $(SIM_RESULTS) -depth -type d -name test_program | xargs rm -rf; \
+ fi
+
+clean_riscv-dv:
+ rm -rf $(RISCVDV_PKG)
+ rm -rf $(COREVDV_PKG)/out_*
+
+clean_compliance:
+ rm -rf $(COMPLIANCE_PKG)
+
+clean_embench:
+ rm -rf $(EMBENCH_PKG)
+ cd $(EMBENCH_TESTS) && \
+ find . ! -path . ! -path ./README.md -delete
+ if [ -d "$(SIM_RESULTS)" ]; then \
+ cd $(SIM_RESULTS) && find . -depth -type d -name "emb_*" | xargs rm -rf; \
+ fi
+
+clean_dpi_dasm_spike:
+ rm -rf $(DPI_DASM_SPIKE_PKG)
+
+clean_svlib:
+ rm -rf $(SVLIB_PKG)
+
+clean_core_v_verif:
+ rm -rf $(CV_VERIF_PKG)
+
+clean_rvvi_stub:
+ rm -rf $(RVVI_STUB_LIB)
diff --git a/mk/uvmt/vcs.mk b/mk/uvmt/vcs.mk
new file mode 100644
index 0000000..e506ebc
--- /dev/null
+++ b/mk/uvmt/vcs.mk
@@ -0,0 +1,391 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+###############################################################################
+#
+# VCS-specific Makefile for the Core-V-Verif "uvmt" testbench.
+#
+###############################################################################
+
+#
+# Synopsys do not (officially) support Ubuntu, so suppress the nonzero return code from VCS
+#
+OS_IS_UBUNTU = $(findstring Ubuntu,$(shell lsb_release -d))
+ifeq ($(OS_IS_UBUNTU),Ubuntu)
+ .IGNORE: hello-world comp test compliance comp_corev-dv corev-dv gen_corev-dv
+endif
+
+# Executables
+VCS = $(CV_SIM_PREFIX) vcs
+#SIMV = $(CV_TOOL_PREFIX) simv -licwait 20
+SIMV = simv -licwait 20
+DVE = $(CV_TOOL_PREFIX) dve
+#VERDI = $(CV_TOOL_PREFIX)verdi
+URG = $(CV_SIM_PREFIX) urg
+
+# Paths
+VCS_RESULTS ?= vcs_results
+VCS_OUT ?= $(SIM_CFG_RESULTS)/vcs_out
+VCS_DIR ?= $(SIM_CFG_RESULTS)/vcs.d
+VCS_ELAB_COV = -cm line+cond+tgl+fsm+branch+assert -cm_dir $(MAKECMDGOALS)/$(MAKECMDGOALS).vdb
+
+# modifications to already defined variables to take into account VCS
+VCS_OVP_MODEL_DPI = $(OVP_MODEL_DPI:.so=) # remove extension as VCS adds it
+VCS_TIMESCALE = $(shell echo "$(TIMESCALE)" | tr ' ' '=') # -timescale=1ns/1ps
+
+VCS_UVM_VERBOSITY ?= UVM_MEDIUM
+
+# Flags
+#VCS_UVMHOME_ARG ?= /opt/uvm/1800.2-2017-0.9/
+#VCS_UVMHOME_ARG ?= /opt/synopsys/vcs-mx/O-2018.09-SP1-1/etc/uvm
+VCS_UVMHOME_ARG ?= /synopsys/vcs/S-2021.09-SP1/etc/uvm
+export VCS_HOME ?= $(abspath $(shell which $(VCS))/../../)
+VCS_UVM_ARGS ?= +define+UVM +incdir+$(VCS_UVMHOME_ARG)/src $(VCS_UVMHOME_ARG)/src/uvm_pkg.sv +UVM_VERBOSITY=$(VCS_UVM_VERBOSITY) -ntb_opts uvm-1.2
+
+VCS_COMP_FLAGS ?= -lca -sverilog \
+ $(SV_CMP_FLAGS) $(VCS_UVM_ARGS) $(VCS_TIMESCALE) \
+ -assert svaext -race=all -ignore unique_checks -full64
+
+VCS_GUI ?=
+VCS_RUN_COV = -cm line+cond+tgl+fsm+branch+assert -cm_dir $(MAKECMDGOALS).vdb
+
+# Necessary libraries for the PMA generator class
+VCS_PMA_INC += +incdir+$(TBSRC_HOME)/uvmt \
+ +incdir+$(CV_CORE_PKG)/rtl/include \
+ +incdir+$(CV_CORE_COREVDV_PKG)/ldgen \
+ +incdir+$(abspath $(MAKE_PATH)/../../../lib/mem_region_gen)
+
+# Need to re-define the LIB paths for VCS to drop the "*.so" extension.
+DPI_DASM_LIB = $(DPI_DASM_PKG)/lib/$(DPI_DASM_ARCH)/libdpi_dasm
+SVLIB_LIB = $(SVLIB_PKG)/../svlib_dpi
+
+# Required by dpi_dasm target
+DPI_INCLUDE ?= $(shell dirname $(shell which vcs))/../include
+
+###############################################################################
+# Common QUIET flag defaults to -quiet unless VERBOSE is set
+ifeq ($(call IS_YES,$(VERBOSE)),YES)
+QUIET=
+else
+QUIET=-q
+endif
+
+################################################################################
+# GUI interactive simulation
+# GUI=YES enables interactive mode
+# ADV_DEBUG=YES currently not supported
+ifeq ($(call IS_YES,$(GUI)),YES)
+VCS_GUI += -gui
+VCS_USER_COMPILE_ARGS += -debug_access+r
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+$(error ADV_DEBUG not yet supported by VCS )
+endif
+endif
+
+################################################################################
+# Waveform generation
+# WAVES=YES enables waveform generation for entire testbench
+# ADV_DEBUG=YES currently not supported
+ifeq ($(call IS_YES,$(WAVES)),YES)
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+$(error ADV_DEBUG not yet supported by VCS )
+VCS_USER_COMPILE_ARGS = +vcs+vcdpluson
+else
+VCS_USER_COMPILE_ARGS = +vcs+vcdpluson
+endif
+endif
+
+################################################################################
+# Waveform (post-process) command line
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+$(error ADV_DEBUG not yet supported by VCS )
+WAVES_CMD = cd $(SIM_RUN_RESULTS) && $(DVE) -vpd vcdplus.vpd
+else
+WAVES_CMD = cd $(SIM_RUN_RESULTS) && $(DVE) -vpd vcdplus.vpd
+endif
+
+################################################################################
+# Coverage options
+# COV=YES generates coverage database, must be specified for comp and run
+URG_MERGE_ARGS = -dbname merged.vdb -group lrm_bin_name -flex_merge union
+MERGED_COV_DIR ?= merged_cov
+
+ifeq ($(call IS_YES,$(COV)),YES)
+VCS_USER_COMPILE_ARGS += $(VCS_ELAB_COV)
+VCS_RUN_COV_FLAGS += $(VCS_RUN_COV)
+endif
+
+# list all vbd files
+COV_RESULTS_LIST = $(wildcard $(SIM_RESULTS)/*/*.vdb)
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+COV_MERGE = cov_merge
+TEST = $(MERGED_COV_DIR)
+else
+COV_MERGE =
+endif
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+COV_ARGS = -dir cov_work/scope/merged
+else
+COV_ARGS = -dir $(TEST_NAME).vdb
+endif
+
+
+################################################################################
+
+VCS_FILE_LIST ?= -f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist
+VCS_RUN_FLAGS ?=
+
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+ ifeq ($(ISS),IMPERAS)
+ VCS_FILE_LIST += -f $(DV_UVMT_PATH)/imperas_iss.flist
+ endif
+ ifeq ($(ISS),SPIKE)
+ VCS_RUN_FLAGS += -sv_lib $(SPIKE_YAML_LIB)
+ VCS_RUN_FLAGS += -sv_lib $(SPIKE_RISCV_LIB)
+ VCS_RUN_FLAGS += -sv_lib $(SPIKE_DISASM_LIB)
+ LIBS = spike_lib
+ endif
+endif
+
+ifeq ($(call IS_YES,$(COMPILE_SPIKE)),YES)
+ VCS_RUN_FLAGS += -sv_lib $(SPIKE_FESVR_LIB)
+ LIBS = spike_lib
+endif
+
+VCS_USER_COMPILE_ARGS += +define+$(CV_CORE_UC)_TRACE_EXECUTION +define+$(CORE_DEFINES)
+
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+ VCS_PLUSARGS += +USE_ISS
+else
+ VCS_PLUSARGS += +DISABLE_OVPSIM
+endif
+
+VCS_RUN_BASE_FLAGS ?= $(VCS_GUI) \
+ $(VCS_PLUSARGS) +ntb_random_seed=$(RNDSEED) \
+ -sv_lib $(VCS_OVP_MODEL_DPI) \
+ -sv_lib $(abspath $(SVLIB_LIB))
+
+# Simulate using latest elab
+VCS_RUN_FLAGS += -assert nopostproc
+VCS_RUN_FLAGS += $(VCS_RUN_BASE_FLAGS)
+VCS_RUN_FLAGS += $(VCS_RUN_WAVES_FLAGS)
+VCS_RUN_FLAGS += $(VCS_RUN_COV_FLAGS)
+VCS_RUN_FLAGS += $(USER_RUN_FLAGS)
+
+###############################################################################
+# Targets
+
+no_rule:
+ @echo 'makefile: SIMULATOR is set to $(SIMULATOR), but no rule/target specified.'
+ @echo 'try "make SIMULATOR=vcs sanity" (or just "make sanity" if shell ENV variable SIMULATOR is already set).'
+
+help:
+ vcs -help
+
+.PHONY: comp test waves cov
+
+mk_vcs_dir:
+ $(MKDIR_P) $(VCS_DIR)
+
+# This special target is to support the special sanity target in the Common Makefile
+hello-world:
+ $(MAKE) test TEST=hello-world
+
+VCS_COMP = $(VCS_COMP_FLAGS) \
+ $(QUIET) \
+ $(VCS_UVM_ARGS) \
+ $(VCS_USER_COMPILE_ARGS) \
+ +incdir+$(DV_UVME_PATH) \
+ +incdir+$(DV_UVMT_PATH) \
+ -f $(CV_CORE_MANIFEST) \
+ $(VCS_FILE_LIST) \
+ $(UVM_PLUSARGS)
+
+comp: mk_vcs_dir $(CV_CORE_PKG) $(SVLIB_PKG) $(OVP_MODEL_DPI) $(LIBS)
+ @echo "$(BANNER)"
+ @echo "* $(SIMULATOR) compile"
+ @echo "* Log: $(SIM_CFG_RESULTS)/vcs.log"
+ @echo "$(BANNER)"
+ mkdir -p $(VCS_OUT)
+ cd $(VCS_OUT) && $(VCS) $(VCS_COMP) -top uvmt_$(CV_CORE_LC)_tb
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+VCS_SIM_PREREQ = comp
+endif
+
+ifeq ($(call IS_YES,$(VCS_SINGLE_STEP)), YES)
+ VCS_SIM_PREREQ = mk_vcs_dir $(CV_CORE_PKG) $(OVP_MODEL_DPI)
+ VCS_COMP_RUN = $(VCS_COMP) $(VCS_RUN_BASE_FLAGS)
+endif
+
+################################################################################
+# If the configuration specified OVPSIM arguments, generate an ovpsim.ic file and
+# set IMPERAS_TOOLS to point to it
+gen_ovpsim_ic:
+ @rm -f $(SIM_RUN_RESULTS)/ovpsim.ic
+ @mkdir -p $(SIM_RUN_RESULTS)
+ @touch $(SIM_RUN_RESULTS)/ovpsim.ic
+ @if [ ! -z "$(CFG_OVPSIM)" ]; then \
+ echo "$(CFG_OVPSIM)" > $(SIM_RUN_RESULTS)/ovpsim.ic; \
+ fi
+export IMPERAS_TOOLS=$(SIM_RUN_RESULTS)/ovpsim.ic
+
+################################################################################
+# The general test target
+test: $(VCS_SIM_PREREQ) hex gen_ovpsim_ic
+ @echo "$(BANNER)"
+ @echo "* Running simulation with $(SIMULATOR)"
+ @echo "$(BANNER)"
+ mkdir -p $(SIM_RUN_RESULTS) && \
+ cd $(SIM_RUN_RESULTS) && \
+ $(VCS_OUT)/$(SIMV) \
+ -l vcs-$(TEST_NAME).log \
+ -cm_name $(TEST_NAME) $(VCS_RUN_FLAGS) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS) \
+ +UVM_TESTNAME=$(TEST_UVM_TEST) \
+ +elf_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).elf \
+ +firmware=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex \
+ +itb_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).itb
+
+###############################################################################
+# Run a single test-program from the RISC-V Compliance Test-suite. The parent
+# Makefile of this .mk implements "all_compliance", the target that
+# compiles the test-programs.
+#
+# There is a dependancy between RISCV_ISA and COMPLIANCE_PROG which *you* are
+# required to know. For example, the I-ADD-01 test-program is part of the rv32i
+# testsuite.
+# So this works:
+# make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+# But this does not:
+# make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+#
+RISCV_ISA ?= rv32i
+COMPLIANCE_PROG ?= I-ADD-01
+
+SIG_ROOT ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)
+SIG ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)_$(RUN_INDEX)/$(COMPLIANCE_PROG).signature_output
+REF ?= $(COMPLIANCE_PKG)/riscv-test-suite/$(RISCV_ISA)/references/$(COMPLIANCE_PROG).reference_output
+TEST_PLUSARGS ?= +signature=$(COMPLIANCE_PROG).signature_output
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+VCS_COMPLIANCE_PREREQ = comp build_compliance
+endif
+
+compliance: $(VCS_COMPLIANCE_PREREQ)
+ mkdir -p $(SIM_RESULTS)/$(COMPLIANCE_PROG)_$(RUN_INDEX) && cd $(SIM_RESULTS)/$(COMPLIANCE_PROG)_$(RUN_INDEX) && \
+ export IMPERAS_TOOLS=$(CORE_V_VERIF)/$(CV_CORE_LC)/tests/cfg/ovpsim_no_pulp.ic && \
+ $(SIM_RESULTS)/$(SIMV) -l vcs-$(COMPLIANCE_PROG).log -cm_test riscv-compliance $(VCS_COMP_RUN) $(TEST_PLUSARGS) \
+ +UVM_TESTNAME=uvmt_$(CV_CORE_LC)_firmware_test_c \
+ +firmware=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).hex \
+ +elf_file=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).elf
+
+###############################################################################
+# Use Google instruction stream generator (RISCV-DV) to create new test-programs
+comp_corev-dv: $(RISCVDV_PKG) $(CV_CORE_PKG)
+ mkdir -p $(SIM_COREVDV_RESULTS)
+ cd $(SIM_COREVDV_RESULTS) && \
+ $(VCS) $(VCS_COMP_FLAGS) \
+ $(QUIET) $(VCS_USER_COMPILE_ARGS) \
+ $(VCS_PMA_INC) \
+ +incdir+$(CV_CORE_COREVDV_PKG)/target/$(CV_CORE_LC) \
+ +incdir+$(RISCVDV_PKG)/user_extension \
+ +incdir+$(COREVDV_PKG) \
+ +incdir+$(CV_CORE_COREVDV_PKG) \
+ $(CFG_COMPILE_FLAGS) \
+ -f $(COREVDV_PKG)/manifest.f \
+ -l vcs.log
+
+corev-dv: clean_riscv-dv clone_riscv-dv comp_corev-dv
+
+gen_corev-dv: $(LIBS)
+ @echo "$(BANNER)"
+ @echo "* Generating $(TEST) with corev-dv..."
+ @echo "* with VCS_RUN_FLAGS = $(VCS_RUN_FLAGS) "
+ @echo "$(BANNER)"
+ mkdir -p $(SIM_COREVDV_RESULTS)/$(TEST)
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ mkdir -p $(SIM_TEST_RESULTS)/$$idx/test_program; \
+ done
+ cd $(SIM_COREVDV_RESULTS)/$(TEST) && \
+ ../$(SIMV) -R $(VCS_RUN_FLAGS) \
+ -l $(TEST)_$(GEN_START_INDEX)_$(GEN_NUM_TESTS).log \
+ +start_idx=$(GEN_START_INDEX) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +asm_file_name_opts=$(TEST) \
+ +ldgen_cp_test_path=$(SIM_TEST_RESULTS) \
+ $(CFG_PLUSARGS) \
+ $(TEST_CFG_FILE_PLUSARGS) \
+ $(GEN_PLUSARGS)
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ cp -f ${BSP}/link_corev-dv.ld ${SIM_TEST_RESULTS}/$$idx/test_program/link.ld; \
+ cp ${SIM_COREVDV_RESULTS}/${TEST}/${TEST}_$$idx.S ${SIM_TEST_RESULTS}/$$idx/test_program; \
+ done
+
+################################################################################
+# Invoke post-process waveform viewer
+waves:
+ $(WAVES_CMD)
+
+################################################################################
+# Invoke post-process coverage viewer
+cov_merge:
+ $(MKDIR_P) $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)
+ rm -rf $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)/*
+ cd $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+ COVERAGE_TARGET_DIR=$(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)
+else
+ COVERAGE_TARGET_DIR=$(SIM_CFG_RESULTS)/$(TEST_NAME)
+endif
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+ COVERAGE_TARGET_DIR=$(SIM_RESULTS)/$(MERGED_COV_DIR)
+else
+ COVERAGE_TARGET_DIR=$(SIM_RESULTS)/$(TEST_NAME)_$(RUN_INDEX)
+endif
+
+# the report is in html format: use a browser to access it when GUI mode is selected
+ifeq ($(call IS_YES,$(GUI)),YES)
+cov: $(COV_MERGE)
+ cd $(COVERAGE_TARGET_DIR) && browse urgReport/dashboard.html
+else
+cov: $(COV_MERGE)
+ cd $(COVERAGE_TARGET_DIR) && $(URG) $(COV_ARGS)
+endif
+
+###############################################################################
+# Clean up your mess!
+
+clean:
+ @echo "$(MAKEFILE_LIST)"
+ rm -rf $(SIM_RESULTS)
+
+# Files created by Eclipse when using the Imperas ISS + debugger
+clean_eclipse:
+ rm -f eguieclipse.log
+ rm -f idebug.log
+ rm -f stdout.txt
+ rm -rf workspace
+
+# All generated files plus the clone of the RTL
+clean_all: clean clean_eclipse clean_riscv-dv clean_test_programs clean_bsp clean_compliance clean_embench clean_dpi_dasm_spike clean_svlib
+ rm -rf $(CV_CORE_PKG)
diff --git a/mk/uvmt/vsim.mk b/mk/uvmt/vsim.mk
new file mode 100644
index 0000000..75e9ed6
--- /dev/null
+++ b/mk/uvmt/vsim.mk
@@ -0,0 +1,585 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+###############################################################################
+#
+# VSIM-specific Makefile for the Core-V-Verif "uvmt" testbench.
+# VSIM is the Mentor Graphics Questa SystemVerilog simulator.
+#
+###############################################################################
+
+# Executables
+VLIB = vlib
+VMAP = vmap
+VLOG = $(CV_SIM_PREFIX) vlog
+VOPT = $(CV_SIM_PREFIX) vopt
+VSIM = $(CV_SIM_PREFIX) vsim
+VISUALIZER = $(CV_TOOL_PREFIX) visualizer
+VCOVER = vcover
+
+# Paths
+VWORK = work
+VSIM_COV_MERGE_DIR = $(SIM_CFG_RESULTS)/$(CFG)/merged
+UVM_HOME ?= $(abspath $(shell which $(VLIB))/../../verilog_src/uvm-1.2/src)
+export QUESTASIM_HOME ?= $(abspath $(shell which $(VLIB))/../../)
+USES_DPI = 1
+
+# Special var to point to tool and installation dependent path of DPI headers.
+# Used to recompile dpi_dasm_spike if needed (by default, not needed).
+DPI_INCLUDE ?= $(abspath $(shell which $(VLIB))/../../include)
+
+# Default flags
+VSIM_USER_FLAGS ?=
+VOPT_COV ?= +cover=setf+$(RTLSRC_VLOG_TB_TOP).
+VSIM_COV ?= -coverage
+VOPT_WAVES_ADV_DEBUG ?= -designfile design.bin
+VSIM_WAVES_ADV_DEBUG ?= -qwavedb=+signal+assertion+ignoretxntime+msgmode=both
+VSIM_WAVES_DO ?= $(VSIM_SCRIPT_DIR)/waves.tcl
+
+# Common QUIET flag defaults to -quiet unless VERBOSE is set
+ifeq ($(call IS_YES,$(VERBOSE)),YES)
+QUIET=
+else
+QUIET=-quiet
+endif
+
+ifeq ($(USES_DPI),1)
+ DPILIB_VLOG_OPT =
+ DPILIB_VSIM_OPT = -sv_lib $(UVM_HOME)/../../../uvm-1.2/linux_x86_64/uvm_dpi
+ DPILIB_TARGET = dpi_lib$(BITS)
+else
+ DPILIB_VLOG_OPT = +define+UVM_NO_DPI
+ DPILIB_VSIM_OPT =
+ DPILIB_TARGET =
+endif
+
+LIBDIR = $(UVM_HOME)/lib
+LIBNAME = uvm_dpi
+
+OPT_RV_ISA_DIR = $(if $(RISCV_ISA),/$(RISCV_ISA),)
+
+###############################################################################
+# LDGEN VLOG (Compilation)
+VSIM_PMA_INC += +incdir+$(TBSRC_HOME)/uvmt \
+ +incdir+$(CV_CORE_PKG)/rtl/include \
+ +incdir+$(CV_CORE_COREVDV_PKG)/ldgen \
+ +incdir+$(abspath $(MAKE_PATH)/../../../lib/mem_region_gen)
+
+VLOG_LDGEN_FLAGS ?= \
+ -suppress 2577 \
+ -suppress 2583 \
+ -suppress 13185 \
+ -suppress 13314 \
+ -suppress 13288 \
+ -suppress 2181 \
+ -suppress 13262 \
+ -timescale "1ns/1ps" \
+ -sv \
+ -mfcu \
+ +acc=rb \
+ $(QUIET)
+
+VOPT_LDGEN_FLAGS ?= \
+ -debugdb \
+ -fsmdebug \
+ -suppress 7034 \
+ +acc \
+ $(QUIET)
+
+VSIM_LDGEN_FLAGS ?= \
+ -batch \
+ -do $(VSIM_SCRIPT_DIR)/vsim.tcl
+
+###############################################################################
+# VLOG (Compilation)
+VLOG_FLAGS ?= \
+ -suppress 2577 \
+ -suppress 2583 \
+ -suppress 13185 \
+ -suppress 13314 \
+ -suppress 13288 \
+ -suppress 2181 \
+ -suppress 13262 \
+ -suppress 13071 \
+ -suppress 13401 \
+ -suppress vlog-2745 \
+ -timescale "1ns/1ps" \
+ -sv \
+ -64 \
+ -mfcu \
+ +acc=rb \
+ $(QUIET) \
+ -writetoplevels uvmt_$(CV_CORE_LC)_tb
+
+VLOG_FILE_LIST = -f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist
+
+VLOG_FLAGS += $(DPILIB_VLOG_OPT)
+
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+ ifeq ($(ISS),IMPERAS)
+ VLOG_FILE_LIST += -f $(DV_UVMT_PATH)/imperas_iss.flist
+ endif
+ ifeq ($(ISS),SPIKE)
+ VSIM_FLAGS += -sv_lib $(SPIKE_CUSTOMEXT_LIB)
+ VSIM_FLAGS += -sv_lib $(SPIKE_RISCV_LIB)
+ VSIM_FLAGS += -sv_lib $(SPIKE_DISASM_LIB)
+ LIBS = spike_lib
+ endif
+endif
+
+ifeq ($(call IS_YES,$(COMPILE_SPIKE)),YES)
+ VSIM_FLAGS += -sv_lib $(SPIKE_FESVR_LIB)
+ LIBS = spike_lib
+endif
+
+VLOG_FLAGS += "+define+$(CV_CORE_UC)_TRACE_EXECUTION"
+VLOG_FLAGS += "+define+UVM"
+VLOG_FLAGS += "+define+$(CORE_DEFINES)"
+
+###############################################################################
+# VOPT (Optimization)
+VOPT_FLAGS ?= \
+ -64 \
+ -debugdb \
+ -fsmdebug \
+ -suppress 7034 \
+ +acc \
+ $(QUIET)
+
+###############################################################################
+# VSIM (Simulaion)
+
+VSIM_FLAGS += $(VSIM_USER_FLAGS)
+VSIM_FLAGS += $(USER_RUN_FLAGS)
+VSIM_FLAGS += -sv_seed $(RNDSEED)
+VSIM_FLAGS += -64
+VSIM_FLAGS += -suppress 7031
+VSIM_FLAGS += -suppress 8858
+VSIM_FLAGS += -suppress 8522
+VSIM_FLAGS += -suppress 8550
+VSIM_FLAGS += -suppress 8549
+VSIM_FLAGS += -permit_unmatched_virtual_intf
+VSIM_DEBUG_FLAGS ?= -debugdb
+VSIM_GUI_FLAGS ?= -gui -debugdb
+VSIM_SCRIPT_DIR = $(abspath $(MAKE_PATH)/../tools/vsim)
+
+VSIM_UVM_ARGS = +incdir+$(UVM_HOME)/src $(UVM_HOME)/src/uvm_pkg.sv
+
+VSIM_FLAGS += -sv_lib $(basename $(OVP_MODEL_DPI))
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+VSIM_FLAGS += +USE_ISS
+else
+VSIM_FLAGS += +DISABLE_OVPSIM
+endif
+ifeq ($(call IS_YES,$(TEST_DISABLE_ALL_CSR_CHECKS)),YES)
+VSIM_FLAGS +="+DISABLE_ALL_CSR_CHECKS"
+endif
+ifneq ($(TEST_DISABLE_CSR_CHECK),)
+VSIM_FLAGS += +DISABLE_CSR_CHECK=$(TEST_DISABLE_CSR_CHECK)
+endif
+
+VSIM_FLAGS += -sv_lib $(basename $(DPI_DASM_LIB))
+VSIM_FLAGS += -sv_lib $(basename $(abspath $(SVLIB_LIB)))
+
+# Skip compile if requested (COMP=NO)
+ifneq ($(call IS_NO,$(COMP)),NO)
+VSIM_SIM_PREREQ = comp
+endif
+
+################################################################################
+# Coverage database generation
+ifeq ($(call IS_YES,$(COV)),YES)
+VOPT_FLAGS += $(VOPT_COV)
+VSIM_FLAGS += $(VSIM_COV)
+VSIM_FLAGS += -do 'set TEST ${VSIM_TEST}; source $(VSIM_SCRIPT_DIR)/cov.tcl'
+endif
+
+################################################################################
+# Waveform generation
+ifeq ($(call IS_YES,$(WAVES)),YES)
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+VSIM_FLAGS += $(VSIM_WAVES_ADV_DEBUG)
+else
+VSIM_FLAGS += -do $(VSIM_WAVES_DO)
+endif
+endif
+
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+VOPT_FLAGS += $(VOPT_WAVES_ADV_DEBUG)
+endif
+
+################################################################################
+# Interactive simulation
+ifeq ($(call IS_YES,$(GUI)),YES)
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+VSIM_FLAGS += -visualizer=+designfile=../design.bin
+else
+VSIM_FLAGS += -gui
+endif
+VSIM_FLAGS += -do $(VSIM_SCRIPT_DIR)/gui.tcl
+else
+VSIM_FLAGS += -batch
+VSIM_FLAGS += -do $(VSIM_SCRIPT_DIR)/vsim.tcl
+endif
+
+################################################################################
+# Coverage command
+COV_FLAGS =
+COV_REPORT = cov_report
+COV_MERGE_TARGET =
+COV_MERGE_FIND = find $(SIM_CFG_RESULTS) -type f -name "*.ucdb" | grep -v merged.ucdb
+COV_MERGE_FLAGS=merge -64 -out merged.ucdb -inputs ucdb.list
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+COV_DIR=$(VSIM_COV_MERGE_DIR)
+COV_MERGE_TARGET=cov_merge
+else
+COV_DIR=$(SIM_RUN_RESULTS)
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+ifeq ($(call IS_YES,$(GUI)),YES)
+# Merged coverage GUI
+COV_FLAGS=-viewcov $(VSIM_COV_MERGE_DIR)/merged.ucdb
+else
+# Merged coverage report
+COV_FLAGS=-c -viewcov $(VSIM_COV_MERGE_DIR)/merged.ucdb -do "file delete -force $(COV_REPORT); coverage report -html -details -precision 2 -annotate -output $(COV_REPORT); exit -f"
+endif
+else
+ifeq ($(call IS_YES,$(GUI)),YES)
+# Test coverage GUI
+COV_FLAGS=-viewcov $(TEST).ucdb
+else
+# Test coverage report
+COV_FLAGS=-c -viewcov $(TEST).ucdb -do "file delete -force $(COV_REPORT); coverage report -html -details -precision 2 -annotate -output $(COV_REPORT); exit -f"
+endif
+endif
+endif
+
+################################################################################
+# Waveform (post-process) command line
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+WAVES_CMD = \
+ cd $(SIM_RUN_RESULTS) && \
+ $(VISUALIZER) \
+ -designfile $(SIM_CFG_RESULTS)/design.bin \
+ -wavefile qwave.db
+else
+WAVES_CMD = \
+ cd $(SIM_RUN_RESULTS) && \
+ $(VSIM) \
+ -gui \
+ -view vsim.wlf
+endif
+
+# Compute vsim (run) prereqs, by default do a full compile + run when running
+# a test, set COMP=NO to skip vlib-vlog-vopt and just run vsim
+ifneq ($(call IS_NO,$(COMP)),NO)
+VSIM_RUN_PREREQ = opt
+endif
+
+################################################################################
+# Targets
+
+.PHONY: no_rule help mk_vsim_dir lib comp opt run
+
+no_rule:
+ @echo 'makefile: SIMULATOR is set to $(SIMULATOR), but no rule/target specified.'
+ @echo 'try "make SIMULATOR=vsim sanity" (or just "make sanity" if shell ENV variable SIMULATOR is already set).'
+
+help:
+ vsim -help
+
+################################################################################
+# ldgen generation targets
+vlog_ldgen: $(CV_CORE_PKG) $(SVLIB_PKG)
+ @echo "$(BANNER)"
+ @echo "* Generating linker scripts in $(SIM_LDGEN_RESULTS)"
+ @echo "$(BANNER)"
+ $(MKDIR_P) $(SIM_LDGEN_RESULTS)
+ if [ ! -d "$(SIM_LDGEN_RESULTS)/$(VWORK)" ]; then \
+ $(VLIB) $(SIM_LDGEN_RESULTS)/$(VWORK); \
+ fi
+
+ cd $(SIM_LDGEN_RESULTS) && \
+ $(VLOG) \
+ $(VLOG_LDGEN_FLAGS) \
+ $(VSIM_PMA_INC) \
+ $(CFG_COMPILE_FLAGS) \
+ $(TBSRC_HOME)/ldgen/ldgen_tb.sv \
+ -l vlog-ldgen.log
+
+vopt_ldgen:
+ cd $(SIM_LDGEN_RESULTS) && \
+ $(VOPT) \
+ $(VOPT_LDGEN_FLAGS) \
+ -work $(VWORK) \
+ ldgen_tb \
+ -o ldgen_tb_vopt \
+ -l vopt-ldgen.log
+
+vsim_ldgen:
+ cd $(SIM_LDGEN_RESULTS) && \
+ $(VSIM) \
+ $(VSIM_LDGEN_FLAGS) \
+ -work $(VWORK) \
+ $(CFG_PLUSARGS) \
+ +ldgen_cp_test_path=$(SIM_LDGEN_RESULTS) \
+ ldgen_tb_vopt \
+ -l vsim-ldgen.log
+
+ldgen: vlog_ldgen vopt_ldgen vsim_ldgen
+
+################################################################################
+# corev-dv generation targets
+
+vlog_corev-dv:
+ $(MKDIR_P) $(SIM_COREVDV_RESULTS)
+ $(MKDIR_P) $(COREVDV_PKG)/out_$(DATE)/run
+ cd $(SIM_COREVDV_RESULTS) && \
+ $(VLIB) $(VWORK)
+ cd $(SIM_COREVDV_RESULTS) && \
+ $(VLOG) \
+ $(VLOG_FLAGS) \
+ +incdir+$(UVM_HOME) \
+ $(VSIM_PMA_INC) \
+ $(UVM_HOME)/uvm_pkg.sv \
+ +incdir+$(CV_CORE_COREVDV_PKG)/target/$(CV_CORE_LC) \
+ +incdir+$(RISCVDV_PKG)/user_extension \
+ +incdir+$(COREVDV_PKG) \
+ +incdir+$(CV_CORE_COREVDV_PKG) \
+ $(CFG_COMPILE_FLAGS) \
+ -f $(COREVDV_PKG)/manifest.f \
+ $(CFG_PLUSARGS) \
+ -l vlog.log
+
+vopt_corev-dv:
+ cd $(SIM_COREVDV_RESULTS) && \
+ $(VOPT) \
+ -work $(VWORK) \
+ $(VOPT_FLAGS) \
+ $(CV_CORE_LC)_instr_gen_tb_top \
+ -o $(CV_CORE_LC)_instr_gen_tb_top_vopt \
+ -l vopt.log
+
+gen_corev-dv: $(LIBS)
+ mkdir -p $(SIM_COREVDV_RESULTS)/$(TEST)
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ mkdir -p $(SIM_TEST_RESULTS)/$$idx/test_program; \
+ done
+ cd $(SIM_COREVDV_RESULTS)/$(TEST) && \
+ $(VMAP) work ../work
+ cd $(SIM_COREVDV_RESULTS)/$(TEST) && \
+ $(VSIM) \
+ $(VSIM_FLAGS) \
+ $(CV_CORE_LC)_instr_gen_tb_top_vopt \
+ $(DPILIB_VSIM_OPT) \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ -l $(TEST)_$(GEN_START_INDEX)_$(GEN_NUM_TESTS).log \
+ +start_idx=$(GEN_START_INDEX) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +asm_file_name_opts=$(TEST) \
+ +ldgen_cp_test_path=$(SIM_TEST_RESULTS) \
+ $(CFG_PLUSARGS) \
+ $(GEN_PLUSARGS)
+
+ # Copy out final assembler files to test directory
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ cp -f ${BSP}/link_corev-dv.ld ${SIM_TEST_RESULTS}/$$idx/test_program/link.ld; \
+ cp ${SIM_COREVDV_RESULTS}/${TEST}/${TEST}_$$idx.S ${SIM_TEST_RESULTS}/$$idx/test_program; \
+ done
+
+comp_corev-dv: $(RISCVDV_PKG) $(CV_CORE_PKG) vlog_corev-dv vopt_corev-dv
+
+corev-dv: clean_riscv-dv clone_riscv-dv comp_corev-dv
+
+###############################################################################
+# Run a single test-program from the RISC-V Compliance Test-suite. The parent
+# Makefile of this .mk implements "all_compliance", the target that
+# compiles the test-programs.
+#
+# There is a dependancy between RISCV_ISA and COMPLIANCE_PROG which *you* are
+# required to know. For example, the I-ADD-01 test-program is part of the rv32i
+# testsuite.
+# So this works:
+# make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+# But this does not:
+# make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+#
+RISCV_ISA ?= rv32i
+COMPLIANCE_PROG ?= I-ADD-01
+
+SIG_ROOT ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)
+SIG ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)/$(COMPLIANCE_PROG).signature_output
+REF ?= $(COMPLIANCE_PKG)/riscv-test-suite/$(RISCV_ISA)/references/$(COMPLIANCE_PROG).reference_output
+COMPLIANCE_RUN_DIR = $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)
+TEST_PLUSARGS ?= +signature=$(COMPLIANCE_PROG).signature_output
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+VSIM_COMPLIANCE_PREREQ = build_compliance
+endif
+
+# Target to run VSIM (i.e. run the simulation)
+compliance: $(VSIM_COMPLIANCE_PREREQ) $(VSIM_RUN_PREREQ) gen_ovpsim_ic
+ @echo "$(BANNER)"
+ @echo "* Running vsim in $(COMPLIANCE_RUN_DIR)"
+ @echo "* Log: $(COMPLIANCE_RUN_DIR)/vsim-$(COMPLIANCE_PROG).log"
+ @echo "$(BANNER)"
+ mkdir -p $(COMPLIANCE_RUN_DIR) && \
+ cd $(COMPLIANCE_RUN_DIR) && \
+ $(VMAP) work $(SIM_CFG_RESULTS)/work
+ cd $(COMPLIANCE_RUN_DIR) && \
+ $(VSIM) \
+ -work $(VWORK) \
+ $(VSIM_FLAGS) \
+ -l vsim-$(COMPLIANCE_PROG).log \
+ $(DPILIB_VSIM_OPT) \
+ +UVM_TESTNAME=uvmt_$(CV_CORE_LC)_firmware_test_c \
+ $(RTLSRC_VOPT_TB_TOP) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS) \
+ +firmware=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).hex \
+ +elf_file=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).elf
+
+compliance: export IMPERAS_TOOLS=$(CORE_V_VERIF)/$(CV_CORE_LC)/tests/cfg/ovpsim_no_pulp.ic
+
+################################################################################
+# Questa simulation targets
+
+mk_vsim_dir:
+ $(MKDIR_P) $(SIM_CFG_RESULTS)
+
+################################################################################
+# If the configuration specified OVPSIM arguments, generate an ovpsim.ic file and
+# set IMPERAS_TOOLS to point to it
+gen_ovpsim_ic:
+ @rm -f $(SIM_RUN_RESULTS)/ovpsim.ic
+ @mkdir -p $(SIM_RUN_RESULTS)
+ @touch $(SIM_RUN_RESULTS)/ovpsim.ic
+ @if [ ! -z "$(CFG_OVPSIM)" ]; then \
+ echo "$(CFG_OVPSIM)" > $(SIM_RUN_RESULTS)/ovpsim.ic; \
+ fi
+export IMPERAS_TOOLS=$(SIM_RUN_RESULTS)/ovpsim.ic
+
+# Target to create work directory in $(VSIM_RESULTS)/
+lib: mk_vsim_dir $(CV_CORE_PKG) $(SVLIB_PKG) $(TBSRC_PKG) $(TBSRC)
+ if [ ! -d "$(SIM_CFG_RESULTS)/$(VWORK)" ]; then \
+ $(VLIB) $(SIM_CFG_RESULTS)/$(VWORK); \
+ fi
+
+# Target to run vlog over SystemVerilog source in $(VSIM_RESULTS)/
+vlog: $(LIBS) lib
+ @echo "$(BANNER)"
+ @echo "* Running vlog in $(SIM_CFG_RESULTS)"
+ @echo "* Log: $(SIM_CFG_RESULTS)/vlog.log"
+ @echo "$(BANNER)"
+ cd $(SIM_CFG_RESULTS) && \
+ $(VLOG) \
+ -work $(VWORK) \
+ -l vlog.log \
+ $(VLOG_FLAGS) \
+ $(CFG_COMPILE_FLAGS) \
+ +incdir+$(DV_UVME_PATH) \
+ +incdir+$(DV_UVMT_PATH) \
+ +incdir+$(UVM_HOME) \
+ $(UVM_HOME)/uvm_pkg.sv \
+ -f $(CV_CORE_MANIFEST) \
+ $(VLOG_FILE_LIST) \
+ $(TBSRC_PKG)
+
+# Target to run vopt over compiled code in $(VSIM_RESULTS)/
+opt: vlog
+ @echo "$(BANNER)"
+ @echo "* Running vopt in $(SIM_CFG_RESULTS)"
+ @echo "* Log: $(SIM_CFG_RESULTS)/vopt.log"
+ @echo "$(BANNER)"
+ cd $(SIM_CFG_RESULTS) && \
+ $(VOPT) \
+ -work $(VWORK) \
+ -l vopt.log \
+ $(VOPT_FLAGS) \
+ $(RTLSRC_VLOG_TB_TOP) \
+ -o $(RTLSRC_VOPT_TB_TOP)
+
+comp: opt
+
+RUN_DIR = $(abspath $(SIM_RUN_RESULTS))
+
+# Target to run VSIM (i.e. run the simulation)
+run: $(VSIM_RUN_PREREQ) gen_ovpsim_ic
+ @echo "$(BANNER)"
+ @echo "* Running vsim in $(RUN_DIR)"
+ @echo "* Log: $(RUN_DIR)/vsim-$(VSIM_TEST).log"
+ @echo "$(BANNER)"
+ mkdir -p $(RUN_DIR) && \
+ cd $(RUN_DIR) && \
+ $(VMAP) work $(SIM_CFG_RESULTS)/work
+ cd $(RUN_DIR) && \
+ $(VSIM) \
+ -work $(VWORK) \
+ $(VSIM_FLAGS) \
+ -l vsim-$(VSIM_TEST).log \
+ $(DPILIB_VSIM_OPT) \
+ +UVM_TESTNAME=$(TEST_UVM_TEST) \
+ $(RTLSRC_VOPT_TB_TOP) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS)
+
+################################################################################
+# Test targets
+
+################################################################################
+# The new general test target
+
+test: VSIM_TEST=$(TEST_PROGRAM)
+test: VSIM_FLAGS += +firmware=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex
+test: VSIM_FLAGS += +elf_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).elf
+test: VSIM_FLAGS += +itb_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).itb
+test: hex run
+
+################################################################################
+# Invoke post-process waveform viewer
+waves:
+ @if [ -z "$(TEST)" ]; then \
+ echo "Error: TEST variable must be defined"; \
+ exit 2; \
+ fi
+ $(WAVES_CMD)
+
+################################################################################
+# Invoke coverage
+cov_merge:
+ $(MKDIR_P) $(VSIM_COV_MERGE_DIR)
+ cd $(VSIM_COV_MERGE_DIR) && \
+ $(COV_MERGE_FIND) > $(VSIM_COV_MERGE_DIR)/ucdb.list
+ cd $(VSIM_COV_MERGE_DIR) && \
+ $(VCOVER) \
+ $(COV_MERGE_FLAGS)
+cov: $(COV_MERGE_TARGET)
+ cd $(COV_DIR) && \
+ $(VSIM) \
+ $(COV_FLAGS)
+
+###############################################################################
+# Clean up your mess!
+
+clean:
+ rm -rf $(SIM_RESULTS)
+
+# All generated files plus the clone of the RTL
+clean_all: clean clean_riscv-dv clean_test_programs clean_bsp clean_compliance clean_embench clean_dpi_dasm_spike clean_svlib
+ rm -rf $(CV_CORE_PKG)
diff --git a/mk/uvmt/xrun.mk b/mk/uvmt/xrun.mk
new file mode 100644
index 0000000..8e2ccb0
--- /dev/null
+++ b/mk/uvmt/xrun.mk
@@ -0,0 +1,510 @@
+###############################################################################
+#
+# Copyright 2020 OpenHW Group
+#
+# Licensed under the Solderpad Hardware Licence, 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
+#
+# https://solderpad.org/licenses/
+#
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
+#
+###############################################################################
+#
+# XRUN-specific Makefile for any uvmt testbench.
+# XRUN is the Cadence Xcelium SystemVerilog simulator (https://cadence.com/)
+#
+###############################################################################
+
+#
+# Cadence do not (officially) support Ubuntu, so suppress the nonzero return code from XRUN
+#
+OS_IS_UBUNTU = $(findstring Ubuntu,$(shell lsb_release -d))
+ifeq ($(OS_IS_UBUNTU),Ubuntu)
+ .IGNORE: hello-world comp test compliance comp_corev-dv corev-dv gen_corev-dv
+endif
+
+# Executables
+XRUN = $(CV_SIM_PREFIX) xrun
+SIMVISION = $(CV_TOOL_PREFIX) simvision
+INDAGO = $(CV_TOOL_PREFIX) indago
+IMC = $(CV_SIM_PREFIX) imc
+
+XRUN_UVMHOME_ARG ?= CDNS-1.2-ML
+
+# Flags
+XRUN_COMP_FLAGS ?= -64bit \
+ -disable_sem2009 \
+ -access +rwc \
+ -nowarn UEXPSC \
+ -lwdgen \
+ -sv \
+ -uvm \
+ -uvmhome $(XRUN_UVMHOME_ARG) \
+ $(TIMESCALE) \
+ $(SV_CMP_FLAGS)
+
+XRUN_LDGEN_COMP_FLAGS ?= -64bit -disable_sem2009 -access +rwc \
+ -nowarn UEXPSC \
+ -nowarn DLCPTH \
+ -sv \
+ $(TIMESCALE) $(SV_CMP_FLAGS)
+
+XRUN_RUN_BASE_FLAGS ?= -64bit $(XRUN_GUI) -licqueue +UVM_VERBOSITY=$(XRUN_UVM_VERBOSITY) \
+ $(XRUN_PLUSARGS) -svseed $(RNDSEED) -sv_lib $(OVP_MODEL_DPI)
+XRUN_GUI ?=
+XRUN_SINGLE_STEP ?=
+XRUN_ELAB_COV = -covdut uvmt_$(CV_CORE_LC)_tb -coverage b:e:f:u
+XRUN_ELAB_COVFILE = -covfile $(abspath $(MAKE_PATH)/../tools/xrun/covfile.tcl)
+XRUN_RUN_COV = -covscope uvmt_$(CV_CORE_LC)_tb \
+ -nowarn CGDEFN
+XRUN_RUN_BASE_FLAGS += -sv_lib $(DPI_DASM_LIB)
+XRUN_RUN_BASE_FLAGS += -sv_lib $(abspath $(SVLIB_LIB))
+
+XRUN_UVM_VERBOSITY ?= UVM_MEDIUM
+
+# Special var to point to tool and installation dependent path of DPI headers.
+# Used to recompile dpi_dasm_spike if needed (by default, not needed).
+DPI_INCLUDE ?= $(shell dirname $(shell which xrun))/../include
+
+# Necessary libraries for the PMA generator class
+XRUN_PMA_INC += +incdir+$(TBSRC_HOME)/uvmt \
+ +incdir+$(CV_CORE_PKG)/rtl/include \
+ +incdir+$(CV_CORE_COREVDV_PKG)/ldgen \
+ +incdir+$(abspath $(MAKE_PATH)/../../../lib/mem_region_gen)
+
+###############################################################################
+# Common QUIET flag defaults to -quiet unless VERBOSE is set
+ifeq ($(call IS_YES,$(VERBOSE)),YES)
+QUIET=
+else
+QUIET=-quiet
+endif
+
+################################################################################
+# GUI interactive simulation
+# GUI=YES enables interactive mode
+# ADV_DEBUG=YES will enable Indago, default is to use SimVision
+ifeq ($(call IS_YES,$(GUI)),YES)
+XRUN_GUI += -gui
+XRUN_USER_COMPILE_ARGS += -linedebug
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+XRUN_GUI += -indago
+endif
+endif
+
+################################################################################
+# Waveform generation
+# WAVES=YES enables waveform generation for entire testbench
+# WAVES_MEM=YES enables tracing memories and large vectors
+# ADV_DEBUG=YES will enable Indago waves, default is to generate SimVision waves
+ifeq ($(call IS_YES,$(WAVES_MEM)),YES)
+ ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+ XRUN_RUN_WAVES_FLAGS = -input $(abspath $(MAKE_PATH)/../tools/xrun/indago_mem.tcl)
+ else
+ XRUN_RUN_WAVES_FLAGS = -input $(abspath $(MAKE_PATH)/../tools/xrun/probe_mem.tcl)
+ endif
+else
+ ifeq ($(call IS_YES,$(WAVES)),YES)
+ ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+ XRUN_RUN_WAVES_FLAGS = -input $(abspath $(MAKE_PATH)/../tools/xrun/indago.tcl)
+ else
+ XRUN_RUN_WAVES_FLAGS = -input $(abspath $(MAKE_PATH)/../tools/xrun/probe.tcl)
+ endif
+ endif
+endif
+
+################################################################################
+# Waveform (post-process) command line
+ifeq ($(call IS_YES,$(ADV_DEBUG)),YES)
+WAVES_CMD = cd $(SIM_RUN_RESULTS) && $(INDAGO) -db ida.db
+else
+WAVES_CMD = cd $(SIM_RUN_RESULTS) && $(SIMVISION) waves.shm
+endif
+
+XRUN_USER_COMPILE_ARGS += $(USER_COMPILE_FLAGS)
+
+################################################################################
+# Coverage options
+# COV=YES generates coverage database, must be specified for comp and run
+IMC_MERGE_ARGS = merge -initial_model union_all -overwrite -message 1
+IMC_REPORT_ARGS = -exec $(CORE_V_VERIF)/$(CV_CORE)/sim/tools/xrun/cov_report.tcl
+MERGED_COV_DIR ?= merged_cov
+
+ifeq ($(call IS_YES,$(COV)),YES)
+XRUN_ELAB_COV_FLAGS += $(XRUN_ELAB_COV)
+XRUN_ELAB_COV_FLAGS += $(XRUN_ELAB_COVFILE)
+XRUN_RUN_COV_FLAGS += $(XRUN_RUN_COV)
+endif
+
+# Find command to gather ucd files
+COV_MERGE_FIND = find "$(SIM_CFG_RESULTS)" -type f -name "*.ucd" | grep -v d_cov | xargs dirname
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+COV_MERGE = cov_merge
+TEST = $(MERGED_COV_DIR)
+else
+COV_MERGE =
+endif
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+COV_DIR ?= $(XRUN_RESULTS)/$(CFG)/$(MERGED_COV_DIR)/cov_work/scope/merged
+else
+COV_DIR ?= cov_work/uvmt_$(CV_CORE_LC)_tb/$(TEST_NAME)
+endif
+
+ifeq ($(call IS_YES,$(GUI)),YES)
+COV_ARGS += -gui
+else
+COV_ARGS += $(IMC_REPORT_ARGS)
+endif
+
+################################################################################
+
+# File to `include "uvm_macros.svh" since Xcelium automatic UVM compilation
+# does not source the macros file.
+XRUN_UVM_MACROS_INC_FILE = $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC)_uvm_macros_inc.sv
+
+XRUN_FILE_LIST ?= -f $(DV_UVMT_PATH)/uvmt_$(CV_CORE_LC).flist
+XRUN_FILE_LIST += -f $(DV_UVMT_PATH)/imperas_iss.flist
+XRUN_USER_COMPILE_ARGS += +define+$(CV_CORE_UC)_TRACE_EXECUTION
+XRUN_USER_COMPILE_ARGS += +define+UVM
+ifeq ($(call IS_YES,$(USE_ISS)),YES)
+ XRUN_PLUSARGS += +USE_ISS
+else
+ XRUN_PLUSARGS += +DISABLE_OVPSIM
+endif
+ifeq ($(call IS_YES,$(USE_RVVI)),YES)
+ XRUN_PLUSARGS +="+USE_RVVI"
+endif
+ifeq ($(call IS_YES,$(TEST_DISABLE_ALL_CSR_CHECKS)),YES)
+ XRUN_PLUSARGS +="+DISABLE_ALL_CSR_CHECKS"
+endif
+ifneq ($(TEST_DISABLE_CSR_CHECK),)
+ XRUN_PLUSARGS += +DISABLE_CSR_CHECK=$(TEST_DISABLE_CSR_CHECK)
+endif
+
+# Simulate using latest elab
+XRUN_RUN_FLAGS ?=
+XRUN_RUN_FLAGS += -covoverwrite
+XRUN_RUN_FLAGS += $(XRUN_RUN_BASE_FLAGS)
+XRUN_RUN_FLAGS += $(XRUN_RUN_COV_FLAGS)
+XRUN_RUN_FLAGS += $(XRUN_USER_RUN_FLAGS)
+XRUN_RUN_FLAGS += $(USER_RUN_FLAGS)
+
+###############################################################################
+# Xcelium warning suppression
+
+# Xcelium constraint solver
+XRUN_RUN_FLAGS += -nowarn XCLGNOPTM
+XRUN_RUN_FLAGS += -nowarn RNDNOXCEL
+
+# Probes
+XRUN_RUN_FLAGS += -nowarn PRLDYN
+
+# Physical repository related to logical library in a cds.lib does not exist
+XRUN_COMP_FLAGS += -nowarn DLCPTH
+
+# Allow extra semicolons
+XRUN_COMP_FLAGS += -nowarn UEXPSC
+
+# SOP expression evaluates to a constant - remove from coverage calculation
+XRUN_COMP_FLAGS += -nowarn COVSEC
+
+# Warning that no timescale defined for package, this is by design as no
+# core-v-verif code should contain its own timescale
+XRUN_COMP_FLAGS += -nowarn TSNSPK
+
+# Warning on expression coverage speedup (only counts always blocks in expression if output changes)
+XRUN_COMP_FLAGS += -nowarn COVVPO
+XRUN_RUN_COV += -nowarn COVVPO
+
+# Warning on adding _T suffix to named block scoped assertion coverage
+XRUN_RUN_FLAGS += -nowarn COVNBT
+
+# Warning about new style struct expression scoring
+XRUN_COMP_FLAGS += -nowarn COVEOS
+
+# +incdir in -f file not used
+XRUN_COMP_FLAGS += -nowarn SPDUSD
+
+# scoring events not included in expression coverage
+XRUN_COMP_FLAGS += -nowarn COVNSO
+
+# instance reporting warings for covergroups
+XRUN_COMP_FLAGS += -nowarn COVCGN
+XRUN_COMP_FLAGS += -nowarn CGPIZE
+
+# per_instance option is 0
+XRUN_COMP_FLAGS += -nowarn CGPIDF
+
+# deselect_coverage -all warnings
+XRUN_COMP_FLAGS += -nowarn CGNSWA
+
+# deselect_coverage -all warnings
+XRUN_COMP_COREV_DV_FLAGS += -nowarn BNDWRN
+XRUN_COMP_COREV_DV_FLAGS += $(CFG_COMPILE_FLAGS)
+
+# instance reporting warings for covergroups
+XRUN_RUN_COV += -nowarn COVCGN
+XRUN_RUN_COV += -nowarn CGPIZE
+
+# Empty overgroup warnings (we purposely empty covergroups as part of filtering w/ configuration variables)
+XRUN_RUN_COV += -nowarn WCRTUP
+XRUN_RUN_COV += -nowarn WCOVPT
+XRUN_RUN_COV += -nowarn WCROSS
+
+# Un-named covergroup instances
+XRUN_RUN_COV += -nowarn CGDEFN
+
+###############################################################################
+# Targets
+
+no_rule:
+ @echo 'makefile: SIMULATOR is set to $(SIMULATOR), but no rule/target specified.'
+ @echo 'try "make SIMULATOR=xrun sanity" (or just "make sanity" if shell ENV variable SIMULATOR is already set).'
+
+help:
+ xrun -help
+
+.PHONY: comp test waves cov ldgen
+
+mk_xrun_dir:
+ $(MKDIR_P) $(SIM_CFG_RESULTS)
+
+# This special target is to support the special sanity target in the Common Makefile
+hello-world:
+ $(MAKE) test TEST=hello-world
+
+XRUN_COMP = $(XRUN_COMP_FLAGS) \
+ $(QUIET) \
+ $(CFG_COMPILE_FLAGS) \
+ $(XRUN_USER_COMPILE_ARGS) \
+ +incdir+$(DV_UVME_PATH) \
+ +incdir+$(DV_UVMT_PATH) \
+ $(XRUN_UVM_MACROS_INC_FILE) \
+ -f $(CV_CORE_MANIFEST) \
+ $(XRUN_FILE_LIST) \
+ $(UVM_PLUSARGS)
+
+comp: mk_xrun_dir $(CV_CORE_PKG) $(SVLIB_PKG)
+ @echo "$(BANNER)"
+ @echo "* Compiling xrun in $(SIM_CFG_RESULTS)"
+ @echo "* Log: $(SIM_CFG_RESULTS)/xrun.log"
+ @echo "$(BANNER)"
+ cd $(SIM_CFG_RESULTS) && $(XRUN) \
+ $(XRUN_COMP) \
+ $(XRUN_ELAB_COV_FLAGS) \
+ -top $(RTLSRC_VLOG_TB_TOP) \
+ -l xrun.log \
+ -elaborate
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+XRUN_SIM_PREREQ = comp
+endif
+
+XRUN_COMP_RUN = $(XRUN_RUN_FLAGS)
+
+ifeq ($(call IS_YES,$(XRUN_SINGLE_STEP)), YES)
+ XRUN_SIM_PREREQ = mk_xrun_dir $(CV_CORE_PKG)
+ XRUN_COMP_RUN = $(XRUN_COMP) $(XRUN_RUN_BASE_FLAGS)
+endif
+
+################################################################################
+# Linker script generator targets
+#
+# Standalone tb that generates appropriate linker files based on a given pma
+# configuration. Uses same code as the generator embedded in corev-dv.
+
+ldgen: $(CV_CORE_PKG)
+ @echo "$(BANNER)"
+ @echo "* Generating linker scripts in $(SIM_LDGEN_RESULTS)"
+ @echo "* Log: $(SIM_LDGEN_RESULTS)/xrun-ldgen.log"
+ @echo "$(BANNER)"
+ $(MKDIR_P) $(SIM_LDGEN_RESULTS)/xcelium.d && \
+ cd $(SIM_LDGEN_RESULTS)/xcelium.d && \
+ $(XRUN) \
+ -l xrun-ldgen.log \
+ $(XRUN_LDGEN_COMP_FLAGS)\
+ $(XRUN_PMA_INC) \
+ $(CFG_PLUSARGS) \
+ $(CFG_COMPILE_FLAGS) \
+ +ldgen_cp_test_path=$(SIM_LDGEN_RESULTS) \
+ $(TBSRC_HOME)/ldgen/ldgen_tb.sv \
+ -top $(basename $(notdir $(TBSRC_HOME)/ldgen/ldgen_tb.sv))
+ cp $(BSP)/link_pma.ld $(SIM_LDGEN_RESULTS)/link.ld
+
+################################################################################
+# If the configuration specified OVPSIM arguments, generate an ovpsim.ic file and
+# set IMPERAS_TOOLS to point to it
+gen_ovpsim_ic:
+ @rm -f $(SIM_CFG_RESULTS)/$(TEST_NAME)/$(RUN_INDEX)/ovpsim.ic
+ @mkdir -p $(SIM_CFG_RESULTS)/$(TEST_NAME)/$(RUN_INDEX);
+ @touch -f $(SIM_CFG_RESULTS)/$(TEST_NAME)/$(RUN_INDEX)/ovpsim.ic
+ @if [ ! -z "$(CFG_OVPSIM)" ]; then \
+ echo "$(CFG_OVPSIM)" > $(SIM_CFG_RESULTS)/$(TEST_NAME)/$(RUN_INDEX)/ovpsim.ic; \
+ fi
+export IMPERAS_TOOLS=ovpsim.ic
+
+################################################################################
+# The new general test target
+
+test: $(XRUN_SIM_PREREQ) hex gen_ovpsim_ic
+ mkdir -p $(SIM_RUN_RESULTS)/test_program && \
+ cd $(SIM_RUN_RESULTS) && \
+ $(XRUN) \
+ -R -xmlibdirname ../../xcelium.d \
+ -l xrun-$(TEST_NAME).log \
+ $(XRUN_COMP_RUN) \
+ $(XRUN_RUN_WAVES_FLAGS) \
+ -covtest $(TEST_NAME) \
+ $(CFG_PLUSARGS) \
+ $(TEST_PLUSARGS) \
+ +UVM_TESTNAME=$(TEST_UVM_TEST) \
+ +elf_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).elf \
+ +firmware=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).hex \
+ +itb_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).itb \
+ +nm_file=$(SIM_TEST_PROGRAM_RESULTS)/$(TEST_PROGRAM)$(OPT_RUN_INDEX_SUFFIX).nm
+ $(POST_TEST)
+
+###############################################################################
+# Run a single test-program from the RISC-V Compliance Test-suite. The parent
+# Makefile of this .mk implements "all_compliance", the target that
+# compiles the test-programs.
+#
+# There is a dependancy between RISCV_ISA and COMPLIANCE_PROG which *you* are
+# required to know. For example, the I-ADD-01 test-program is part of the rv32i
+# testsuite.
+# So this works:
+# make compliance RISCV_ISA=rv32i COMPLIANCE_PROG=I-ADD-01
+# But this does not:
+# make compliance RISCV_ISA=rv32imc COMPLIANCE_PROG=I-ADD-01
+#
+RISCV_ISA ?= rv32i
+COMPLIANCE_PROG ?= I-ADD-01
+
+SIG_ROOT ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)
+SIG ?= $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX)/$(COMPLIANCE_PROG).signature_output
+REF ?= $(COMPLIANCE_PKG)/riscv-test-suite/$(RISCV_ISA)/references/$(COMPLIANCE_PROG).reference_output
+TEST_PLUSARGS ?= +signature=$(COMPLIANCE_PROG).signature_output
+
+ifneq ($(call IS_NO,$(COMP)),NO)
+XRUN_COMPLIANCE_PREREQ = comp build_compliance
+endif
+
+compliance: $(XRUN_COMPLIANCE_PREREQ)
+ mkdir -p $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX) && \
+ cd $(SIM_CFG_RESULTS)/$(RISCV_ISA)/$(COMPLIANCE_PROG)/$(RUN_INDEX) && \
+ export IMPERAS_TOOLS=$(CORE_V_VERIF)/$(CV_CORE_LC)/tests/cfg/ovpsim_no_pulp.ic && \
+ $(XRUN) -R -xmlibdirname ../../../xcelium.d \
+ -l xrun-$(COMPLIANCE_PROG).log \
+ -covtest riscv-compliance $(XRUN_COMP_RUN) \
+ $(TEST_PLUSARGS) \
+ $(XRUN_RUN_WAVES_FLAGS) \
+ +UVM_TESTNAME=uvmt_$(CV_CORE_LC)_firmware_test_c \
+ +firmware=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).hex \
+ +elf_file=$(COMPLIANCE_PKG)/work/$(RISCV_ISA)/$(COMPLIANCE_PROG).elf
+
+
+
+###############################################################################
+# Use Google instruction stream generator (RISCV-DV) to create new test-programs
+comp_corev-dv: $(RISCVDV_PKG) $(CV_CORE_PKG)
+ mkdir -p $(SIM_COREVDV_RESULTS)
+ cd $(SIM_COREVDV_RESULTS) && \
+ $(XRUN) $(XRUN_COMP_FLAGS) \
+ -xmlibdirname ./xcelium.d \
+ $(QUIET) \
+ $(XRUN_USER_COMPILE_ARGS) \
+ $(XRUN_PMA_INC) \
+ $(XRUN_COMP_COREV_DV_FLAGS) \
+ $(XRUN_UVM_MACROS_INC_FILE) \
+ -f $(CV_CORE_MANIFEST) \
+ -top $(CV_CORE_LC)_instr_gen_tb_top \
+ -elaborate \
+ +incdir+$(CV_CORE_COREVDV_PKG)/target/$(CV_CORE_LC) \
+ +incdir+$(RISCVDV_PKG)/user_extension \
+ +incdir+$(COREVDV_PKG) \
+ +incdir+$(CV_CORE_COREVDV_PKG) \
+ -f $(COREVDV_PKG)/manifest.f \
+ -l xrun.log
+
+corev-dv: clean_riscv-dv \
+ clone_riscv-dv \
+ comp_corev-dv
+
+# Copy (with cleanout) out final assembler files to test directory
+# This includes the generated linker script files if they are present in the
+# generated tests folder
+gen_corev-dv:
+ mkdir -p $(SIM_COREVDV_RESULTS)/$(TEST)
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ mkdir -p $(SIM_TEST_RESULTS)/$$idx/test_program; \
+ done
+ cd $(SIM_COREVDV_RESULTS)/$(TEST) && \
+ $(XRUN) -R -xmlibdirname ../xcelium.d \
+ $(XRUN_RUN_FLAGS) \
+ -xceligen rand_struct \
+ -l $(TEST)_$(GEN_START_INDEX)_$(GEN_NUM_TESTS).log \
+ +start_idx=$(GEN_START_INDEX) \
+ +num_of_tests=$(GEN_NUM_TESTS) \
+ +UVM_TESTNAME=$(GEN_UVM_TEST) \
+ +asm_file_name_opts=$(TEST) \
+ +ldgen_cp_test_path=$(SIM_TEST_RESULTS) \
+ $(CFG_PLUSARGS) \
+ $(GEN_PLUSARGS)
+
+ for (( idx=${GEN_START_INDEX}; idx < $$((${GEN_START_INDEX} + ${GEN_NUM_TESTS})); idx++ )); do \
+ cp -f ${BSP}/link_corev-dv.ld ${SIM_TEST_RESULTS}/$$idx/test_program/link.ld; \
+ cp ${SIM_COREVDV_RESULTS}/${TEST}/${TEST}_$$idx.S ${SIM_TEST_RESULTS}/$$idx/test_program; \
+ done
+
+################################################################################
+# Invoke post-process waveform viewer
+waves:
+ $(WAVES_CMD)
+
+################################################################################
+# Invoke post-process coverage viewer
+cov_merge:
+ $(MKDIR_P) $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)
+ rm -rf $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)/*
+ $(COV_MERGE_FIND) > $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)/ucd.list
+ cd $(SIM_CFG_RESULTS)/$(MERGED_COV_DIR) && \
+ $(IMC) -execcmd "$(IMC_MERGE_ARGS) -runfile ucd.list -out merged; exit"
+
+ifeq ($(call IS_YES,$(MERGE)),YES)
+ COVERAGE_TARGET_DIR=$(SIM_CFG_RESULTS)/$(MERGED_COV_DIR)
+else
+ COVERAGE_TARGET_DIR=$(SIM_CFG_RESULTS)/$(TEST_NAME)/$(RUN_INDEX)
+endif
+
+cov: $(COV_MERGE)
+ cd $(COVERAGE_TARGET_DIR) && \
+ IMC_PAGE_VIEWS_DIR=$(CORE_V_VERIF)/$(CV_CORE)/sim/tools/xrun \
+ $(IMC) -load $(COV_DIR) $(COV_ARGS)
+
+###############################################################################
+# Clean up your mess!
+
+clean:
+ @echo "$(MAKEFILE_LIST)"
+ rm -rf $(SIM_RESULTS)
+
+# Files created by Eclipse when using the Imperas ISS + debugger
+clean_eclipse:
+ rm -f eguieclipse.log
+ rm -f idebug.log
+ rm -f stdout.txt
+ rm -rf workspace
+
+# All generated files plus the clone of the RTL
+clean_all: clean clean_eclipse clean_riscv-dv clean_test_programs clean_bsp clean_compliance clean_embench clean_dpi_dasm_spike clean_svlib
+ rm -rf $(CV_CORE_PKG)
diff --git a/sim/ExternalRepos.mk b/sim/ExternalRepos.mk
index c4ef83f..c395e24 100644
--- a/sim/ExternalRepos.mk
+++ b/sim/ExternalRepos.mk
@@ -13,7 +13,10 @@ export SHELL = /bin/bash
CV_CORE_REPO ?= https://github.com/openhwgroup/cve2
CV_CORE_BRANCH ?= main
CV_CORE_HASH ?= 370793f52488d1022d0554d194ad24f125156acc
-CV_CORE_TAG ?= none
+
+CV_VERIF_REPO ?= https://github.com/MikeOpenHWGroup/core-v-verif
+CV_VERIF_BRANCH ?= no_spike
+CV_VERIF_HASH ?= head
RISCVDV_REPO ?= https://github.com/google/riscv-dv
RISCVDV_BRANCH ?= master
diff --git a/sim/uvmt/.gitignore b/sim/uvmt/.gitignore
index 8079cf5..c8cee9d 100644
--- a/sim/uvmt/.gitignore
+++ b/sim/uvmt/.gitignore
@@ -1,2 +1,3 @@
make.cmd
+dsim*
*_results
diff --git a/sim/uvmt/Makefile b/sim/uvmt/Makefile
index c34db58..c2a580d 100644
--- a/sim/uvmt/Makefile
+++ b/sim/uvmt/Makefile
@@ -25,7 +25,7 @@
# "Constants"
MAKE = make
MAKE_PATH := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
-export CORE_V_VERIF = $(abspath $(MAKE_PATH)/../../..)
+export CORE_V_VERIF = $(abspath $(MAKE_PATH)/../..)
export CV_CORE ?= cv32e20
DPI_DASM_SPIKE_REPO ?= https://github.com/riscv/riscv-isa-sim.git
diff --git a/tb/uvmt/uvmt_cv32e20_debug_assert.sv b/tb/assertions/uvmt_cv32e20_debug_assert.sv
similarity index 100%
rename from tb/uvmt/uvmt_cv32e20_debug_assert.sv
rename to tb/assertions/uvmt_cv32e20_debug_assert.sv
diff --git a/tb/uvmt/uvmt_cv32e20_interrupt_assert.sv b/tb/assertions/uvmt_cv32e20_interrupt_assert.sv
similarity index 100%
rename from tb/uvmt/uvmt_cv32e20_interrupt_assert.sv
rename to tb/assertions/uvmt_cv32e20_interrupt_assert.sv
diff --git a/tb/uvmt/assertions/uvmt_cv32e20_debug_assert.sv b/tb/uvmt/assertions/uvmt_cv32e20_debug_assert.sv
new file mode 100644
index 0000000..a6a512e
--- /dev/null
+++ b/tb/uvmt/assertions/uvmt_cv32e20_debug_assert.sv
@@ -0,0 +1,512 @@
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
+//
+// Copyright 2020,2022 OpenHW Group
+// Copyright 2020 Datum Technology Corporation
+//
+// Licensed under the Solderpad Hardware Licence, 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
+//
+// https://solderpad.org/licenses/
+//
+// 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.
+//
+
+// TODO: replace with CV32E20-specific DEBUG assertions
+module uvmt_cv32e20_debug_assert;
+// import uvm_pkg::*;
+// import cv32e20_pkg::*;
+// (
+// uvmt_cv32e20_debug_cov_assert_if cov_assert_if
+// );
+//
+// // ---------------------------------------------------------------------------
+// // Local parameters
+// // ---------------------------------------------------------------------------
+// localparam WFI_INSTR_MASK = 32'hffffffff;
+// localparam WFI_INSTR_DATA = 32'h10500073;
+// // ---------------------------------------------------------------------------
+// // Local variables
+// // ---------------------------------------------------------------------------
+// string info_tag = "CV32E20_DEBUG_ASSERT";
+// logic [31:0] pc_at_dbg_req; // Capture PC when debug_req_i or ebreak is active
+// logic [31:0] pc_at_ebreak; // Capture PC when ebreak
+// logic [31:0] halt_addr_at_entry;
+// logic halt_addr_at_entry_flag;
+// logic [31:0] exception_addr_at_entry;
+// logic exception_addr_at_entry_flag;
+// logic [31:0] tdata2_at_entry;
+// // Locally track which debug cause should be used
+// logic [2:0] debug_cause_pri;
+// logic [31:0] boot_addr_at_entry;
+//
+// // Locally track pc in ID stage to detect first instruction of debug code
+// logic [31:0] prev_id_pc;
+// logic first_debug_ins_flag;
+// logic first_debug_ins;
+// logic decode_valid;
+// // ---------------------------------------------------------------------------
+// // Clocking blocks
+// // ---------------------------------------------------------------------------
+//
+// // Single clock, single reset design, use default clocking
+// default clocking @(posedge cov_assert_if.clk_i); endclocking
+// default disable iff !(cov_assert_if.rst_ni);
+//
+// assign cov_assert_if.is_ebreak = cov_assert_if.is_decoding &
+// cov_assert_if.id_stage_instr_valid_i &
+// (cov_assert_if.id_stage_instr_rdata_i == 32'h00100073) &
+// cov_assert_if.id_stage_is_compressed == 1'b0;
+//
+// assign cov_assert_if.is_cebreak = cov_assert_if.is_decoding &
+// cov_assert_if.id_stage_instr_valid_i &
+// (cov_assert_if.id_stage_instr_rdata_i == 32'h00100073) &
+// cov_assert_if.id_stage_is_compressed == 1'b1;
+//
+// assign cov_assert_if.is_mulhsu = cov_assert_if.is_decoding &
+// cov_assert_if.id_stage_instr_valid_i &
+// cov_assert_if.id_stage_instr_rdata_i[31:25] == 7'h1 &
+// cov_assert_if.id_stage_instr_rdata_i[14:12] == 3'b010 &
+// cov_assert_if.id_stage_instr_rdata_i[6:0] == 7'h33;
+//
+//
+// assign decode_valid = cov_assert_if.id_stage_instr_valid_i & cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DECODE;
+// // ---------------------------------------
+// // Assertions
+// // ---------------------------------------
+//
+// // check that we enter debug mode when expected.
+// // CSR checks are done in other assertions
+// property p_enter_debug;
+// $changed(debug_cause_pri) && (debug_cause_pri != 3'b000) && !cov_assert_if.debug_mode_q
+// |-> decode_valid [->1:2] ##0 cov_assert_if.debug_mode_q;
+// endproperty
+// a_enter_debug: assert property(p_enter_debug)
+// else
+// `uvm_error(info_tag, $sformatf("Debug mode not entered after exepected cause %d", debug_cause_pri));
+//
+// // Checck that depc gets the correct value when debug mode is entered.
+// property p_debug_mode_pc;
+// $rose(first_debug_ins) |-> cov_assert_if.debug_mode_q && (prev_id_pc == halt_addr_at_entry) && (cov_assert_if.depc_q == pc_at_dbg_req);
+// endproperty
+//
+// a_debug_mode_pc: assert property(p_debug_mode_pc)
+// else
+// `uvm_error(info_tag, $sformatf("Debug mode entered with wrong pc. pc==%08x",prev_id_pc));
+//
+// // Check that debug with cause haltreq is correct
+// property p_debug_mode_ext_req;
+// $rose(cov_assert_if.debug_mode_q) && (cov_assert_if.dcsr_q[8:6] == cv32e20_pkg::DBG_CAUSE_HALTREQ)
+// |-> debug_cause_pri == cv32e20_pkg::DBG_CAUSE_HALTREQ;
+// endproperty
+//
+// a_debug_mode_ext_req: assert property(p_debug_mode_ext_req)
+// else
+// `uvm_error(info_tag, $sformatf("Debug cause not correct for haltreq, cause = %d",cov_assert_if.dcsr_q[8:6]));
+//
+// // Check that debug with cause ebreak is correct
+// property p_cebreak_debug_mode;
+// $rose(cov_assert_if.debug_mode_q) && (cov_assert_if.dcsr_q[8:6] == cv32e20_pkg::DBG_CAUSE_EBREAK)
+// |-> debug_cause_pri == cv32e20_pkg::DBG_CAUSE_EBREAK;
+// endproperty
+//
+// a_cebreak_debug_mode: assert property(p_cebreak_debug_mode)
+// else
+// `uvm_error(info_tag,$sformatf("Debug mode with wrong cause after ebreak, case = %d",cov_assert_if.dcsr_q[8:6]));
+//
+// // c.ebreak without dcsr.ebreakm results in exception at mtvec
+// // Exclude single stepping as the sequence gets very complicated
+// property p_cebreak_exception;
+// disable iff(cov_assert_if.debug_req_i | !cov_assert_if.rst_ni)
+// $rose(cov_assert_if.is_cebreak) && cov_assert_if.dcsr_q[15] == 1'b0 && !cov_assert_if.debug_mode_q && cov_assert_if.is_decoding && cov_assert_if.id_valid &&
+// !cov_assert_if.debug_req_i && !cov_assert_if.dcsr_q[2]
+// |-> (decode_valid) [->1:2] ##0 !cov_assert_if.debug_mode_q && (cov_assert_if.mcause_q[5:0] === cv32e20_pkg::EXC_CAUSE_BREAKPOINT)
+// && (cov_assert_if.mepc_q == pc_at_ebreak) &&
+// (cov_assert_if.id_stage_pc == cov_assert_if.mtvec);
+// endproperty
+//
+// a_cebreak_exception: assert property(p_cebreak_exception)
+// else
+// `uvm_error(info_tag,$sformatf("Exception not entered correctly after c.ebreak with dcsr.ebreak=0"));
+//
+// // ebreak without dcsr.ebreakm results in exception at mtvec
+// // Exclude single stepping as the sequence gets very complicated
+// property p_ebreak_exception;
+// disable iff(cov_assert_if.debug_req_i | !cov_assert_if.rst_ni)
+// $rose(cov_assert_if.is_ebreak) && cov_assert_if.dcsr_q[15] == 1'b0 && !cov_assert_if.debug_mode_q && cov_assert_if.is_decoding && cov_assert_if.id_valid &&
+// !cov_assert_if.debug_req_i && !cov_assert_if.dcsr_q[2]
+// |-> (decode_valid) [->1:2] ##0 !cov_assert_if.debug_mode_q && (cov_assert_if.mcause_q[5:0] === cv32e20_pkg::EXC_CAUSE_BREAKPOINT)
+// && (cov_assert_if.mepc_q == pc_at_ebreak) &&
+// (cov_assert_if.id_stage_pc == cov_assert_if.mtvec);
+// endproperty
+//
+// // TODO: Fails formal as above
+// a_ebreak_exception: assert property(p_ebreak_exception)
+// else
+// `uvm_error(info_tag,$sformatf("Exception not entered correctly after ebreak with dcsr.ebreak=0"));
+// // c.ebreak during debug mode results in relaunch of debug mode
+//
+// property p_cebreak_during_debug_mode;
+// $rose(cov_assert_if.is_cebreak) ##0 cov_assert_if.debug_mode_q |-> decode_valid [->2] ##0 cov_assert_if.debug_mode_q &&
+// (cov_assert_if.id_stage_pc == halt_addr_at_entry); // TODO should check no change in dpc and dcsr
+// endproperty
+//
+// a_cebreak_during_debug_mode: assert property(p_cebreak_during_debug_mode)
+// else
+// `uvm_error(info_tag,$sformatf("Debug mode not restarted after c.ebreak"));
+//
+// // ebreak during debug mode results in relaunch
+// property p_ebreak_during_debug_mode;
+// $rose(cov_assert_if.is_ebreak) ##0 cov_assert_if.debug_mode_q |-> decode_valid [->2] ##0 cov_assert_if.debug_mode_q &&
+// (cov_assert_if.id_stage_pc == halt_addr_at_entry); // TODO should check no change in dpc and dcsr
+// endproperty
+//
+// a_ebreak_during_debug_mode: assert property(p_ebreak_during_debug_mode)
+// else
+// `uvm_error(info_tag,$sformatf("Debug mode not restarted after ebreak"));
+//
+// // Trigger match results in debug mode
+// property p_trigger_match;
+// cov_assert_if.trigger_match_i ##0 cov_assert_if.tdata1[2] ##0 !cov_assert_if.debug_mode_q ##0 cov_assert_if.id_stage_instr_valid_i ##0 cov_assert_if.is_decoding
+// |-> decode_valid [->2] ##0 (cov_assert_if.debug_mode_q && (cov_assert_if.dcsr_q[8:6]=== cv32e20_pkg::DBG_CAUSE_TRIGGER) &&
+// (cov_assert_if.depc_q == tdata2_at_entry)) &&
+// (cov_assert_if.id_stage_pc == halt_addr_at_entry);
+// endproperty
+//
+// a_trigger_match: assert property(p_trigger_match)
+// else
+// `uvm_error(info_tag, $sformatf("Debug mode not correctly entered after trigger match depc=%08x, tdata2=%08x", cov_assert_if.depc_q, tdata2_at_entry));
+//
+// // Address match without trigger enabled should NOT result in debug mode
+// property p_trigger_match_disabled;
+// $rose(cov_assert_if.addr_match) && !cov_assert_if.debug_mode_q |-> ##[1:6] !cov_assert_if.debug_mode_q;
+// endproperty
+//
+// a_trigger_match_disabled: assert property(p_trigger_match_disabled)
+// else
+// `uvm_error(info_tag, "Trigger match with tdata[2]==0 resulted in debug mode");
+//
+// // Exception in debug mode results in pc->dm_exception_addr_i
+// property p_debug_mode_exception;
+// $rose(cov_assert_if.illegal_insn_i) && cov_assert_if.debug_mode_q && cov_assert_if.is_decoding |-> (decode_valid & cov_assert_if.id_valid) [->2] ##0 cov_assert_if.debug_mode_q && (cov_assert_if.id_stage_pc == exception_addr_at_entry);
+// endproperty
+//
+// a_debug_mode_exception : assert property(p_debug_mode_exception)
+// else
+// `uvm_error(info_tag, $sformatf("Exception in debug mode not handled incorrectly. dm=%d, pc=%08x", cov_assert_if.debug_mode_q, cov_assert_if.id_stage_pc));
+//
+// // ECALL in debug mode results in pc->dm_exception_addr_i
+// property p_debug_mode_ecall;
+// $rose(cov_assert_if.ecall_insn_i) && cov_assert_if.debug_mode_q && cov_assert_if.is_decoding && cov_assert_if.id_stage_instr_valid_i
+// |-> (decode_valid & cov_assert_if.id_valid) [->1:3] ##0 cov_assert_if.debug_mode_q && (cov_assert_if.id_stage_pc == exception_addr_at_entry);
+// endproperty
+//
+// a_debug_mode_ecall : assert property(p_debug_mode_ecall)
+// else
+// `uvm_error(info_tag, $sformatf("ECALL in debug mode not handled incorrectly. dm=%d, pc=%08x", cov_assert_if.debug_mode_q, cov_assert_if.id_stage_pc));
+//
+// // IRQ in debug mode are masked
+// property p_irq_in_debug;
+// cov_assert_if.debug_mode_q |-> !cov_assert_if.irq_ack_o;
+// endproperty
+//
+// a_irq_in_debug : assert property(p_irq_in_debug)
+// else
+// `uvm_error(info_tag, $sformatf("IRQ not ignored while in debug mode"));
+//
+// // WFI in debug mode does not sleep
+// property p_wfi_in_debug;
+// cov_assert_if.debug_mode_q && $rose(cov_assert_if.is_wfi) |-> ##6 !cov_assert_if.core_sleep_o;
+// endproperty
+//
+// a_wfi_in_debug : assert property(p_wfi_in_debug)
+// else
+// `uvm_error(info_tag, $sformatf("WFI in debug mode cause core_sleep_o=1"));
+//
+// // Debug request while sleeping makes core wake up and enter debug mode
+// // wit cause=haltreq
+// property p_sleep_debug_req;
+// cov_assert_if.in_wfi && cov_assert_if.debug_req_i |=> !cov_assert_if.core_sleep_o |-> decode_valid [->1:2] ##0 cov_assert_if.debug_mode_q &&
+// cov_assert_if.dcsr_q[8:6] == cv32e20_pkg::DBG_CAUSE_HALTREQ;
+// endproperty
+//
+// a_sleep_debug_req : assert property(p_sleep_debug_req)
+// else
+// `uvm_error(info_tag, $sformatf("Did not exit sleep(== %d) after debug_req_i. Debug_mode = %d cause = %d", cov_assert_if.core_sleep_o, cov_assert_if.debug_mode_q, cov_assert_if.dcsr_q[8:6]));
+//
+// // Accessing debug regs in m-mode is illegal
+// property p_debug_regs_mmode;
+// cov_assert_if.csr_access && !cov_assert_if.debug_mode_q && cov_assert_if.id_stage_instr_rdata_i[31:20] inside {'h7B0, 'h7B1, 'h7B2, 'h7B3} |->
+// cov_assert_if.illegal_insn_i;
+// endproperty
+//
+// a_debug_regs_mmode : assert property(p_debug_regs_mmode)
+// else
+// `uvm_error(info_tag, "Accessing debug regs in M-mode did not result in illegal instruction");
+//
+// // Exception while single step -> PC is set to exception handler before
+// // debug
+// property p_single_step_exception;
+// !cov_assert_if.debug_mode_q && cov_assert_if.dcsr_q[2] && cov_assert_if.illegal_insn_q |-> ##[1:20] cov_assert_if.debug_mode_q && (cov_assert_if.depc_q == cov_assert_if.mtvec);
+// endproperty
+//
+// a_single_step_exception : assert property(p_single_step_exception)
+// else
+// `uvm_error(info_tag, "PC not set to exception handler after single step with exception");
+//
+// // Trigger during single step
+// property p_single_step_trigger;
+// !cov_assert_if.debug_mode_q && cov_assert_if.dcsr_q[2] && cov_assert_if.addr_match && cov_assert_if.tdata1[2] && cov_assert_if.id_stage_instr_valid_i|->
+// ##[1:20] cov_assert_if.debug_mode_q && (cov_assert_if.dcsr_q[8:6] == cv32e20_pkg::DBG_CAUSE_TRIGGER) && (cov_assert_if.depc_q == pc_at_dbg_req);
+// endproperty
+//
+// a_single_step_trigger : assert property (p_single_step_trigger)
+// else
+// `uvm_error(info_tag, $sformatf("Single step and trigger error: depc = %08x, cause = %d",cov_assert_if.depc_q, cov_assert_if.dcsr_q[8:6]));
+//
+// // Single step WFI must not result in sleeping
+// property p_single_step_wfi;
+// !cov_assert_if.debug_mode_q && cov_assert_if.dcsr_q[2] && cov_assert_if.is_wfi |->
+// decode_valid [->2] ##0 cov_assert_if.debug_mode_q && !cov_assert_if.core_sleep_o;
+// endproperty
+//
+// a_single_step_wfi : assert property(p_single_step_wfi)
+// else
+// `uvm_error(info_tag, "Debug mode not entered after single step WFI or core went sleeping");
+//
+// // Executing with single step with no irq results in debug mode
+// property p_single_step;
+// !cov_assert_if.debug_mode_q && cov_assert_if.dcsr_q[2] && !cov_assert_if.dcsr_q[11] && decode_valid |=> decode_valid [->1] ##0 cov_assert_if.debug_mode_q;
+// endproperty
+//
+// a_single_step: assert property(p_single_step)
+// else
+// `uvm_error(info_tag, "Debug mode not entered for single step");
+//
+// // dret in M-mode will cause illegal instruction
+// // If pending debug req, illegal insn will not assert
+// // until resume
+// property p_mmode_dret;
+// !cov_assert_if.debug_mode_q && cov_assert_if.is_dret && !cov_assert_if.debug_req_i |-> ##1 cov_assert_if.illegal_insn_q;
+// endproperty
+//
+// a_mmode_dret : assert property(p_mmode_dret)
+// else
+// `uvm_error(info_tag, "Executing dret in M-mode did not result in illegal instruction");
+//
+// // dret in D-mode will restore pc and exit D-mode
+// property p_dmode_dret;
+// cov_assert_if.debug_mode_q && cov_assert_if.is_dret |-> decode_valid [->2] ##0 !cov_assert_if.debug_mode_q && (cov_assert_if.id_stage_pc == cov_assert_if.depc_q);
+// endproperty
+//
+// a_dmode_dret : assert property(p_dmode_dret)
+// else
+// `uvm_error(info_tag, "Dret did not cause correct return from debug mode");
+//
+// // Check that trigger regs cannot be written from M-mode
+// // TSEL, and TDATA3 are tied to zero, hence no register to check
+// property p_mmode_tdata1_write;
+// !cov_assert_if.debug_mode_q && cov_assert_if.csr_access && cov_assert_if.csr_op == 'h1 && cov_assert_if.id_stage_instr_rdata_i[31:20] == 'h7A1 |-> ##2 $stable(cov_assert_if.tdata1);
+// endproperty
+//
+// a_mmode_tdata1_write : assert property(p_mmode_tdata1_write)
+// else
+// `uvm_error(info_tag, "Writing tdata1 from M-mode not allowed to change register value!");
+//
+// property p_mmode_tdata2_write;
+// !cov_assert_if.debug_mode_q && cov_assert_if.csr_access && cov_assert_if.csr_op == 'h1 && cov_assert_if.id_stage_instr_rdata_i[31:20] == 'h7A2 |-> ##2 $stable(cov_assert_if.tdata2);
+// endproperty
+//
+// a_mmode_tdata2_write : assert property(p_mmode_tdata2_write)
+// else
+// `uvm_error(info_tag, "Writing tdata2 from M-mode not allowed to change register value!");
+//
+// // Check that mcycle works as expected when not sleeping
+// // Counter can be written an arbitrary value, check that
+// // it changed only when not being written to
+// property p_mcycle_count;
+// !cov_assert_if.mcountinhibit_q[0] && !cov_assert_if.core_sleep_o && !(cov_assert_if.csr_we_int && (cov_assert_if.csr_addr ==12'hB00 || cov_assert_if.csr_addr == 12'hB80)) |=> $changed(cov_assert_if.mcycle);
+// endproperty
+//
+// a_mcycle_count : assert property(p_mcycle_count)
+// else
+// `uvm_error(info_tag, "Mcycle not counting when mcountinhibit[0] is cleared!");
+//
+// // Check that minstret works as expected when not sleeping
+// // Check only when not written to
+// property p_minstret_count;
+// !cov_assert_if.mcountinhibit_q[2] && cov_assert_if.inst_ret && !cov_assert_if.core_sleep_o
+// && !(cov_assert_if.csr_we_int && (cov_assert_if.csr_addr == 12'hB02 || cov_assert_if.csr_addr == 12'hB82))
+// |=> (cov_assert_if.minstret == ($past(cov_assert_if.minstret)+1));
+// endproperty
+//
+// a_minstret_count : assert property(p_minstret_count)
+// else
+// `uvm_error(info_tag, "Minstret not counting when mcountinhibit[2] is cleared!");
+//
+// // Check debug_req_i and irq on same cycle.
+// // Should result in debug mode with regular pc in depc,
+// // not pc from interrupt handler
+// // PC is checked in another assertion
+// property p_debug_req_and_irq;
+// cov_assert_if.debug_req_i && cov_assert_if.pending_enabled_irq && cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DECODE
+// |-> (decode_valid & cov_assert_if.id_valid) [->1:2] ##0 cov_assert_if.debug_mode_q;
+// endproperty
+//
+// a_debug_req_and_irq : assert property(p_debug_req_and_irq)
+// else
+// `uvm_error(info_tag, "Debug mode not entered after debug_req_i and irq on same cycle");
+//
+// // debug_req at reset should result in debug mode and no instructions
+// // executed
+// property p_debug_at_reset;
+// cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::RESET && cov_assert_if.debug_req_i |->
+// decode_valid [->1:2] ##0 cov_assert_if.debug_mode_q && (cov_assert_if.depc_q == boot_addr_at_entry);
+//
+// endproperty
+//
+// a_debug_at_reset : assert property(p_debug_at_reset)
+// else
+// `uvm_error(info_tag, "Debug mode not entered correctly at reset!");
+//
+// // Check that we cover the case where a debug_req_i
+// // comes while flushing due to an illegal insn, causing
+// // dpc to be set to the exception handler entry addr
+// property p_illegal_insn_debug_req;
+// (cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::FLUSH_EX | cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::FLUSH_WB) && cov_assert_if.illegal_insn_q & cov_assert_if.debug_req_i & !cov_assert_if.debug_mode_q|-> decode_valid [->1:2] ##0 cov_assert_if.debug_mode_q && cov_assert_if.depc_q == cov_assert_if.mtvec;
+// endproperty
+//
+// a_illegal_insn_debug_req : assert property(p_illegal_insn_debug_req)
+// else
+// `uvm_error(info_tag, "Debug mode not entered correctly while handling illegal instruction!");
+// // -------------------------------------------
+// // Capture internal states for use in checking
+// // -------------------------------------------
+// always @(posedge cov_assert_if.clk_i or negedge cov_assert_if.rst_ni) begin
+// if(!cov_assert_if.rst_ni) begin
+// pc_at_dbg_req <= 32'h0;
+// pc_at_ebreak <= 32'h0;
+// end else begin
+// // Capture debug pc
+// if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DBG_TAKEN_ID) begin
+// pc_at_dbg_req <= cov_assert_if.id_stage_pc;
+// end else if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DBG_TAKEN_IF) begin
+// pc_at_dbg_req <= cov_assert_if.if_stage_pc;
+// end
+//
+// // Capture pc at ebreak
+// if(cov_assert_if.is_ebreak || cov_assert_if.is_cebreak ) begin
+// pc_at_ebreak <= cov_assert_if.id_stage_pc;
+// end
+// end
+// end
+//
+// // Keep track of wfi state
+// always @(posedge cov_assert_if.clk_i or negedge cov_assert_if.rst_ni) begin
+// if (!cov_assert_if.rst_ni) begin
+// cov_assert_if.in_wfi <= 1'b0;
+// end
+// else begin
+// // Enter wfi if we have a valid instruction, not in debug mode and not
+// // single stepping
+// if (cov_assert_if.is_wfi && !cov_assert_if.debug_mode_q && cov_assert_if.is_decoding && cov_assert_if.id_stage_instr_valid_i & !cov_assert_if.dcsr_q[2]) begin
+// cov_assert_if.in_wfi <= 1'b1;
+//
+// end else if (cov_assert_if.pending_enabled_irq || cov_assert_if.debug_req_i)
+// cov_assert_if.in_wfi <= 1'b0;
+//
+// end
+// end
+//
+// // Capture dm_halt_addr_i value
+// always@ (posedge cov_assert_if.clk_i or negedge cov_assert_if.rst_ni) begin
+// if(!cov_assert_if.rst_ni) begin
+// halt_addr_at_entry_flag <= 1'b0;
+// end else begin
+// if(!halt_addr_at_entry_flag) begin
+// if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DBG_TAKEN_ID | cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DBG_TAKEN_IF) begin
+// halt_addr_at_entry <= {cov_assert_if.dm_halt_addr_i[31:2], 2'b00};
+// tdata2_at_entry <= cov_assert_if.tdata2;
+// halt_addr_at_entry_flag <= 1'b1;
+// end
+// end
+//
+// // Clear flag while not in dmode or we see ebreak in debug
+// if((!cov_assert_if.debug_mode_q & halt_addr_at_entry_flag) | (cov_assert_if.debug_mode_q & (cov_assert_if.is_ebreak | cov_assert_if.is_cebreak)))
+// halt_addr_at_entry_flag <= 1'b0;
+//
+// // Capture boot addr
+// if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::BOOT_SET)
+// boot_addr_at_entry <= {cov_assert_if.boot_addr_i[31:2], 2'b00};
+// end
+// end
+// always@ (posedge cov_assert_if.clk_i) begin
+// if((cov_assert_if.illegal_insn_i | cov_assert_if.ecall_insn_i) & cov_assert_if.pc_set & cov_assert_if.debug_mode_q)
+// exception_addr_at_entry = {cov_assert_if.dm_exception_addr_i[31:2], 2'b00};
+// end
+//
+// assign cov_assert_if.addr_match = (cov_assert_if.id_stage_pc == cov_assert_if.tdata2);
+// assign cov_assert_if.dpc_will_hit = (cov_assert_if.depc_n == cov_assert_if.tdata2);
+// assign cov_assert_if.is_wfi = cov_assert_if.id_stage_instr_valid_i & cov_assert_if.id_valid &
+// ((cov_assert_if.id_stage_instr_rdata_i & WFI_INSTR_MASK) == WFI_INSTR_DATA);
+// assign cov_assert_if.pending_enabled_irq = |(cov_assert_if.irq_i & cov_assert_if.mie_q);
+// assign cov_assert_if.is_dret = cov_assert_if.id_valid & cov_assert_if.id_stage_instr_valid_i & cov_assert_if.is_decoding & (cov_assert_if.id_stage_instr_rdata_i == 32'h7B200073);
+//
+// // Track which debug cause should be expected
+// always@ (posedge cov_assert_if.clk_i or negedge cov_assert_if.rst_ni) begin
+// if( !cov_assert_if.rst_ni) begin
+// debug_cause_pri <= 3'b000;
+// end else begin
+// // Debug evaluated in decode state with valid instructions only
+// //if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DECODE & !cov_assert_if.debug_mode_q) begin
+// if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DECODE) begin
+// if(cov_assert_if.is_decoding & cov_assert_if.id_stage_instr_valid_i) begin
+// if(cov_assert_if.trigger_match_i)
+// debug_cause_pri <= 3'b010;
+// else if((cov_assert_if.dcsr_q[15]) & (cov_assert_if.is_ebreak | cov_assert_if.is_cebreak))
+// debug_cause_pri <= 3'b001;
+// else if(cov_assert_if.debug_req_i)
+// debug_cause_pri <= 3'b011;
+// else if(cov_assert_if.dcsr_q[2])
+// debug_cause_pri <= 3'b100;
+// else
+// debug_cause_pri <= 3'b000;
+//
+// end
+//
+// end else if(cov_assert_if.ctrl_fsm_cs == cv32e20_pkg::DBG_TAKEN_IF) begin
+// if(cov_assert_if.debug_req_i) begin
+// debug_cause_pri <= 3'b011;
+// end else if(cov_assert_if.dcsr_q[2]) begin
+// debug_cause_pri <= 3'b100;
+// end
+// end
+// end
+// end
+//
+// // Track PC in id stage to detect first instruction of debug code
+// always@ (posedge cov_assert_if.clk_i or negedge cov_assert_if.rst_ni) begin
+// if( !cov_assert_if.rst_ni) begin
+// prev_id_pc <= 32'h0;
+// first_debug_ins_flag <= 1'b0;
+// first_debug_ins <= 1'b0;
+// end else begin
+// prev_id_pc <= cov_assert_if.id_stage_pc;
+// first_debug_ins <= 1'b0;
+// if(cov_assert_if.debug_mode_q) begin
+// if(!first_debug_ins_flag) begin
+// if(cov_assert_if.is_decoding & cov_assert_if.id_stage_instr_valid_i) begin
+// first_debug_ins_flag <= 1'b1;
+// first_debug_ins <= 1'b1;
+// end
+// end
+// end else begin
+// first_debug_ins_flag <= 1'b0;
+// end
+// end
+// end
+endmodule : uvmt_cv32e20_debug_assert
diff --git a/tb/uvmt/assertions/uvmt_cv32e20_interrupt_assert.sv b/tb/uvmt/assertions/uvmt_cv32e20_interrupt_assert.sv
new file mode 100644
index 0000000..204e153
--- /dev/null
+++ b/tb/uvmt/assertions/uvmt_cv32e20_interrupt_assert.sv
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
+//
+// Copyright 2020,2022 OpenHW Group
+// Copyright 2020 Datum Technology Corporation
+//
+// Licensed under the Solderpad Hardware Licence, 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
+//
+// https://solderpad.org/licenses/
+//
+// 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.
+//
+
+module uvmt_cv32e20_interrupt_assert
+ import uvm_pkg::*;
+ import uvme_cv32e20_pkg::*;
+ (
+
+ input clk, // Gated clock
+ input clk_i, // Free-running core clock
+ input rst_ni,
+
+ // Core inputs
+ input fetch_enable_i, // external core fetch enable
+
+ // External interrupt interface
+ input [31:0] irq_i,
+ input irq_ack_o,
+ input [4:0] irq_id_o,
+
+ // External debug req (for WFI modeling)
+ input debug_req_i,
+ input debug_mode_q,
+
+ // CSR Interface
+ input [5:0] mcause_n, // mcause_n[5]: interrupt, mcause_n[4]: vector
+ input [31:0] mip, // machine interrupt pending
+ input [31:0] mie_q, // machine interrupt enable
+ input [31:0] mie_n, // machine interrupt enable
+ input mstatus_mie, // machine mode interrupt enable
+ input [1:0] mtvec_mode_q, // machine mode interrupt vector mode
+
+ // Instruction fetch stage
+ input if_stage_instr_rvalid_i, // Instruction word is valid
+ input [31:0] if_stage_instr_rdata_i, // Instruction word data
+
+ // Instruction ID stage (determines executed instructions)
+ input id_stage_instr_valid_i, // instruction word is valid
+ input [31:0] id_stage_instr_rdata_i, // Instruction word data
+ input [4:0] ctrl_fsm_cs, // Controller FSM to get hint for interrupt taken
+
+ // Determine whether to cancel instruction if branch taken
+ input branch_taken_ex,
+
+ // WFI Interface
+ input core_sleep_o
+ );
+
+ // ---------------------------------------------------------------------------
+ // Local parameters
+ // ---------------------------------------------------------------------------
+ localparam NUM_IRQ = 32;
+ localparam VALID_IRQ_MASK = 32'hffff_0888; // Valid external interrupt signals
+
+ localparam WFI_INSTR_MASK = 32'hffffffff;
+ localparam WFI_INSTR_DATA = 32'h10500073;
+
+ localparam WFI_WAKEUP_LATENCY = 40;
+
+ // ---------------------------------------------------------------------------
+ // Local variables
+ // ---------------------------------------------------------------------------
+ string info_tag = "CV32E20_IRQ_ASSERT";
+
+ wire [31:0] pending_enabled_irq;
+ wire [31:0] pending_enabled_irq_q;
+
+ wire id_instr_is_wfi; // ID instruction is a WFI
+ reg in_wfi; // Local model of WFI state of core
+
+ reg[31:0] irq_q;
+
+ reg[31:0] next_irq;
+ reg next_irq_valid;
+
+ reg[31:0] next_irq_q;
+ reg next_irq_valid_q;
+ reg[31:0] saved_mie_q;
+
+ reg[31:0] expected_irq;
+ logic expected_irq_ack;
+
+ reg[31:0] last_instr_rdata;
+
+ // ---------------------------------------------------------------------------
+ // Clocking blocks
+ // ---------------------------------------------------------------------------
+
+ // Single clock, single reset design, use default clocking
+ default clocking @(posedge clk_i); endclocking
+ default disable iff !(rst_ni);
+
+ // ---------------------------------------------------------------------------
+ // Begin module code
+ // ---------------------------------------------------------------------------
+ assign pending_enabled_irq = irq_i & mie_n;
+ assign pending_enabled_irq_q = irq_q & mie_n;
+
+ // ---------------------------------------------------------------------------
+ // Interrupt interface checks
+ // ---------------------------------------------------------------------------
+/* *** LRH commented out
+ // irq_ack_o is always a pulse
+ property p_irq_ack_o_pulse;
+ irq_ack_o |=> !irq_ack_o;
+ endproperty
+ a_irq_ack_o_pulse: assert property(p_irq_ack_o_pulse)
+ else
+ `uvm_error(info_tag,
+ "Interrupt ack was asserted for more than one cycle");
+
+ // irq_id_o is never a reserved irq
+ property p_irq_id_o_not_reserved;
+ irq_ack_o |-> VALID_IRQ_MASK[irq_id_o];
+ endproperty
+ a_irq_id_o_not_reserved: assert property(p_irq_id_o_not_reserved)
+ else
+ `uvm_error(info_tag,
+ $sformatf("int_id_o output is 0x%0x which is reserved", irq_id_o));
+
+ // irq_id_o is never a disabled irq
+ property p_irq_id_o_mie_enabled;
+ irq_ack_o |-> mie_n[irq_id_o];
+ endproperty
+ a_irq_id_o_mie_enabled: assert property(p_irq_id_o_mie_enabled)
+ else
+ `uvm_error(info_tag,
+ $sformatf("irq_id_o output is 0x%0x which is disabled in MIE: 0x%08x", irq_id_o, mie_n));
+
+ // irq_ack_o cannot be asserted if mstatus_mie is deasserted
+ property p_irq_id_o_mstatus_mie_enabled;
+ irq_ack_o |-> mstatus_mie;
+ endproperty
+ a_irq_id_o_mstatus_mie_enabled: assert property(p_irq_id_o_mstatus_mie_enabled)
+ else
+ `uvm_error(info_tag,
+ $sformatf("int_id_o output is 0x%0x but MSTATUS.MIE is disabled", irq_id_o));
+
+ // ---------------------------------------------------------------------------
+ // Interrupt CSR checks
+ // ---------------------------------------------------------------------------
+
+ // Coverage for individual interupt assertions
+ sequence s_irq_taken(irq);
+ irq_i[irq] ##0 mie_q[irq] ##0 mstatus_mie ##0 irq_ack_o ##0 irq_id_o == irq;
+ endsequence : s_irq_taken
+
+ // Interrupt fired, global interrupts enabled, but not taken due to global MSTATUS.MIE setting
+ property p_irq_masked(irq);
+ irq_i[irq] ##0 !mie_q[irq] ##0 mstatus_mie;
+ endproperty : p_irq_masked
+
+ // Interrupt fired and locally enabled in MIE, but masked due to MSTATUS_MIE
+ property p_irq_masked_mstatus(irq);
+ irq_i[irq] ##0 mie_q[irq] ##0 !mstatus_mie;
+ endproperty : p_irq_masked_mstatus
+
+ // Interrupt taken
+ property p_irq_taken(irq);
+ s_irq_taken(irq);
+ endproperty : p_irq_taken
+
+ // Interrupt enabled via MIE locally masked
+ property p_irq_masked_then_enabled(irq);
+ irq_i[irq] ##0 !mie_q[irq] ##0 mstatus_mie ##1 irq_i[irq] ##0 mie_q[irq] ##0 mstatus_mie;
+ endproperty : p_irq_masked_then_enabled
+
+ // Interrupt enabled via MSTATUS_MIE locally masked
+ property p_irq_masked_mstatus_then_enabled(irq);
+ irq_i[irq] ##0 mie_q[irq] ##0 !mstatus_mie ##1 irq_i[irq] ##0 mie_q[irq] ##0 mstatus_mie;
+ endproperty : p_irq_masked_mstatus_then_enabled
+
+ // Interrupt request deasserted when enabled but not acked
+ property p_irq_deasserted_while_enabled_not_acked(irq);
+ irq_i[irq] ##0 mie_q[irq] ##0 mstatus_mie ##0 !irq_ack_o ##1
+ !irq_i[irq] ##0 !irq_ack_o;
+ endproperty : p_irq_deasserted_while_enabled_not_acked
+
+ // Interrupt taken in each supported mtvec mode
+ property p_irq_in_mtvec(irq, mtvec);
+ s_irq_taken(irq) ##0 mtvec_mode_q == mtvec;
+ endproperty
+
+ generate for(genvar gv_i = 0; gv_i < NUM_IRQ; gv_i++) begin : gen_irq_cov
+ if (VALID_IRQ_MASK[gv_i]) begin : gen_valid
+ c_irq_masked: cover property(p_irq_masked(gv_i));
+ c_irq_masked_mstatus: cover property(p_irq_masked_mstatus(gv_i));
+ c_irq_taken: cover property(p_irq_taken(gv_i));
+ c_irq_masked_then_enabled: cover property(p_irq_masked_then_enabled(gv_i));
+ c_irq_masked_mstatus_then_enabled: cover property(p_irq_masked_mstatus_then_enabled(gv_i));
+ c_irq_deasserted_while_enabled_not_acked: cover property(p_irq_deasserted_while_enabled_not_acked(gv_i));
+ c_irq_in_mtvec_fixed: cover property(p_irq_in_mtvec(gv_i, 0));
+ c_irq_in_mtvec_vector: cover property(p_irq_in_mtvec(gv_i, 1));
+ end
+ end
+ endgenerate
+
+ */ // LRH Commented out assertions
+
+ // Detect arbitration of interrupt assertion
+ always @* begin
+ next_irq_valid = 1'b0;
+ next_irq = '0;
+ casex ({pending_enabled_irq_q[31:16], pending_enabled_irq_q[11], pending_enabled_irq_q[3], pending_enabled_irq_q[7]})
+ 19'b1???_????_????_????_???: begin next_irq = 'd31; next_irq_valid = '1; end
+ 19'b01??_????_????_????_???: begin next_irq = 'd30; next_irq_valid = '1; end
+ 19'b001?_????_????_????_???: begin next_irq = 'd29; next_irq_valid = '1; end
+ 19'b0001_????_????_????_???: begin next_irq = 'd28; next_irq_valid = '1; end
+ 19'b0000_1???_????_????_???: begin next_irq = 'd27; next_irq_valid = '1; end
+ 19'b0000_01??_????_????_???: begin next_irq = 'd26; next_irq_valid = '1; end
+ 19'b0000_001?_????_????_???: begin next_irq = 'd25; next_irq_valid = '1; end
+ 19'b0000_0001_????_????_???: begin next_irq = 'd24; next_irq_valid = '1; end
+ 19'b0000_0000_1???_????_???: begin next_irq = 'd23; next_irq_valid = '1; end
+ 19'b0000_0000_01??_????_???: begin next_irq = 'd22; next_irq_valid = '1; end
+ 19'b0000_0000_001?_????_???: begin next_irq = 'd21; next_irq_valid = '1; end
+ 19'b0000_0000_0001_????_???: begin next_irq = 'd20; next_irq_valid = '1; end
+ 19'b0000_0000_0000_1???_???: begin next_irq = 'd19; next_irq_valid = '1; end
+ 19'b0000_0000_0000_01??_???: begin next_irq = 'd18; next_irq_valid = '1; end
+ 19'b0000_0000_0000_001?_???: begin next_irq = 'd17; next_irq_valid = '1; end
+ 19'b0000_0000_0000_0001_???: begin next_irq = 'd16; next_irq_valid = '1; end
+ 19'b0000_0000_0000_0000_1??: begin next_irq = 'd11; next_irq_valid = '1; end
+ 19'b0000_0000_0000_0000_01?: begin next_irq = 'd3; next_irq_valid = '1; end
+ 19'b0000_0000_0000_0000_001: begin next_irq = 'd7; next_irq_valid = '1; end
+ endcase
+ end
+
+ always @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ irq_q <= 0;
+ next_irq_q <= 0;
+ next_irq_valid_q <= 0;
+ saved_mie_q <= 0;
+ end
+ else begin
+ irq_q <= irq_i;
+ next_irq_q <= next_irq;
+ next_irq_valid_q <= next_irq_valid;
+ saved_mie_q <= mie_q;
+ end
+ end
+
+ always @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni)
+ expected_irq <= 0;
+ else
+ expected_irq <= next_irq_q;
+ end
+
+ assign expected_irq_ack = next_irq_valid & mstatus_mie;
+
+/* *** LRH commented out
+ // Check expected interrupt wins
+ property p_irq_arb;
+ irq_ack_o |-> irq_id_o == next_irq;
+ endproperty
+ a_irq_arb: assert property(p_irq_arb)
+ else
+ `uvm_error(info_tag,
+ $sformatf("Expected winning interrupt: %0d, actual interrupt: %0d", next_irq, irq_id_o))
+
+ // Check that an interrupt is expected
+ property p_irq_expected;
+ irq_ack_o |-> expected_irq_ack;
+ endproperty
+ a_irq_expected: assert property(p_irq_expected)
+ else
+ `uvm_error(info_tag,
+ $sformatf("Did not expect interrupt ack: %0d", irq_id_o))
+
+ // ---------------------------------------------------------------------------
+ // The infamous "first" flag (kludge for $past() handling of t=0 values)
+ // Would like to use a leading ##1 in the property instead but this currently
+ // does not work with dsim
+ // ---------------------------------------------------------------------------
+ reg first;
+ always @(posedge clk or negedge rst_ni)
+ if (!rst_ni)
+ first <= 1'b1;
+ else
+ first <= 1'b0;
+
+ // mip reflects flopped interrupt inputs (irq_i) regardless of other configuration
+ // Note that this runs on the gated clock
+ property p_mip_irq_i;
+ @(posedge clk)
+ !first |-> mip == ($past(irq_i) & VALID_IRQ_MASK);
+ endproperty
+ a_mip_irq_i: assert property(p_mip_irq_i)
+ else
+ `uvm_error(info_tag,
+ $sformatf("MIP of 0x%08x does not follow flopped irq_i input: 0x%08x", mip, $past(irq_i)));
+
+ // mip should not be reserved
+ property p_mip_not_reserved;
+ (mip & ~VALID_IRQ_MASK) == 0;
+ endproperty
+ a_mip_not_reserved: assert property(p_mip_not_reserved)
+ else
+ `uvm_error(info_tag,
+ $sformatf("MIP of reserved interrupt is asserted: mip = 0x%08x", mip));
+
+ // ---------------------------------------------------------------------------
+ // Instruction coverage when taking an interrupt
+ // ---------------------------------------------------------------------------
+ always @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ last_instr_rdata <= '0;
+ end
+ else if (id_stage_instr_valid_i) begin
+ last_instr_rdata <= id_stage_instr_rdata_i;
+ end
+ end
+
+ // ---------------------------------------------------------------------------
+ // WFI Checks
+ // ---------------------------------------------------------------------------
+ assign is_wfi = id_stage_instr_valid_i &&
+ ((id_stage_instr_rdata_i & WFI_INSTR_MASK) == WFI_INSTR_DATA) &&
+ !branch_taken_ex;
+ always @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ in_wfi <= 1'b0;
+ end
+ else begin
+ if (is_wfi)
+ in_wfi <= 1'b1;
+ else if (|pending_enabled_irq || debug_req_i)
+ in_wfi <= 1'b0;
+ end
+ end
+
+ /* *** // LRH Commented out assertions.
+
+ // WFI assertion will assert core_sleep_o in 6 clocks
+ property p_wfi_assert_core_sleep_o;
+ !pending_enabled_irq_q ##0 !in_wfi ##1 !pending_enabled_irq_q ##0
+ ((!pending_enabled_irq && !debug_mode_q && !debug_req_i) throughout in_wfi[*38])
+ |-> core_sleep_o;
+ endproperty
+ a_wfi_assert_core_sleep_o: assert property(p_wfi_assert_core_sleep_o)
+ else
+ `uvm_error(info_tag,
+ "Aassertion of core_sleep_o did not occur within 6 clocks")
+
+ // core_sleep_o deassertion in wfi should be followed by WFI deassertion
+ property p_core_sleep_deassert;
+ $fell(core_sleep_o) ##0 in_wfi |-> ##1 !in_wfi;
+ endproperty
+ a_core_sleep_deassert: assert property(p_core_sleep_deassert)
+ else
+ `uvm_error(info_tag,
+ "Deassertion of core_sleep_o in WFI not followed by WFI wakeup");
+
+ // When WFI deasserts the core should be awake
+ property p_wfi_deassert_core_sleep_o;
+ core_sleep_o ##1 pending_enabled_irq |-> !core_sleep_o;
+ endproperty
+ a_wfi_deassert_core_sleep_o: assert property(p_wfi_deassert_core_sleep_o)
+ else
+ `uvm_error(info_tag,
+ "Deassertion of WFI occurred and core is still asleep");
+
+ // WFI wakeup to next instruction fetch
+ property p_wfi_wake_to_instr_fetch;
+ disable iff (!rst_ni || !fetch_enable_i || debug_mode_q)
+ core_sleep_o ##0 in_wfi ##1 !in_wfi[->1] |-> ##[1:WFI_WAKEUP_LATENCY] if_stage_instr_rvalid_i;
+ endproperty
+ a_wfi_wake_to_instr_fetch: assert property(p_wfi_wake_to_instr_fetch)
+ else
+ `uvm_error(info_tag,
+ $sformatf("Core did not start fetching %0d cycles after WFI completed", WFI_WAKEUP_LATENCY));
+
+ // Cover property, detect sleep deassertion due to asserted and non-asserted interrupts
+ property p_wfi_wake_mstatus_mie(irq, mie);
+ $fell(in_wfi) ##0 irq_i[irq] ##0 mie_q[irq] ##0 mstatus_mie == mie;
+ endproperty
+ generate for(genvar gv_i = 0; gv_i < 32; gv_i++) begin : gen_wfi_cov
+ if (VALID_IRQ_MASK[gv_i]) begin
+ c_wfi_wake_mstatus_mie_0: cover property(p_wfi_wake_mstatus_mie(gv_i, 0));
+ c_wfi_wake_mstatus_mie_1: cover property(p_wfi_wake_mstatus_mie(gv_i, 1));
+ end
+ end
+ endgenerate
+ */ // LRH Commented out assertions.
+endmodule : uvmt_cv32e20_interrupt_assert
diff --git a/tb/uvmt/imperas_dv.flist b/tb/uvmt/imperas_dv.flist
index da8df96..2430fab 100644
--- a/tb/uvmt/imperas_dv.flist
+++ b/tb/uvmt/imperas_dv.flist
@@ -1,5 +1,6 @@
//
-// Copyright 2022 OpenHW Group
+// Copyright 2022, 2024 OpenHW Group
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,20 +15,24 @@
// limitations under the License.
//
-///////////////////////////////////////
+// Edit this file as per your specific usage (or not) of the Synopsys ImperasDV product.
+
// ImperasDV
-// - The traditional location of the Imperas reference model is under vendor_lib in this repo.
-// - The proposed new location of the Imperas reference model is in an installation directory
-// that is external to this repo.
-//
+// - The ImperasDV model is assumed to be installed in ${IMPERAS_HOME}, an
+// installation directory that is external to this repo.
-+incdir+${IMPERAS_HOME}
-+incdir+${IMPERAS_HOME}/ImpProprietary/include/host
-+incdir+${IMPERAS_HOME}/ImpProprietary/source/host/riscvISACOV/source
+//+incdir+${IMPERAS_HOME}
+//+incdir+${IMPERAS_HOME}/ImpProprietary/include/host
+//+incdir+${IMPERAS_HOME}/ImpProprietary/source/host/riscvISACOV/source
+//
+//-f ${IMPERAS_HOME}/ImpPublic/source/host/rvvi/rvvi.f
+//-f ${IMPERAS_HOME}/ImpProprietary/source/host/idv/idv.f
+//
-//${TBSRC_HOME}/uvmt/uvmt_cv32e20_imperas_riscv_coverage_config.svh
--f ${IMPERAS_HOME}/ImpPublic/source/host/rvvi/rvvi.f
--f ${IMPERAS_HOME}/ImpProprietary/source/host/idv/idv.f
+// RVVI "stubs" for use when the environment does not support ImperasDV.
+${RVVI_HOME}/source/host/rvvi/rvviApiPkg.sv
+${RVVI_HOME}/source/host/rvvi/rvviTrace.sv
// ImperasDV test bench wrapper
${TBSRC_HOME}/uvmt/uvmt_cv32e20_imperas_dv_wrap.sv
+
diff --git a/tb/uvmt/uvmt_cv32e20.flist b/tb/uvmt/uvmt_cv32e20.flist
index eeec759..8a422f7 100644
--- a/tb/uvmt/uvmt_cv32e20.flist
+++ b/tb/uvmt/uvmt_cv32e20.flist
@@ -35,7 +35,7 @@
// Libraries
-f ${DV_SVLIB_PATH}/svlib_pkg.flist
-
+-f ${DV_UVMT_PATH}/imperas_dv.flist
// Environments
-f ${DV_UVME_PATH}/uvme_cv32e20_pkg.flist
@@ -56,7 +56,6 @@ ${DV_UVMT_PATH}/uvmt_cv32e20_tb.sv
${TBSRC_HOME}/uvmt/uvmt_cv32e20_tb.sv
${TBSRC_HOME}/uvmt/uvmt_cv32e20_dut_wrap.sv
-// FIXME:Find a better location
-// FIXME:fix usage of RTL package (currently non-existant cv32e20_pkg.sv)
-${DV_UVMT_PATH}/uvmt_cv32e20_interrupt_assert.sv
-${DV_UVMT_PATH}/uvmt_cv32e20_debug_assert.sv
+// CV32E20 assertions files
+${DV_UVMT_PATH}/../assertions/uvmt_cv32e20_interrupt_assert.sv
+${DV_UVMT_PATH}/../assertions/uvmt_cv32e20_debug_assert.sv
diff --git a/tb/uvmt/uvmt_cv32e20_dut_wrap.sv b/tb/uvmt/uvmt_cv32e20_dut_wrap.sv
index 395581d..2e60aef 100644
--- a/tb/uvmt/uvmt_cv32e20_dut_wrap.sv
+++ b/tb/uvmt/uvmt_cv32e20_dut_wrap.sv
@@ -136,7 +136,8 @@ module uvmt_cv32e20_dut_wrap #(
.ram_cfg_i ( prim_ram_1p_pkg::RAM_1P_CFG_DEFAULT ),
.hart_id_i ( 32'h0000_0000 ),
- .boot_addr_i ( core_cntrl_if.boot_addr ), //<---MJS changing to 0
+ //.boot_addr_i ( core_cntrl_if.boot_addr ), //<---MJS changing to 0
+ .boot_addr_i ( 32'h0000_0000 ),
// Instruction memory interface
.instr_req_o ( obi_memory_instr_if.req ), // core to agent
@@ -158,14 +159,14 @@ module uvmt_cv32e20_dut_wrap #(
.data_err_i ( '0 ),
// Interrupt inputs
- .irq_software_i ( irq_uvma[3]),
- .irq_timer_i ( irq_uvma[7]),
- .irq_external_i ( irq_uvma[11]),
- .irq_fast_i ( irq_uvma[31:16]),
- .irq_nm_i ( irq_uvma[0]), // non-maskeable interrupt
+ .irq_software_i ( 1'b0/*irq_uvma[3]*/),
+ .irq_timer_i ( 1'b0/*irq_uvma[7]*/),
+ .irq_external_i ( 1'b0/*irq_uvma[11]*/),
+ .irq_fast_i ( 16'h0000/*irq_uvma[31:16]*/),
+ .irq_nm_i ( 1'b0/*irq_uvma[0]*/), // non-maskeable interrupt
// Debug Interface
- .debug_req_i (debug_req_uvma),
+ .debug_req_i (1'b0/*debug_req_uvma*/),
.crash_dump_o (),
// RISC-V Formal Interface
diff --git a/tb/uvmt/uvmt_cv32e20_imperas_dv_wrap.sv b/tb/uvmt/uvmt_cv32e20_imperas_dv_wrap.sv
index 2b6787f..760bea9 100644
--- a/tb/uvmt/uvmt_cv32e20_imperas_dv_wrap.sv
+++ b/tb/uvmt/uvmt_cv32e20_imperas_dv_wrap.sv
@@ -78,8 +78,12 @@
///////////////////////////////////////////////////////////////////////////////
// Module wrapper for Imperas DV.
////////////////////////////////////////////////////////////////////////////
-// `define USE_ISS
`ifdef USE_ISS
+ `define USE_ISS_IMPERAS
+`endif // USE_ISS
+
+`ifndef FORMAL
+`ifdef USE_ISS_IMPERAS
`include "idv/idv.svh" // located in $IMPERAS_HOME/ImpProprietary/include/host
@@ -542,10 +546,10 @@ module uvmt_cv32e20_imperas_dv_wrap
// void'(rvvi.net_push(nmi, nmi));
// end
- /////////////////////////////////////////////////////////////////////////////
- // REF control
- /////////////////////////////////////////////////////////////////////////////
- task ref_init;
+ /////////////////////////////////////////////////////////////////////////////
+ // REF control
+ /////////////////////////////////////////////////////////////////////////////
+ task ref_init;
string test_program_elf;
reg [31:0] hart_id;
@@ -630,6 +634,24 @@ module uvmt_cv32e20_imperas_dv_wrap
void'(rvviRefMemorySetVolatile('h15001000, 'h15001007)); //TODO: deal with int return value
endtask // ref_init
endmodule : uvmt_cv32e20_imperas_dv_wrap
-`endif // USE_ISS
+`else // USE_ISS_IMPERAS
+/////////////////////////////////////////////////////////////////////////////
+// Stub for ImperasDV wrapper
+/////////////////////////////////////////////////////////////////////////////
+module uvmt_cv32e20_imperas_dv_wrap import uvm_pkg::*;
+ #( parameter FPU = 0,
+ parameter ZFINX = 0
+ )
+
+ ( rvviTrace rvvi ); // RVVI SystemVerilog Interface
+
+ string info_tag = "ImperasDV_stub";
+
+ task ref_init;
+ `uvm_info(info_tag, "Using a \"stub\" in place of ImperasDV.", UVM_NONE)
+ endtask // ref_init
+
+endmodule : uvmt_cv32e20_imperas_dv_wrap
+`endif // USE_ISS_IMPERAS
`endif // __UVMT_CV32E20_IMPERAS_DV_WRAP_SV__
diff --git a/tb/uvmt/uvmt_cv32e20_tb.sv b/tb/uvmt/uvmt_cv32e20_tb.sv
index 0b1f0cb..5732ab1 100644
--- a/tb/uvmt/uvmt_cv32e20_tb.sv
+++ b/tb/uvmt/uvmt_cv32e20_tb.sv
@@ -33,11 +33,7 @@ module uvmt_cv32e20_tb;
import uvm_pkg::*;
import uvmt_cv32e20_pkg::*;
import uvme_cv32e20_pkg::*;
- `ifndef FORMAL
- `ifdef USE_ISS_IMPERAS
import rvviApiPkg::*;
- `endif
- `endif
`ifdef SET_NUM_MHPMCOUNTERS
parameter int CORE_PARAM_NUM_MHPMCOUNTERS = `SET_NUM_MHPMCOUNTERS;
@@ -69,9 +65,9 @@ module uvmt_cv32e20_tb;
// DUT Wrapper Interfaces
uvmt_cv32e20_vp_status_if vp_status_if(.tests_passed(),
- .tests_failed(),
- .exit_valid(),
- .exit_value()); // Status information generated by the Virtual Peripherals in the DUT WRAPPER memory.
+ .tests_failed(),
+ .exit_valid(),
+ .exit_value()); // Status information generated by the Virtual Peripherals in the DUT WRAPPER memory.
uvme_cv32e20_core_cntrl_if core_cntrl_if(); // Static and quasi-static core control inputs.
uvmt_cv32e20_core_status_if core_status_if(.core_busy(),
.sec_lvl()); // Core status outputs
@@ -80,7 +76,7 @@ module uvmt_cv32e20_tb;
uvmt_cv32e20_step_compare_if step_compare_if();
uvmt_cv32e20_isa_covg_if isa_covg_if();
- bind cve2_core
+ bind cve2_core
uvma_rvfi_instr_if rvfi_instr_if(
.clk ( clknrst_if.clk),
.reset_n ( clknrst_if.reset_n)
@@ -92,20 +88,15 @@ module uvmt_cv32e20_tb;
);
// RVVI SystemVerilog Interface
- `ifndef FORMAL
- `ifdef USE_ISS
- rvviTrace #( .NHART(1), .RETIRE(1)) rvvi_if();
- `endif
- `endif
+ rvviTrace #( .NHART(1), .RETIRE(1)) rvvi_if();
/**
* DUT WRAPPER instance:
* This is an update of the riscv_wrapper.sv from PULP-Platform RI5CY project with
* a few mods to bring unused ports from the CORE to this level using SV interfaces.
*/
- uvmt_cv32e20_dut_wrap #(
- )
- dut_wrap (.*);
+ uvmt_cv32e20_dut_wrap #()
+ dut_wrap (.*);
bind uvmt_cv32e20_dut_wrap
uvma_obi_memory_assert_if_wrp#(
@@ -241,13 +232,13 @@ module uvmt_cv32e20_tb;
// TODO: replace with CV32E20-specific DEBUG assertions
uvmt_cv32e20_debug_assert u_debug_assert(/*.cov_assert_if(debug_cov_assert_if)*/);
- // IMPERAS DV
- `ifndef FORMAL
- `ifdef USE_ISS_IMPERAS
- uvmt_cv32e20_imperas_dv_wrap #(
- ) imperas_dv (rvvi_if);
- `endif
- `endif
+// // IMPERAS DV
+// `ifndef FORMAL
+// `ifdef USE_ISS_IMPERAS
+// uvmt_cv32e20_imperas_dv_wrap #(
+// ) imperas_dv (rvvi_if);
+// `endif
+// `endif
// // Only drive haltreq if we have an external request
// // TODO: replace with ImperasDV
@@ -284,32 +275,38 @@ module uvmt_cv32e20_tb;
// // End of ISS WRAPPER instanitation and step-and-compare logic.
/////////////////////////////////////////////////////////////////////////////
- /**
- * Test bench entry point.
- */
+ // Informational print message on loading of OVPSIM ISS to benchmark some elf image loading times
+ // OVPSIM runs its initialization at the #1ns timestamp, and should dominate the initial startup time
+ uvmt_cv32e20_imperas_dv_wrap #() imperas_dv (rvvi_if);
+
+
+ //
+ // Test bench entry point.
+ // In theory, this will be the only 'initial' block in the entire environment.
+ //
initial begin : test_bench_entry_point
// Specify time format for simulation (units_number, precision_number, suffix_string, minimum_field_width)
$timeformat(-9, 3, " ns", 8);
// Add interfaces handles to uvm_config_db
- uvm_config_db#(virtual uvma_debug_if )::set(.cntxt(null), .inst_name("*.env.debug_agent"), .field_name("vif"), .value(debug_if) );
- uvm_config_db#(virtual uvma_clknrst_if )::set(.cntxt(null), .inst_name("*.env.clknrst_agent"), .field_name("vif"), .value(clknrst_if) );
- uvm_config_db#(virtual uvma_interrupt_if )::set(.cntxt(null), .inst_name("*.env.interrupt_agent"), .field_name("vif"), .value(interrupt_if) );
- uvm_config_db#(virtual uvma_obi_memory_if )::set(.cntxt(null), .inst_name("*.env.obi_memory_instr_agent"), .field_name("vif"), .value(obi_memory_instr_if) );
- uvm_config_db#(virtual uvma_obi_memory_if )::set(.cntxt(null), .inst_name("*.env.obi_memory_data_agent"), .field_name("vif"), .value(obi_memory_data_if) );
- uvm_config_db#(virtual uvmt_cv32e20_vp_status_if )::set(.cntxt(null), .inst_name("*"), .field_name("vp_status_vif"), .value(vp_status_if) );
- uvm_config_db#(virtual uvme_cv32e20_core_cntrl_if )::set(.cntxt(null), .inst_name("*"), .field_name("core_cntrl_vif"), .value(core_cntrl_if) );
- uvm_config_db#(virtual uvmt_cv32e20_core_status_if )::set(.cntxt(null), .inst_name("*"), .field_name("core_status_vif"), .value(core_status_if) );
- uvm_config_db#(virtual uvmt_cv32e20_step_compare_if )::set(.cntxt(null), .inst_name("*"), .field_name("step_compare_vif"), .value(step_compare_if) );
- uvm_config_db#(virtual uvmt_cv32e20_isa_covg_if )::set(.cntxt(null), .inst_name("*"), .field_name("isa_covg_vif"), .value(isa_covg_if) );
- uvm_config_db#(virtual uvmt_cv32e20_debug_cov_assert_if)::set(.cntxt(null), .inst_name("*.env"), .field_name("debug_cov_vif"), .value(debug_cov_assert_if) );
- uvm_config_db#(virtual uvmt_cv32e20_vp_status_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("vp_status_vif"), .value(vp_status_if) );
- uvm_config_db#(virtual uvmt_cv32e20_isa_covg_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("isa_covg_vif"), .value(isa_covg_if) );
- uvm_config_db#(virtual uvma_interrupt_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("intr_vif"), .value(interrupt_if) );
- uvm_config_db#(virtual uvma_debug_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("debug_vif"), .value(debug_if) );
- uvm_config_db#(virtual uvma_rvfi_instr_if )::set(.cntxt(null), .inst_name("*.env.rvfi_agent"), .field_name("instr_vif0"), .value(dut_wrap.cv32e20_top_i.u_cve2_top.u_cve2_core.rvfi_instr_if));
- uvm_config_db#(virtual uvma_rvfi_unified_csr_if#(4096,32))::set(.cntxt(null), .inst_name("*.env.rvfi_agent"), .field_name("csr_vif0"), .value(dut_wrap.cv32e20_top_i.u_cve2_top.u_cve2_core.cs_registers_i.rvfi_csr_if));
+ uvm_config_db#(virtual uvma_debug_if )::set(.cntxt(null), .inst_name("*.env.debug_agent"), .field_name("vif"), .value(debug_if) );
+ uvm_config_db#(virtual uvma_clknrst_if )::set(.cntxt(null), .inst_name("*.env.clknrst_agent"), .field_name("vif"), .value(clknrst_if) );
+ uvm_config_db#(virtual uvma_interrupt_if )::set(.cntxt(null), .inst_name("*.env.interrupt_agent"), .field_name("vif"), .value(interrupt_if) );
+ uvm_config_db#(virtual uvma_obi_memory_if )::set(.cntxt(null), .inst_name("*.env.obi_memory_instr_agent"), .field_name("vif"), .value(obi_memory_instr_if) );
+ uvm_config_db#(virtual uvma_obi_memory_if )::set(.cntxt(null), .inst_name("*.env.obi_memory_data_agent"), .field_name("vif"), .value(obi_memory_data_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_vp_status_if )::set(.cntxt(null), .inst_name("*"), .field_name("vp_status_vif"), .value(vp_status_if) );
+ uvm_config_db#(virtual uvme_cv32e20_core_cntrl_if )::set(.cntxt(null), .inst_name("*"), .field_name("core_cntrl_vif"), .value(core_cntrl_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_core_status_if )::set(.cntxt(null), .inst_name("*"), .field_name("core_status_vif"), .value(core_status_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_step_compare_if )::set(.cntxt(null), .inst_name("*"), .field_name("step_compare_vif"), .value(step_compare_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_isa_covg_if )::set(.cntxt(null), .inst_name("*"), .field_name("isa_covg_vif"), .value(isa_covg_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_debug_cov_assert_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("debug_cov_vif"), .value(debug_cov_assert_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_vp_status_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("vp_status_vif"), .value(vp_status_if) );
+ uvm_config_db#(virtual uvmt_cv32e20_isa_covg_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("isa_covg_vif"), .value(isa_covg_if) );
+ uvm_config_db#(virtual uvma_interrupt_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("intr_vif"), .value(interrupt_if) );
+ uvm_config_db#(virtual uvma_debug_if )::set(.cntxt(null), .inst_name("*.env"), .field_name("debug_vif"), .value(debug_if) );
+ uvm_config_db#(virtual uvma_rvfi_instr_if )::set(.cntxt(null), .inst_name("*.env.rvfi_agent"), .field_name("instr_vif0"), .value(dut_wrap.cv32e20_top_i.u_cve2_top.u_cve2_core.rvfi_instr_if));
+ uvm_config_db#(virtual uvma_rvfi_unified_csr_if#(4096,32))::set(.cntxt(null), .inst_name("*.env.rvfi_agent"), .field_name("csr_vif0"), .value(dut_wrap.cv32e20_top_i.u_cve2_top.u_cve2_core.cs_registers_i.rvfi_csr_if));
// TODO: fix this
//uvm_config_db#(virtual RVVI_memory )::set(.cntxt(null), .inst_name("*.env"), .field_name("rvvi_memory_vif"), .value(iss_wrap.ram.memory) );
@@ -323,29 +320,23 @@ module uvmt_cv32e20_tb;
// TODO: the E40P env uses this, but it is not clear that the E20 ever will.
//uvm_config_db#(int)::set(.cntxt(null), .inst_name("*"), .field_name("CORE_PARAM_PULP_XPULP"), .value(CORE_PARAM_PULP_XPULP) );
- // Run test
- uvm_top.enable_print_topology = 0; // ENV coders enable this as a debug aid
- uvm_top.finish_on_completion = 1;
- uvm_top.run_test();
+ fork
+ begin
+ #0.9ns; // overcome race
+ imperas_dv.ref_init();
+ end
+ begin
+ // Run test
+ uvm_top.enable_print_topology = 0; // ENV coders enable this as a debug aid
+ uvm_top.finish_on_completion = 1;
+ uvm_top.run_test();
+ end
+ join
+
end : test_bench_entry_point
assign core_cntrl_if.clk = clknrst_if.clk;
- // Informational print message on loading of OVPSIM ISS to benchmark some elf image loading times
- // OVPSIM runs its initialization at the #1ns timestamp, and should dominate the initial startup time
- `ifndef FORMAL // Formal ignores initial blocks, avoids unnecessary warning
- // overcome race
- `ifdef USE_ISS_IMPERAS
- initial begin
- if ($test$plusargs("USE_ISS")) begin
- #0.9ns;
- imperas_dv.ref_init();
- end
- end
- `endif
- `endif
-
-
// Capture the test status and exit pulse flags
// TODO: put this logic in the vp_status_if (makes it easier to pass to ENV)
always @(posedge clknrst_if.clk) begin
@@ -394,10 +385,7 @@ module uvmt_cv32e20_tb;
void'(uvm_config_db#(bit)::get(null, "", "sim_finished", sim_finished));
// Shutdown the Reference Model
- `ifdef USE_ISS_IMPERAS
- // Exit handler for ImperasDV
void'(rvviRefShutdown());
- `endif
// In most other contexts, calls to $display() in a UVM environment are
// illegal. Here they are OK because the UVM environment has shut down
diff --git a/tb/uvmt/uvmt_cv32e20_tdefs.sv b/tb/uvmt/uvmt_cv32e20_tdefs.sv
index 975c29f..2c14137 100644
--- a/tb/uvmt/uvmt_cv32e20_tdefs.sv
+++ b/tb/uvmt/uvmt_cv32e20_tdefs.sv
@@ -1,36 +1,42 @@
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
-// Copyright 2020,2022 OpenHW Group
+// Copyright 2020,2022,2024 OpenHW Group
// Copyright 2020 Datum Technology Corporation
-//
+//
// Licensed under the Solderpad Hardware Licence, 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
-//
+//
// https://solderpad.org/licenses/
-//
+//
// 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.
-//
+//
`ifndef __UVMT_CV32E20_TDEFS_SV__
`define __UVMT_CV32E20_TDEFS_SV__
-/**
- * Test Program Type. See the Verification Strategy for a discussion of this.
- */
+// Test Program Type. See the Verification Strategy for a discussion of this.
typedef enum {
PREEXISTING_SELFCHECKING,
PREEXISTING_NOTSELFCHECKING,
GENERATED_SELFCHECKING,
GENERATED_NOTSELFCHECKING,
NO_TEST_PROGRAM
- } test_program_type;
+ } test_program_type;
+
+// Selector for the Reference Model
+typedef enum bit [1:0] {
+ NONE = 2'b00,
+ SPIKE = 2'b01,
+ IMPERAS_DV = 2'b10,
+ BOTH = 2'b11
+ } ref_model_enum;
`endif // __UVMT_CV32E20_TDEFS_SV__
diff --git a/tests/programs/custom/hello-world/hello-world.c b/tests/programs/custom/hello-world/hello-world.c
index dd45327..9cbe4cc 100644
--- a/tests/programs/custom/hello-world/hello-world.c
+++ b/tests/programs/custom/hello-world/hello-world.c
@@ -137,7 +137,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
else {
- printf("\n");
+ printf("\nEXIT_SUCCESS!\n");
return EXIT_SUCCESS;
}
}
diff --git a/tests/uvmt/base-tests/uvmt_cv32e20_base_test.sv b/tests/uvmt/base-tests/uvmt_cv32e20_base_test.sv
index 52166ca..b252f0d 100644
--- a/tests/uvmt/base-tests/uvmt_cv32e20_base_test.sv
+++ b/tests/uvmt/base-tests/uvmt_cv32e20_base_test.sv
@@ -35,8 +35,8 @@ class uvmt_cv32e20_base_test_c extends uvm_test;
rand uvmt_cv32e20_test_randvars_c test_randvars ;
rand uvme_cv32e20_cfg_c env_cfg ;
rand uvme_cv32e20_cntxt_c env_cntxt ;
- uvml_logs_rs_text_c rs ;
- uvml_logs_reg_logger_cbs_c reg_cbs ;
+ uvml_logs_rs_text_c rs ;
+ uvml_logs_reg_logger_cbs_c reg_cbs ;
// Components
uvme_cv32e20_env_c env ;
@@ -285,6 +285,9 @@ task uvmt_cv32e20_base_test_c::configure_phase(uvm_phase phase);
`uvm_info("BASE TEST", "set load_instr_mem", UVM_NONE)
end
+ // Need to tell the TB module which Reference Model we are using.
+ uvm_config_db#(ref_model_enum)::set(uvm_root::get(), "*", "ref_model", test_cfg.ref_model);
+
//TODO: is this OK?!?
super.configure_phase(phase);
`uvm_info("BASE TEST", "configure_phase() complete", UVM_HIGH)
@@ -333,7 +336,7 @@ function void uvmt_cv32e20_base_test_c::phase_ended(uvm_phase phase);
`uvm_error("END_OF_TEST", $sformatf("DUT WRAPPER virtual peripheral signaled exit_value=%0h.", evalue))
end
else begin
- `uvm_info("END_OF_TEST", $sformatf("DUT WRAPPER virtual peripheral signaled exit_value=%0h.", evalue), UVM_NONE)
+ `uvm_info("END_OF_TEST", $sformatf("DUT WRAPPER virtual peripheral signaled exit_value=%0h.", evalue), UVM_DEBUG)
end
end
@@ -383,7 +386,6 @@ function void uvmt_cv32e20_base_test_c::create_cfg();
test_cfg = uvmt_cv32e20_test_cfg_c::type_id::create("test_cfg");
env_cfg = uvme_cv32e20_cfg_c ::type_id::create("env_cfg" );
- //ral = env_cfg.ral;
endfunction : create_cfg
diff --git a/tests/uvmt/base-tests/uvmt_cv32e20_test_cfg.sv b/tests/uvmt/base-tests/uvmt_cv32e20_test_cfg.sv
index 9bc6e38..0838c22 100644
--- a/tests/uvmt/base-tests/uvmt_cv32e20_test_cfg.sv
+++ b/tests/uvmt/base-tests/uvmt_cv32e20_test_cfg.sv
@@ -24,29 +24,14 @@
*/
class uvmt_cv32e20_test_cfg_c extends uvm_object;
- //typedef enum {
- // PREEXISTING_SELFCHECKING,
- // PREEXISTING_NOTSELFCHECKING,
- // GENERATED_SELFCHECKING,
- // GENERATED_NOTSELFCHECKING,
- // NONE
- // } test_program_type;
-
-
// Knobs for environment control
rand int unsigned startup_timeout ; // Specified in nanoseconds (ns)
rand int unsigned heartbeat_period; // Specified in nanoseconds (ns)
rand int unsigned watchdog_timeout; // Specified in nanoseconds (ns)
-
+
// Knobs for test-program control
rand test_program_type tpt;
- // Command line arguments for controlling RAL
- // (note: its not clear if this ENV will use the RAL)
- string cli_block_name_str = "BLKNM";
- bit cli_block_name_override = 0;
- //uvm_reg_block cli_selected_block;
-
// Command line arguments for FIRMWARE (Test Program) selection
// +firmware=
string cli_firmware_select_str = "firmware";
@@ -60,65 +45,51 @@ class uvmt_cv32e20_test_cfg_c extends uvm_object;
bit cli_uvm_banner_select_override = 0;
string cli_uvm_banner_name_str = "";
- // Run-time control
- bit run_riscv_gcc_toolchain = 0;
- bit print_uvm_runflow_banner = 0;
-
- `uvm_object_utils_begin(uvmt_cv32e20_test_cfg_c)
- `uvm_field_int(heartbeat_period, UVM_DEFAULT)
- `uvm_field_int(watchdog_timeout, UVM_DEFAULT)
+ // Run-time control defaults
+ bit run_riscv_gcc_toolchain = 0;
+ bit print_uvm_runflow_banner = 0;
+ ref_model_enum ref_model = NONE;
- `uvm_field_enum(test_program_type, tpt, UVM_DEFAULT)
-
- //`uvm_field_object(cli_selected_block, UVM_DEFAULT)
- `uvm_field_int(run_riscv_gcc_toolchain, UVM_DEFAULT)
+ `uvm_object_utils_begin(uvmt_cv32e20_test_cfg_c)
+ `uvm_field_int(heartbeat_period, UVM_DEFAULT)
+ `uvm_field_int(watchdog_timeout, UVM_DEFAULT)
+ `uvm_field_int(run_riscv_gcc_toolchain, UVM_DEFAULT)
`uvm_field_int(print_uvm_runflow_banner, UVM_DEFAULT)
+
+ `uvm_field_enum(test_program_type, tpt, UVM_DEFAULT)
+ `uvm_field_enum(ref_model_enum, ref_model, UVM_DEFAULT)
`uvm_object_utils_end
-
-
+
+
constraint timeouts_default_cons {
soft startup_timeout == 100_000_000; // Set to be huge for now so that sim can finish
- soft heartbeat_period == 200_000; // 2 us // TODO Set default Heartbeat Monitor period for uvmt_cv32e20_base_test_c
+ soft heartbeat_period == 200_000; // 2 us // TODO Set default Heartbeat Monitor period for uvmt_cv32e20_base_test_c
soft watchdog_timeout == 100_000_000; // 10 ms // TODO Set default Watchdog timeout period for uvmt_cv32e20_base_test_c
}
-
- //constraint test_type_default_cons {
- // soft tpt == NONE;
- //}
-
+
/**
* Default constructor.
*/
extern function new(string name="uvmt_cv32e20_test_cfg");
-
+
/**
* TODO Describe uvmt_cv32e20_test_cfg_c::process_cli_args()
*/
extern function void process_cli_args();
-
+
endclass : uvmt_cv32e20_test_cfg_c
function uvmt_cv32e20_test_cfg_c::new(string name="uvmt_cv32e20_test_cfg");
-
+
super.new(name);
-
+
endfunction : new
function void uvmt_cv32e20_test_cfg_c::process_cli_args();
-
+
string cli_block_name_parsed_str = "";
-
- // RAL control
- cli_block_name_override = 0; //default
- if (uvm_cmdline_proc.get_arg_value({"+", cli_block_name_str, "="}, cli_block_name_parsed_str)) begin
- if (cli_block_name_parsed_str != "") begin
- cli_block_name_override = 1;
- //cli_selected_block = ral.get_block_by_name(cli_block_name_parsed_str);
- `uvm_info("TEST_CFG", $sformatf("process_cli_args() RAL block_name=%s", cli_block_name_str), UVM_LOW)
- end
- end
// Test program (firmware) selection
cli_firmware_select_override = 0; // default
@@ -141,8 +112,26 @@ function void uvmt_cv32e20_test_cfg_c::process_cli_args();
end
end
+ // Select a Reference Model.
+ // To maintain backward compatibility, +USE_ISS will enable the ImperasDV reference model.
+ // +SPIKE, +IMPERAS_DV and +BOTH allows user to select Spike or Imperas or both.
+ // Unless you specify a Reference Model, you don't get one.
+ if ($test$plusargs("USE_ISS")) begin
+ ref_model = IMPERAS_DV; // backward compatibility
+ end
+ else begin
+ ref_model = NONE;
+ if ( ($test$plusargs("SPIKE") ) &&
+ ($test$plusargs("IMPERAS") )
+ ) ref_model = BOTH;
+ if ( $test$plusargs("SPIKE") ) ref_model = SPIKE;
+ if ( $test$plusargs("IMPERAS") ) ref_model = IMPERAS_DV;
+ if ( $test$plusargs("BOTH") ) ref_model = BOTH;
+ end
+ `uvm_info("TEST_CFG", $sformatf("Reference Model selected for this test: %s", ref_model.name()), UVM_NONE)
+
`uvm_info("TEST_CFG", "process_cli_args() complete", UVM_HIGH)
-
+
endfunction : process_cli_args
diff --git a/tests/uvmt/compliance-tests/uvmt_cv32e20_firmware_test.sv b/tests/uvmt/compliance-tests/uvmt_cv32e20_firmware_test.sv
index d50bcaa..de4c685 100644
--- a/tests/uvmt/compliance-tests/uvmt_cv32e20_firmware_test.sv
+++ b/tests/uvmt/compliance-tests/uvmt_cv32e20_firmware_test.sv
@@ -115,7 +115,7 @@ task uvmt_cv32e20_firmware_test_c::run_phase(uvm_phase phase);
end
phase.raise_objection(this);
- `uvm_info("TEST", "Started RUN", UVM_NONE)
+ `uvm_info("TEST", "run_phase has raised objection...", UVM_HIGH)
// The firmware is expected to write exit status and pass/fail indication to the Virtual Peripheral
wait (
(vp_status_vif.exit_valid == 1'b1) ||
@@ -124,8 +124,16 @@ task uvmt_cv32e20_firmware_test_c::run_phase(uvm_phase phase);
);
repeat (100) @(posedge env_cntxt.clknrst_cntxt.vif.clk);
//TODO: exit_value will not be valid - need to add a latch in the vp_status_vif
- `uvm_info("TEST", $sformatf("Finished RUN: exit status is %0h", vp_status_vif.exit_value), UVM_NONE)
+ begin
+ string mystr = "Finished run_phase:\n";
+ mystr = {mystr,$sformatf(" exit_value is %0h\n", vp_status_vif.exit_value)};
+ mystr = {mystr,$sformatf(" exit_valid is %0h\n", vp_status_vif.exit_valid)};
+ mystr = {mystr,$sformatf(" test_failed is %0h\n", vp_status_vif.tests_failed)};
+ mystr = {mystr,$sformatf(" test_passed is %0h\n", vp_status_vif.tests_passed)};
+ `uvm_info("TEST", $sformatf("%s", mystr), UVM_DEBUG)
+ end
phase.drop_objection(this);
+ `uvm_info("TEST", "run_phase has dropped objection...", UVM_HIGH)
endtask : run_phase
diff --git a/vendor_lib/.gitignore b/vendor_lib/.gitignore
index f970075..a9930f8 100644
--- a/vendor_lib/.gitignore
+++ b/vendor_lib/.gitignore
@@ -1 +1,3 @@
-embench/
\ No newline at end of file
+embench/
+verilab/
+openhwgroup_core-v-verif/
diff --git a/vendor_lib/README.md b/vendor_lib/README.md
index 797a3e1..dfbfabd 100644
--- a/vendor_lib/README.md
+++ b/vendor_lib/README.md
@@ -2,11 +2,20 @@
This is where you will find "vendor" Verification Components used the CORE-V verification environments.
-# imperas
-Source files used to support the Imperas Instruction Set Simulator.
-
# google
Verification components from Google. Note that the bulk of the code is cloned
to directories below this directory by the scriptware and/or Makefiles that
compile the verification environment and launch simulations.
+# imperas
+Source files used to support the Imperas OVPsim Instruction Set Simulator.
+Note that this model is not used in the CV32E20 (kept here for historical reference).
+
+#riscv-verification
+A copy (not clone) of RVVI-Trace and RVVI-Api headers files from the 20240403.0 branch of https://github.com/riscv-verification/RVVI
+
+# riscv-arch-test
+Files cloned from https://github.com/riscv-non-isa/riscv-arch-test
+
+# verilab
+Cloned from https://www.verilab.com/post/svlib-a-programmers-utility-library-for-systemverilog
diff --git a/vendor_lib/riscv/.gitignore b/vendor_lib/riscv-arch-test/.gitignore
similarity index 100%
rename from vendor_lib/riscv/.gitignore
rename to vendor_lib/riscv-arch-test/.gitignore
diff --git a/vendor_lib/riscv-arch-test/README.md b/vendor_lib/riscv-arch-test/README.md
new file mode 100644
index 0000000..171629f
--- /dev/null
+++ b/vendor_lib/riscv-arch-test/README.md
@@ -0,0 +1,2 @@
+### RISCV
+RISC-V Compliance Test-suite will be cloned here.
diff --git a/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvvi.f b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvvi.f
new file mode 100755
index 0000000..689c262
--- /dev/null
+++ b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvvi.f
@@ -0,0 +1,6 @@
+///////////////////////////////////////////////////////////////////////////////
+// Files for RVVI inclusion
+///////////////////////////////////////////////////////////////////////////////
+
+${IMPERAS_HOME}/ImpPublic/source/host/rvvi/rvviApiPkg.sv
+${IMPERAS_HOME}/ImpPublic/source/host/rvvi/rvviTrace.sv
diff --git a/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviApiPkg.sv b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviApiPkg.sv
new file mode 100644
index 0000000..0c3f2a4
--- /dev/null
+++ b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviApiPkg.sv
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2005-2024 Imperas Software Ltd., www.imperas.com
+ *
+ * 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.
+ *
+ */
+
+`ifndef _RVVI_API_PKG__
+`define _RVVI_API_PKG__
+
+package rvviApiPkg;
+
+`ifdef UVM
+import uvm_pkg::*;
+`endif
+
+parameter RVVI_API_VERSION_MAJOR = 1;
+parameter RVVI_API_VERSION_MINOR = 34;
+parameter RVVI_TRUE = 1;
+parameter RVVI_FALSE = 0;
+//parameter RVVI_INVALID_INDEX = -1;
+parameter RVVI_MEMORY_PRIVILEGE_READ = 1;
+parameter RVVI_MEMORY_PRIVILEGE_WRITE = 2;
+parameter RVVI_MEMORY_PRIVILEGE_EXEC = 4;
+parameter RVVI_API_VERSION = ((RVVI_API_VERSION_MAJOR << 24) | RVVI_API_VERSION_MINOR);
+
+typedef enum {
+ RVVI_METRIC_RETIRES = 0,
+ RVVI_METRIC_TRAPS = 1,
+ RVVI_METRIC_MISMATCHES = 2,
+ RVVI_METRIC_COMPARISONS_PC = 3,
+ RVVI_METRIC_COMPARISONS_GPR = 4,
+ RVVI_METRIC_COMPARISONS_FPR = 5,
+ RVVI_METRIC_COMPARISONS_CSR = 6,
+ RVVI_METRIC_COMPARISONS_VR = 7,
+ RVVI_METRIC_COMPARISONS_INSBIN = 8,
+ RVVI_METRIC_CYCLES = 9,
+ RVVI_METRIC_ERRORS = 10,
+ RVVI_METRIC_WARNINGS = 11,
+ RVVI_METRIC_FATALS = 12
+} rvviMetricE;
+
+import "DPI-C" context function byte rvviVersionCheck(
+ input int version);
+
+import "DPI-C" context function byte rvviRefInit(
+ input string programPath);
+
+import "DPI-C" context function byte rvviRefPcSet(
+ input int hartId,
+ input longint address);
+
+import "DPI-C" context function byte rvviRefShutdown();
+
+import "DPI-C" context function byte rvviRefCsrSetVolatile(
+ input int hartId,
+ input int csrIndex);
+
+import "DPI-C" context function byte rvviRefMemorySetVolatile(
+ input longint addressLow,
+ input longint addressHigh);
+
+import "DPI-C" context function longint rvviRefNetIndexGet(
+ input string name);
+
+import "DPI-C" context function int rvviRefVrGet(
+ input int hartId,
+ input int vrIndex,
+ input int byteIndex);
+
+import "DPI-C" context function void rvviDutVrSet(
+ input int hartId,
+ input int vrIndex,
+ input int byteIndex,
+ input int data);
+
+import "DPI-C" context function void rvviDutFprSet(
+ input int hartId,
+ input int fprIndex,
+ input longint value);
+
+import "DPI-C" context function void rvviDutGprSet(
+ input int hartId,
+ input int gprIndex,
+ input longint value);
+
+import "DPI-C" context function void rvviDutCsrSet(
+ input int hartId,
+ input int csrIndex,
+ input longint value);
+
+import "DPI-C" context function void rvviRefNetGroupSet(
+ input longint netIndex,
+ input int group);
+
+import "DPI-C" context function void rvviRefNetSet(
+ input longint netIndex,
+ input longint value,
+ input longint when);
+
+import "DPI-C" context function longint rvviRefNetGet(
+ input longint netIndex);
+
+import "DPI-C" context function void rvviDutRetire(
+ input int hartId,
+ input longint dutPc,
+ input longint dutInsBin,
+ input byte debugMode);
+
+import "DPI-C" context function void rvviDutTrap(
+ input int hartId,
+ input longint dutPc,
+ input longint dutInsBin);
+
+import "DPI-C" context function void rvviRefReservationInvalidate(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefEventStep(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefGprsCompare(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefGprsCompareWritten(
+ input int hartId,
+ input byte ignoreX0);
+
+import "DPI-C" context function byte rvviRefInsBinCompare(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefPcCompare(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefCsrCompare(
+ input int hartId,
+ input int csrIndex);
+
+import "DPI-C" context function void rvviRefCsrCompareEnable(
+ input int hartId,
+ input int csrIndex,
+ input byte enableState);
+
+import "DPI-C" context function void rvviRefCsrCompareMask(
+ input int hartId,
+ input int csrIndex,
+ input longint mask);
+
+import "DPI-C" context function byte rvviRefCsrsCompare(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefVrsCompare(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefFprsCompare(
+ input int hartId);
+
+import "DPI-C" context function void rvviRefGprSet(
+ input int hartId,
+ input int gprIndex,
+ input longint gprValue);
+
+import "DPI-C" context function longint rvviRefGprGet(
+ input int hartId,
+ input int gprIndex);
+
+import "DPI-C" context function int rvviRefGprsWrittenGet(
+ input int hartId);
+
+import "DPI-C" context function longint rvviRefPcGet(
+ input int hartId);
+
+import "DPI-C" context function longint rvviRefCsrGet(
+ input int hartId,
+ input int csrIndex);
+
+import "DPI-C" context function longint rvviRefInsBinGet(
+ input int hartId);
+
+import "DPI-C" context function void rvviRefFprSet(
+ input int hartId,
+ input int fprIndex,
+ input longint fprValue);
+
+import "DPI-C" context function longint rvviRefFprGet(
+ input int hartId,
+ input int fprIndex);
+
+import "DPI-C" context function void rvviDutBusWrite(
+ input int hartId,
+ input longint address,
+ input longint value,
+ input longint byteEnableMask);
+
+import "DPI-C" context function void rvviRefMemoryWrite(
+ input int hartId,
+ input longint address,
+ input longint data,
+ input int size);
+
+import "DPI-C" context function longint rvviRefMemoryRead(
+ input int hartId,
+ input longint address,
+ input int size);
+
+import "DPI-C" context function string rvviDasmInsBin(
+ input int hartId,
+ input longint address,
+ input longint insBin);
+
+import "DPI-C" context function string rvviRefCsrName(
+ input int hartId,
+ input int csrIndex);
+
+import "DPI-C" context function string rvviRefGprName(
+ input int hartId,
+ input int gprIndex);
+
+import "DPI-C" context function byte rvviRefCsrPresent(
+ input int hartId,
+ input int csrIndex);
+
+import "DPI-C" context function byte rvviRefFprsPresent(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefVrsPresent(
+ input int hartId);
+
+import "DPI-C" context function string rvviRefFprName(
+ input int hartId,
+ input int fprIndex);
+
+import "DPI-C" context function string rvviRefVrName(
+ input int hartId,
+ input int vrIndex);
+
+import "DPI-C" context function string rvviErrorGet();
+
+import "DPI-C" context function longint rvviRefMetricGet(
+ input rvviMetricE metric);
+
+import "DPI-C" context function void rvviRefCsrSet(
+ input int hartId,
+ input int csrIndex,
+ input longint value);
+
+import "DPI-C" context function void rvviRefStateDump(
+ input int hartId);
+
+import "DPI-C" context function byte rvviRefProgramLoad(
+ input string programPath);
+
+import "DPI-C" context function byte rvviRefCsrSetVolatileMask(
+ input int hartId,
+ input int csrIndex,
+ input longint csrMask);
+
+import "DPI-C" context function void rvviDutCycleCountSet(
+ input longint cycleCount);
+
+import "DPI-C" context function byte rvviRefConfigSetInt(
+ input longint configParam,
+ input longint value);
+
+import "DPI-C" context function byte rvviRefConfigSetString(
+ input longint configParam,
+ input string value);
+
+import "DPI-C" context function int rvviRefCsrIndex(
+ input int hartId,
+ input string csrName);
+
+import "DPI-C" context function byte rvviRefMemorySetPrivilege(
+ input longint addrLo,
+ input longint addrHi,
+ input int access);
+
+import "DPI-C" context function void rvviRefVrSet(
+ input int hartId,
+ input int vrIndex,
+ input int byteIndex,
+ input int data);
+
+import "DPI-C" context function void setContextExtMemory(input string func);
+
+endpackage: rvviApiPkg
+
+`endif // _RVVI_API_PKG__
+
diff --git a/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviTrace.sv b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviTrace.sv
new file mode 100644
index 0000000..9e469ec
--- /dev/null
+++ b/vendor_lib/riscv-verification/RVVI/source/host/rvvi/rvviTrace.sv
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2005-2024 Imperas Software Ltd., www.imperas.com
+ *
+ * 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.
+ *
+ */
+
+`define NUM_REGS 32
+`define NUM_CSRS 4096
+
+`define RVVI_TRACE_VERSION_MAJOR 1
+`define RVVI_TRACE_VERSION_MINOR 5
+
+/*
+ * A single DTM (Debug Transport Module), connects
+ * via the DMI (Debug Module Interface) to
+ * a DM (Debug Module), which can control N harts
+ *
+ */
+interface dm
+#(
+ parameter int ILEN = 32, // Instruction length in bits
+ parameter int XLEN = 32, // GPR length in bits
+ parameter int FLEN = 32, // FPR length in bits
+ parameter int VLEN = 256, // Vector register size in bits
+ parameter int NHART = 1, // Number of harts reported
+ parameter int RETIRE = 1 // Number of instructions that can retire during valid event
+);
+ //
+ // RISCV DM signals
+ //
+ wire clk; // Interface clock
+ wire rd; // read
+ wire wr; // write
+ wire [31:0] address;
+ wire [31:0] data;
+
+ bit [(XLEN-1):0] store [127:0]; // Storage for DM registers
+
+endinterface
+
+interface rvviTrace
+#(
+ parameter int ILEN = 32, // Instruction length in bits
+ parameter int XLEN = 32, // GPR length in bits
+ parameter int FLEN = 32, // FPR length in bits
+ parameter int VLEN = 256, // Vector register size in bits
+ parameter int NHART = 1, // Number of harts reported
+ parameter int RETIRE = 1 // Number of instructions that can retire during valid event
+);
+ //
+ // RISCV output signals
+ //
+ wire clk; // Interface clock
+ wire valid [(NHART-1):0][(RETIRE-1):0]; // Valid event
+ wire [63:0] order [(NHART-1):0][(RETIRE-1):0]; // Unique event order count (no gaps or reuse)
+
+ wire [(ILEN-1):0] insn [(NHART-1):0][(RETIRE-1):0]; // Instruction bit pattern
+ wire trap [(NHART-1):0][(RETIRE-1):0]; // State update without instruction retirement
+ wire debug_mode [(NHART-1):0][(RETIRE-1):0]; // Retired instruction executed in debug mode
+
+ // Program counter
+ wire [(XLEN-1):0] pc_rdata [(NHART-1):0][(RETIRE-1):0]; // PC of instruction
+
+ // X Registers
+ wire [31:0][(XLEN-1):0] x_wdata [(NHART-1):0][(RETIRE-1):0]; // X data value
+ wire [31:0] x_wb [(NHART-1):0][(RETIRE-1):0]; // X data writeback (change) flag
+
+ // F Registers
+ wire [31:0][(FLEN-1):0] f_wdata [(NHART-1):0][(RETIRE-1):0]; // F data value
+ wire [31:0] f_wb [(NHART-1):0][(RETIRE-1):0]; // F data writeback (change) flag
+
+ // V Registers
+ wire [31:0][(VLEN-1):0] v_wdata [(NHART-1):0][(RETIRE-1):0]; // V data value
+ wire [31:0] v_wb [(NHART-1):0][(RETIRE-1):0]; // V data writeback (change) flag
+
+ // Control and Status Registers
+ wire [4095:0][(XLEN-1):0] csr [(NHART-1):0][(RETIRE-1):0]; // Full CSR Address range
+ wire [4095:0] csr_wb [(NHART-1):0][(RETIRE-1):0]; // CSR writeback (change) flag
+
+ // Atomic Memory Control
+ wire lrsc_cancel[(NHART-1):0][(RETIRE-1):0]; // Implementation defined cancel
+
+ //
+ // Optional
+ //
+ wire [(XLEN-1):0] pc_wdata [(NHART-1):0][(RETIRE-1):0]; // PC of next instruction
+ wire intr [(NHART-1):0][(RETIRE-1):0]; // (RVFI Legacy) Flag first instruction of trap handler
+ wire halt [(NHART-1):0][(RETIRE-1):0]; // Halted instruction
+ wire [1:0] ixl [(NHART-1):0][(RETIRE-1):0]; // XLEN mode 32/64 bit
+ wire [1:0] mode [(NHART-1):0][(RETIRE-1):0]; // Privilege mode of operation
+
+ //
+ // Optional DMI Interface
+ //
+ dm dm();
+
+ //
+ // Synchronization of NETs
+ //
+ longint vslot;
+ always @(posedge clk) begin
+ vslot <= vslot + 1;
+ end
+
+ string name[$];
+ longint unsigned value[$];
+ longint unsigned tslot[$];
+ longint unsigned nets[string];
+
+ function automatic void net_push(input string pname, input longint unsigned pvalue);
+ name.push_front(pname);
+ value.push_front(pvalue);
+ tslot.push_front(vslot);
+ endfunction
+
+ function automatic int net_pop(output string pname, output longint unsigned pvalue, output longint unsigned pslot);
+ int ok;
+ string msg;
+ if (name.size() > 0) begin
+ pname = name.pop_back();
+ pvalue = value.pop_back();
+ pslot = tslot.pop_back();
+ nets[pname] = pvalue;
+ ok = 1;
+ end else begin
+ ok = 0;
+ end
+ return ok;
+ endfunction
+
+endinterface
diff --git a/vendor_lib/riscv-verification/stubs/.gitignore b/vendor_lib/riscv-verification/stubs/.gitignore
new file mode 100644
index 0000000..140f8cf
--- /dev/null
+++ b/vendor_lib/riscv-verification/stubs/.gitignore
@@ -0,0 +1 @@
+*.so
diff --git a/vendor_lib/riscv-verification/stubs/README.md b/vendor_lib/riscv-verification/stubs/README.md
new file mode 100644
index 0000000..80717d2
--- /dev/null
+++ b/vendor_lib/riscv-verification/stubs/README.md
@@ -0,0 +1,11 @@
+# RVVI Stubs
+
+This directory contains "stub" implementations of various DPI calls implemented by ImperaDV.
+It is a goal of the CV32E20 project to support a verification environment that can run with or without ImperasDV,
+and these stubs are implemented to make it easier to use (or not) ImperasDV at compile-time.
+
+The stubs are automatically compiled by the Makefiles as needed.
+To build them seperately:
+```
+% make rvvi_stub CV_CORE=cv32e20
+```
diff --git a/vendor_lib/riscv-verification/stubs/rvviApiStubs.c b/vendor_lib/riscv-verification/stubs/rvviApiStubs.c
new file mode 100644
index 0000000..c7c952b
--- /dev/null
+++ b/vendor_lib/riscv-verification/stubs/rvviApiStubs.c
@@ -0,0 +1,5 @@
+#include "svdpi.h"
+extern char rvviRefShutdown()
+{
+ return 0;
+}
diff --git a/vendor_lib/riscv/README.md b/vendor_lib/riscv/README.md
deleted file mode 100644
index 748a14b..0000000
--- a/vendor_lib/riscv/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-### RISCV
-RISC-V Compliance Test-suite.
-
-The Makefiles (e.g. ../../cv32/sim/uvmt_cv32/Makefile) are expected to support targets to clone a specific hash/tag of the RISC-V Compliance Test-suite here.
diff --git a/vendor_lib/verilab/svlib_dpi.so b/vendor_lib/verilab/svlib_dpi.so
deleted file mode 100755
index c88d8ce..0000000
Binary files a/vendor_lib/verilab/svlib_dpi.so and /dev/null differ