picker/example/Pack/README.md

9.2 KiB
Raw Permalink Blame History

快速开始

使用picker pack功能可以将UVM环境进行打包成动态库并通过TLM2.0进行和其他高级语言的数据通信 picker可以解析UVM中的sequence生成一个UVM的agent组件和Python的agent类。agent中需要用户实现sequence的构造和处理接收到的sequence。具体的使用方法我们后面再讲。首先我们来介绍picker工具的安装

安装picker

手动安装picker以及相关依赖可以参考网站 open-verify.cc

在北京开源芯片研究院大机房上使用时我们提供了picker以及所需要的依赖通过执行/nfs/home/songfangyuan/picker_workspace/set_picker_env.sh脚本即可将picker添加到环境变量中 source set_picker_env.sh pack 执行命令并检查是否安装成功 bsub -Is picker --helppicker目前有pack和export两个功能所需依赖不同若想使用picker export,请执行如下命令 source set_picker_env.sh export

测试Examples

# send: UVM send some sequence to Python
bash example/Pack/release-pack.sh send

# receive: Python send some sequence to UVM
bash example/Pack/release-pack.sh receive

# both: UVM send some sequence to Python , then Python send them to UVM and compare
bash example/Pack/release-pack.sh both

picker pack 运行需要 gcc7.3uvmc等相关依赖若果运行失败请检查环境变量中是否配置

picker Pack 介绍

在本节中,我们简单介绍一下上面的例子,以双向通信为例 在/example/Pack路径下我们提供了一个加法器的sequenceadder_trans.sv,内容如下

class adder_trans extends uvm_sequence_item;
  rand bit [7:0] a;
  rand bit [7:0] b;
  
  `uvm_object_utils_begin(adder_trans)
    `uvm_field_int(a,UVM_ALL_ON)
    `uvm_field_int(b,UVM_ALL_ON)
  `uvm_component_utils_end

  function new(string name = "adder_trans");
    super.new(name);
  endfunction
  
  function void display();
    $display("Transaction: a=%d, b=%d", a, b);
  endfunction
endclass

通过picker pack adder_trans.sv -e即可生成agent和对应双向通信的示例代码

picker生成的文件结构如下

sequence_name
|-- sequence_name_xagent.sv
|-- sequence_name_xagent.py
|-- example
|   |--example_uvm.sv
|   |--example_python.py
|   |--Makefile

进入example目录,执行make命令即可运行

  • UVM agent 包括xmonitor和xdriver两个基类xagent_config配置类将sequence打包成字节流并通过 TLM2.0 发送到Python以及接收Python发送来的字节流并解析为sequence用户可以根据需要实现 UVM => Python, Python => UVM, UVM <=> Python的数据传输
    • xmonitor负责从interface上读取sequence并发送到Python其中的sequence_send()用于构建待发送的sequence需要由用户实现
    • xdriver负责接收Python发送来的sequence其中的sequence_receive()用于c处理接收到的sequence(),根据需求由用户实现
    • 用户需要继承基类创建自己的drivermonitor组件并实现上述方法
    • 在实例化agent时通过xagent_config,将用户定义的driver和monitor组件配置给agent
  • Python agent 包含驱动UVM的Agent(),和sequence的定义发送接收方法

通过picker pack <sequence_name>.sv -e-e参数可以产生<sequence_name>对应的UVM和Python的双向通信的示例下面两个例子演示UVM和Python之间的单向通信 下面我们将通过一个加法器的sequence来演示如何实现通信该部分代码位于/example/pack目录下

UVM发送到Python

进入/example/pack/目录下,执行picker pack adder_trans.sv ,即可生成对应的文件,将/example/pack/Python2UVM运行make命令

UVM端

要实现UVM发送sequence到Python

  • 首先创建自己的 monitor 继承于Adder_sequence_xmonitor然后实现sequence_send方法sequence_send方法中只需要构造出要发送的transaction
