• [UVMC]UVM Connect基础教程


    UVM Connect基础教程

    --- Integrating SystemC into UVM

           前言:尽管 UVM 为构建参考模型提供了高级抽象,但 SystemC 在用于设计和验证的高级模型方面具有传统。 为了允许在 UVM 测试平台中重用使用 SystemC 编写的参考模型,UVMC 在 SystemC 和 SystemVerilog UVM 模型和组件之间提供 TLM1 和 TLM2 连接(参见图 1)。

                   

    Figure 1 - UVMC: SystemC and SystemVerilog sides

           对于 TLM 通信,验证组件必须同意它们正在交换的数据。 使用事务参数化这些组件使它们能够建立 UVMC 连接 [1]。 

    一、一个例子

           为了说明 UVM Connect 的使用,将使用图 2 的测试平台作为示例。 与简单的加法器测试台不同,这个测试台没有监视器,也没有驱动程序,一旦检查的是模块refmod_low(用SystemC编写)的操作,在refmod(用SystemC编写的另一个模块)的操作中。

           两个 refmod 的操作都非常简单:它们只是获取来自 uvm_tlm_analysis_fifo 的 from_refmod 和 from_refmod_low 的事务(带有消息的字符串),并将这些事务分别放入 uvm_tlm_fifo 的 to_refmod 和 to_refmod_low 中。

           序列读取图 3 的树的文件,并且定序器将事务发送到 path_tr,其中使用 analysis_port 将其传输到 uvm_tlm_analysis_fifo 的 from_refmod 和 from_refmod_low。

     Figure 3 - Tree containing transactions for the sequence

           测试平台的代码及其 refmods 可以在下面看到。

    • The class packet_in that defines the input transaction
    1. class packet_in extends uvm_sequence_item;
    2. string message;
    3. `uvm_object_utils_begin(packet_in)
    4. `uvm_field_string(message, UVM_DEFAULT|UVM_HEX)
    5. `uvm_object_utils_end
    6. function new(string name="packet_in");
    7. super.new(name);
    8. endfunction: new
    9. endclass: packet_in
    •  The class packet_out that defines the output transaction
    1. class packet_out extends uvm_sequence_item;
    2. string message;
    3. `uvm_object_utils_begin(packet_out)
    4. `uvm_field_string(message, UVM_DEFAULT|UVM_HEX)
    5. `uvm_object_utils_end
    6. function new(string name="packet_in");
    7. super.new(name);
    8. endfunction: new
    9. endclass: packet_out
    •  The sequence_in that generates the transactions withe the DPI function read_message()
    1. import "DPI-C" context function string read_message(string msg);
    2. class sequence_in extends uvm_sequence #(packet_in);
    3. `uvm_object_utils(sequence_in)
    4. function new(string name="sequence_in");
    5. super.new(name);
    6. endfunction: new
    7. int data_file, scan_file;
    8. string filename;
    9. function void open_file();
    10. data_file = $fopen("myfile.txt", "r");
    11. if(data_file == 0)begin
    12. $display("file could not be open!!!");
    13. end
    14. endfunction: open_file
    15. task body();
    16. packet_in tr;
    17. open_file();
    18. while(1)begin
    19. scan_file = $fscanf(data_file, "%s", filename);
    20. tr = packet_in::type_id::create("tr");
    21. start_item(tr);
    22. tr.message = read_message(filename);
    23. finish_item(tr);
    24. if($feof(data_file))
    25. break;
    26. end
    27. $finish();
    28. endtask: body
    29. endclass: sequence_in
    •  The DPI function called in the sequence_in
    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace std;
    6. extern "C" const char* read_message(const char* message){
    7. string msg;
    8. ifstream myfile(message);
    9. if(myfile.is_open()){
    10. getline(myfile, msg);
    11. return msg.c_str();
    12. }
    13. else
    14. cout << "unable to open file";
    15. }
    •  The sequencer that sends the transaction to the class path_tr
    1. class sequencer extends uvm_sequencer #(packet_in);
    2. `uvm_component_utils(sequencer)
    3. function new (string name = "sequencer", uvm_component parent = null);
    4. super.new(name, parent);
    5. endfunction
    6. endclass: sequencer
    • The class path_tr that trasmits the transaction to the uvm_tlm_analysis_fifo's from_refmod and from_refmod_low using an analysis_port
    1. class path_tr extends uvm_driver #(packet_in);
    2. packet_in tr;
    3. `uvm_component_utils(path_tr)
    4. uvm_analysis_port #(packet_in) item_collected_port;
    5. function new(string name, uvm_component parent);
    6. super.new(name, parent);
    7. item_collected_port = new ("item_collected_port", this);
    8. endfunction
    9. virtual task run_phase(uvm_phase phase);
    10. forever begin
    11. seq_item_port.get_next_item(tr);
    12. begin_tr(tr, "path_tr");
    13. item_collected_port.write(tr);
    14. end_tr(tr);
    15. seq_item_port.item_done();
    16. end
    17. endtask
    18. endclass: path_tr
    •  The refmod (written in SystemC)
    1. #include "systemc.h"
    2. #include "tlm.h"
    3. #include
    4. using namespace std;
    5. using namespace tlm;
    6. struct tr {
    7. string message;
    8. };
    9. #include "uvmc.h"
    10. using namespace uvmc;
    11. UVMC_UTILS_1(tr, message)
    12. SC_MODULE(refmod) {
    13. sc_port > in;
    14. sc_port > out;
    15. void p() {
    16. tr tr;
    17. while(1){
    18. tr = in->get();
    19. cout <<"refmod: " <"\n";
    20. out->put(tr);
    21. }
    22. }
    23. SC_CTOR(refmod): in("in"), out("out") { SC_THREAD(p); }
    24. };
    • The refmod_low (written in SystemC)
    1. SC_MODULE(refmod_low){
    2. sc_port > in;
    3. sc_port > out;
    4. void p() {
    5. tr tr;
    6. while(1){
    7. tr = in->get();
    8. cout <<"refmod_low: " <"\n";
    9. out->put(tr);
    10. }
    11. }
    12. SC_CTOR(refmod_low): in("in"), out("out") { SC_THREAD(p); }
    13. };
    •  The sc_main (file top.cpp) for making connections on the SystemC side
    1. #include "refmod.cpp"
    2. #include "refmod_low.cpp"
    3. int sc_main(int argc, char* argv[]) {
    4. refmod refmod_i("refmod_i");
    5. refmod_low refmod_low_i("refmod_low_i");
    6. uvmc_connect(refmod_i.in, "refmod_i.in");
    7. uvmc_connect(refmod_low_i.in, "refmod_low_i.in");
    8. uvmc_connect(refmod_i.out, "refmod_i.out");
    9. uvmc_connect(refmod_low_i.out, "refmod_low_i.out");
    10. sc_start();
    11. return(0);
    12. }
    •  The class comparator that expects transactions from the outputs of the refmod and refmod_low in order to compare them
    1. class comparator #(type T = packet_in) extends uvm_scoreboard;
    2. typedef comparator #(T) this_type;
    3. `uvm_component_utils(this_type)
    4. uvm_tlm_fifo #(T) from_refmod;
    5. uvm_tlm_fifo#(T) from_refmod_low;
    6. T tr1, tr2;
    7. int match, mismatch;
    8. function new(string name, uvm_component parent);
    9. super.new(name, parent);
    10. from_refmod = new("from_refmod", null, 1);
    11. from_refmod_low = new("from_refmod_low", null, 1);
    12. tr1 = new("tr1");
    13. tr2 = new("tr2");
    14. endfunction
    15. function void connect_phase(uvm_phase phase);
    16. uvmc_tlm1 #(T)::connect(from_refmod.put_export, "refmod_i.out");
    17. uvmc_tlm1#(T)::connect(from_refmod_low.put_export, "refmod_low_i.out");
    18. endfunction: connect_phase
    19. task run_phase(uvm_phase phase);
    20. forever begin
    21. from_refmod.get(tr1);
    22. from_refmod_low.get(tr2);
    23. compare();
    24. end
    25. endtask: run_phase
    26. virtual function void compare();
    27. if(tr1.message == tr2.message) begin
    28. $display("Comparator MATCH");
    29. match++;
    30. end
    31. else begin
    32. $display("Comparator MISMATCH");
    33. mismatch++;
    34. end
    35. endfunction: compare
    36. endclass: comparator
    •  The environment class
    1. `include "comparator.sv"
    2. class env extends uvm_env;
    3. sequencer sqr;
    4. path_tr path;
    5. comparator #(packet_out) comp;
    6. uvm_tlm_analysis_fifo #(packet_in) to_refmod;
    7. uvm_tlm_analysis_fifo #(packet_in) to_refmod_low;
    8. `uvm_component_utils(env)
    9. function new(string name, uvm_component parent = null);
    10. super.new(name, parent);
    11. to_refmod = new("to_refmod", this);
    12. to_refmod_low = new("to_refmod_low", this);
    13. endfunction
    14. virtual function void build_phase(uvm_phase phase);
    15. super.build_phase(phase);
    16. sqr = sequencer::type_id::create("sqr", this);
    17. path = path_tr::type_id::create("path", this);
    18. comp = comparator #(packet_out)::type_id::create("comp", this);
    19. endfunction
    20. virtual function void connect_phase(uvm_phase phase);
    21. path.seq_item_port.connect(sqr.seq_item_export);
    22. path.item_collected_port.connect(to_refmod.analysis_export);
    23. uvmc_tlm1 #(packet_in)::connect(to_refmod.get_export, "refmod_i.in");
    24. path.item_collected_port.connect(to_refmod_low.analysis_export);
    25. uvmc_tlm1 #(packet_in)::connect(to_refmod_low.get_export, "refmod_low_i.in");
    26. endfunction
    27. virtual function void end_of_elaboration_phase(uvm_phase phase);
    28. super.end_of_elaboration_phase(phase);
    29. endfunction
    30. endclass
    •  The test class
    1. class test extends uvm_test;
    2. env env_h;
    3. sequence_in seq;
    4. `uvm_component_utils(test)
    5. function new(string name, uvm_component parent = null);
    6. super.new(name, parent);
    7. endfunction
    8. virtual function void build_phase(uvm_phase phase);
    9. super.build_phase(phase);
    10. env_h = env::type_id::create("env_h", this);
    11. seq = sequence_in::type_id::create("seq", this);
    12. endfunction
    13. task run_phase(uvm_phase phase);
    14. seq.start(env_h.sqr);
    15. endtask: run_phase
    16. endclass: test
    •  The top module(top.sv)
    1. import uvm_pkg::*;
    2. import uvmc_pkg::*;
    3. `include "uvm_macros.svh"
    4. `include "packet_in.sv"
    5. `include "packet_out.sv"
    6. `include "sequence_in.sv"
    7. `include "sequencer.sv"
    8. `include "path_tr.sv"
    9. `include "env.sv"
    10. `include "test.sv"
    11. //Top
    12. module top;
    13. initial begin
    14. `ifdef INCA
    15. $recordvars();
    16. `endif
    17. `ifdef VCS
    18. $vcdpluson;
    19. `endif
    20. `ifdef QUESTA
    21. $wlfdumpvars();
    22. set_config_int("*", "recording_detail", 1);
    23. `endif
    24. run_test("test");
    25. end
    26. endmodule
    •  在顶部模块中,应导入 uvm 连接包(import uvmc_pkg::*;)。 图 4 显示了 refmod 和 refmod_low(SystemC 端)与比较器(SystemVerilog 端)之间的连接。

    • SystemC端的连接可以在sc_main的以下几行中看到:
    1. uvmc_connect(refmod_i.out, "refmod_i.out");
    2. uvmc_connect(refmod_low_i.out, "refmod_low_i.out");
    •  SystemVerilog 端的连接可以在比较器的以下行中看到:
    1. function void connect_phase(uvm_phase phase);
    2. uvmc_tlm1 #(T)::connect(from_refmod.put_export, "refmod_i.out");
    3. uvmc_tlm1#(T)::connect(from_refmod_low.put_export, "refmod_low_i.out");
    4. endfunction: connect_phase

  • 相关阅读:
    tp6教程
    Linux——手把手教你解决sudo指令无法使用的问题
    【老生谈算法】自动控制中常用的Matlab函数合集——自动控制
    linux中安装jdk
    【C++实现】线程池的设计与实现
    第15章 Linux的Makefile与Cmake编程
    网站上线如何检查?
    Riverlane联手Rigetti:解决超导量子计算机关键纠错步骤
    制作出浪漫玫瑰?SoildWorks:“我可以!”
    利用pytorch自定义CNN网络(四):损失函数和优化器
  • 原文地址:https://blog.csdn.net/gsjthxy/article/details/126877213