Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
0747afbddec0ad176980429fe3100b32edb71d4a

* [dv] Enable C/C++ code sourcing with VCS in .core (Canberk Topal)
* [dv/dv_base_reg] Remove duplicated `get_map_by_name` method (Cindy
  Chen)
* [prim] Pulse Sync assertion to check input/output (Eunchan Kim)
* [sparse_fsm_flop] Create flop macro to increase DV coverage (Michael
  Schaffner)
* [dvsim] Make build-randomization opt-in (Srikrishna Iyer)
* [xcelium] Fix compile error (Srikrishna Iyer)
* [dv/cov] fpv_csr_assert only collect assertion coverage (Cindy Chen)
* [dv/jtag] Fix chip_level jtag csr rw failure (Cindy Chen)
* [rtl] Convert some non-ANSI parameters to localparams (Rupert
  Swarbrick)
* [prim] Waive unused parameters for Verilator in prim_generic_otp
  (Rupert Swarbrick)
* [prim] Make a variable widening explicit in prim_present.sv (Rupert
  Swarbrick)
* [prim] Waive some ALWCOMBORDER Verilator warnings in prim_arbiter_*
  (Rupert Swarbrick)
* [prim] Fix Verilator lint warnings in prim_gf_mult.sv (Rupert
  Swarbrick)
* [prim] Make some widening comparisons explicit in prim_clock_*.sv
  (Rupert Swarbrick)
* [prim] Waive unused EnableAlertTriggerSVA for verilator lint (Rupert
  Swarbrick)
* [bazel,dvsim] Add build rules for dvsim.py (Timothy Trippel)
* [prim] Fix a bunch of Verilator lint errors in prim_packer.sv
  (Rupert Swarbrick)
* [prim_sparse_fsm_flop/lint] Move waiver to correct file (Michael
  Schaffner)
* [rv_dm dv] Test drive compile-time seed (Srikrishna Iyer)
* [dvsim] Introduce Verilog compile-time seeds (Srikrishna Iyer)
* [dvsim] Treat `tests: ["N/A"]` as an ignored testpoint (Srikrishna
  Iyer)
* [hw/dv] Removed colon from Questa build and run fail patterns.
  (David Pudner)
* [hw/dv] Code review changes for running questa simulations. (David
  Pudner)
* [hw/dv] Added apache license header to questa_initial_setup.sh.
  (David Pudner)
* [doc/ug] Updated opentitan documentation to include information
  about Questa use. (David Pudner)
* [hw/dv] Added Questa dvsim files (David Pudner)
* [dv/unr] Blackbox common security modules from UNR flow (Cindy Chen)
* [dv] Minor fix to error message in mem_model.sv (Rupert Swarbrick)
* [keymgr] Update keymgr to use prim_edn_req (Timothy Chen)
* [doc] Fix rendering of special characters in testplan table (Rupert
  Swarbrick)
* [dv] enable tlul_assert for csr part2 (Rasmus Madsen)
* [dv] Enable tlul_assert for CSR tests (Weicai Yang)
* [dv] Add valid/ready req/ack coverage for push_pull agent (Weicai
  Yang)
* [dv,verilator] Make multiple sim_ctrl extensions play nicely (Rupert
  Swarbrick)
* [chip dv] Add AST initialization routine (Srikrishna Iyer)
* [top] auto generate (Timothy Chen)
* [reggen] Make field 'qe' behavior consistent (Timothy Chen)
* [prim] IFDEF_CODE waiver in sparsefsm flop (Eunchan Kim)
* [dv] Update checklist for all blocks (Weicai Yang)
* [dv/entropy_src] Temp remove stress_all_with_rand_reset test (Cindy
  Chen)

Signed-off-by: Canberk Topal <ctopal@lowrisc.org>
This commit is contained in:
Canberk Topal 2022-03-31 14:08:12 +01:00 committed by Canberk Topal
parent 68b56ef0f5
commit 4c1a4ed1df
53 changed files with 826 additions and 91 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/opentitan
rev: 7c4f8b3fde4bb625ac3330ff52d3f66507190fe5
rev: 0747afbddec0ad176980429fe3100b32edb71d4a
}
}

View file

@ -365,11 +365,17 @@ class dv_base_reg_block extends uvm_reg_block;
.map(map));
endfunction
// Set default map for this block and all its sub-blocks.
function void set_default_map_w_subblks(uvm_reg_map map);
// Set default map for this block and all its sub-blocks by name.
// This function only works if user is setting default map for all blocks under the hierarchy
// with the same map name.
function void set_default_map_w_subblks_by_name(string map_name);
dv_base_reg_block subblks[$];
set_default_map(map);
uvm_reg_map map = this.get_map_by_name(map_name);
`DV_CHECK(map != null)
this.set_default_map(map);
get_dv_base_reg_blocks(subblks);
foreach (subblks[i]) subblks[i].set_default_map_w_subblks(map);
foreach (subblks[i]) subblks[i].set_default_map_w_subblks_by_name(map_name);
endfunction
endclass

View file

@ -534,3 +534,10 @@
100 :/ 1 \
};
`endif
// Enables build-time randomization of fixed design constants.
//
// This is meant to be overridden externally by passing `+define+BUILD_SEED=<value>`.
`ifndef BUILD_SEED
`define BUILD_SEED 1
`endif

View file

@ -483,11 +483,14 @@ class mem_bkdr_util extends uvm_object;
endfunction
// load mem from file
virtual function void load_mem_from_file(string file);
virtual task load_mem_from_file(string file);
check_file(file, "r");
this.file = file;
->readmemh_event;
endfunction
// The delay below avoids a race condition between this mem backdoor load and a subsequent
// backdoor write to a particular location.
#0;
endtask
// save mem contents to file
virtual function void write_mem_to_file(string file);

View file

@ -32,7 +32,7 @@ class mem_model #(int AddrWidth = bus_params_pkg::BUS_AW,
`uvm_info(`gfn, $sformatf("Read Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH)
end else begin
`DV_CHECK_STD_RANDOMIZE_FATAL(data)
`uvm_error(`gfn, $sformatf("read to uninitialzed addr 0x%0h", addr))
`uvm_error(`gfn, $sformatf("read from uninitialized addr 0x%0h", addr))
end
return data;
endfunction

View file

