UVM糖果爱好者教程 - 21. TLM 1示例

在之前的文章中,我们看了TLM 1类的概述。 本文将为您提供一些使用TLM 1类的示例代码。

components

我们创建了以下组件来演示不同类型的TLM 1接口。 jelly_bean_sequencer(最左边的组件)创建jelly_bean_transaction的一个对象,名为jb_req。 jb_req通过几个TLM 1接口一直传送到右边(jelly_bean_transporter)。 jelly_bean_transporter评估jb_req的风格,并返回另一个名为jb_rsp(jelly-bean response)的带有更新后的taste属性的jelly_bean_transaction。 jb_rsp最后被传回给jelly_bean_subscriber。 虽然这个例子是tb中通常不这么用,但是它会向你展示各种TLM 1接口。


                                                                                     TLM 1示例连接

jelly_bean_sequencer

jelly_bean_sequencer是专门用于jelly_bean_transaction的uvm_sequencer。

typedef uvm_sequencer#(jelly_bean_transaction) jelly_bean_sequencer;

jelly_bean_put_driver

jelly_bean_put_driver是一个uvm_driver,这意味着它有一个seq_item_port。第4行声明另一个端口(put_port)。 在run_phase中从seq_item_port(第19行)获取一个jb_req,然后将它放到put_port(第21行)。

class jelly_bean_put_driver extends uvm_driver#( jelly_bean_transaction );
   `uvm_component_utils( jelly_bean_put_driver )
 
   uvm_put_port#( jelly_bean_transaction ) put_port;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
      put_port = new( .name( "put_port" ), .parent( this ) );
   endfunction: build_phase
 
   task run_phase( uvm_phase phase );
      jelly_bean_transaction jb_req;
 
      forever begin
         seq_item_port.get_next_item( jb_req );
         `uvm_info( get_type_name(), "[seq_item_port]-->{jb_req}-->[put_port]", UVM_NONE )
         put_port.put( jb_req );
         seq_item_port.item_done();
      end
   endtask: run_phase
endclass: jelly_bean_put_driver

jelly_bean_master

jelly_bean_master有一个uvm_get_port(get_port,第4行),一个uvm_master_port(master_port,第5和6行)和一个uvm_analysis_port(rsp_ap,第7行)。 在run_phase中从get_port(第25行)获得一个jb_req,然后将其放到master_port(第27行)。 jelly_bean_master等待jelly bean响应(jb_rsp,第29行),然后将其写入rsp_ap(第31行)。

class jelly_bean_master extends uvm_component;
   `uvm_component_utils( jelly_bean_master )
 
   uvm_get_port#( jelly_bean_transaction ) get_port;
   uvm_master_port#( .REQ( jelly_bean_transaction ), 
                     .RSP( jelly_bean_transaction ) ) master_port;
   uvm_analysis_port#( jelly_bean_transaction ) rsp_ap;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
      get_port    = new( .name( "get_port" ),    .parent( this ) );
      master_port = new( .name( "master_port" ), .parent( this ) );
      rsp_ap      = new( .name( "rsp_ap" ),      .parent( this ) );
   endfunction: build_phase
 
   task run_phase( uvm_phase phase );
      jelly_bean_transaction jb_req;
      jelly_bean_transaction jb_rsp;
 
      forever begin
         get_port.get( jb_req );
         `uvm_info( get_type_name(), "[get_port]-->{jb_req}-->[master_port]", UVM_NONE )
         master_port.put( jb_req );
         `uvm_info( get_type_name(), "{jb_rsp}< --[master_port]", UVM_NONE )
         master_port.get( jb_rsp );
         `uvm_info( get_type_name(), "{jb_rsp}-->[rsp_ap]", UVM_NONE )
         rsp_ap.write( jb_rsp );
      end
   endtask: run_phase
endclass: jelly_bean_master

jelly_bean_slave

jelly_bean_slave有一个uvm_master_imp(master_export,第4到6行)和一个uvm_transport_port(trans_port,第7和8行)。 jelly_bean_slave也有两个队列; req_q存储jb_reqs,rsp_q存储jb_rsps。 jelly_bean_slave实现uvm_master_imp的访问方法;即put,try_put,can_put,get,try_get,can_get,peek,try_peek和can_peek(第34到81行)。 在run_phase中从req_q获得jb_req(如果可用),然后调用trans_port的传输(第28行)。

