Update code from upstream repository
https://github.com/lowRISC/opentitan to revision
3f35d4e42757aeed3f9699d7965f20af41d9d36f

* [dv] Initial flash_ctrl DV testbench (Srikrishna Iyer)
* [dv] Cleanup Xcelium warning: unconnected port (Srikrishna Iyer)
* [dv] Cleanup Xcelium warning: default arg (Srikrishna Iyer)
* [dv] Clean up for phase_read_to_end (Weicai Yang)
* [DV] Remove urandom from task port (Dawid Zimonczyk)
* [doc] Update lint commands in readme (Michael Schaffner)
* [dv] Refactor watchdog_ok_to_end (Srikrishna Iyer)

Signed-off-by: Philipp Wagner <phw@lowrisc.org>
This commit is contained in:
Philipp Wagner 2020-05-29 09:59:45 +01:00 committed by Philipp Wagner
parent dd39ec0c91
commit b95ff21c28
10 changed files with 90 additions and 93 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/lowRISC/opentitan
rev: 249b4c316cd6626d13e17edd8a52ca60c004af96
rev: 3f35d4e42757aeed3f9699d7965f20af41d9d36f
}
}

View file

@ -172,11 +172,13 @@ interface clk_rst_if #(
// 2 - async assert, async dessert
// 3 - clk gated when reset asserted
// Note: for power on reset, please ensure pre_reset_dly_clks is set to 0
task automatic apply_reset(int pre_reset_dly_clks = 0,
int reset_width_clks = $urandom_range(4, 20),
int post_reset_dly_clks = 0,
int rst_n_scheme = 1);
// TODO #2338 issue workaround - $urandom call moved from default argument value to function body
task automatic apply_reset(int pre_reset_dly_clks = 0,
integer reset_width_clks = 'x,
int post_reset_dly_clks = 0,
int rst_n_scheme = 1);
int dly_ps;
if ($isunknown(reset_width_clks)) reset_width_clks = $urandom_range(4, 20);
dly_ps = $urandom_range(0, clk_period_ps);
wait_clks(pre_reset_dly_clks);
case (rst_n_scheme)

View file