@ -2,6 +2,27 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// coverage for sampling all the combination of valid and ready
covergroup valid_ready_cg(string name, string path) with function sample(bit valid, bit ready);
option.per_instance = 1;
option.name = {path, "::", name};
cp_valid_ready: coverpoint {valid, ready};
endgroup : valid_ready_cg
// coverage for sampling all the combination of valid and ready
covergroup req_ack_cg(string name, string path) with function sample(bit req, bit ack);
option.per_instance = 1;
option.name = {path, "::", name};
// Not a possible combination if this is non-4-phases mode.
// But this will happen in the 4 phases req-ack handshake.
// In that case, this value has to happen after 2'b11, so no need to sample it
cp_req_ack: coverpoint {req, ack} {
ignore_bins ack_wo_req = {2'b01};
}
endgroup : req_ack_cg
class push_pull_agent_cov #(parameter int HostDataWidth = 32,
parameter int DeviceDataWidth = HostDataWidth)
extends dv_base_agent_cov #(
@ -9,15 +30,16 @@ class push_pull_agent_cov #(parameter int HostDataWidth = 32,
);
`uvm_component_param_utils(push_pull_agent_cov#(HostDataWidth, DeviceDataWidth))
`uvm_component_new
// the base class provides the following handles for use:
// push_pull_agent_cfg: cfg
// covergroups
function new(string name, uvm_component parent);
super.new(name, parent);
// instantiate all covergroups here
endfunction : new
valid_ready_cg m_valid_ready_cg;
req_ack_cg m_req_ack_cg;
function void build_phase(uvm_phase phase);
if (cfg.agent_type == PushAgent) begin
m_valid_ready_cg = new("m_valid_ready_cg", `gfn);
end else begin
m_req_ack_cg = new("m_req_ack_cg", `gfn);
end
endfunction : build_phase
endclass

View file

