简体   繁体   中英

SystemVerilog macro through task

How to send macros as parameters through a task?

In the testbench:

`define CPU1 tb.top.dual_processor_db_wrapper_i.dual_processor_db_i.cpu1.inst
`define CPU2 tb.top.dual_processor2_db_wrapper_i.dual_processor2_db_i.cpu2.inst

initial begin
    fork
        cpu_init(`CPU1);
        cpu_init(`CPU2);
    join
    // Other stuff with `CPU1 and `CPU2
    
    `CPU1.write_data(addr, 4, data, resp); // Works
end

task cpu_init(cpu);
    cpu.por_srstb_reset(1'b1); // Does not work
    // Other init stuff
endtask

Error when compiling:

ERROR: [VRFC 10-2991] 'por_srstb_reset' is not declared under prefix 'cpu'

The type of the `CPUs is unknown (to me). Perhaps Xilinx has a type for it, since it references their MPSoC VIP?

I assume por_srstb_reset and write_data are tasks or functions from Xilinx MPSoC VIP, but I'm not sure.

Xilinx documentation is very sparse

I general, it is possible to pass a macro as an argument to a task . However, it is not possible to pass a hierarchical reference as an argument to a task (it is illegal).

Operations on hierarchical references are very limited, in general.

Your task declaration is equivalent to the following:

task cpu_init (input logic cpu);

The cpu variable is a 1-bit type. So, the following is legal:

`define CPU1 1'b1
cpu_init(`CPU1);

The type of the argument must match between the declaration and the task call.

There is another approach to this problem by using bind and abstract/concrete classes

package pkg;
  interface class abstract_init;
    pure virtual task init; // prototype for each method you need
  endclass
  abstract_init lookup[string]; // database of concrete classes for each instance
endpackage

module bind_module #(string lookup_name);
  import pkg::*;
  class concrete_init implements abstract_init;
    function new;
      lookup[lookup_name] = this; // register this instance 
    endfunction
    virtual task init;
      processor.reset(); // upwards reference
    endtask
  endclass
  concrete_init c = new; // each instance of this module gets registered in lookup
endmodule
    


`define cpu1 top.dut.cpu1
`define cpu2 top.dut.cpu2
// macro turns any argument into a quoted string
`define Q(arg) `"arg`"
    
module top;
  dut dut();
  bind `cpu1 bind_module #(.lookup_name(`Q(`cpu1))) b();
  bind `cpu2 bind_module #(.lookup_name(`Q(`cpu2))) b();
  initial fork
    pkg::lookup[`Q(`cpu1)].init;
    pkg::lookup[`Q(`cpu2)].init;
  join

endmodule

module dut;
  processor cpu1();
  processor cpu2();
endmodule

module processor;
  initial $display("Starting %m");
  task reset;
    #1 $display("executing reset on %m");
  endtask
endmodule

This is described more detail in my DVCon paper: The Missing Link: The Testbench to DUT Connection .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM