In reply to Monarch Dave:
SVA does not allow the access of local variables from the action block.
Some simulators do report the value of the variables upon a failure. However, if you absolutely want to have access you can do what I have in the example below. In this example,
the property is
(a, v=b, t=$realtime) |=> (b==v); // where b and v are int.
import uvm_pkg::*; `include "uvm_macros.svh"
module top;
bit clk, a;
int b, temp;
string tID="My project";
realtime tr;
default clocking @(posedge clk); endclocking
initial forever #10 clk=!clk;
function void report_fail(int v, b, realtime t);
if (b!=v)
`uvm_info(tID,$sformatf("Fail for @attempt time=%t v=%d, b=%d", t, v, b), UVM_LOW);
endfunction
property p_test;
int v;
realtime t;
(a, v=b, t=$realtime) |=> (1, report_fail(v, b, t)) ##0 (b==v);
endproperty
ap_test: assert property(p_test);
initial begin
repeat(200) begin
@(posedge clk);
#2 if (!randomize(a, b) with
{ a dist {1'b1:=2, 1'b0:=1};
b inside {[2:5]};
}) `uvm_error("MYERR", "This is a randomize error")
end
$finish;
end
endmodule
you can change the UVM verbosity with th ewneeded verbosity with: simulation_command +UVM_VERBOSITY=UVM_HIGH filename.sv
Code file: http://systemverilog.us/vdispvar2.sv
Results
I have a similar situation where I need to use the local variable of my property inside the sequence which it calls. But this is not allowed by SVA.
Below is my requirement :
sequence seq_timer_irq_to_fccu;
($rose(Ctrl[16])) ##1 (1,timer=timer-1'b1) [*0:$] ##1 timer==0 ##0 ($rose(timer_irq) && $rose(TmrIrq_status[0]));
endsequence
sequence seq_timer_irq_internal;
(!(Ctrl[16])) ##1 (1,timer=timer-1'b1) [*0:$] ##1 timer==0 ##0 (!(timer_irq) && $rose(TmrIrq_status[0]));
endsequence
property ASSERT_TIMER_IRQ;
int timer = 0;
@(posedge ipg_clk) disable iff (async_reset_b == 1'b0)
(($rose(Ctrl[0])) && !timer_irq, timer=TmrReLd+1'b1) |-> (seq_timer_irq_to_fccu or seq_timer_irq_internal); // TmrReLd is local signal inside my interface which is connected to the RTL top.
endproperty
The above code is giving syntax error which I expect here. Could anyone please suggest me how can I achieve my goal here.
In reply to birenkumar:
Your issue is your improper use of Local variables in formal arguments and in sequence and property declarations. Below is an expalanation from my SVA Handbook 4th Edition on the use of passing property local variables into sequences.
Please take note that on complex assertions with local variables, I prefer the use of tasks
as explained in my recent paper: https://verificationacademy.com/forums/systemverilog/paper-understanding-sva-engine-simple-alternate-solutions
Abstract: Understanding the engine behind SVA provides not only a better appreciation and limitations of SVA, but in some situations provide features that cannot be simply implemented with the current definition of SVA. This paper first explains, by example, how a relatively simple assertion example can be written without SVA with the use of SystemVerilog tasks; this provides the basis for understanding the concepts of multithreading and exit of threads upon a condition, such as an error in the assertion. The paper then provides examples that use computational variables within threads; those variables can cause, in some cases, errors in SVA. The strict emulation model with tasks solves this issue.
I’ll work on the testimonial.
Ben Cohen http://www.systemverilog.us/ben@systemverilog.us
For training, consulting, services: contact Home - My cvcblr
One time I used a function with static variable to enable communication between assertion threads. Worked well in that case. Maybe someone will use this concept, and I’m also wondering what you will think of it. Here is the code extract:
function void count_sync(output int o_counter, input bit reset);
static int counter = 0;
begin
counter = reset ? 0 : counter+1;
o_counter = counter;
end
endfunction
property sync_processed;
int counter = 0;
( seq_single(k28_5, k30_7, d0_6) , count_sync(counter, 0)) |->
(counter == 3) |-> ##1 ($rose(asic_rst) ##1 $fell(asic_rst), count_sync(counter, 1));
endproperty
The difference is it is encapsulated inside a function so only a call to this function can modify it. The use I cited was exactly what you mentioned - to achieve exclusivity for termination for every third thread (when and only when a sequence repeated 3 times there should be a viable result). Now I see it could probably be dealt with using first_match(). Thanks for your opinion. I will try to avoid static variables for communication between threads in any other circumstances than mentioned.
Another example using the idea of Ben. Thanks
In this case i do not use the uvm macros and the property is measuring the time a signal (SHIFT_LATCH) is being zero.
function void report_fail(time cur_time, time neglatch_leading, time min_latch_time_ps);
//error condition BAD CASE
if ((cur_time-neglatch_leading)<=min_latch_time_ps) begin
$display("DEBUG_ERROR property_latch_too_short at %t with measured latch_time:%t and MIN_LATCH_TIME_PS:%t negedge latch time:%t \n", cur_time, cur_time-neglatch_leading ,min_latch_time_ps, neglatch_leading);
end
endfunction
property property_latch_too_short;
time leading;
disable iff(!SHIFT_RESETn)
@(negedge SHIFT_LATCH)
(1, leading = $time) |->
@(posedge SHIFT_LATCH)
(1, report_fail($time,leading,MIN_LATCH_TIME_PS)) ##0 //adding this to the last good case condition allows you print ONLY IN CASE OF ASSERTION CONDITION failure
((($time-leading)>MIN_LATCH_TIME_PS), $display("property_latch_too_short at %t with MIN_LATCH_TIME_PS:%t and measured latch_time:%t \n", $time, MIN_LATCH_TIME_PS, $time-leading));//GOOD CASE
endproperty
// FUNCTIONAL COVERAGE
c_property_latch_too_short: cover property(property_latch_too_short);
//ASSERTION OF PROPERTY
a_property_latch_too_short : assert property (property_latch_too_short) else $error($sformatf("UVM_ERROR Width of LATCH less than %t ps. Min Latch time violation at time %t",MIN_LATCH_TIME_PS,$time) );