Search code examples
system-verilogmodelsimtest-benchquestasim

Dynamic generation of signal spies in testbench


I have a .txt file that contains certain signals that I want to monitor in my testbench during the application of some stimulus.

I am creating an initial block in which I am reading the file and then I try to generate a init_signal_spy() for every one of the lines that I have read.

The code that I have written up until this point has the following format:

module testbench();

    logic probes[];

    initial begin : read_signals_to_dump_at 

        automatic int    fd;
        automatic string fname,line,line_stripped; 
        
        if ($value$plusargs("sigfile=%s",fname)) begin : read

            fd = $fopen(fname,"r");
            
            while($fgets(line,fd)) begin 

                //static logic net_to_be_probed;
             
                automatic sig_and_spy entry = new();
                
                // Trim away the '\n' from the line.
                line_stripped = line.substr(0,line.len()-2);
                
                // Resize the array
                probes = new [probes.size() + 1] (probes);
                
                // Link the extracted new line with the probe list
                // - this raises an error "An invalid empty string was passed in as the Destination object."
                // - expected since the last element is empty...
                $init_signal_spy(line_stripped, probes[probes.size()-1] , 1);

            end

        end 

    end           : read_signals_to_dump_at 

endmodule

In the code above, just before I issue the generation for the spy, I get why the error

An invalid empty string was passed in as the Destination object.

is generated by the compiler. Although the array has been resized, it does not hold any element i.e., its empty. Thus, I tried creating locally a logic variable that then I assign to the signal spy within the loop in the following manner:

module testbench();

    logic probes[];

    initial begin : read_signals_to_dump_at 

        automatic int    fd;
        automatic string fname,line,line_stripped; 
        
        if ($value$plusargs("sigfile=%s",fname)) begin : read

            fd = $fopen(fname,"r");
            
            while($fgets(line,fd)) begin 

                logic new_probe;
                                
                // Trim away the '\n' from the line.
                line_stripped = line.substr(0,line.len()-2);
                
                // Resize the array and copy old values.
                probes = new [probes.size() + 1] (probes);
                
                // Add the new probe to the Testbenchs' probes array
                probes[probes.size()-1] = new_probe;
                
                // Again, An invalid empty string was passed in as the Destination object.
                $init_signal_spy(line_stripped, probes[probes.size()-1] , 1);

            end

        end 

    end           : read_signals_to_dump_at 

endmodule

But then again, I see the same error at runtime during the simulation. So...Is there a way of achieving such a "dynamic" signal monitoring in the testbench somehow? As far as I understood the error concerns that the destination object is NOT a signal of the testbench. Thus the logic new_probe has no effect. Which is to be expected I mean, but is there a way of achieving the desired behavior in the Testbench via sysverilog?


Solution

  • You have at least two problems.

    1. Both the source and destination arguments to init_signal_spy() need to be strings. Your destination argument is an integral variable with a 0 value, and that gets interpreted as a null string. init_signal_spy() was designed for mixed language simulation, and using strings was the only way to achieve that.
    2. Your destination variable should be queue, not a dynamic array. Every time you re-size a dynamic array, the previous elements get relocated and that breaks the previous connection made by signal spy.

    This example shows the proper syntax for string this up

    module top;
      int A[$];
      int s1,s2;
      initial begin
        A.push_back(0);
        $init_signal_spy("s1","A[0]");
        A.push_back(0);
        $init_signal_spy("s2","A[1]");
        #1 s1 = 1;
        #1 s2 = 2;
        #1 $display("%p",A);
      end
    endmodule
    

    A far better solution for performance is converting your .txt file into actual SystemVerilog code that can be compiled into your testbench.