@ -26,6 +26,7 @@ class push_pull_monitor #(parameter int HostDataWidth = 32,
collect_trans(phase);
// Collect partial pull reqs for the reactive pull device agent.
collect_pull_req();
collect_cov();
join_none
endtask
@ -108,6 +109,22 @@ class push_pull_monitor #(parameter int HostDataWidth = 32,
end
endtask
virtual protected task collect_cov();
if (cfg.en_cov) begin
if (cfg.agent_type == PushAgent) begin
forever @(cfg.vif.mon_cb.ready or cfg.vif.mon_cb.valid) begin
`WAIT_FOR_RESET
cov.m_valid_ready_cg.sample(cfg.vif.mon_cb.ready, cfg.vif.mon_cb.valid);
end // forever
end else begin // PullAgent
forever @(cfg.vif.mon_cb.req or cfg.vif.mon_cb.ack) begin
`WAIT_FOR_RESET
cov.m_req_ack_cg.sample(cfg.vif.mon_cb.req, cfg.vif.mon_cb.ack);
end // forever
end // PushAgent or PullAgent
end // cfg.en_cov
endtask
`undef WAIT_FOR_RESET
// Creates and writes the item to the analysis_port.

View file

@ -45,6 +45,27 @@
is_sim_mode: 1
en_build_modes: ["{tool}_loopdetect"]
}
// Enables randomization of testbench / RTL build.
//
// Build randomization is achieved by passing `--build-seed <optional-seed>` on the dvsim
// command-line. If not passed, the build is not randomized. Build randomization is achieved
// in two ways. One of them is setting the pre-processor macro `BUILD_SEED` to the seed value,
// which is done below. The SystemVerilog testbench sources can use the `BUILD_SEED` macro
// value to set some design constants (such as parameters) upon instantiation. The `BUILD_SEED`,
// if not set externally (by passing the --build-seed switch) is set to 1 in
// `hw/dv/sv/dv_utils/dv_macros.svh`. The other way is by passing the {seed} value to utility
// scripts that generate packages that contain randomized constants. These utility scripts can
// be invoked as a `pre_build_cmd`, wrapped within the `build_seed` sim mode in the DUT
// simulation configuration Hjson file. All forms of build randomization must be wrapped within
// this `build_seed` sim mode. They will all use the same {seed} value, which allows us to
// deterministically reproduce failures. The `--build-seed` switch is expected to be passed
// when running the nightly regressions. The `seed` value set by dvsim is a 32-bit unsigned
// integer (unless specified on the command-line).
{
name: build_seed
is_sim_mode: 1
build_opts: ["+define+BUILD_SEED={seed}"]
}
]
run_modes: [

View file

@ -0,0 +1,115 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{
build_cmd: "{job_prefix} {QUESTA_HOME}/questasim/linux_x86_64/qrun -optimize"
run_cmd: "{job_prefix} {QUESTA_HOME}/questasim/linux_x86_64/qrun -simulate"
build_opts: [ "-timescale 1ns/1ps",
"-outdir {build_dir}/qrun.out",
"-uvm -uvmhome {QUESTA_HOME}/questasim/verilog_src/uvm-1.2",
"-mfcu",
"-f {sv_flist}",
// List multiple tops for the simulation. Prepend each top level with `-top`.
"{eval_cmd} echo {sim_tops} | sed -E 's/(\\S+)/-top \\1/g'",
"-voptargs=\"+acc=nr\""
]
run_opts: [ "-outdir {build_dir}/qrun.out",
"-sv_seed {seed}",
// dv_macros.svh has a macro printing null using %0d
// format specifier, Questa throws an error on this
// we demote this error in Questa
"-suppress vsim-8323",
// Questa forces all declared virtual interfaces to be allocated,
// even in classes that are not even created at runtime. The switch
// below demotes the associated error thrown.
"-permit_unmatched_virtual_intf",
"+UVM_TESTNAME={uvm_test}",
"+UVM_TEST_SEQ={uvm_test_seq}",
"-do {run_script}"
]
// Supported wave dumping formats (in order of preference).
supported_wave_formats: []
// Default tcl script used when running the sim. Override if needed.
run_script: "{dv_root}/tools/questa/sim.tcl"
// Coverage related.
cov_db_dir: "{scratch_path}/coverage/{build_mode}.ucdb"
// Individual test specific coverage data - this will be deleted if the test fails
// so that coverage from failiing tests is not included in the final report.
cov_db_test_dir_name: "{run_dir_name}.{seed}"
cov_db_test_dir: "{cov_db_dir}/snps/coverage/db/testdata/{cov_db_test_dir_name}"
// Merging coverage.
// "cov_db_dirs" is a special variable that appends all build directories in use.
// It is constructed by the tool itself.
cov_merge_dir: "{scratch_path}/cov_report"
cov_merge_db_dir: ""
cov_merge_cmd: ""
cov_merge_opts: []
// Generate covreage reports in text as well as html.
cov_report_dir: "{scratch_path}/cov_report"
cov_report_cmd: ""
cov_report_opts: []
cov_report_txt: "{cov_report_dir}/dashboard.txt"
// Analyzing coverage - this is done by invoking --cov-analyze switch. It opens up the
// GUI for visual analysis.
cov_analyze_dir: "{scratch_path}/cov_analyze"
cov_analyze_cmd: ""
cov_analyze_opts: []
// By default, collect all coverage metrics.
cov_metrics: "bcestf"
// pass and fail patterns
build_fail_patterns: ["^## \\*\\* Error.*$"
"^\\*\\* Error.*$"]
run_fail_patterns: ["^\\*\\* Error.*$"]
build_modes: [
{
name: questa_gui
is_sim_mode: 1
build_opts: []
run_opts: ["-gui"]
}
{
name: questa_waves
is_sim_mode: 1
}
// TODO Questa coverage only currently supported in the GUI with no merging
{
name: questa_cov
is_sim_mode: 1
build_opts: ["+cover={cov_metrics}"]
run_opts: ["-coverage", "-gui"]
}
// TODO support profiling for questa
{
name: questa_profile
is_sim_mode: 1
build_opts: []
run_opts: []
}
{
name: questa_xprop
is_sim_mode: 1
build_opts: []
}
{
// TODO: Add build and run options to enable zero delay loop detection.
name: questa_loopdetect
is_sim_mode: 1
build_opts: []
run_opts: []
}
]
}

View file

@ -2,10 +2,11 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
export SHELL := /bin/bash
export SHELL := /bin/bash
.DEFAULT_GOAL := all
LOCK_SW_BUILD_DIR ?= flock --timeout 3600 ${sw_build_dir} --command
LOCK_ROOT_DIR ?= flock --timeout 3600 ${proj_root} --command
LOCK_SW_BUILD_DIR ?= flock --timeout 3600 ${sw_build_dir} --command
all: build run
@ -18,7 +19,11 @@ pre_build:
@echo "[make]: pre_build"
mkdir -p ${build_dir}
ifneq (${pre_build_cmds},)
cd ${build_dir} && ${pre_build_cmds}
# pre_build_cmds are likely changing the in-tree sources. We hence use FLOCK
# utility to prevent multiple builds that may be running in parallel from
# stepping on each other. TODO: Enforce the list of pre_build_cmds is
# identical across all build modes.
${LOCK_ROOT_DIR} "cd ${build_dir} && ${pre_build_cmds}"
endif
gen_sv_flist: pre_build

View file

@ -0,0 +1,17 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Different from `stress_tests.hjson`, this hjson only include `stress_all` test to serve as a
// temporary import for IPs that are at V2 stage and does not support `stress_all_with_rand_reset`
// sequence.
{
tests: [
{
name: "{name}_stress_all"
uvm_test_seq: "{name}_stress_all_vseq"
// 10ms
run_opts: ["+test_timeout_ns=10000000000"]
}
]
}

View file

@ -0,0 +1,18 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
# Remove leading "# " from the front of log file lines and run the test if not in gui mode.
# This provides compatibility for log file error checking with other supported simulators within Opentitan.
set gui 0
if {[info exists ::env(GUI)]} {
set gui "$::env(GUI)"
}
if {$gui == 0} {
set PrefMain(LinePrefix) ""
run -all
} else {
set PrefMain(LinePrefix) ""
}

View file

@ -15,6 +15,9 @@
-moduletree prim_esc_receiver
-moduletree prim_prince // prim_prince is verified in a separate DV environment.
-moduletree prim_lfsr // prim_lfsr is verified in FPV.
// csr_assert_fpv is an auto-generated csr read assertion module. So only assertion coverage is
// meaningful to collect.
-moduletree *csr_assert_fpv
begin tgl
-tree tb
@ -28,6 +31,8 @@ begin tgl
end
begin assert
+moduletree *csr_assert_fpv
// These three assertions in prim_lc_sync and prim_mubi* check when `lc_ctrl_pkg::lc_tx_t` or
// `mubi*_t` input are neither `On` or `Off`, it is interrupted to the correct `On` or `Off`
// after one clock cycle. This behavior is implemented outside of IP level design thus these

View file

@ -7,6 +7,7 @@
+moduletree *_reg_top
+node tb.dut tl_*
+assert tb.dut.tlul_assert*
// Remove everything else from toggle coverage except:
// - `prim_alert_sender`: the `alert_test` task under `cip_base_vseq` drives `alert_test_i` and

View file

@ -10,8 +10,8 @@
# Provide the reset specification: signal_name, active_value, num clk cycles reset to be active
-reset rst_ni 0 20
# Black box some of the modules
# -blackBoxes -type design *
# Black box common security modules
-blackBoxes -type design prim_count+prim_spare_fsm+prim_double_lfsr
# Name of the generated exclusion file
-save_exclusion $SCRATCH_PATH/cov_unr/unr_exclude.el

View file

@ -14,6 +14,9 @@ deselect_coverage -betfs -module prim_esc_sender...
deselect_coverage -betfs -module prim_esc_receiver...
deselect_coverage -betfs -module prim_prince...
deselect_coverage -betfs -module prim_lfsr...
// csr_assert_fpv is an auto-generated csr read assertion module. So only assertion coverage is
// meaningful to collect.
deselect_coverage -betf -module *csr_assert_fpv...
// Only collect toggle coverage on the DUT and the black-boxed IP (above) ports.
deselect_coverage -toggle -module ${DUT_TOP}...

View file

@ -8,6 +8,7 @@ include_ccf ${dv_root}/tools/xcelium/common.ccf
// Only collect code coverage on the *_reg_top instance.
deselect_coverage -betfs -module ${DUT_TOP}...
select_coverage -befs -module *_reg_top...
select_coverage -assert -module tlul_assert
// Include toggle coverage on `prim_alert_sender` because the `alert_test` task under
// `cip_base_vseq` drives `alert_test_i` and verifies `alert_rx/tx` handshake in each IP.

View file

@ -112,7 +112,7 @@ bool VerilatorMemUtil::ParseCLIArguments(int argc, char **argv,
// some arguments
optind = 1;
while (1) {
int c = getopt_long(argc, argv, ":r:m:f:l:E:h", long_options, nullptr);
int c = getopt_long(argc, argv, "-:r:m:f:l:E:h", long_options, nullptr);
if (c == -1) {
break;
}
@ -122,6 +122,7 @@ bool VerilatorMemUtil::ParseCLIArguments(int argc, char **argv,
switch (c) {
case 0:
case 1:
break;
case 'r':
load_args.push_back(

View file

@ -25,3 +25,8 @@ targets:
default:
filesets:
- files_cpp
tools:
vcs:
vcs_options:
- '-CFLAGS -I../../src/lowrisc_dv_verilator_memutil_dpi_0/cpp'
- '-lelf'

View file

@ -19,3 +19,8 @@ targets:
default:
filesets:
- files_cpp
tools:
vcs:
vcs_options:
- '-CFLAGS -I../../src/lowrisc_dv_verilator_memutil_dpi_scrambled_0/cpp'
- '-lelf'

View file

@ -13,6 +13,13 @@ class SimCtrlExtension {
* Parse command line arguments
*
* Process all recognized command-line arguments from argc/argv.
* Note that other extensions might also be registered with their
* own command line arguments.
*
* To make this work properly, the extension must only parse options
* (no positional arguments) and must leave the ordering of argv
* unchanged. In particular, if the code uses getopt_long, it should
* pass an optstring argument starting with a '-' character.
*
* @param argc, argv Standard C command line arguments
* @param exit_app Indicate that program should terminate

View file

@ -114,7 +114,7 @@ bool VerilatorSimCtrl::ParseCommandArgs(int argc, char **argv, bool &exit_app) {
{nullptr, no_argument, nullptr, 0}};
while (1) {
int c = getopt_long(argc, argv, ":c:th", long_options, nullptr);
int c = getopt_long(argc, argv, "-:c:th", long_options, nullptr);
if (c == -1) {
break;
}
@ -124,6 +124,7 @@ bool VerilatorSimCtrl::ParseCommandArgs(int argc, char **argv, bool &exit_app) {
switch (c) {
case 0:
case 1:
break;
case 't':
if (!tracing_possible_) {

View file

@ -13,3 +13,7 @@ targets:
default:
filesets:
- files_dv
tools:
vcs:
vcs_options:
- '-CFLAGS -I../../src/lowrisc_dv_crypto_prince_ref_0.1'

View file

@ -18,3 +18,7 @@ targets:
default:
filesets:
- files_cpp
tools:
vcs:
vcs_options:
- '-CFLAGS -I../../src/lowrisc_dv_scramble_model_0'

View file

@ -16,3 +16,7 @@ targets:
default:
filesets:
- files_dv
tools:
vcs:
vcs_options:
- '-CFLAGS -I../../src/lowrisc_dv_secded_enc_0'

View file

@ -20,3 +20,26 @@ split_var -module "prim_arbiter_tree" -var "sel_tree"
split_var -module "prim_arbiter_tree" -var "mask_tree"
split_var -module "prim_arbiter_tree" -var "idx_tree"
split_var -module "prim_arbiter_tree" -var "data_tree"
// Waive ALWCOMBORDER warnings about the tree variables. We've got
// lines like "req_tree[Pa] = req_tree[C0] | req_tree[C1];" and it
// seems that the ALWCOMBORDER warning isn't affected by the split_var
// rules above.
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_fixed.sv" -match "*data_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_fixed.sv" -match "*gnt_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_fixed.sv" -match "*idx_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_fixed.sv" -match "*req_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*req_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*prio_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*sel_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*mask_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*idx_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_tree.sv" -match "*data_tree*"
lint_off -rule ALWCOMBORDER -file "*/rtl/prim_arbiter_ppc.sv" -match "*ppc_out*"
// Waive unused clk and reset signals: they're just used for
// assertions (which Verilator doesn't see)
lint_off -rule UNUSED -file "*/rtl/prim_arbiter_fixed.sv" -match "*clk_i*"
lint_off -rule UNUSED -file "*/rtl/prim_arbiter_fixed.sv" -match "*rst_ni*"

View file

@ -6,7 +6,10 @@
waive -rules {UNDEF_MACRO_REF} -location {prim_assert.sv} -regexp {Macro definition for 'ASSERT_RPT' includes expansion of undefined macro '__(FILE|LINE)__'} \
-comment "This is an UVM specific macro inside our assertion shortcuts"
# unfortunately most tools do not support line wrapping within the declaration of macro functions, hence we have to waive
# line length violations.
# unfortunately most tools do not support line wrapping within the declaration of macro functions,
# hence we have to waive line length violations.
waive -rules {LINE_LENGTH} -location {prim_assert.sv} -msg {Line length of} \
-comment "Some macros cannot be line-wrapped, as some tools do not support that."
waive -rules {LINE_LENGTH} -location {prim_flop_macros.sv} -msg {Line length of} \
-comment "Some macros cannot be line-wrapped, as some tools do not support that."

View file

@ -0,0 +1,10 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`verilator_config
// The EnableAlertTriggerSVA parameter is only used by modules bound
// in for DV testing. Waive the warning that we don't read it.
lint_off -rule UNUSED -file "*/rtl/prim_double_lfsr.sv" -match "*EnableAlertTriggerSVA*"

