Write function

I have pasted my code below.

I have analysis_port instantiated in class and_driver and and_monitor from where I am calling write function (drv_to_scb.write(from and_driver) and to_scoreboard.write(from and_monitor)) .

In the Scoreboard, instead of using uvm_analysis_imp_*, I used uvm_analysis_export and connected it to and_predictor’s analysis_export.

And inside and_predictor, I have connected analysis_export to expfifo and outfifo as shown below.
I didn’t define the write function anywhere in and_predictor or even in and_scoreboard.
I am not using put function to write to uvm_tlm_analysis_fifo in the below mentioned code.
I am calling write function in and_monitor as well as in and_driver as shown below and I am seeing the data getting written to uvm_tlm_analysis_fifo. can this happen?

class and_driver extends uvm_driver#(packet);

   virtual and_if vif;
   packet g;
  **uvm_analysis_port #(packet) drv_to_scb;**

   `uvm_component_utils(and_driver)

    function new (string name, uvm_component parent);
      super.new(name,parent);
    endfunction : new

    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      drv_to_scb = new("drv_to_scb",this);
      if(!and_vif_config::get(this,"","vif",vif))
        `uvm_fatal("NOVIF",{"virtual interface is not defined. set it for:",get_full_name(),".vif"});
    endfunction: build_phase

     virtual task run_phase(uvm_phase phase);
      fork
         get_and_drive();
      join
     endtask: run_phase

     virtual task get_and_drive();
       forever begin
          seq_item_port.get_next_item(req);
          $display("writing to scoreboard");
         **drv_to_scb.write(req);**
          $cast(g,req.clone());
          drive_pins(g);
          seq_item_port.item_done();
       end
     endtask : get_and_drive

     virtual task drive_pins(packet trans);
       begin
        vif.a =  trans.a;
        vif.b =  trans.b;
        vif.c =  trans.c;
        #25;
       end
     endtask : drive_pins 

endclass : and_driver


class and_monitor extends uvm_monitor;
   `uvm_component_utils(and_monitor)
   **uvm_analysis_port #(packet) to_scoreboard;**
   virtual and_if vif;
   packet pkt;

    function new (string name, uvm_component parent);
      super.new(name,parent);
      to_scoreboard = new("to_scoreboard",this);
      pkt = new();
    endfunction : new

    function void build_phase(uvm_phase phase);
      virtual and_if aif;
      super.build_phase(phase);
    if(!and_vif_config::get(this,"","vif",aif))
        `uvm_fatal("NOVIF",{"virtual interface is not defined. set it for:",get_full_name(),".vif"});
      $display("vif assigned");
      vif = aif;
    endfunction: build_phase

    task run_phase(uvm_phase phase);
      fork 
         forever @(vif.a or vif.b or vif.c or vif.d or vif.d or vif.e or vif.f or vif.y or vif.z) 
         begin
             #3;
             pkt.a = vif.a;
             pkt.b = vif.b;
             pkt.c = vif.c;
             pkt.d = vif.d;
             pkt.e = vif.e;
             pkt.f = vif.f;
             pkt.y = vif.y;
             pkt.z = vif.z;
             $display("to_scoreboard write called",$time);
             **to_scoreboard.write(pkt);**
         end
       join
    endtask
endclass : and_monitor


class and_scoreboard extends uvm_scoreboard;
 `uvm_component_utils(and_scoreboard)
 packet pkt1;
 packet pkt2;
 and_predictor abcd;

 **uvm_analysis_export #(packet) m_imp_mon;
  uvm_analysis_export #(packet) m_imp_drv;**
 
  function new(string name, uvm_component parent);
    super.new(name,parent);
    m_imp_mon = new("m_imp_mon",this);
    m_imp_drv = new("m_imp_drv",this);
    abcd = new("abcd",this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
**m_imp_drv.connect(abcd.m_imp_drv_pred);
    m_imp_mon.connect(abcd.m_imp_mon_pred);**
  endfunction
  
 
   task run_phase(uvm_phase phase);

   endtask

endclass

class and_predictor extends uvm_component;
  `uvm_component_utils(and_predictor)
  uvm_analysis_export #(packet) m_imp_mon_pred;
  uvm_analysis_export #(packet) m_imp_drv_pred;
   uvm_tlm_analysis_fifo #(packet) expfifo;
   uvm_tlm_analysis_fifo #(packet) outfifo;
   packet pkt1;
   packet pkt2;
  
    function new(string name, uvm_component parent);
    super.new(name,parent);
    expfifo = new("expfifo",this);
    outfifo = new("outfifo",this);
    pkt1 = new("pkt1");
    pkt2 = new("pkt2");
      m_imp_mon_pred = new("m_imp_mon_pred",this);
      m_imp_drv_pred = new("m_imp_drv_pred",this);
    endfunction
  
    function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
   **m_imp_drv_pred.connect(expfifo.analysis_export);
    m_imp_mon_pred.connect(outfifo.analysis_export);**
    endfunction
  

 
      task run_phase(uvm_phase phase);
     packet exp_pkt,act_pkt;
     forever begin
        expfifo.get(exp_pkt);
        outfifo.get(act_pkt);
        exp_pkt.y = (exp_pkt.a && exp_pkt.b && exp_pkt.c);
        if((act_pkt.y != exp_pkt.y))  begin
          $display("predictor act_pkt.y is %d",act_pkt.y);
          $display("pred act_pkt.z is %d",act_pkt.z);
          $display("pred exp_pkt.y is %d",exp_pkt.y);
          $display("pred exp_pkt.z is %d",exp_pkt.z);
           `uvm_error(get_type_name(),"Dayalan Comparison FAIL");
        end else begin
          $display("pred act_pkt.y is %d",act_pkt.y);
          $display("pred act_pkt.z is %d",act_pkt.z);
          $display("pred exp_pkt.y is %d",exp_pkt.y);
          $display("pred exp_pkt.z is %d",exp_pkt.z);

           `uvm_info(get_type_name(),"Dayalan Comparison PASS",UVM_NONE);
        end
     end
   endtask
  