class jelly_bean_slave extends uvm_component;
   `uvm_component_utils( jelly_bean_slave )
 
   uvm_master_imp#( .REQ( jelly_bean_transaction ), 
                    .RSP( jelly_bean_transaction ),
                    .IMP( jelly_bean_slave ) ) master_export;
   uvm_transport_port#( .REQ( jelly_bean_transaction ),
                        .RSP( jelly_bean_transaction ) ) trans_port;
   jelly_bean_transaction req_q[$];
   jelly_bean_transaction rsp_q[$];
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
      master_export = new( "master_export", this );
      trans_port    = new( .name( "trans_port" ), .parent( this ) );
   endfunction: build_phase
 
   task run_phase( uvm_phase phase );
      jelly_bean_transaction jb_rsp;
 
      forever begin
         wait ( req_q.size() > 0 );
         `uvm_info( get_type_name(), "(master_export)---{jb_req}-->[trans_port]", UVM_NONE )
         trans_port.transport( req_q.pop_front(), jb_rsp );
         `uvm_info( get_type_name(), "{jb_rsp}< --[trans_port]", UVM_NONE )
         rsp_q.push_back( jb_rsp );
      end
   endtask: run_phase
 
   virtual task put( input jelly_bean_transaction t );
      req_q.push_back( t );
   endtask: put
 
   virtual function bit try_put( input jelly_bean_transaction t );
      req_q.push_back( t );
      return 1;
   endfunction: try_put
 
   virtual function bit can_put();
      return 1;
   endfunction: can_put
 
   virtual task get( output jelly_bean_transaction t );
      wait ( rsp_q.size() > 0 );
      t = rsp_q.pop_front();
   endtask: get
 
   virtual function bit try_get( output jelly_bean_transaction t );
      if ( rsp_q.size() > 0 ) begin
         t = rsp_q.pop_front();
         return 1;
      end else begin
         return 0;
      end
   endfunction: try_get
 
   virtual function bit can_get();
      return rsp_q.size() > 0;
   endfunction: can_get
 
   virtual task peek( output jelly_bean_transaction t );
      wait ( rsp_q.size() > 0 );
      t = rsp_q[0];
   endtask: peek
 
   virtual function bit try_peek( output jelly_bean_transaction t );
      if ( rsp_q.size() > 0 ) begin
         t = rsp_q[0];
         return 1;
      end else begin
         return 0;
      end
   endfunction: try_peek
 
   virtual function bit can_peek();
      return rsp_q.size() > 0;
   endfunction: can_peek
endclass: jelly_bean_slave

jelly_bean_transporter

jelly_bean_transporter有一个uvm_transport_imp(trans_export,第4至6行)并实现其访问方法;即transport和nb_transport(第17至32行)。这些方法创建jelly bean响应(jb_rsp,第24行),评估jelly bean请求的风味并相应地更新jb_rsp的taste属性(第26至29行)。

class jelly_bean_transporter extends uvm_component;
   `uvm_component_utils( jelly_bean_transporter )
 
   uvm_transport_imp#( .REQ( jelly_bean_transaction ),
                       .RSP( jelly_bean_transaction ),
                       .IMP( jelly_bean_transporter ) ) trans_export;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
      trans_export = new( "trans_export", this );
   endfunction: build_phase
 
   virtual task transport( input  jelly_bean_transaction jb_req,
                           output jelly_bean_transaction jb_rsp );
      assert( nb_transport( jb_req, jb_rsp ) );
   endtask: transport
 
   virtual function bit nb_transport( input  jelly_bean_transaction jb_req,
                                      output jelly_bean_transaction jb_rsp );
      jb_rsp = jelly_bean_transaction::type_id::create( "jb_rsp" );
      jb_rsp.copy( jb_req );
      if ( jb_req.flavor == jelly_bean_transaction::CHOCOLATE && jb_req.sour )
        jb_rsp.taste = jelly_bean_transaction::YUCKY;
      else
        jb_rsp.taste = jelly_bean_transaction::YUMMY;
      `uvm_info( get_type_name(), { "Returning:\n", jb_rsp.sprint() }, UVM_NONE )
      return 1;
   endfunction: nb_transport
endclass: jelly_bean_transporter

jelly_bean_subscriber

jelly_bean_subscriber是一个uvm_subscriber,这意味着它有一个analysis_export。 jelly_bean_subscriber实现了analysis_export的写入方法(第8至10行)。

class jelly_bean_subscriber extends uvm_subscriber#( jelly_bean_transaction );
   `uvm_component_utils( jelly_bean_subscriber )
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void write( jelly_bean_transaction t );
      `uvm_info( get_type_name(), { "Received:\n", t.sprint() }, UVM_NONE )
   endfunction: write
endclass: jelly_bean_subscriber

jelly_bean_agent

jelly_bean_agent实例化所有组件并将它们连接在一起。

class jelly_bean_agent extends uvm_agent;
   `uvm_component_utils( jelly_bean_agent )
 
   jelly_bean_sequencer                    jb_seqr;
   jelly_bean_put_driver                   jb_put_drvr;
   uvm_tlm_fifo#( jelly_bean_transaction ) jb_fifo;
   jelly_bean_master                       jb_master;
   jelly_bean_slave                        jb_slave;
   jelly_bean_transporter                  jb_trans;
   jelly_bean_subscriber                   jb_sub;
 
   function new( string name, uvm_component parent );
      super.new( name, parent );
   endfunction: new
 
   function void build_phase( uvm_phase phase );
      super.build_phase( phase );
      jb_seqr     = jelly_bean_sequencer  ::type_id::create( .name( "jb_seqr" ),     .parent( this ) );
      jb_put_drvr = jelly_bean_put_driver ::type_id::create( .name( "jb_put_drvr" ), .parent( this ) );
      jb_fifo     = new(                                     .name( "jb_fifo" ),     .parent( this ) );
      jb_master   = jelly_bean_master     ::type_id::create( .name( "jb_master" ),   .parent( this ) );
      jb_slave    = jelly_bean_slave      ::type_id::create( .name( "jb_slave" ),    .parent( this ) );
      jb_trans    = jelly_bean_transporter::type_id::create( .name( "jb_trans" ),    .parent( this ) );
      jb_sub      = jelly_bean_subscriber ::type_id::create( .name( "jb_sub" ),      .parent( this ) );
   endfunction: build_phase
 
   function void connect_phase( uvm_phase phase );
      super.connect_phase( phase );
      jb_put_drvr.seq_item_port.connect( jb_seqr.seq_item_export );
      jb_put_drvr.     put_port.connect( jb_fifo.put_export );
      jb_master.       get_port.connect( jb_fifo.get_peek_export );
      jb_master.    master_port.connect( jb_slave.master_export );
      jb_slave.      trans_port.connect( jb_trans.trans_export );
      jb_master.         rsp_ap.connect( jb_sub.analysis_export );
   endfunction: connect_phase