View file

@ -6,3 +6,4 @@
// This parameter is only used in DV/FPV.
lint_off -rule UNUSED -file "*/rtl/prim_sparse_fsm_flop.sv" -match "*EnableAlertTriggerSVA*"
lint_off -rule UNUSED -file "*/rtl/prim_sparse_fsm_flop.sv" -match "*CustomForceName*"

View file

@ -4,8 +4,8 @@
#
# waiver file for prim_sparse_fsm_flop
waive -rules {IFDEF_CODE} -location {prim_sparse_fsm_flop.sv} -regexp {.*unused_valid_st.*} \
-comment "The unused_valid_st signal is used purely for DV only and is switched to a constant during lint / synth."
waive -rules {IFDEF_CODE} -location {prim_sparse_fsm_flop.sv} -regexp {.*(unused_valid_st|unused_err_o).*} \
-comment "The unused_valid_st / unused_err_o signals are used purely for DV only and is switched to a constant during lint / synth."
waive -rules {PARAM_NOT_USED} -location {prim_sparse_fsm_flop.sv} -regexp {.*StateEnumT.*} \
-comment "The state enum is used only during DV / FPV."

View file

@ -13,6 +13,7 @@ filesets:
- rtl/prim_assert_yosys_macros.svh : {is_include_file : true}
- rtl/prim_assert_standard_macros.svh : {is_include_file : true}
- rtl/prim_assert_sec_cm.svh : {is_include_file : true}
- rtl/prim_flop_macros.sv : {is_include_file : true}
file_type: systemVerilogSource
files_verilator_waiver:

View file

@ -19,6 +19,9 @@ filesets:
depend:
# common waivers
- lowrisc:lint:common
files:
- lint/prim_double_lfsr.vlt
file_type: vlt
files_ascentlint_waiver:
depend:

View file

@ -141,5 +141,6 @@
`endif
`include "prim_assert_sec_cm.svh"
`include "prim_flop_macros.sv"
`endif // PRIM_ASSERT_SV

View file

@ -65,7 +65,7 @@ module prim_clock_meas #(
end else if (!ref_en && |ref_cnt) begin
ref_cnt <= '0;
ref_valid <= '0;
end else if (ref_en && (ref_cnt == RefCnt - 1)) begin
end else if (ref_en && (int'(ref_cnt) == RefCnt - 1)) begin
// restart count and measure
ref_cnt <= '0;
ref_valid <= 1'b1;

View file

@ -27,7 +27,7 @@ module prim_clock_timeout #(
logic [CntWidth-1:0] cnt;
logic ack;
logic timeout;
assign timeout = cnt >= TimeOutCnt;
assign timeout = int'(cnt) >= TimeOutCnt;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
cnt <= '0;

View file

@ -17,6 +17,8 @@ module prim_edn_req
import prim_alert_pkg::*;
#(
parameter int OutWidth = 32,
// Repetition check for incoming edn data
parameter bit RepCheck = 0,
// EDN Request latency checker
//
@ -37,6 +39,7 @@ module prim_edn_req
output logic ack_o,
output logic [OutWidth-1:0] data_o,
output logic fips_o,
output logic err_o, // incoming data failed repetition check
// EDN side
input clk_edn_i,
input rst_edn_ni,
@ -69,6 +72,31 @@ module prim_edn_req
.data_o ( {word_fips, word_data} )
);
if (RepCheck) begin : gen_rep_chk
logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] word_data_q;
always_ff @(posedge clk_i) begin
if (word_ack) begin
word_data_q <= word_data;
end
end
// do not check until we have received at least the first entry
logic chk_rep;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
chk_rep <= '0;
end else if (word_ack) begin
chk_rep <= 1'b1;
end
end
// whenever a new word is received, check if it is identical to the last
// word
assign err_o = chk_rep & word_ack & (word_data == word_data_q);
end else begin : gen_no_rep_chk // block: gen_rep_chk
assign err_o = '0;
end
prim_packer_fifo #(
.InW(edn_pkg::ENDPOINT_BUS_WIDTH),
.OutW(OutWidth),