endclass

In reply to dayalan.natarajan:

How do you see data are transfered to the fifos?

In reply to dayalan.natarajan:

Yes, that would work as the “analysis_export” of the uvm_tlm_analysis_fifo has a built in write() You can think of it this way, “analysis_export” is putting that transaction (from uvm_analysis_export) into the FIFO via the “hidden” write() implementation.

This is very similar to how one can makes use of uvm_tlm_fifo to get around on the put() and get() implementations. For eg.

/**** Producer ***/
uvm_put_port #(transaction_type) put_port;

// Somewhere as part the run_phase
put_port.put(abc);

/*** Consumer ***/
uvm_get_port #(transaction_type) get_port;

// somewhere as part of the run_phase
get_port.get(xyz);

/*** ENV ***/
uvm_tlm_fifo #(transaction_type) tlm_fifo;

// connect_phase
producer.put_port.connect(tlm_fifo.put_export); // hidden put implementation
consumer.get_port.connect(tlm_fifo.get_export); // hidden get implementation

In reply to dayalan.natarajan:

If you don’t have any write function implemented it should report an error like this:
Sub-class ‘apb_coverage’ does not override all virtual methods of abstract superclass ‘uvm_subscriber__2’ (this is what Questa is saying). The apb_coverage is connected to the apb_monitor, which calls the write method.
Because the write function is a virtual method you have to deliver an implementation.
If you do not, then it has to report an error.

In reply to dayalan.natarajan:

Thanks for your reply Abhishek. What you mentioned is true for the connection between and_scoreboard and and_predictor component’s as uvm_tlm_analysis_fifo has inbuilt write function.

But my question is how the write function call from monitor and driver is driving/transmitting the data into Scoreboard.

Thanks for your reply chr_sue.
I am not seeing any error while running my simulation. I have pasted the simulation log below for your reference

UVM_INFO @ 0: reporter [RNTST] Running test seqr_and…
vif assigned
writing to scoreboard
to_scoreboard write called 3
pred act_pkt.y is 0
pred act_pkt.z is 0
pred exp_pkt.y is 0
pred exp_pkt.z is 0
UVM_INFO testbench.sv(80) @ 3: uvm_test_top.and_env0.agent0.scoreboard0.abcd [and_predictor] Dayalan Comparison PASS
UVM_INFO testbench.sv(274) @ 25: uvm_test_top.and_env0.agent0.sequencer0@@seq0 [oneonezero] seq0 wrote : a= x1, b = x1, c = x0** UVM_INFO testbench.sv(542) @ 25: uvm_test_top [seqr_and] second sequence writing to scoreboard to_scoreboard write called 28 pred act_pkt.y is 1 pred act_pkt.z is 0 pred exp_pkt.y is 1 pred exp_pkt.z is 0 **UVM_INFO testbench.sv(80) @ 28: uvm_test_top.and_env0.agent0.scoreboard0.abcd [and_predictor] Dayalan Comparison PASS** **UVM_INFO testbench.sv(196) @ 50: uvm_test_top.and_env0.agent0.sequencer0@@seq1 [all_ones] seq1 wrote : a= x1, b = x1, c = x1
UVM_INFO testbench.sv(544) @ 60: uvm_test_top [seqr_and] all sequence done
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_objection.svh(1270) @ 60: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase
UVM_INFO /apps/vcsmx/etc/uvm-1.2/src/base/uvm_report_server.svh(847) @ 60: reporter [UVM/REPORT/SERVER]
— UVM Report Summary —

** Report counts by severity
UVM_INFO : 9
UVM_WARNING : 18
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1
[TEST_DONE] 1
[TPRGED] 18
[UVM/RELNOTES] 1
[all_ones] 1
[and_predictor] 2
[oneonezero] 1
[seqr_and] 2

$finish called from file “/apps/vcsmx/etc/uvm-1.2/src/base/uvm_root.svh”, line 527.
$finish at simulation time 60
V C S S i m u l a t i o n R e p o r t
Time: 60 ns
CPU Time: 0.360 seconds; Data structure size: 0.2Mb
Fri Apr 8 07:35:40 2016
Done

In reply to dayalan.natarajan:

The error message has to appear when constructing/connecting the class-based testbench, not during simulation.
Using get/put is a different story. But haave in mind get and put are blocking. You might miss/lose transactions.

In reply to dayalan.natarajan:

“But my question is how the write function call from monitor and driver is driving/transmitting the data into Scoreboard.”

Since you say the SB is receiving the packets, I’m pretty sure you have something on these lines in the connect_phase() of your Env.

agent0.driver0.drv_to_scb.connect(agent0.scoreboard0.m_imp_drv);
agent0.monitor0.drv_to_scb.connect(agent0.scoreboard0.m_imp_mon);

And via the SB export channels, your and_predictor “abcd” is receiving the packets.