endclass: jelly_bean_agent

Simulation

这是一个仿真输出的摘录。

# UVM_INFO ../src/tutorial_20.sv(118) @ 0: uvm_test_top.jb_env.jb_agent.jb_seqr@@jb_seq [one_jelly_bean_sequence] Generated:
# UVM_INFO ../src/tutorial_20.sv(152) @ 0: uvm_test_top.jb_env.jb_agent.jb_put_drvr [jelly_bean_put_driver] [seq_item_port]-->{jb_req}-->[put_port]
# UVM_INFO ../src/tutorial_20.sv(188) @ 0: uvm_test_top.jb_env.jb_agent.jb_master [jelly_bean_master] [get_port]-->{jb_req}-->[master_port]
# UVM_INFO ../src/tutorial_20.sv(223) @ 0: uvm_test_top.jb_env.jb_agent.jb_slave [jelly_bean_slave] (master_export)---{jb_req}-->[trans_port]
# UVM_INFO ../src/tutorial_20.sv(282) @ 0: uvm_test_top.jb_env.jb_agent.jb_trans [jelly_bean_transporter] Returning:
# UVM_INFO ../src/tutorial_20.sv(225) @ 0: uvm_test_top.jb_env.jb_agent.jb_slave [jelly_bean_slave] {jb_rsp}< --[trans_port]
# UVM_INFO ../src/tutorial_20.sv(190) @ 0: uvm_test_top.jb_env.jb_agent.jb_master [jelly_bean_master] {jb_rsp}<--[master_port]
# UVM_INFO ../src/tutorial_20.sv(192) @ 0: uvm_test_top.jb_env.jb_agent.jb_master [jelly_bean_master] {jb_rsp}-->[rsp_ap]
# UVM_INFO ../src/tutorial_20.sv(298) @ 0: uvm_test_top.jb_env.jb_agent.jb_sub [jelly_bean_subscriber] Received:
我希望本教程能帮助你理解TLM 1接口。

猜你喜欢

转载自blog.csdn.net/zhajio/article/details/80756063