View file

@ -0,0 +1,74 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`ifndef PRIM_FLOP_MACROS_SV
`define PRIM_FLOP_MACROS_SV
/////////////////////////////////////
// Default Values for Macros below //
/////////////////////////////////////
`define PRIM_FLOP_CLK clk_i
`define PRIM_FLOP_RST rst_ni
`define PRIM_FLOP_RESVAL '0
/////////////////////
// Register Macros //
/////////////////////
// TODO: define other variations of register macros so that they can be used throughout all designs
// to make the code more concise.
// Register with asynchronous reset.
`define PRIM_FLOP_A(__d, __q, __resval = `PRIM_FLOP_RESVAL, __clk = `PRIM_FLOP_CLK, __rst_n = `PRIM_FLOP_RST) \
always_ff @(posedge __clk or negedge __rst_n) begin \
if (!__rst_n) begin \
__q <= __resval; \
end else begin \
__q <= __d; \
end \
end
///////////////////////////
// Macro for Sparse FSMs //
///////////////////////////
// Simulation tools typically infer FSMs and report coverage for these separately. However, tools
// like Xcelium and VCS seem to have problems inferring FSMs if the state register is not coded in
// a behavioral always_ff block in the same hierarchy. To that end, this uses a modified variant
// with a second behavioral register definition for RTL simulations so that FSMs can be inferred.
// Note that in this variant, the __q output is disconnected from prim_sparse_fsm_flop and attached
// to the behavioral flop. An assertion is added to ensure equivalence between the
// prim_sparse_fsm_flop output and the behavioral flop output in that case.
`define PRIM_FLOP_SPARSE_FSM(__name, __d, __q, __type, __resval = `PRIM_FLOP_RESVAL, __clk = `PRIM_FLOP_CLK, __rst_n = `PRIM_FLOP_RST, __alert_trigger_sva_en = 1) \
`ifdef SIMULATION \
prim_sparse_fsm_flop #( \
.StateEnumT(__type), \
.Width($bits(__type)), \
.ResetValue($bits(__type)'(__resval)), \
.EnableAlertTriggerSVA(__alert_trigger_sva_en), \
.CustomForceName(`PRIM_STRINGIFY(__q)) \
) __name ( \
.clk_i ( __clk ), \
.rst_ni ( __rst_n ), \
.state_i ( __d ), \
.state_o ( ) \
); \
`PRIM_FLOP_A(__d, __q, __resval, __clk, __rst_n) \
`ASSERT(``__name``_A, __q === ``__name``.state_o) \
`else \
prim_sparse_fsm_flop #( \
.StateEnumT(__type), \
.Width($bits(__type)), \
.ResetValue($bits(__type)'(__resval)), \
.EnableAlertTriggerSVA(__alert_trigger_sva_en) \
) __name ( \
.clk_i ( __clk ), \
.rst_ni ( __rst_n ), \
.state_i ( __d ), \
.state_o ( __q ) \
); \
`endif
`endif // PRIM_FLOP_MACROS_SV

View file

@ -33,13 +33,13 @@ module prim_gf_mult #(
// The field-generating, irreducible polynomial of degree Width.
// Can for example be a Conway polynomial, see
// http://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/CP2.html
// For Width = 33, the Conway polynomial hast bits 32, 15, 9, 7, 4, 3, 0 set to one.
parameter logic[Width-1:0] IPoly = 1'b1 << 15 |
1'b1 << 9 |
1'b1 << 7 |
1'b1 << 4 |
1'b1 << 3 |
1'b1 << 0
// For Width = 33, the Conway polynomial has bits 32, 15, 9, 7, 4, 3, 0 set to one.
parameter logic[Width-1:0] IPoly = Width'(1'b1) << 15 |
Width'(1'b1) << 9 |
Width'(1'b1) << 7 |
Width'(1'b1) << 4 |
Width'(1'b1) << 3 |
Width'(1'b1) << 0
) (
input clk_i,
input rst_ni,
@ -94,7 +94,7 @@ module prim_gf_mult #(
end else begin : gen_decomposed
// multiply is done
assign ack_o = cnt == (Loops - 1);
assign ack_o = int'(cnt) == (Loops - 1);
// advance the stage count and also advance the bit position count
always_ff @(posedge clk_i or negedge rst_ni) begin
@ -102,7 +102,7 @@ module prim_gf_mult #(
cnt <= '0;
end else if (req_i && ack_o) begin
cnt <= '0;
end else if (req_i && cnt < (Loops - 1)) begin
end else if (req_i && int'(cnt) < (Loops - 1)) begin
cnt <= cnt + 1'b1;
end
end
@ -155,14 +155,14 @@ module prim_gf_mult #(
// Galois multiply step
function automatic logic [Width-1:0] gf_mult(
logic [StagesPerCycle-1:0][Width-1:0] matrix,
logic [StagesPerCycle-1:0][Width-1:0] matrix_,
logic [StagesPerCycle-1:0] operand
);
logic [Width-1:0] mult_out;
logic [Width-1:0] add_vector;
mult_out = '0;
for (int i = 0; i < StagesPerCycle; i++) begin
add_vector = operand[i] ? matrix[i] : '0;
add_vector = operand[i] ? matrix_[i] : '0;
mult_out = mult_out ^ add_vector;
end
return mult_out;

View file

@ -19,7 +19,7 @@ module prim_lc_combine #(
// Determine whether which multibit value is considered "active" for the
// purpose of the logical function below.
parameter lc_ctrl_pkg::lc_tx_t ActiveValue = (ActiveLow) ? lc_ctrl_pkg::Off : lc_ctrl_pkg::On;
localparam lc_ctrl_pkg::lc_tx_t ActiveValue = (ActiveLow) ? lc_ctrl_pkg::Off : lc_ctrl_pkg::On;
// Truth tables:
//
// ActiveLow: 0, CombineMode: 0 (active-high "OR")

View file

@ -32,15 +32,17 @@ module prim_packer #(
localparam int ConcatW = Width + InW; // Input concatenated width
localparam int PtrW = $clog2(ConcatW+1);
localparam int IdxW = prim_util_pkg::vbits(InW);
localparam int OnesCntW = $clog2(InW+1);
logic valid_next, ready_next;
logic [Width-1:0] stored_data, stored_mask;
logic [ConcatW-1:0] concat_data, concat_mask;
logic [ConcatW-1:0] shiftl_data, shiftl_mask;
logic [InW-1:0] shiftr_data, shiftr_mask;
logic [PtrW-1:0] pos, pos_next; // Current write position
logic [IdxW-1:0] lod_idx; // result of Leading One Detector
logic [$clog2(InW+1)-1:0] inmask_ones; // Counting Ones for mask_i
logic [PtrW-1:0] pos, pos_next; // Current write position
logic [IdxW-1:0] lod_idx; // result of Leading One Detector
logic [OnesCntW-1:0] inmask_ones; // Counting Ones for mask_i
logic ack_in, ack_out;
@ -52,7 +54,7 @@ module prim_packer #(
// counting mask_i ones
inmask_ones = '0;
for (int i = 0 ; i < InW ; i++) begin
inmask_ones = inmask_ones + mask_i[i];
inmask_ones = inmask_ones + OnesCntW'(mask_i[i]);
end
end
@ -64,9 +66,9 @@ module prim_packer #(
unique case ({ack_in, ack_out})
2'b00: pos_next = pos;
2'b01: pos_next = (pos <= OutW) ? '0 : pos - OutW;
2'b01: pos_next = (int'(pos) <= OutW) ? '0 : pos - OutW[PtrW-1:0];
2'b10: pos_next = pos_with_input;
2'b11: pos_next = (pos_with_input <= OutW) ? '0 : pos_with_input - OutW;
2'b11: pos_next = (int'(pos_with_input) <= OutW) ? '0 : pos_with_input - OutW[PtrW-1:0];
default: pos_next = pos;
endcase
end
@ -87,7 +89,7 @@ module prim_packer #(
lod_idx = 0;
for (int i = InW-1; i >= 0 ; i--) begin
if (mask_i[i] == 1'b1) begin
lod_idx = $unsigned(i);
lod_idx = IdxW'(unsigned'(i));
end
end
end
@ -96,9 +98,13 @@ module prim_packer #(
assign ack_out = valid_o & ready_i;
// Data process =============================================================
// shiftr : Input data shifted right to put the leading one at bit zero
assign shiftr_data = (valid_i) ? data_i >> lod_idx : '0;
assign shiftr_mask = (valid_i) ? mask_i >> lod_idx : '0;
// shiftl : Input data shifted into the current stored position
assign shiftl_data = (valid_i) ? Width'(data_i >> lod_idx) << pos : '0;
assign shiftl_mask = (valid_i) ? Width'(mask_i >> lod_idx) << pos : '0;
assign shiftl_data = ConcatW'(shiftr_data) << pos;
assign shiftl_mask = ConcatW'(shiftr_mask) << pos;
// concat : Merging stored and shiftl
assign concat_data = {{(InW){1'b0}}, stored_data & stored_mask} |
@ -206,7 +212,7 @@ module prim_packer #(
// Output signals ===========================================================
assign valid_next = (pos >= OutW) ? 1'b 1 : flush_valid;
assign valid_next = (int'(pos) >= OutW) ? 1'b 1 : flush_valid;
// storage space is InW + OutW. So technically, ready_o can be asserted even
// if `pos` is greater than OutW. But in order to do that, the logic should
@ -214,7 +220,7 @@ module prim_packer #(
// with `valid_i`. It creates a path from `valid_i` --> `ready_o`.
// It may create a timing loop in some modules that use `ready_o` to
// `valid_i` (which is not a good practice though)
assign ready_next = pos <= OutW;
assign ready_next = int'(pos) <= OutW;
// Output request
assign valid_o = valid_next;

View file

@ -136,7 +136,7 @@ module prim_present #(
// Note that for a full-round implementation the output index
// will be 0 for enc/dec for the last round (either due to wraparound or subtraction).
localparam int LastRoundIdx = (Decrypt != 0 || NumRounds == 31) ? 0 : NumRounds+1;
assign data_o = (idx_o == LastRoundIdx) ?
assign data_o = (int'(idx_o) == LastRoundIdx) ?
data_state[NumPhysRounds] ^
round_key[NumPhysRounds][KeyWidth-1 : KeyWidth-DataWidth] :
data_state[NumPhysRounds];

View file

@ -32,6 +32,28 @@ module prim_pulse_sync (
end
end
// source active must come far enough such that the destination domain has time
// to create a valid pulse.
`ifdef INC_ASSERT
logic src_active_flag;
// source active flag tracks whether there is an ongoing "toggle" event.
// Until this toggle event is accepted by the destination domain (negative edge of
// of the pulse output), the source side cannot toggle again.
always_ff @(posedge clk_src_i or negedge dst_pulse_o or negedge rst_src_ni) begin
if (!rst_src_ni) begin
src_active_flag <= '0;
end else if (!dst_pulse_o && src_active_flag) begin
src_active_flag <= '0;
end else if (src_pulse_i) begin
src_active_flag <= 1'b1;
end
end
`ASSERT(SrcPulseCheck_M, src_pulse_i |-> !src_active_flag, clk_src_i, !rst_src_ni)
`endif
//////////////////////////////////////////////////////////
// synchronize level signal to destination clock domain //
//////////////////////////////////////////////////////////
@ -63,4 +85,6 @@ module prim_pulse_sync (
// edge detection
assign dst_pulse_o = dst_level_q ^ dst_level;
`ASSERT(DstPulseCheck_A, dst_pulse_o |=> !dst_pulse_o, clk_dst_i, !rst_dst_ni)
endmodule

View file

@ -5,21 +5,29 @@
`include "prim_assert.sv"
module prim_sparse_fsm_flop #(
parameter type StateEnumT = logic,
parameter int Width = 1,
parameter logic [Width-1:0] ResetValue = 0,
parameter type StateEnumT = logic [Width-1:0],
parameter logic [Width-1:0] ResetValue = '0,
// This should only be disabled in special circumstances, for example
// in non-comportable IPs where an error does not trigger an alert.
parameter bit EnableAlertTriggerSVA = 1
`ifdef SIMULATION
,
// In case this parameter is set to a non-empty string, the
// prim_sparse_fsm_flop_if will also force the signal with this name
// in the parent module that instantiates prim_sparse_fsm_flop.
parameter string CustomForceName = ""
`endif
) (
input clk_i,
input rst_ni,
input [Width-1:0] state_i,
output logic [Width-1:0] state_o
input clk_i,
input rst_ni,
input StateEnumT state_i,
output StateEnumT state_o
);
logic unused_err_o;
logic [Width-1:0] state_raw;
prim_flop #(
.Width(Width),
.ResetValue(ResetValue)
@ -27,15 +35,16 @@ module prim_sparse_fsm_flop #(
.clk_i,
.rst_ni,
.d_i(state_i),
.q_o(state_o)
.q_o(state_raw)
);
assign state_o = StateEnumT'(state_raw);
`ifdef INC_ASSERT
assign unused_err_o = is_undefined_state(state_o);
function automatic logic is_undefined_state(logic [Width-1:0] sig);
function automatic logic is_undefined_state(StateEnumT sig);
for (int i = 0, StateEnumT t = t.first(); i < t.num(); i += 1, t = t.next()) begin
if (StateEnumT'(sig) === t) return 0;
if (sig === t) return 0;
end
return 1;
endfunction

View file

@ -45,14 +45,6 @@ module prim_subreg
.wr_data
);
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
qe <= 1'b0;
end else begin
qe <= we;
end
end
logic wr_en_buf;
prim_buf #(
.Width(1)
@ -61,6 +53,9 @@ module prim_subreg
.out_o(wr_en_buf)
);
// feed back out for consolidation
assign qe = wr_en_buf;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
q <= RESVAL;

View file

@ -2,3 +2,9 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
`verilator_config
// The generic OTP module doesn't use vendor-specific parameters
lint_off -rule UNUSED -file "*/rtl/prim_generic_otp.sv" -match "*VendorTestOffset*"
lint_off -rule UNUSED -file "*/rtl/prim_generic_otp.sv" -match "*VendorTestSize*"

View file

@ -10,3 +10,4 @@ waive -rules {HIER_NET_NOT_READ HIER_BRANCH_NOT_READ} -regexp {unused_.*}
waive -rules {HIER_NET_NOT_READ HIER_BRANCH_NOT_READ} -regexp {gen_.*\.unused_.*}
waive -rules {ONE_BRANCH} -regexp {unique case statement has only one branch}

222
vendor/lowrisc_ip/util/dvsim/BUILD vendored Normal file
View file

@ -0,0 +1,222 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
load("@rules_python//python:defs.bzl", "py_binary")
load("@ot_python_deps//:requirements.bzl", "requirement")
package(default_visibility = ["//visibility:public"])
py_library(
name = "utils",
srcs = ["utils.py"],
deps = [
requirement("hjson"),
requirement("mistletoe"),
requirement("premailer"),
],
)
py_library(
name = "sim_utils",
srcs = ["sim_utils.py"],
)
py_library(
name = "msg_buckets",
srcs = [
"MsgBucket.py",
"MsgBuckets.py",
],
deps = [
":utils",
],
)
py_library(
name = "modes",
srcs = ["Modes.py"],
deps = [
":utils",
],
)
py_library(
name = "timer",
srcs = ["Timer.py"],
)
py_library(
name = "status_printer",
srcs = ["StatusPrinter.py"],
deps = [
requirement("enlighten"),
],
)
py_library(
name = "launcher",
srcs = [
"Launcher.py",
"LauncherFactory.py",
"LocalLauncher.py",
"LsfLauncher.py",
],
deps = [
":utils",
],
)
py_library(
name = "deploy",
srcs = ["Deploy.py"],
deps = [
":launcher",
":sim_utils",
":utils",
requirement("tabulate"),
],
)
py_library(
name = "scheduler",
srcs = ["Scheduler.py"],
deps = [
":launcher",
":status_printer",
":timer",
":utils",
],
)
py_library(
name = "cfg_json",
srcs = ["CfgJson.py"],
deps = [
":utils",
],
)
py_library(
name = "flow_cfg",
srcs = ["FlowCfg.py"],
deps = [
":cfg_json",
":launcher",
":scheduler",
":utils",
requirement("hjson"),
],
)
py_library(
name = "oneshot_cfg",
srcs = ["OneShotCfg.py"],
deps = [
":deploy",
":flow_cfg",
":modes",
":utils",
],
)
py_library(
name = "lint_cfg",
srcs = ["LintCfg.py"],
deps = [
":msg_buckets",
":oneshot_cfg",
":utils",
requirement("tabulate"),
],
)
py_library(
name = "formal_cfg",
srcs = ["FormalCfg.py"],
deps = [
":oneshot_cfg",
":utils",
requirement("hjson"),
requirement("tabulate"),
],
)
py_library(
name = "cdc_cfg",
srcs = ["CdcCfg.py"],
deps = [
":lint_cfg",
":msg_buckets",
":utils",
requirement("tabulate"),
],
)
py_library(
name = "testplan",
srcs = ["Testplan.py"],
deps = [
requirement("hjson"),
requirement("mistletoe"),
requirement("tabulate"),
],
)
py_library(
name = "sim_results",
srcs = ["SimResults.py"],
deps = [
":testplan",
],
)
py_library(
name = "sim_cfg",
srcs = ["SimCfg.py"],
deps = [
":deploy",
":flow_cfg",
":modes",
":sim_results",
":testplan",
":utils",
requirement("tabulate"),
],
)
py_library(
name = "syn_cfg",
srcs = ["SynCfg.py"],
deps = [
":oneshot_cfg",
":utils",
requirement("hjson"),
requirement("tabulate"),
],
)
py_library(
name = "cfg_factory",
srcs = ["CfgFactory.py"],
deps = [
":cdc_cfg",
":cfg_json",
":formal_cfg",
":lint_cfg",
":sim_cfg",
":syn_cfg",
],
)
py_binary(
name = "dvsim",
srcs = ["dvsim.py"],
deps = [
":cfg_factory",
":deploy",
":launcher",
":timer",
":utils",
],
)

View file

@ -298,6 +298,7 @@ class CompileSim(Deploy):
def __init__(self, build_mode, sim_cfg):
self.build_mode_obj = build_mode
self.seed = sim_cfg.build_seed
super().__init__(sim_cfg)
def _define_attrs(self):

View file

@ -74,6 +74,7 @@ class SimCfg(FlowCfg):
self.en_run_modes = []
self.en_run_modes.extend(args.run_modes)
self.build_unique = args.build_unique
self.build_seed = args.build_seed
self.build_only = args.build_only
self.run_only = args.run_only
self.reseed_ovrd = args.reseed
@ -105,6 +106,8 @@ class SimCfg(FlowCfg):
self.en_build_modes.append("profile")
if self.xprop_off is not True:
self.en_build_modes.append("xprop")
if self.build_seed:
self.en_build_modes.append("build_seed")
# Options built from cfg_file files
self.project = ""
@ -618,6 +621,11 @@ class SimCfg(FlowCfg):
results_str += f"### Simulator: {self.tool.upper()}\n"
# Print the build seed used for clarity.
if self.build_seed and not self.run_only:
results_str += ("### Build randomization enabled with "
f"--build-seed {self.build_seed}\n")
if not results.table:
results_str += "No results to display.\n"

View file

@ -17,6 +17,7 @@ from tabulate import tabulate
class Result:
'''The results for a single test'''
def __init__(self, name, passing=0, total=0):
self.name = name
self.passing = passing
@ -138,6 +139,12 @@ class Testpoint(Element):
# testpoint.
self.test_results = []
# If tests key is set to ["N/A"], then don't map this testpoint to the
# simulation results.
self.not_mapped = False
if self.tests == ["N/A"]:
self.not_mapped = True
def __str__(self):
return super().__str__() + (f" Milestone: {self.milestone}\n"
f" Tests: {self.tests}\n")
@ -192,6 +199,17 @@ class Testpoint(Element):
self.tests is an empty list, indicate 0/1 passing so that it is
factored into the final total.
"""
# If no written tests were indicated for this testpoint, then reuse
# the testpoint name to count towards "not run".
if not self.tests:
self.test_results = [Result(name=self.name, passing=0, total=0)]
return
# Skip if this testpoint is not meant to be mapped to the simulation
# results.
if self.not_mapped:
return
for tr in test_results:
assert isinstance(tr, Result)
if tr.name in self.tests:
@ -205,11 +223,6 @@ class Testpoint(Element):
if test not in tests_mapped:
self.test_results.append(Result(name=test, passing=0, total=0))
# If no written tests were indicated for this testpoint, then reuse
# the testpoint name to count towards "not run".
if not self.tests:
self.test_results = [Result(name=self.name, passing=0, total=0)]
class Testplan:
"""The full testplan
@ -450,6 +463,8 @@ class Testplan:
def get_milestone_regressions(self):
regressions = defaultdict(set)
for tp in self.testpoints:
if tp.not_mapped:
continue
if tp.milestone in tp.milestones[1:]:
regressions[tp.milestone].update({t for t in tp.tests if t})
@ -467,39 +482,54 @@ class Testplan:
"""
assert fmt in ["pipe", "html"]
def _fmt_text(text, fmt):
return mistletoe.markdown(text) if fmt == "html" else text
# Map between the requested format and a pair (tabfmt, formatter) where
# tabfmt is the "tablefmt" argument for tabulate.tabulate and formatter
# converts the input Markdown text to something we can pass to the
# formatter.
fmt_configs = {
# For Markdown output, we pass the input text straight through
'pipe': ('pipe', lambda x: x),
# For HTML output, we convert the Markdown to HTML using the
# mistletoe library. The tablefmt argument should be 'unsafehtml'
# in this case because this already escapes things like '<' and
# don't want to double-escape them when tabulating.
'html': ('unsafehtml', mistletoe.markdown)
}
tabfmt, formatter = fmt_configs[fmt]
if self.testpoints:
lines = [_fmt_text("\n### Testpoints\n", fmt)]
lines = [formatter("\n### Testpoints\n")]
header = ["Milestone", "Name", "Tests", "Description"]
colalign = ("center", "center", "left", "left")
table = []
for tp in self.testpoints:
desc = _fmt_text(tp.desc.strip(), fmt)
# TODO(astanin/python-tabulate#126): Tabulate does not
# convert \n's to line-breaks.
desc = formatter(tp.desc.strip())
# tests is a list of strings. We want to insert them into a
# table and (conveniently) we can put one on each line in both
# Markdown and HTML mode by interspersing with '<br>' tags.
tests = "<br>\n".join(tp.tests)
table.append([tp.milestone, tp.name, tests, desc])
lines += [
tabulate(table,
headers=header,
tablefmt=fmt,
tablefmt=tabfmt,
colalign=colalign)
]
if self.covergroups:
lines += [_fmt_text("\n### Covergroups\n", fmt)]
lines += [formatter("\n### Covergroups\n")]
header = ["Name", "Description"]
colalign = ("center", "left")
table = []
for covergroup in self.covergroups:
desc = _fmt_text(covergroup.desc.strip(), fmt)
desc = formatter(covergroup.desc.strip())
table.append([covergroup.name, desc])
lines += [
tabulate(table,
headers=header,
tablefmt=fmt,
tablefmt=tabfmt,
colalign=colalign)
]
@ -527,6 +557,9 @@ class Testplan:
"""
ms = testpoint.milestone
for tr in testpoint.test_results:
if not tr:
continue
if tr.name in tests_seen:
continue

View file

@ -47,6 +47,8 @@ The following attributes are used to define each testpoint, at minimum:
To cater to these needs, we provide the ability to set a list of written tests for each testpoint.
It is used to not only indicate the current progress so far into each milestone, but also map the simulation results to the testpoints to generate the final report table.
This list is initially empty - it is gradually updated as tests are written.
Setting this list to `["N/A"]` will prevent this testpoint entry from being mapped to the simulation results.
The testpoint will however, still show up in the generated testplan table.
* **tags: list of tags relevant for this testpoint**

View file

@ -23,6 +23,7 @@ import argparse
import datetime
import logging as log
import os
import random
import shlex
import subprocess
import sys
@ -259,8 +260,7 @@ def parse_reseed_multiplier(as_str: str) -> float:
ret = float(as_str)
except ValueError:
raise argparse.ArgumentTypeError('Invalid reseed multiplier: {!r}. '
'Must be a float.'
.format(as_str))
'Must be a float.'.format(as_str))
if ret <= 0:
raise argparse.ArgumentTypeError('Reseed multiplier must be positive.')
return ret
@ -285,7 +285,7 @@ def parse_args():
help=("Explicitly set the tool to use. This is "
"optional for running simulations (where it can "
"be set in an .hjson file), but is required for "
"other flows. Possible tools include: vcs, "
"other flows. Possible tools include: vcs, questa,"
"xcelium, ascentlint, verixcdc, veriblelint, verilator, dc."))
parser.add_argument("--list",
@ -472,7 +472,16 @@ def parse_args():
'(l), medium (m), high (h), full (f) or debug (d).'
' The default value is set in config files.'))
seedg = parser.add_argument_group('Test seeds')
seedg = parser.add_argument_group('Build / test seeds')
seedg.add_argument("--build-seed",
nargs="?",
type=int,
const=random.getrandbits(32),
metavar="S",
help=('Randomize the build. Uses the seed value passed '
'an additional argument, else it randomly picks '
'a 32-bit unsigned integer.'))
seedg.add_argument("--seeds",
"-s",
@ -652,8 +661,9 @@ def main():
setattr(args, "timestamp_long", curr_ts.strftime(TS_FORMAT_LONG))
setattr(args, "timestamp", curr_ts.strftime(TS_FORMAT))
# Register the seeds from command line with RunTest class.
# Register the seeds from command line with the RunTest class.
RunTest.seeds = args.seeds
# If we are fixing a seed value, no point in tests having multiple reseeds.
if args.fixed_seed:
args.reseed = 1

View file

@ -230,11 +230,13 @@ Review | [V3_CHECKLIST_SCOPED][] | Not Started |
Documentation | [SEC_CM_TESTPLAN_COMPLETED][] | Not Started |
Tests | [FPV_SEC_CM_VERIFIED][] | Not Started |
Tests | [SIM_SEC_CM_VERIFIED][] | Not Started |
Coverage | [SIM_COVERAGE_REVIEWED][] | Not Started |
Review | [SEC_CM_DV_REVIEWED][] | Not Started |
[SEC_CM_TESTPLAN_COMPLETED]: {{<relref "/doc/project/checklist.md#sec_cm_testplan_completed" >}}
[FPV_SEC_CM_VERIFIED]: {{<relref "/doc/project/checklist.md#fpv_sec_cm_verified" >}}
[SIM_SEC_CM_VERIFIED]: {{<relref "/doc/project/checklist.md#sim_sec_cm_verified" >}}
[SIM_COVERAGE_REVIEWED]: {{<relref "/doc/project/checklist.md#sim_coverage_reviewed" >}}
[SEC_CM_DV_REVIEWED]: {{<relref "/doc/project/checklist.md#sec_cm_dv_reviewed" >}}
<%text>### V3</%text>