Connections to DUT Interfaces(从Connect/AbstractConcreteConfigDB开始_2)

上一篇 / 下一篇  2018-09-29 11:09:15

        Connecting the testbench to the DUT  

       使用抽象类和具体类的测试平台与DUT的连接类似于使用虚拟接口来进行连接的情况。通过虚拟接口连接,虚拟接口句柄放置在事务传输器例如driver或monitor内部,并使该句柄指向连接到DUT的接口的实例【也即是等价于将一层层传下来的实际物理接口传给driver或monitor中的虚拟接口句柄】。在抽象/具体类方法中,抽象类类型的句柄放在transactor中。具体类的实例化在包装器模块(wb_bus_protocol_module)内部进行,且抽象类句柄指向具体类的实例。

       【此处需一幅图】

       在上图中,DUT和wb_bus_protocol_module包装在包装模块wb_bus_wrapper之中。这是为了实现多个wishbone buses的模块化和便利性。
       下面的代码显示了包装器模块中的具体类的实例,以及用于创建具体类实例的method(“延迟分配器”,即在需要之前不分配实例的method)。

       module wb_bus_protocol_module #(int WB_ID = 0, int num_masters = 8, int num_slaves = 8,
                                                                     int data_width = 32, int addr_width = 32)
              (
               // Port declarations
               // WISHBONE common signals
               output logic clk,
               output logic rst,
               ...
               );

               // Concrete class declaration
               class wb_bus_concr_c #(int ID = WB_ID) extends wb_bus_abs_c;
                    ...
               endclass

               // instance of concrete class
               wb_bus_concr_c wb_bus_concr_c_inst;

               // lazy allocation of concrete class
               function wb_bus_abs_c get_wb_bus_concr_c_inst();
                    if(wb_bus_concr_c_inst == null)
                        wb_bus_concr_c_inst = new();
                   return (wb_bus_concr_c_inst);
               endfunction

               initial
                  //set concrete class object in config space
                  uvm_config_db #(wb_bus_abs_c)::set(null, "uvm_test_top",
                                                                                $sformatf("WB_BUS_CONCR_INST_%0d",WB_ID),
                                                                                get_wb_bus_concr_c_inst());

               // WISHBONE BFM instance
               wishbone_bus_syscon_bfm wb_bfm(
                   .clk( clk ),
                   .rst( rst ),
                   ...
                );
       endmodule

       具体类实例的位置以与虚拟接口连接相同的方式提供给transactor,使用config_db API将指向具体类实例的句柄传递给test class,然后通过配置对象从test class传递到transactor在上面的代码中,在初始块内部,使用config_db API将具体实例的句柄放在配置空间内。
       在test class中,concrete driver class实例的句柄从配置数据库中获取,并放置在可供wishbone agent使用的配置对象中。建议使用此方法,因为它遵循推荐的使用模型,用于将信息从DUT传递到测试平台,这将在有关虚拟接口的文章中详细讨论。

       class test_mac_simple_duplex extends uvm_test;
       ...

            mac_env env_0;
            wb_config wb_config_0; // config object for WISHBONE BUS 0
            ...

            function void set_wishbone_config_params();
                 wb_config_0 = new();
                 if (!uvm_config_db #(wb_bus_bfm_driver_base)::get(this, "",
                                        $sformatf("WB_BUS_BFM_DRIVER_C_INST_%0h", wb_config_0.m_wb_id),
                                        wb_config_0.m_wb_bfm_driver)) // concrete class object
                     `uvm_fatal(report_id, "Can't read WB_BUS_BFM_DRIVER_C_INST");
                 ...
                 uvm_config_db#(wb_config)::set(this, "env_0*", "wb_config", wb_config_0); // put in config
                 ...
            endfunction

            function void build_phase(uvm_phase phase);
                 super.build_phase(phase);
                 set_wishbone_config_params();
                 set_mii_config_params();
                 ...
            endfunction : build_phase
            ...

       endclass

       在driver内部,通过从test class提供的配置对象中获取位置,使抽象类句柄指向具体类的实例。

       // WISHBONE master driver
       class wb_bus_bfm_driver extends uvm_driver #(wb_txn, wb_txn);
            `uvm_component_utils(wb_bus_bfm_driver)

            uvm_analysis_port #(wb_txn) wb_drv_ap;
            bit [2:0] m_id; // Wishbone bus master ID
            wb_config m_config;
            wb_bus_abs_c m_wb_bus_abs_c;

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

            function void build_phase(uvm_phase phase);
                 super.build_phase(phase);
                 if (!uvm_config_db #(wb_config)::get(this, "", "wb_config", m_config)) // get config object
                     `uvm_fatal("Config Fatal", "Can't get the wb_config")
                 m_id = m_config.m_wb_master_id;
                 wb_drv_ap = new("wb_drv_ap", this);
                 // Assign abstract class handle to concrete object
                 m_wb_bus_abs_c = m_config.m_wb_bus_abs_c;
            endfunction : build_phase

            task run_phase(uvm_phase phase);
                 wb_txn req_txn;
                 forever begin
                     seq_item_port.get(req_txn); // get transaction
                     @ ( m_wb_bus_abs_c.pos_edge_clk) #1; // sync to clock edge + 1 time step
                     case(req_txn.txn_type) //what type of transaction?
                           NONE: `uvm_info($sformatf("WB_M_DRVR_%0d",m_id),
                                                                    $sformatf("wb_txn %0d the wb_txn_type was type NONE",
                                                                    req_txn.get_transaction_id()), UVM_LOW)
                           WRITE: wb_write_cycle(req_txn);
                           READ: wb_read_cycle(req_txn);
                           RMW: wb_rmw_cycle(req_txn);
                           WAIT_IRQ: fork wb_irq(req_txn); join_none
                           default: `uvm_error($sformatf("WB_M_DRVR_%0d",m_id),
                                                                      $sformatf("wb_txn %0d the wb_txn_type was type illegal",
                                                                      req_txn.get_transaction_id()) )
                     endcase
                 end
            endtask : run_phase

            //READ 1 or more cycles
            virtual task wb_read_cycle(wb_txn req_txn);
                wb_txn rsp_txn;
                m_wb_bus_abs_c.wb_read_cycle(req_txn, m_id, rsp_txn);
                seq_item_port.put(rsp_txn); // send rsp object back to sequence
                wb_drv_ap.write(rsp_txn); //broadcast read transaction with results
            endtask

            //WRITE 1 or more write cycles
            virtual task wb_write_cycle(wb_txn req_txn);
                wb_txn orig_req_txn;
                $cast(orig_req_txn, req_txn.clone()); //save off copy of original req transaction
                m_wb_bus_abs_c.wb_write_cycle(req_txn, m_id);
                wb_drv_ap.write(orig_req_txn); //broadcast orignal transaction
            endtask

            //RMW ( read-modify_write)
            virtual task wb_rmw_cycle(ref wb_txn req_txn);
                `uvm_info($sformatf("WB_M_DRVR_%0d",m_id),
                                             "Wishbone RMW instruction not implemented yet",UVM_LOW )
            endtask

            // wait for an interrupt
            virtual task wb_irq(wb_txn req_txn);
                wb_txn rsp_txn;
                m_wb_bus_abs_c.wb_irq(req_txn, rsp_txn);
                seq_item_port.put(rsp_txn); // send rsp object back to sequence
            endtask

       endclass

       当driver在运行任务中收到WISHBONE写事务时,它调用其wb_write_cycle()task,该task使用抽象类句柄(m_wb_bus_abs_c)来调用具体类中的wb_write_cycle()method,该method又调用BFM之中的wb_write_cycle()method

       Multiple instance considerations

       当存在DUT和BFM的多个实例时,每个具体类的实例需要“不加规划”,以便可以进行正确的配对。做这个的一个方法是对包装类和具体类进行参数化。在此示例中,提供了一个整数值,即WISHBONE总线ID(WB_ID),以生成唯一的字符串。这样做是为了在总线id和具体类之间建立相关性。有关使具体类实例唯一的另一种方法在协议模块的文章中有所描述(参见底部)。本文中的完整源代码实际上在top_mac中有两个wishbone包装器类实例,而不是图中所示的实例,因此有两个WISHBONE总线,MAC等。在测试平台上,每个WISHBONE总线都有一个wishbone环境,而不是图中所示的仅仅一个。为每个wishbone环境生成单独的配置对象。本文未显示多个实例的详细信息,但可以在源代码中查看。

     (在http://verificationacademy.com/uvm-ovm上在线下载源代码示例)。


TAG:

ee_king的个人空间 引用 删除 ee_king   /   2018-09-29 14:45:31
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2018-12-06  
      1
2345678
9101112131415
16171819202122
23242526272829
3031     

数据统计

  • 访问量: 14964
  • 日志数: 48
  • 建立时间: 2018-09-03
  • 更新时间: 2018-10-12

RSS订阅

Open Toolbar