0
votes

I have a vendor-supplied BFM module instantiated deep in my hierarchy; let's call the path top.dut.u1.u2.bfm1. The BFM's API is a little archaic and messy for our needs. I would like to write an "object" (class? interface? something else?) that will provide tasks with a simpler calling interface, and can call the tasks of the specific BFM that it has been "linked" with. It's this "linking" that I can't figure out.

I have a simple version defined as a module, that uses a `define to specify the path to the BFM, something along the lines of:

`define BFM top.dut.u1.u2.bfm1
module bfm_wrapper;
  ...
  task read_burst(...);
    ...
    `BFM.read_burst(...);
  endtask;
  ...
endmodule

Obviously this isn't very reusable. How do I replace `BFM with something more portable or abstracted to the next higher level?

I'm a relative newbie with SystemVerilog, and I'm not even using UVM yet, but I'll take the plunge if there's something there that will help. Any help is appreciated.

[Update] A couple of restrictions that I didn't mention:

  1. I can't change or replace the vendor-supplied BFM. I'd prefer to not even wrap it (i.e., instantiate it in my wrapper).
  2. For reasons that I don't want to go into here, the BFM needs to be instantiated inside the DUT. Changing that would require more effort than I can invest right now.
2
I'm not sure I understand how to use bind in this situation. Are you saying to bind bfm_wrapper into the scope where the BFM is instantiated? If so, what do I put in place of `BFM in the above (pseudo)code? - Jabberwock
Your wrapper can bind to u2's module or path. In the wrapper, have its own read_burst task that uses "Upwards name referencing" IEEE1800-2012 ยง23.8. The wrapper itself can contain the code to link your auxiliary code to classes, virtual interfaces, uvm_config_db, etc. - Greg
If I bind it to u2, I'm still not sure how to reference the BFM. For the wrapper to be reusable, I can't assume it's called bfm1. In fact, I don't want to assume that there's only one BFM (e.g., if u2 contains two independent buses). Or did you mean "bind to bfm1"? I'll read up on referencing and see if that would work. - Jabberwock

2 Answers

0
votes

Bind together with abstract interfaces will help you make the connection to the BFM. Take a look at two of my DVCon papers

http://www.doulos.com/downloads/events/DVCon_08_abstractBFM_final.pdf

http://events.dvcon.org/2012/proceedings/papers/01P_3.pdf

[UPDATE]

package bfm_pkg;
interface class bfm_api;
   pure virtual task read_burst(...);
endclass
endpackage

module bfm_wrapper;
 import bfm_pkg::*;
  ...
  class wrapper extends bfm_api;
  task read_burst(...);
    `BFM.read_burst(...);
  endtask;
  endclass
  wrapper h = new();
endmodule

Then from withing your classes, you can write

import bfm_pkg;:*;
class someclass
  bfm_api h;
  task foo;
   ...
   h.read_burst(...);
  endtask
endclass

Now you just need to get the handle to h in your bfm_wrapper to the h inside object foo. If you are using the UVM, then the uvm_config_db would help here, otherwise you'll need to create your own mechanism to copy the handle h.

0
votes

The final answer (first suggested by @toolic and @Greg, later by @dave_59) is to use bind to dynamically put the wrapper where the vendor BFM can be found with "upwards name referencing" (specifically, by putting the wrapper inside of the vendor BFM). So my code above would look something like:

`define BFM top.dut.u1.u2.bfm1
module top;
  ...
  // Instantiate my wrapper code inside of the vendor's BFM
  bind `BFM bfm_wrapper my_bfm();

  // BFM commands go here
  initial begin
    wait (`BFM.reset === 0) @(posedge `BFM.clk);
    `BFM.my_bfm.my_read_burst(...);
    ...
  end
endmodule

module bfm_wrapper;
  ...
  task my_read_burst(...);
    ...
    read_burst(...);
  endtask;
  ...
endmodule

My apologies if there are any typos. My code didn't wind up looking exactly like this.

Note that I didn't completely get rid of the define. That would probably require the more elegant techniques in @dave_59's papers. But I did at least move it out of the reusable part of the code, which is good enough for now.