How to check in SystemVerilog that signal went high during simulation using ModelSim - system-verilog-assertions

I need to check, whether during the testbenching the particular signal went at least for a single clock cycle to logic 1.
I've tested following asserts, which shall be equivalent:
initial assert property (
#(posedge clk_tree_x.ClkRsBST_ix.clk)
s_eventually TS.TSUpdated) else
$error("Was not active");
and
initial begin
assert property (#(posedge clk_tree_x.ClkRsBST_ix.clk)
strong(##[*] TS.TSUpdated)) else
$error("Was not active");
end
In simulation using Mentor ModelSim SE64 2021.1 the results are extremely weird.
On first simulation pass the simulation completely ignores this assert. On second simulation pass ModelSim apparently uses results of previous simulation to announce before even the newly run simulation happens that the assert triggered:
# Time: 2005087500 ps Started: 5 ns Scope: tb_bst_provider.DUT.fook File: bst_provider.sv Line: 669
# ** Warning: (vsim-8777) Breakpointing based on severity while evaluating concurrent assertion is not supported.
# Time: 2005087500 ps Iteration: 0 Region: /tb_bst_provider/DUT File: bst_provider.sv
Not sure whether this is consistent behaviour to all strong properties, but it is hardly useful for any sort of unit testing, as the tests never run twice using the same parameters.
Is there any way how to assert that 'signal is not present through the simulation run', which actually works with modelsim?

I am not sure if you can do it with an assertion. You can detect not active signal using an assertion coverage. In any case you should not place an assertion in the initial block.
Potentially checking for activity can be done without using an assertion as in the following example.
always #(posedge clk) begin
if (sig == 1)
active <= 1;
end
final begin
if (!active)
$error("was not active");
else
$info ("it was active");
end
Just make sure that you have a normal exit from simulation or final might not be executed at all in case of interrupts.

Related

Assertion writing without clock for async reset

I have two resets in my design. Reset_a and Reset_b. both are asynchronous reset can come at any pint of time.
i have to write assertion to check if Reset_a is asserted Reset_b also assert at any point.
We don't have clock enable in this case.
can anyone help how to write assertion?
I have tried below code.
reset_assertion_check:
assert property (#(posedge reset_a) $rose(reset_b) ##[*0:$] reset_b)
else
$error("reset error");
create dummy clock(any period) on test bench, then use the dummy clock to check Reset_a and Reset_b use assertion.

arm64 ptrace SINGLESTEP: are the steps described in this paper correct?

I was reading the paper Hiding in the Shadows: Empowering ARM for Stealthy Virtual Machine Introspection and I was wondering whether the steps they are described in paragraph "2.3 Debug Exceptions" were correct or not:
AArch64 allows to generate Software Step exceptions by setting the SS
bit of the Monitor Debug System Control MDSCR_EL1 and Saved Program
Status Register SPSR of the target exception level. For instance, to
single-step a hit breakpoint in EL1 the monitor must set the
MDSCR_EL1.SS and SPSR_EL1.SS bits. After returning to the trapped
instruction, the SPSR will be written to the process state PSTATE
register in EL1. Consequently, the CPU executes the next instruction
and generates a Software Step exception.
I have tried to understand how single-stepping happens in freeBSD, and I am noticing a mismatch.
I am basing the following lines of code to the release 12.3.0 of freeBSD (4 December 2021), commit: 70cb68e7a00ac0310a2d0ca428c1d5018e6d39e1. I chose to base this question on freeBSD because, in my opinion, following its code is easier than Linux, but the same principles shall be common to both families.
According to my understanding, this is what happens in freeBSD:
1- Ptrace single step is invoked, arriving in the architecture-independent code proc_sstep(), in sys_process.c:
int proc_sstep(struct thread *td)
{
PROC_ACTION(ptrace_single_step(td));
}
2- Architecture-dependent code ptrace_single_step()is called, in arm64/ptrace_machdep.c:
int ptrace_single_step(struct thread *td)
{
td->td_frame->tf_spsr |= PSR_SS;
td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
return (0);
}
Here single step bit (number 21) is set in the "Process State" of the tracee (tracee = thread that is traced) and a flag is set.
3- After a while, the traced task will be selected for scheduling. In cpu_throw() of swtch.S (where the new thread takes place), the flags of the new thread are checked, to see if it must single step:
/* If we are single stepping, enable it */
ldr w5, [x4, #PCB_FLAGS]
set_step_flag w5, x6
4- set_step_flag macro in defined in the same swtch.S:
.macro set_step_flag pcbflags, tmp
tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
mrs \tmp, mdscr_el1
orr \tmp, \tmp, #1
msr mdscr_el1, \tmp
isb
999:
.endm
Here, if the single-step flag is set, it sets the single step bit of register MDSCR_EL1 (bit in position 0).
4- To the best of my understanding, the combination of single step bit on SPSR_EL1 of the "Pstate" + single step bit on MDSCRL_EL1 implies that the tracee execute 1 instruction and it traps.
5- Trap is recognized as a EXCP_SOFTSTP_EL0 and it is handled in do_el0_sync() function of trap.c:
case EXCP_SOFTSTP_EL0:
td->td_frame->tf_spsr &= ~PSR_SS;
td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
WRITE_SPECIALREG(mdscr_el1,
READ_SPECIALREG(mdscr_el1) & ~DBG_MDSCR_SS);
call_trapsignal(td, SIGTRAP, TRAP_TRACE,
(void *)frame->tf_elr, exception);
userret(td, frame);
break;
Here, all the flags are reset and the traced thread receives a SIGTRAP (sent by itself, I think). Being traced, it will stop. And the tracer, at this point, can return from a possible waitpid().
What I could observe differs from the paper explanation. Can you check and correct the steps that I listed, please ?

UVM end of test

In case I want to end the simulation from my monitor (I know that it is not the recommended way) how can I do this?
lets say I got this code inside my monitor:
Virtual task monitor_run();
fork
forever begin
.....
end
forever begin
.....
end
forever begin
.....
end
join
endtask : monitor_run
Every forever loop check that outputs of the DUT came on time, in case they doesnt it should stop simulation.
This special monitor should break the simulation in case of mismatch(error) and there is no Scoreboard.
I still want to manage nice end of simulation behaviour. I tried use raise and drop objection but I get an error of OBJT_ZERO sometimes. Does anyone knows a good way to end the simulation in that case?
thanks!
The UVM is set up by default so that uvm_report_fatal ends the test immediately, and uvm_report_error lets the simulation continue until hitting an error limit that you can set. And you can control the actions of each severity for an individual component. See uvm_report_object which is the base class of uvm_component.
Upon ending the test, the UVM calls uvm_report_server::report_summarize() that dumps out all the severity counts. If you insist, you can create a final block in your testbench module that gathers the severity counts from the report server and print the last message. For example:
module top;
initial run_test();
uvm_report_server rs = uvm_report_server::get_server();
final if (rs.get_severity_count(UVM_FATAL) != 0 ||
rs.get_severity_count(UVM_ERROR) !=0 )
$display("Test Failed");
endmodule
But this is really unnecessary and may not catch other non-UVM errors like assertion failures or timing checks. Many tools have a TESTSTATUS exit code that reports the most severe message encounte, UVM or tool.

How to get the status of property in the RTL

In some scenarios, injecting error will trigger the assert to be fail. so , I pass the switch to turn off this assert by $testplusargs. Is there a way to get the status of property(vacuous true, real true or fail) at the end of test cases, for example by PLI or other ways supplied by simulator(I am using vcs). Anyone has some idea for this? Thanks a lot.
You can register some VPI callbacks to the assertion and check the number of failed/passed counts.
You could also in system verilog count number of pass/fail of the property with the action blocks.
For example :
assert property(p_test) begin
pass_cnt++;
end else begin
fail_cnt++
end

Is there a way to assert that all signals in a design are initialized on rising clock during reset?

Just from the tester flow (no changes to design) is there a quick way to assert that all the design signals are initialized during reset?
Design uses synchronous active low reset.
On the rising edge of reset I want to assert that every signal in the design is not 'U' without having to call out each signal or architecture.
Using VHDL 2008, Modelsim 10.1c with HDL Designer.
You can adapt the use of the Modelsim when command from this answer to look for 'U' in any signals after the synchronous reset is released. As it exists it works with scalars and arrays but cannot examine record members.
Note that the rising edge of reset is not the time that reset is released since you are using synchronous reset. I would make the test wait for the first falling edge of clock when reset is high to test for 'U'. This will ensure that you see the new state on signals when their drivers update after the reset. The when expression would be something like:
"clk'event and clk = '0' and reset = '1' and $sig = [string repeat U [string length [examine $sig]]]"
Another option would be to create a sentinel signal in the testbench that evaluates to true when reset is released and test for that in the when expression:
signal reset_inactive : boolean;
process(clk) is
begin
if rising_edge(clk) then
if reset = '1' then
reset_inactive <= true;
else
reset_inactive <= false;
end if;
end if;
end process;
...
When expression:
"reset_inactive'event and reset_inactive = true and $sig = ..."
Once complete it would be a good idea to cancel the waits with the nowait command to avoid the performance hit of having a wait on every signal in the design since you only need this test after reset.