Welcome ! This website will help YOU (recent graduates/professionals) learn verification languages like SystemVerilog and UVM. Register for free and access more content !

We have seen the scenario in TLM - Put, where data sent to componentB is executed using the put() method defined in B. Let us consider the case where there are two components A and C connected to B's export. Then, any data object sent by either componentA or componentC will be received by componentB and operated upon by the same put() method. If there's a need to be able to process them separately, you would need to have two separate put() methods.

componentA and componentC connected to same export

UVM provides us with the `uvm_*_put_imp_decl () macro to deal with cases when the component needs to provide two put implementation ports.

 
`uvm_put_imp_decl (_1)
`uvm_put_imp_decl (_2)
 
class my_put_imp #(type T=int) extends uvm_component;
  uvm_put_imp_1 #(T, my_put_imp #(T)) put_imp1;
  uvm_put_imp_2 #(T, my_put_imp #(T)) put_imp2;
 
  function void put_1 (input T t);
    // puts coming from put_imp1
  endfunction
 
  function void put_2 (input T t);
    // puts coming from put_imp2
  endfunction
  ...
endclass
 

Note the following from the sample code above:

  • `uvm_put_imp_decl should be outside the class
  • uvm_put_imp class used inside my_put_imp should have the argument passed to the macro appended to it.
  • put() function/task should also have the argument appended to it.

UVM will create two new classes by the name uvm_put_imp_1 and uvm_put_imp_2 when the macros are called. That is the reason why you have to append the argument to uvm_put_imp when trying to create an object. Even the put() method defined in those classes have the argument appended to it. You may give any name as the argument instead of _1 and _2, but make sure to use the same afterwards.

compA and compC connected to separate ports on compB

Example

Let's first create componentA and componentC.

 
//------------------------ componentA -------------------------------------
 
  class componentA extends uvm_component;
   `uvm_component_utils (componentA)
 
   // We are creating a put_port parameterized to use a "simple_packet" type of data
   uvm_blocking_put_port #(simple_packet) put_port;
   simple_packet  pkt;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // Remember that put_port is a class object and it will have to be 
      // created with new ()
      put_port = new ("put_port", this);
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      // Let us generate 5 packets and send it via the put_port
      repeat (2) begin
         pkt = simple_packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
         `uvm_info ("COMPA", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
         put_port.put (pkt);
      end
   endtask
endclass
 
//------------------------ componentC -------------------------------------
class componentC extends uvm_component;
   `uvm_component_utils (componentC)
 
   // We are creating a put_port which will accept a "simple_packet" type of data
   uvm_blocking_put_port #(simple_packet) put_port;
   simple_packet  pkt;
 
   function new (string name = "componentC", uvm_component parent= null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // Remember that put_port is a class object and it will have to be 
      // created with new ()
      put_port = new ("put_port", this);
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      // Let us generate 5 packets and send it via the put_port
      repeat (2) begin
         pkt = simple_packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
         `uvm_info ("COMPC", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
         put_port.put (pkt);
      end
   endtask
endclass
 

Coming to componentB, notice that we have used the sample code shown before to implement the macros.

 
`uvm_blocking_put_imp_decl (_1)
`uvm_blocking_put_imp_decl (_2)
 
class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
   // Mention type of transaction, and type of class that implements the put ()
   uvm_blocking_put_imp_1 #(simple_packet, componentB) put_imp1;
   uvm_blocking_put_imp_2 #(simple_packet, componentB) put_imp2;
 
   function new (string name = "componentB", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      put_imp1 = new ("put_imp1", this);
      put_imp2 = new ("put_imp2", this);
   endfunction
 
   task put_1 (simple_packet pkt);
      `uvm_info ("COMPB", "Packet received from put_1", UVM_LOW)
      pkt.print (uvm_default_line_printer);
   endtask
 
   task put_2 (simple_packet pkt);
      `uvm_info ("COMPB", "Packet received from put_2", UVM_LOW)
      pkt.print (uvm_default_line_printer);
   endtask
endclass
 

Environment will have all the three component instantiations, and connect componentA with componentB's put_imp1 port, while componentC will be connected to componentB's put_imp2.

 
class my_env extends uvm_env;
   `uvm_component_utils (my_env)
 
   componentA compA;
   componentC compC;
   componentB compB;
 
   function new (string name = "my_env", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      compA = componentA::type_id::create ("compA", this);
      compC = componentC::type_id::create ("compC", this);
      compB = componentB::type_id::create ("compB", this);
   endfunction
 
   virtual function void connect_phase (uvm_phase phase);
      compA.put_port.connect (compB.put_imp1);  
      compC.put_port.connect (compB.put_imp2);
   endfunction
endclass
 


Simulation Results

----------------------------------------------------------------
CDNS-UVM-1.1d (14.22-s009)
(C) 2007-2013 Mentor Graphics Corporation
(C) 2007-2013 Cadence Design Systems, Inc.
(C) 2006-2013 Synopsys, Inc.
(C) 2011-2013 Cypress Semiconductor Corp.
----------------------------------------------------------------
UVM_INFO @ 0: reporter [RNTST] Running test base_test...
UVM_INFO @ 0: reporter [UVMTOP] UVM testbench topology:
---------------------------------------------------
Name            Type                    Size  Value
---------------------------------------------------
uvm_test_top    base_test               -     @2602
  m_top_env     my_env                  -     @2668
    compA       componentA              -     @2699
      put_port  uvm_blocking_put_port   -     @2808
    compB       componentB              -     @2759
      put_imp1  uvm_blocking_put_imp_1  -     @2861
      put_imp2  uvm_blocking_put_imp_2  -     @2910
    compC       componentC              -     @2729
      put_port  uvm_blocking_put_port   -     @2962
---------------------------------------------------

UVM_INFO ./tb/tlm.sv(95) @ 0: uvm_test_top.m_top_env.compC [COMPC] Packet sent to CompB
pkt: (simple_packet@3032) { addr: 'h53  data: 'hc4  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(144) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from put_2
pkt: (simple_packet@3032) { addr: 'h53  data: 'hc4  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(95) @ 0: uvm_test_top.m_top_env.compC [COMPC] Packet sent to CompB
pkt: (simple_packet@3051) { addr: 'h40  data: 'h3f  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(144) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from put_2
pkt: (simple_packet@3051) { addr: 'h40  data: 'h3f  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB
pkt: (simple_packet@3014) { addr: 'h2f  data: 'h64  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(139) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from put_1
pkt: (simple_packet@3014) { addr: 'h2f  data: 'h64  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(61) @ 0: uvm_test_top.m_top_env.compA [COMPA] Packet sent to CompB
pkt: (simple_packet@3061) { addr: 'hb8  data: 'h27  rwb: 'h0  }
UVM_INFO ./tb/tlm.sv(139) @ 0: uvm_test_top.m_top_env.compB [COMPB] Packet received from put_1
pkt: (simple_packet@3061) { addr: 'hb8  data: 'h27  rwb: 'h0  }

--- UVM Report catcher Summary ---

Was this article helpful ?

We use cookies to personalize content and ads, to provide social media features and to analyze our traffic. You consent to our cookies if you continue to use our website. To find out more about the cookies we use and how to delete them, see our privacy policy.

  I accept cookies from this site.
Agree
EU Cookie Directive plugin by www.channeldigital.co.uk