Getting assertion property arguments in vpi

Hi,
Whenever a assertion fails, my vpi app is triggered and I am able to get till the property handle. But unable to get the arguments of this property.

if ( reason == cbAssertionFailure ) 
  {
    assertion_error_count ++;
    if ( DEBUG_ACNT ) vpi_printf("Assertion error detected\n");

    if(vpi_get(vpiType,assrtH) == vpiAssert) { 
        vpi_printf("%s, It is an assertion\n",vpi_get_str(vpiFullName,assrtH));
    ///////////////////////////////////////////////////

    vpiHandle prptyH;
    prptyH = vpi_handle(vpiProperty,assrtH); 
    //vpi_printf("%s, It is a property\n",vpi_get_str(vpiDefName,prptyH));

    if (prptyH == NULL) {
        vpi_printf("ERROR: property handle is empty\n");
    }

    vpiHandle argsH,argH;
    argsH = vpi_iterate(vpiArgument,prptyH);

    if (argsH == NULL) {
        vpi_printf("ERROR: arguments handle is empty\n");
    }

    s_vpi_value current_value;
    current_value.format = vpiBinStrVal; /* read value as a string */
    while((argH = vpi_scan(argsH)) != NULL) {
        //vpi_get_value(exprH, &current_value);
        //vpi_printf("%s, It is the expr\n",current_value.value.str);
        vpi_printf("%s, It is an arg\n",vpi_get_str(vpiName,argH));
    }
    

    ///////////////////////////////////////////////////

Here, I get NULL for argsH. From property handle to argument handle, there is a one to many relationship but unable to understand why it is getting NULL.

In reply to Roshan Khatri:

It would help to show a simple complete testcase (SystemVerilog & C code).

Hi dave_59,

SV code :


module tb;

  import "DPI-C" function int register_assertions();
  import "DPI-C" function int assertion_errors();

reg clk,rst;
reg a,d11;
wire out;
int acount;

dut dut1 (d11,a,rst,clk,out);

always
 #5 clk = ~clk;

initial begin
        clk=0;rst=1;
    #10 rst=0; d11=0;a=0;
end

  initial begin
     $display("SVA testcase");
     acount = register_assertions();
     $display("Note: %0d assertions registered in testbench",acount);
     #20;
         d11=0;a=0;
     #20 d11=1;
     #30 d11=0;
     #30 d11=1;
     #20       a=1;
     #30 d11=0;

     #300 acount = assertion_errors();
     if ( acount > 0 ) $display("Note: %0d assertion errors seen during simulation",acount);
     #100 $finish;

  end


initial begin
  $monitor($time,"in=%0b a=%0b out=%0b rst=%0b",dut1.in,dut1.a,out,rst);
end

//reg source_flop="dut1.src.q1",
  //  destination_flop="dut1.dst.q2";

property p1;
  @(posedge clk) dut1.in != $past(dut1.in,1) |-> (out == $past(out))[*10];
endproperty

a_p1: assert property (p1);

endmodule


C code :

#include "vpi_user.h"
#include "vpi_abv_cds.h"
#include "sv_vpi_user.h"

#define NULL ((void *)(0))
#define DEBUG_ACNT 1

static int assertion_error_count = 0;

static int assertion_error_detected ( int reason, p_vpi_time timeP, vpiHandle assrtH, 
      p_vpi_attempt_info attemptP, char *user_data)
{
  if ( reason == cbAssertionFailure ) 
  {
    assertion_error_count ++;
    if ( DEBUG_ACNT ) vpi_printf("Assertion error detected\n");

    if(vpi_get(vpiType,assrtH) == vpiAssert) { 
        vpi_printf("%s, It is an assertion\n",vpi_get_str(vpiFullName,assrtH));
    ///////////////////////////////////////////////////

    vpiHandle prptyH;
    prptyH = vpi_handle(vpiProperty,assrtH); 
    //vpi_printf("%s, It is a property\n",vpi_get_str(vpiDefName,prptyH));

    if (prptyH == NULL) {
        vpi_printf("ERROR: property handle is empty\n");
    }

    vpiHandle argsH,argH;
    argsH = vpi_iterate(vpiArgument,prptyH);

    if (argsH == NULL) {
        vpi_printf("ERROR: arguments handle is empty\n");
    }

    //s_vpi_value current_value;
    //current_value.format = vpiBinStrVal; /* read value as a string */
    while((argH = vpi_scan(argsH)) != NULL) {
        vpi_printf("%s, It is an arg\n",vpi_get_str(vpiName,argH));
        //vpi_get_value(argH, &current_value);
        //vpi_printf("%s, It is the arg val\n",current_value.value.str);
    }
    

    ///////////////////////////////////////////////////
    }
  }
  return assertion_error_count;
}

static int register_assertion_1scope(vpiHandle scopeH)
{
  int mtype;
  vpiHandle assrtI, assrtH, parentH;
  vpiHandle subI, subH;
  int acount = 0;

  /* Look for assertions inside modules, programs and interface objects. */
  if ( DEBUG_ACNT ) vpi_printf("\nProcessing scope %s for assertions\n",vpi_get_str(vpiFullName,scopeH));
  mtype = vpi_get(vpiType,scopeH);
  if ( mtype == vpiModule || mtype == vpiProgram || mtype == vpiInterface ) 
  {
    /* Find any assertion directives in this scope */
    if ( (assrtI = vpi_iterate(vpiAssertion,scopeH)) ) 
      while ( (assrtH = vpi_scan(assrtI)) )
      {
        if ( vpi_get(vpiType,assrtH) == vpiAssert )
	{
          parentH = vpi_handle(vpiInstance,assrtH);
	  if ( parentH == scopeH )
	  {
            /* Register the callback function to catch an error transition on this assertion */
	    vpi_register_assertion_cb ( assrtH, cbAssertionFailure, assertion_error_detected, NULL );
	    acount++;
	    if ( DEBUG_ACNT ) vpi_printf("  Registered cb for %s\n",vpi_get_str(vpiFullName,assrtH));
	  }
	}
      }
  }
  /* Finish by processing the subscopes to this scope */
  if ( (subI = vpi_iterate(vpiInternalScope,scopeH)) )
       while ( (subH = vpi_scan(subI)) ) acount += register_assertion_1scope(subH);
  if ( DEBUG_ACNT ) vpi_printf("End scope %s with %d assertions\n\n",
       vpi_get_str(vpiFullName,scopeH),acount);
  return acount;
}

int register_assertions ( void )
{
  vpiHandle topI,topH;
  int acount = 0;
  if ( DEBUG_ACNT ) vpi_printf("Registering assertions to detect errors during simulation\n");
  /* Loop over the top level scopes in the design registering assertions for each */
  if ( (topI = vpi_iterate(vpiModule,NULL)) )  
       while ( (topH = vpi_scan(topI)) ) acount += register_assertion_1scope(topH);
  if ( (topI = vpi_iterate(vpiProgram,NULL)) )  
       while ( (topH = vpi_scan(topI)) ) acount += register_assertion_1scope(topH);
  if ( (topI = vpi_iterate(vpiInterface,NULL)) )  
       while ( (topH = vpi_scan(topI)) ) acount += register_assertion_1scope(topH);
  return acount;
}

int assertion_errors(void)
{
  return assertion_error_count;
}

In reply to Roshan Khatri:

Your property p1 has no formal arguments. If you are looking to find variables used inside the property_spec (i.e. dut1.in, out), you will need to parse the specification.

Thanks Dave Rich, it works!