@ -10,13 +10,9 @@ class dv_base_monitor #(type ITEM_T = uvm_sequence_item,
CFG_T cfg;
COV_T cov;
// extended monitor needs to drive ok_to_end = 0 when bus is busy, set to 1 when it's not busy
// Indicates activity on the interface, driven only within the `monitor_ready_to_end()` task.
protected bit ok_to_end = 1;
// make sure at least we add ok_to_end_delay_ns once and invoke monitor_ready_to_end once
// after enter phase_ready_to_end
protected bit watchdog_done;
// Analysis port for the collected transfer.
uvm_analysis_port #(ITEM_T) analysis_port;
@ -38,64 +34,73 @@ class dv_base_monitor #(type ITEM_T = uvm_sequence_item,
`uvm_fatal(`gfn, "this method is not supposed to be called directly!")
endtask
// UVM callback which is invoked during phase sequencing.
virtual function void phase_ready_to_end(uvm_phase phase);
if (phase.is(uvm_run_phase::get())) begin
if (watchdog_done) fork
monitor_ready_to_end();
join_none
if (!ok_to_end || !watchdog_done) begin
phase.raise_objection(this, $sformatf("%s objection raised", `gfn));
`uvm_info(`gfn, $sformatf("Raised objection, because ok_to_end: %0b, watchdog_done: %0b",
ok_to_end, watchdog_done), UVM_MEDIUM)
fork
begin
// wait until ok_to_end is set plus the delay of ok_to_end_delay_ns
watchdog_ok_to_end();
phase.drop_objection(this, $sformatf("%s objection dropped", `gfn));
`uvm_info(`gfn, $sformatf("Dropped objection"), UVM_MEDIUM)
end
join_none;
end
end
if (!phase.is(uvm_run_phase::get())) return;
fork
monitor_ready_to_end();
watchdog_ok_to_end(phase);
join_none
endfunction
// This watchdog will wait for ok_to_end_delay_ns while checking for any
// traffic on the bus during this period.
// If traffic is seen before ok_to_end_delay_ns, the watchdog will keep
// repeating this process until the traffic has stopped.
virtual task watchdog_ok_to_end();
fork
begin : isolation_fork
bit watchdog_reset;
// Ensures that ok_to_end when asserted, stays asserted for 1 ok_to_end_delay_ns period.
//
// If ok_to_end de-asserts before the watchdog expires, it waits for it to assert again
// and restarts the timer. This ensures that there is sufficient drain time to allow the
// simulation to end gracefully. It raises and drops the objection at the appropriate times.
virtual task watchdog_ok_to_end(uvm_phase run_phase);
bit objection_raised;
bit watchdog_done;
uint watchdog_restart_count = 1;
fork
forever begin
// check the bus interface for any traffic. If any, extend timer for one more
// ok_to_end_delay_ns
@(ok_to_end or watchdog_reset);
if (!ok_to_end && !watchdog_reset) watchdog_reset = 1;
end
forever begin
#(cfg.ok_to_end_delay_ns * 1ns);
if (!watchdog_reset) begin
break;
end else begin
`uvm_info(`gfn, "Resetting phase watchdog timer", UVM_HIGH)
watchdog_reset = 0;
forever begin
if (!objection_raised) begin
`uvm_info(`gfn, "watchdog_ok_to_end: raising objection", UVM_MEDIUM)
run_phase.raise_objection(this, {`gfn, " objection raised"});
objection_raised = 1'b1;
end
// Start the timer only when ok_to_end is asserted.
wait(ok_to_end);
`uvm_info(`gfn, $sformatf("watchdog_ok_to_end: starting the timer (count: %0d)",
watchdog_restart_count++), UVM_MEDIUM)
fork
begin: isolation_fork
fork
begin
watchdog_done = 1'b0;
#(cfg.ok_to_end_delay_ns * 1ns);
watchdog_done = 1'b1;
end
end
join_any;
disable fork;
@(ok_to_end);
join_any
disable fork;
end: isolation_fork
join
watchdog_done = 1;
end : isolation_fork
join
// The #0 delay ensures that we sample the stabilized value of ok_to_end in the condition
// below in case it toggles more than once in the same simulation time-step.
#0;
// If ok_to_end stayed high throughout the watchdog timer expiry, then drop the objection.
if (ok_to_end && watchdog_done) begin
`uvm_info(`gfn, "watchdog_ok_to_end: dropping objection", UVM_MEDIUM)
run_phase.drop_objection(this, {`gfn, " objection dropped"});
objection_raised = 1'b0;
// Wait for ok_to_end to de-assert again in future.
wait(!ok_to_end);
end
end
endtask
// this task will be invoked as non-blocking thread when phase first enters phase_ready_to_end
// extended class can override this task to update ok_to_end
// Asserts/de-asserts ok_to_end to indicate bus activity.
//
// This task is invoked in a forked thread within `phase_ready_to_end()`, which is callback
// invoked by UVM at the end of the phase. The forked thread does not join. Hence, the extended
// monitor needs to override this function and assert ok_to_end based on the activity on the bus
// (assert it when idle, de-assert when its not) in a forever loop.
virtual task monitor_ready_to_end();
endtask
endclass
endclass

View file

@ -13,7 +13,8 @@ class dv_base_reg_block extends uvm_reg_block;
endfunction
// provide build function to supply base addr
virtual function void build(uvm_reg_addr_t base_addr, csr_utils_pkg::csr_excl_item csr_excl);
virtual function void build(uvm_reg_addr_t base_addr,
csr_utils_pkg::csr_excl_item csr_excl = null);
`uvm_fatal(`gfn, "this method is not supposed to be called directly!")
endfunction

View file

@ -45,18 +45,6 @@ class dv_base_scoreboard #(type RAL_T = dv_base_reg_block,
end
endtask
// raise / drop objections based on certain events
virtual function void process_objections(bit raise);
if (raise && !obj_raised) begin
m_current_phase.raise_objection(this, $sformatf("%s objection raised", `gfn));
obj_raised = 1'b1;
end
else if (!raise && obj_raised) begin
m_current_phase.drop_objection(this, $sformatf("%s objection dropped", `gfn));
obj_raised = 1'b0;
end
endfunction
virtual function void reset(string kind = "HARD");
// reset the ral model
if (cfg.has_ral) ral.reset(kind);

View file

@ -74,15 +74,17 @@ In this example this would be `lint/aes.waiver` for AscentLint and `lint/aes.vlt
In order to manually run lint on a specific block, make sure AscentLint is properly installed and step into the `hw/lint` folder.
The makefile in that folder contains all targets that can be manually invoked.
For example, to run lint on AES, do:
```
make ip-aes_lint
```console
$ cd $REPO_TOP/hw/lint
$ make ip-aes_lint
```
This run will exit with PASSED status on the command line if there are no lint errors or warnings.
Otherwise it will exit with ERROR status, in which case you can get more information by running
```
make clean
make ip-aes_lint
make report
```console
$ cd $REPO_TOP/hw/lint
$ make clean
$ make ip-aes_lint
$ make report
```
In order to build all lint targets and produce a summary report, the `make all` target can be invoked.
For more detailed information on a particular lint run you can inspect the tool output inside the build folder that is created by FuseSoC.
@ -91,8 +93,9 @@ Note that all AscentLint targets have a Verilator and Verible counterparts that
This enables designers without access to AscentLint to iterate with open-source tools before making their first Pull Request.
For batch regressions we have integrated this flow into the `dvsim` tool, which can be invoked as follows from the root of the project repository:
```
util/dvsim.py hw/top_earlgrey/lint/ascentlint/top_earlgrey_lint_cfgs.hjson --tool "ascentlint" --purge -mp 1
```console
$ cd $REPO_TOP
$ util/dvsim/dvsim.py hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson --tool ascentlint --purge -mp 1
```
where the `top_earlgrey_lint_cfgs.hjson` file contains all the lint targets to be run in that regression (currently all available comportable IPs and the top-level are run).
The `purge` option ensures that the scratch directory is fully erased before starting the build, and `mp 1` sets the number of parallel workers to one (should be set depending on your licensing situation).

View file

@ -23,10 +23,9 @@ class ${name}_base_test extends dv_base_test #(
super.build_phase(phase);
cfg.has_ral = 1'b0;
endfunction
% endif
% endif
// the base class also looks up UVM_TEST_SEQ plusarg to create and run that seq in
// the run_phase; as such, nothing more needs to be done
endclass : ${name}_base_test

View file

@ -77,4 +77,3 @@
}
]
}

View file

@ -14,6 +14,7 @@ module tb;
`include "dv_macros.svh"
wire clk, rst_n;
wire devmode;
% if is_cip:
% if has_interrupts:
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
@ -34,7 +35,7 @@ module tb;
// TODO: declare alert interfaces according to the list_of_alerts
alert_if alert_names(.clk(clk), .rst_n(rst_n))
% endif
pins_if #(1) devmode_if();
pins_if #(1) devmode_if(devmode);
tl_if tl_if(.clk(clk), .rst_n(rst_n));
% endif
% for agent in env_agents:

View file

@ -11,16 +11,15 @@
entries: [
{
name: sanity
desc: '''**Goal**: Basic sanity test acessing a major datapath in ${name.upper()}.
desc: '''
Basic sanity test acessing a major datapath within the ${name}.
**Stimulus**: Describe the stimulus procedure.
**Stimulus**:
- TBD
**Checks**": Describe the self-check procedure.
- add bullets as needed
- second bullet<br>
describe second bullet
Start a new paragraph.'''
**Checks**:
- TBD
'''
milestone: V1
tests: ["${name}_sanity"]
}