class example_monitor extends adder_trans_xmonitor;
    `uvm_component_utils(example_monitor)
    virtual example_interface     vif;
    adder_trans                   newtr;
    function new (string name = "example_monitor", uvm_component parent = null);
        super.new(name,parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        if(!uvm_config_db#(virtual example_interface)::get(this,"","vif",vif))
            `uvm_fatal("example_env","virtual interface must be set for vif")
    endfunction

  
    task sequence_send (adder_trans tr);
        @(posedge vif.clk iff(vif.valid));
        newtr = new("newtr");
        tr.randomize();
        `uvm_info("example_monitor",$sformatf("uvm send sequence: \n%s", tr.sprint()), UVM_LOW)
        
    endtask //sequence_receive
endclass
  • 在env中实例化Adder_trans_xagent,Adder_trans_xagent_config
  • Adder_trans_xagent_config 需要配置用于通信的端口名称和用户自己定义的driver和monitor的类型在这里我们将上面example_monitor的类型
class example_env extends uvm_env;
    `uvm_component_utils(example_env)
    adder_trans_xagent            xagent;
    adder_trans_xagent_config     xagent_config;
    virtual example_interface     vif;
    
    function new (string name = "example_env", uvm_component parent = null);
        super.new(name,parent);
        xagent_config = new("xagent_config");
        xagent_config.mon_type = example_monitor::get_type();
        uvm_config_db#(adder_trans_xagent_config)::set(this,"xagent", "adder_trans_xagent_config", xagent_config);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        xagent = adder_trans_xagent::type_id::create("xagent",this);
        if(!uvm_config_db#(virtual example_interface)::get(this,"","vif",vif))
            `uvm_fatal("example_env","virtual interface must be set for vif")
    endfunction

    virtual task main_phase(uvm_phase phase);
        phase.raise_objection(this);
        for (int i = 0; i < 30; i++)begin
            @(posedge vif.clk)
            vif.data <= i;
            vif.valid <= 1'b1;

            @(posedge vif.clk)
            vif.valid <= 1'b0;
        end
    endtask

endclass

Python端

在python端需要将创建对应的agent与与对应的处理接收到的sequence的方法

  • agent中共需要三个参数,第一个参数为发送通道的名称第二个和第三个参数为接收通道的名称和处理接收sequence的方法
  • agent可以同时创建发送和接收两个通道也可以根据需要只创建发送或者接收通道
if __name__ == "__main__":

    def receive_sequence(message):
        sequence = adder_trans(message)
        print("python receive sequence",sequence.a,sequence.b)
        
    agent = Agent("","adder_trans",receive_sequence)
    
    agent.run(200)

Python发送到UVM

UVM端

要实现Python发送sequence到UVM

  • 首先创建自己的 driver 继承于Adder_sequence_xdriver然后实现sequence_receive方法用于处理接收到的sequence
class example_driver extends adder_trans_xdriver;
    `uvm_component_utils(example_driver);

    function new (string name = "example_driver", uvm_component parent = null);
        super.new(name,parent);
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
    endfunction

    function sequence_receive(adder_trans tr);
        `uvm_info("example_driver", $sformatf("uvm receive message: \n%s",tr.sprint()), UVM_LOW)
    endfunction
endclass
  • 在env中实例化Adder_trans_xagent,Adder_trans_xagent_config
  • Adder_trans_xagent_config 需要配置用于通信的端口名称和用户自己定义的driver和monitor的类型在这里我们将上面example_monitor的类型
class example_env extends uvm_env;
    `uvm_component_utils(example_env)
    adder_trans_xagent            xagent;
    adder_trans_xagent_config     xagent_config;
    virtual example_interface     vif;
    
    function new (string name = "example_env", uvm_component parent = null);
        super.new(name,parent);
        xagent_config = new("xagent_config");
        xagent_config.drv_type = example_driver::get_type();
        uvm_config_db#(adder_trans_xagent_config)::set(this,"xagent", "adder_trans_xagent_config", xagent_config);
    endfunction

    function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        xagent = adder_trans_xagent::type_id::create("xagent",this);
        if(!uvm_config_db#(virtual example_interface)::get(this,"","vif",vif))
            `uvm_fatal("example_env","virtual interface must be set for vif")
    endfunction

    virtual task main_phase(uvm_phase phase);
        phase.raise_objection(this);
        for (int i = 0; i < 30; i++)begin
            @(posedge vif.clk)
            vif.data <= i;
            vif.valid <= 1'b1;

            @(posedge vif.clk)
            vif.valid <= 1'b0;
        end
    endtask

endclass

Python端

在python端需要将创建对应的agent与sequence

  • 这里的agent只需要发送通道的名字
if __name__ == "__main__":

    agent = Agent("adder_trans")
    
    for i in range(10):
        sequence = adder_trans()
        sequence.a.value = i
        sequence.b.value = i + 1
        sequence.send(agent)
        agent.run(1)
    

UVM环境中集成picker

TBD