【IC每日一题:IC验证面试--UVM验证-2】
IC每日一题:IC验证面试--UVM验证-2
- 2.9 get_next_iterm()和try_next_item()的区别?
- 2.10 一个典型的UVM验证平台,谈一下UVM验证环境结构,各个组件之间的关系?
- 2.11 uvm组件之间通信的方式? analysis_port和其他的区别?analysis_port是否可以不连或者连接多个import?
- 2.12 uvm_tlm_anlysis_fifo类是什么,有什么端口?
- 2.13 UVM组件中常用的方法,各种phase关系,phase机制?
- 2.14 phase中的domain概念
- 2.15 run_phase和main_phase之间的关系?
- 2.16 UVM组件的通信方式TLM的接口分类和用法,peek和get的差异;
- 2.17 sequence和item(uvm_sequence, uvm_sequence_item)的分类;
- 2.18 为什么会有sequence,sequencer以及driver,为什么我们分开实现,这样做的好处是什么?
- 2.19 如何在driver中使用interface?
- 2.20 config_db的作用以及传递其使用时的参数含义
【博客首发与微信公众号《漫谈芯片与编程》,欢迎专注一下】
本篇博客开始介绍IC验证基本功–UVM-2的相关问题;
2.9 get_next_iterm()和try_next_item()的区别?
get_next_item() 和 try_next_item() 是 uvm_sequencer 类提供的两个方法,用于从 sequencer 中获取下一个transaction。
get_next_item()–阻塞调用:
这个方法会阻塞当前的执行线程,直到 sequencer 中有可用的 item。如果 sequencer 中没有 item,调用 get_next_item() 的线程会一直等待,直到有 item 被放入 sequencer。一旦获取到 item,get_next_item() 会返回这个 item,并且调用者可以继续执行。
task run_phase(uvm_phase phase);forever beginseq_item_port.get_next_item(req); // 阻塞调用,直到有新的事务可用drive(req); // 处理事务seq_item_port.item_done(); // 通知序列器事务已完成end
endtask
try_next_item()–非阻塞调用
当驱动器调用 try_next_item() 时,如果当前没有可用的事务,它会立即返回,不会阻塞。try_next_item() 返回一个布尔值,表示是否成功获取到事务。
task run_phase(uvm_phase phase);forever beginif (seq_item_port.try_next_item(req)) { // 非阻塞调用drive(req); // 处理事务seq_item_port.item_done(); // 通知序列器事务已完成} else {// 没有事务时执行其他任务do_something_else();}end
endtask
典型应用场景:
- get_next_item():当你希望驱动器总是等待事务并按顺序处理时,使用 get_next_item()。这是最常见的用法,特别是在简单的驱动器实现中。
- try_next_item():当你希望驱动器在没有事务时能够执行其他任务,或者在多事务流场景下需要灵活处理时,使用 try_next_item()。这在需要更高的响应性和灵活性的场景中非常有用
2.10 一个典型的UVM验证平台,谈一下UVM验证环境结构,各个组件之间的关系?
UVM验证环境的基本组成:
环境(uvm_env):包含所有验证组件。
代理(uvm_agent):包含驱动器、监视器和序列器,与DUT进行交互。
驱动器(uvm_driver):将事务转换为信号,驱动到DUT。
监视器(uvm_monitor):监控DUT的输入和输出,并将信号转换为事务。
序列器(uvm_sequencer):从序列中获取事务并传递给驱动器。
序列(uvm_sequence):生成事务。
参考模型 (reference_model): 参考模型是一个功能性的模型,它独立于DUT实现同样的功能,参考模型的输出可以用来与DUT的实际输出进行比较,从而判断DUT的功能是否正确。
记分板(uvm_scoreboard):检查DUT的输出是否符合预期。
虚拟接口(virtual interface):连接UVM组件与DUT。
寄存器模型(uvm_reg_block):描述DUT中的寄存器和寄存器块。
在这里重点介绍一下参考模型的Demo:
class my_reference_model extends uvm_component;`uvm_component_utils(my_reference_model)uvm_analysis_imp #(my_transaction, my_reference_model) imp;function new(string name, uvm_component parent);super.new(name, parent);imp = new("imp", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctionfunction void write(my_transaction tr);// 执行与DUT相同的操作// 例如:计算期望的结果my_transaction exp_tr = tr.clone();exp_tr.data = perform_function(tr.data); // 假设有一个函数 perform_function// 将期望的结果发送到记分板`uvm_info("REF_MODEL", $sformatf("Expected data: %h", exp_tr.data), UVM_HIGH)// 这里假设记分板已经连接到了参考模型的分析端口endfunction// 假设这是一个简单的函数,模拟DUT的功能function bit [7:0] perform_function(bit [7:0] input_data);// 实现一些功能,例如简单的加法return input_data + 1;endfunctionendclassclass my_scoreboard extends uvm_scoreboard;`uvm_component_utils(my_scoreboard)uvm_analysis_imp #(my_transaction, my_scoreboard) imp;uvm_tlm_analysis_fifo #(my_transaction) exp_fifo;function new(string name, uvm_component parent);super.new(name, parent);imp = new("imp", this);exp_fifo = new("exp_fifo", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctionfunction void write(my_transaction tr);// 将DUT的实际输出放入FIFOimp.write(tr);endfunctionfunction void check_phase(uvm_phase phase);my_transaction act_tr, exp_tr;while (exp_fifo.try_get(exp_tr)) beginif (!imp.get(act_tr)) begin`uvm_error("SB", "No actual transaction to compare with expected")continue;endif (act_tr.data !== exp_tr.data) begin`uvm_error("SB", $sformatf("Data mismatch: Expected %h, Actual %h", exp_tr.data, act_tr.data))end else begin`uvm_info("SB", $sformatf("Data match: %h", act_tr.data), UVM_HIGH)endendendfunction
endclassclass my_env extends uvm_env;`uvm_component_utils(my_env)my_agent agent;my_scoreboard scoreboard;my_reference_model ref_model;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);agent = my_agent::type_id::create("agent", this);scoreboard = my_scoreboard::type_id::create("scoreboard", this);ref_model = my_reference_model::type_id::create("ref_model", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);agent.monitor.ap.connect(scoreboard.imp);agent.monitor.ap.connect(ref_model.imp);endfunctionendclass
2.11 uvm组件之间通信的方式? analysis_port和其他的区别?analysis_port是否可以不连或者连接多个import?
UVM组件之间的通信方式:
1.TLM ports and exports:
uvm_port 和 uvm_export: 用于请求-响应式的通信。例如,uvm_blocking_put_port 和 uvm_blocking_get_port。
uvm_analysis_port 和 uvm_analysis_imp: 用于单向数据流的通信,主要用于监控和收集数据。
2.Phases and Callbacks
通过 UVM 的 phase 机制,可以在特定的 phase 中进行组件间的通信。回调(callbacks)也可以用于在特定事件发生时进行通信。
3.uvm_config_db
通过 uvm_config_db 机制,可以在组件之间传递配置信息;
uvm_analysis_port可以不连接任何uvm_analysis_imp–这种情况下,发送的数据将被忽略
uvm_analysis_port可以连接多个uvm_analysis_imp,允许多个组件同时接收相同的数据;是通过uvm_analysis_port::connect方法来实现的
uvm_analysis_port和uvm_analysis_imp的实现示例:
// 定义一个简单的事务类
class my_transaction extends uvm_sequence_item;rand int data;`uvm_object_utils(my_transaction)function new(string name = "my_transaction");super.new(name);endfunction
endclass// 定义一个产生事务的组件
class producer extends uvm_component;`uvm_component_utils(producer)uvm_analysis_port #(my_transaction) ap;function new(string name, uvm_component parent);super.new(name, parent);ap = new("ap", this);endfunctiontask run_phase(uvm_phase phase);my_transaction tr;tr = my_transaction::type_id::create("tr");tr.randomize();ap.write(tr); // 将事务发送到分析端口endtask
endclass// 定义一个接收事务的组件
class consumer extends uvm_component;`uvm_component_utils(consumer)uvm_analysis_imp #(my_transaction, consumer) imp;function new(string name, uvm_component parent);super.new(name, parent);imp = new("imp", this);endfunctionfunction void write(my_transaction t);`uvm_info("CONSUMER", $sformatf("Received data: %0d", t.data), UVM_HIGH)endfunction
endclass// 定义顶层环境
class env extends uvm_env;`uvm_component_utils(env)producer prod;consumer cons1, cons2;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);prod = producer::type_id::create("prod", this);cons1 = consumer::type_id::create("cons1", this);cons2 = consumer::type_id::create("cons2", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);prod.ap.connect(cons1.imp); // 连接到第一个消费者prod.ap.connect(cons2.imp); // 连接到第二个消费者endfunction
endclass// 测试用例
module top;initial beginrun_test();end
endmodule
2.12 uvm_tlm_anlysis_fifo类是什么,有什么端口?
uvm_tlm_analysis_fifo 是 UVM(Universal Verification Methodology)提供的一个类,它结合了 TLM(Transaction Level Modeling)和 FIFO(First-In-First-Out)的功能,用于在验证环境中存储和转发事务。这个类特别适用于需要缓存事务数据的场景,例如在监控器和记分板之间传递数据。
uvm_tlm_analysis_fifo的主要端口:
- uvm_analysis_imp:
用于接收事务数据。这是一个单向的数据流,通常用于监控器将数据发送到 FIFO。 - uvm_get_port:
用于从 FIFO 中取出事务数据。这是一个请求-响应式的端口,通常用于记分板或其他组件从 FIFO 中获取数据
使用uvm_tlm_analysis_fifo的端口:
//==transaction
class my_transaction extends uvm_sequence_item;rand int data;`uvm_object_utils(my_transaction)function new(string name = "my_transaction");super.new(name);endfunction
endclass//==monitor
class my_monitor extends uvm_monitor;`uvm_component_utils(my_monitor)uvm_analysis_port #(my_transaction) ap;virtual my_if vif;function new(string name, uvm_component parent);super.new(name, parent);ap = new("ap", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);if (!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))`uvm_fatal("NOVIF", "Failed to get vif")endfunctiontask run_phase(uvm_phase phase);my_transaction tr;forever begin@(posedge vif.clk);if (vif.valid && vif.ready) begintr = my_transaction::type_id::create("tr");tr.data = vif.data;ap.write(tr); // 将事务发送到分析端口endendendtask
endclass//==scoreboard
class my_scoreboard extends uvm_scoreboard;`uvm_component_utils(my_scoreboard)uvm_tlm_analysis_fifo #(my_transaction) fifo;function new(string name, uvm_component parent);super.new(name, parent);fifo = new("fifo", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctiontask run_phase(uvm_phase phase);my_transaction tr;forever beginfifo.get(tr); // 从 FIFO 中取出事务`uvm_info("SCOREBOARD", $sformatf("Received data: %0d", tr.data), UVM_HIGH)endendtask
endclass//==env
class my_env extends uvm_env;`uvm_component_utils(my_env)my_monitor monitor;my_scoreboard scoreboard;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);monitor = my_monitor::type_id::create("monitor", this);scoreboard = my_scoreboard::type_id::create("scoreboard", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);monitor.ap.connect(scoreboard.fifo.analysis_export); // 连接监控器和 FIFOendfunction
endclass//==test
class my_test extends uvm_test;`uvm_component_utils(my_test)my_env env;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env = my_env::type_id::create("env", this);endfunction
endclass//==module
module top;initial beginrun_test("my_test");end
endmodule
uvm_tlm_analysis_fifo 可以有效地在监控器和记分板之间传递和缓存事务数据。
2.13 UVM组件中常用的方法,各种phase关系,phase机制?
组件的生命周期是通过一系列的phase来管理的。这些phase包括构建阶段(Build Phase)、连接阶段(Connect Phase)、运行阶段(Run Phase)等。
new():构造函数,用于创建组件实例。
build_phase():构建阶段,用于创建和配置组件的子组件。
connect_phase():连接阶段,用于连接组件之间的端口和接口。
pre_run_phase():在仿真运行之前的一些配置准备阶段;
run_phase():运行阶段,执行组件的主要功能,如发送事务、接收事务等。
report_phase():仿真结束后,报告阶段,用于生成验证结果的报告。
Phase机制:UVM的phase机制是通过一个全局的phase控制器来管理的。这个控制器负责调度和执行各个phase。在每个phase开始时,控制器会调用所有组件的相应phase方法。组件可以通过重载这些方法来实现自定义的行为。
function new(string name, uvm_component parent);super.new(name, parent);
endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);// 创建子组件my_child = my_child::type_id::create("my_child", this);
endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);// 连接端口my_child.my_port.connect(my_other_child.my_export);
endfunctionfunction void start_of_simulation_phase(uvm_phase phase);super.start_of_simulation_phase(phase);// 初始化某些全局变量global_var = 0;
endfunctiontask run_phase(uvm_phase phase);super.run_phase(phase);// 生成激励repeat (10) beginmy_transaction tr = my_transaction::type_id::create("tr");tr.randomize();my_sequencer.starting_sequence.put(tr);end
endtaskfunction void report_phase(uvm_phase phase);super.report_phase(phase);// 生成报告uvm_report_server::get_server().write_report_messages();
endfunction
2.14 phase中的domain概念
domain 是一个用于管理和同步不同时钟域之间的信号和事件的概念。在不同的模块可能运行在不同的时钟频率上,这就需要一种机制来确保跨时钟域的信号传输和事件处理是正确和可靠的;
domain 通常与 clocking block 一起使用,clocking block 是一种特殊的代码块,用于描述信号在时钟边沿上的行为。通过将信号声明在 clocking block 中,可以确保信号的采样和驱动是同步的,并且符合特定的时钟约束。
// 定义一个时钟域
clocking cb @(posedge clk);input data;output ack;
endclocking// 在组件中使用时钟域
class MyComponent extends uvm_component;virtual clocking cb;function new(string name, uvm_component parent);super.new(name, parent);// 初始化时钟域cb = new("cb", this);endfunctiontask run_phase(uvm_phase phase);forever begin// 在时钟上升沿采样输入数据@(cb);data = cb.data;// 处理数据//...// 在时钟上升沿驱动输出信号cb.ack <= 1'b1;@(cb);cb.ack <= 1'b0;endendtask
endclass
在这个示例中,clocking block cb 定义了一个时钟域,其中包含一个输入信号 data 和一个输出信号 ack。在 MyComponent 类中,run_phase 任务使用 @(cb) 来等待时钟上升沿,然后采样输入数据并驱动输出信号。
2.15 run_phase和main_phase之间的关系?
run_phase和main phase(动态运行)都是task phase,且是并行运行的,后者称为动态运行(run-time)的phase。
如果想执行一些耗费时间的代码,那么要在此phase下任意一个component中至少提起一次objection,这个结论只适用于12个run-time的phase。对于run_phase则不适用,由于run_phase与动态运行的phase是并行运行的,如果12个动态运行的phase有objection被提起,那么run_phase根本不需要raise_objection就可以自动执行。
2.16 UVM组件的通信方式TLM的接口分类和用法,peek和get的差异;
事务级建模(Transaction Level Modeling,TLM)是一种用于在验证环境中进行组件间通信的方法。TLM 接口和方法提供了一种标准化的方式来实现组件之间的通信。
UVM提供的TLM接口分类:put/get 接口和 analysis 接口;
put/get 接口:
uvm_put_port/uvm_put_imp:
用于将数据从一个组件传递到另一个组件,发送方不需要接收方的响应。
uvm_get_port/uvm_get_imp:
用于从另一个组件请求数据,发送方需要接收方的响应。
uvm_peek_port/uvm_peek_imp:
用于查看另一个组件中的数据,但不移除数据。类似于 get,但不会消耗数据。
uvm_transport_port/uvm_transport_imp:
用于双向通信,发送方发送数据并接收响应。
analysis 接口:
uvm_analysis_port/uvm_analysis_imp:
用于单向数据流,通常用于监控和收集数据。发送方不需要接收方的响应。
class my_transaction extends uvm_sequence_item;rand int data;`uvm_object_utils(my_transaction)function new(string name = "my_transaction");super.new(name);endfunction
endclassclass producer extends uvm_component;`uvm_component_utils(producer)uvm_put_port #(my_transaction) put_port;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);put_port = new("put_port", this);endfunctiontask run_phase(uvm_phase phase);my_transaction tr;tr = my_transaction::type_id::create("tr");tr.randomize();put_port.put(tr); // 将事务发送到 put_portendtask
endclassclass consumer extends uvm_component;`uvm_component_utils(consumer)uvm_get_imp #(my_transaction, consumer) get_imp;function new(string name, uvm_component parent);super.new(name, parent);get_imp = new("get_imp", this);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);endfunctionfunction void get(my_transaction tr);`uvm_info("CONSUMER", $sformatf("Received data: %0d", tr.data), UVM_HIGH)endfunction
endclassclass my_env extends uvm_env;`uvm_component_utils(my_env)producer prod;consumer cons;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);prod = producer::type_id::create("prod", this);cons = consumer::type_id::create("cons", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);prod.put_port.connect(cons.get_imp); // 连接 put_port 和 get_impendfunction
endclassclass my_test extends uvm_test;`uvm_component_utils(my_test)my_env env;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env = my_env::type_id::create("env", this);endfunction
endclassmodule top;initial beginrun_test("my_test");end
endmodule
【总结】
put/get 接口:用于组件之间的数据传递。put 用于发送数据,get 用于接收数据并消耗数据。peek 用于查看数据但不消耗数据。
analysis 接口:用于单向数据流,通常用于监控和收集数据。uvm_analysis_port 用于发送数据,uvm_analysis_imp 用于接收数据。
2.17 sequence和item(uvm_sequence, uvm_sequence_item)的分类;
uvm_sequence_item(transaction)
uvm_sequence_item 是 UVM 中表示单个事务的基本类。uvm_sequence_item 类通常包含事务的数据字段,如地址、数据、命令类型等。事务类可以包含随机化约束,用于生成符合特定条件的事务。
class my_transaction extends uvm_sequence_item;rand bit [31:0] address;rand bit [⅛:0] data;rand bit [2:0] command;constraint c_address {address inside { [0:1023] };}constraint c_data {data dist { [0:255] := 7, [256:511] := ˜3 };}constraint c_command {command inside { READ, WRITE, NOP };}`uvm_object_utils_begin(my_transaction)`uvm_field_int(address, UVM_DEFAULT)`uvm_field_int(data, UVM_DEFAULT)`uvm_field_int(command, UVM_DEFAULT)`uvm_object_utils_endfunction new(string name = "my_transaction");super.new(name);endfunction
endclass
uvm_sequence
uvm_sequence 是 UVM 中用于控制事务生成和发送的类。它负责创建事务并将其发送到 uvm_sequencer,后者再将事务传递给 uvm_driver。
class read_sequence extends uvm_sequence #(read_transaction);`uvm_object_utils(read_sequence)function new(string name = "read_sequence");super.new(name);endfunctionvirtual task body();read_transaction tr;repeat (10) begin`uvm_do(tr) // 生成并发送读事务endendtask
endclassclass write_sequence extends uvm_sequence #(write_transaction);`uvm_object_utils(write_sequence)function new(string name = "write_sequence");super.new(name);endfunctionvirtual task body();write_transaction tr;repeat (10) begin`uvm_do(tr) // 生成并发送写事务endendtask
endclassclass mixed_sequence extends uvm_sequence #(read_transaction, write_transaction);`uvm_object_utils(mixed_sequence)function new(string name = "mixed_sequence");super.new(name);endfunctionvirtual task body();read_transaction read_tr;write_transaction write_tr;repeat (5) begin`uvm_do(read_tr) // 生成并发送读事务`uvm_do(write_tr) // 生成并发送写事务endendtask
endclass
【总结】
item 是事务的基本单元,包含了验证环境中事务的最小信息。
sequence 是一系列 item 的集合,用于构建和管理验证环境中的测试场景。
通过合理地分类和设计 uvm_sequence 和 uvm_sequence_item,从而可以构建灵活且高效的激励生成机制,提高验证平台的可重用性和可维护性;
2.18 为什么会有sequence,sequencer以及driver,为什么我们分开实现,这样做的好处是什么?
首先介绍一下各自的职责:
sequence:负责生成事务(transaction),并将其发送到sequencer。sequence可以包含复杂的逻辑,如随机化、条件分支等,以生成多样化的测试场景。
sequencer:作为sequence和driver之间的桥梁,负责接收sequence发送的事务,并将其转发给driver。sequencer还可以对事务进行仲裁和调度,确保事务按照正确的顺序和时间发送给driver。
driver:负责将接收到的事务转换为实际的信号电平,并驱动到DUT(Device Under Test)的接口上。driver通常与DUT的接口协议紧密相关,需要实现具体的信号驱动逻辑。
好处:
1.职责单一:
事务生成与硬件驱动分离:sequence 专注于事务生成,而 driver 专注于硬件驱动。这种分离使得事务生成逻辑和硬件驱动逻辑可以独立开发和调试。
仲裁与调度:sequencer 负责事务的仲裁和调度,使得 sequence 和 driver 不必关心这些细节。这种分离使得 sequence 和 driver 可以专注于各自的核心功能。
2.灵活性和可拓展性:
可以轻松地添加新的 sequence 来生成不同的激励模式。
可以通过配置 sequencer 来改变事务的调度策略。
可以通过嵌套 sequence 来构建复杂的激励模式。
可以通过添加新的 driver 来支持不同的 DUT 接口。
3.易于调试和维护:
隔离问题:
如果某个组件出现问题,可以单独调试该组件,而不影响其他组件。
清晰的责任划分:
每个组件都有明确的职责,使得问题定位更加容易。
代码简洁:
每个组件的代码量相对较少,使得代码更加简洁和易于阅读。
//====transaction
class my_transaction extends uvm_sequence_item;rand bit [31:0] address;rand bit [⅛:0] data;rand bit [2:0] command;`uvm_object_utils_begin(my_transaction)`uvm_field_int(address, UVM_DEFAULT)`uvm_field_int(data, UVM_DEFAULT)`uvm_field_int(command, UVM_DEFAULT)`uvm_object_utils_endfunction new(string name = "my_transaction");super.new(name);endfunction
endclass//==sequence
class my_sequence extends uvm_sequence #(my_transaction);`uvm_object_utils(my_sequence)function new(string name = "my_sequence");super.new(name);endfunctionvirtual task body();my_transaction tr;repeat (10) begintr = my_transaction::type_id::create("tr");start_item(tr);assert(tr.randomize() with { address inside {[0:1023]}; });finish_item(tr);endendtask
endclass//==driver
class my_driver extends uvm_driver #(my_transaction);`uvm_component_utils(my_driver)virtual my_if vif;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);if (!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))`uvm_fatal("NOVIF", "Failed to get vif")endfunctiontask run_phase(uvm_phase phase);my_transaction tr;forever beginseq_item_port.get_next_item(tr);drive_transaction(tr);seq_item_port.item_done();endendtasktask drive_transaction(my_transaction tr);vif.cb.address <= tr.address;vif.cb.data <= tr.data;vif.cb.command <= tr.command;@(vif.cb);endtask
endclass//==sequencer
class my_sequencer extends uvm_sequencer #(my_transaction);`uvm_component_utils(my_sequencer)function new(string name, uvm_component parent);super.new(name, parent);endfunction
endclass//==env
class my_env extends uvm_env;`uvm_component_utils(my_env)my_sequencer seqr;my_driver drv;function new(string name, uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);seqr = my_sequencer::type_id::create("seqr", this);drv = my_driver::type_id::create("drv", this);endfunctionfunction void connect_phase(uvm_phase phase);super.connect_phase(phase);drv.seq_item_port.connect(seqr.seq_item_export);endfunction
endclass
通过这种分离的设计,UVM验证环境可以更加灵活、高效地进行事务级验证,同时提高代码的可维护性和可重用性。
2.19 如何在driver中使用interface?
在driver中进行virtual interface声明,并接收来自顶层通过config_db传递的interface。
// 定义一个简单的interface
interface my_interface (input clk, input rst_n);logic [7:0] data;logic valid;logic ready;
endinterface// driver的实现
class my_driver extends uvm_driver #(my_transaction);// 实例化interfacevirtual my_interface vif;function new(string name, uvm_component parent);super.new(name, parent);endfunction// 在build_phase中获取interface的句柄function void build_phase(uvm_phase phase);super.build_phase(phase);if (!uvm_config_db#(virtual my_interface)::get(this, "", "vif", vif)) begin`uvm_error("my_driver", "Failed to get vif handle")endendfunction// 在run_phase中使用interface与DUT通信task run_phase(uvm_phase phase);my_transaction tr;forever beginseq_item_port.get_next_item(tr);// 使用interface中的信号驱动DUTvif.data <= tr.data;vif.valid <= 1'b1;@(posedge vif.clk);while (!vif.ready) @(posedge vif.clk);vif.valid <= 1'b0;seq_item_port.item_done();endendtask
endclass
2.20 config_db的作用以及传递其使用时的参数含义
config_db 在 UVM(Universal Verification Methodology)是一个配置数据库,用于在验证环境中的不同组件之间传递配置信息–来配置和共享参数;
uvm_config_db 提供了两种主要的方法来设置和获取配置信息:uvm_config_db#(T)::set uvm_config_db#(T)::get;
// 在测试用例中设置配置信息
class my_test extends uvm_test;my_agent my_agent_inst;function void build_phase(uvm_phase phase);super.build_phase(phase);my_agent_inst = my_agent::type_id::create("my_agent_inst", this);// 设置配置信息uvm_config_db#(int)::set(this, "my_agent_inst", "num_transactions", 100);endfunction
endclass// 在代理(agent)中获取配置信息
class my_agent extends uvm_agent;int num_transactions;function void build_phase(uvm_phase phase);super.build_phase(phase);// 获取配置信息if (!uvm_config_db#(int)::get(this, "", "num_transactions", num_transactions)) begin`uvm_error("my_agent", "Failed to get num_transactions config")end// 使用配置信息`uvm_info("my_agent", $sformatf("Number of transactions: %0d", num_transactions), UVM_LOW)endfunction
endclass
在build_phase中的执行顺序是从上到下进行执行的;
相关文章:
【IC每日一题:IC验证面试--UVM验证-2】
IC每日一题:IC验证面试--UVM验证-2 2.9 get_next_iterm()和try_next_item()的区别?2.10 一个典型的UVM验证平台,谈一下UVM验证环境结构,各个组件之间的关系?2.11 uvm组件之间通信的方式? analysis_port和其…...
SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
这是一篇港科大学生在google research 实习期间发在ECCV2024的语义引导生成式修复的文章,港科大陈启峰也挂了名字。从首页图看效果确实很惊艳,尤其是第三行能用文本调控修复结果牌上的字。不过看起来更倾向于生成,对原图内容并不是很复原&…...
#揭秘万维网:从静态页面到智能互联网
揭秘万维网:从静态页面到智能互联网 今天刚上了学校开设的课程,于是便有了下文的思考内容。 在当今数字化时代,Web(万维网)扮演着重要的角色,成为人们获取信息、沟通交流和进行商业活动的主要平台。 1. …...
【计算机基础——数据结构——红黑树】
1. 红黑树(RBTree) 为什么HashMap不直接使用AVL树,而是选择了红黑树呢? 由于AVL树必须保证左右子树平衡,Max(最大树高-最小树高) < 1,所以在插入的时候很容易出现不平衡的情况,一旦这样&…...
Sentinel — 微服务保护
微服务架构将大型应用程序拆分为多个小而独立的服务,每个服务可以独立部署和扩展。然而,微服务系统需要面对的挑战也随之增加,例如服务之间的依赖、分布式环境下的故障传播和安全问题。因此,微服务保护措施是确保系统在高并发、资…...
Cynet:全方位一体化安全防护工具
前言 1999年,布鲁斯施奈尔曾说过:“复杂性是安全最大的敌人。”彼时还是19年前,而现在,网络安全已然变得更加繁杂。 近日我在网上冲浪过程中发现了这么一个平台性质的软件,看似具有相当强的防护能力。 根据Cynet的描…...
python中常见的8种数据结构之一数组的应用
在Python中,数组是一种常见的数据结构,用于存储一系列相同类型的元素。在实际应用中,数组可以用于解决各种问题。 以下是数组在Python中的一些常见应用: 1. 存储和访问数据:数组可以用于存储和访问一组数据。可以通过…...
安装多个低版本谷歌Chrome浏览器用于测试,适配Vue3+vite项目
安装多个低版本谷歌Chrome浏览器用于测试,适配Vue3vite项目 问题:使用vue3tsvite搭建了一个项目,在chrome新版本浏览器上无问题,但是部署到现场页面直接空白,且控制台报错: Uncaugnt SyntaxError: Unexpe…...
UI组件---如何设置el-pagination分页组件的背景色
1. 要替换 el-pagination 组件的背景色,您可以通过自定义CSS来实现。 具体的CSS规则取决于您想要更改的是哪个部分的背景色,例如普通页码、活跃页码、上下导航箭头等。以下是一些示例CSS规则,您可以根据自己的需求进行调整: /* …...
LabVIEW编程过程中为什么会出现bug?
在LabVIEW编程过程中,Bug的产生往往源自多方面原因。以下从具体的案例角度分析一些常见的Bug成因和调试方法,以便更好地理解和预防这些问题。 1. 数据流错误 案例:在一个LabVIEW程序中,多个计算节点依赖相同的输入数据&#…...
论文阅读《Structure-from-Motion Revisited》
摘要 增量式地运动结构恢复是从无序图像集合中进行三维重建的一个普遍策略。虽然增量式地重建系统在各个方面上都取得了巨大的进步,但鲁棒性、准确性、完整度和尺度仍然是构建真正通用管道的关键问题。我们提出了一种新的运动结构恢复技术,它改进了目前…...
RK android14 第三方app获取su权限
需要修改的地方如下 frameworks/base/core/jni/com_android_internal_os_Zygote.cpp kernel-6.1/security/commoncap.c system/core/init/selinux.cpp system/core/libcutils/fs_config.cpp system/extras/su/su.cpp device/rockchip/common/BoardConfig.mk device/rockchip…...
线程与进程的区别(面试)
一.进程 进程:一个程序启动起来,就会对应一个进程,进程就是系统分配资源的基本单位。 上面一部分进程是我们自己去执行应用的可执行文件, 而另一部分是操作系统自动启动的进程. 二.线程 线程:线程是进程中的一个执行单元ÿ…...
OpenDroneMap Webodm
OpenDroneMap & Webodm OpenDroneMap Webodm 开源无人机航拍系列图像及其它系列图像三维重建软件。很棒的开源无人机测绘软件OpenDroneMap,从航拍图像生成精确的地图、高程模型、3D 模型和点云。 应用领域 Mapping & Surveying 测绘和测量 从图像测量获得高精度的可…...
Could not create task ‘:shared_preferences_android:generateDebugUnitTestConfig‘
flutter项目使用shared_preferences库的时候,打开flutter项目中的android项目运行,会出现如下错误信息: A build operation failed. Could not create task :shared_preferences_android:generateDebugUnitTestConfig. Could not create…...
CSS教程(四)- 字体
1、尺寸单位 px 像素单位% 百分比,参照父元素对应属性的值进行计算em 字体尺寸单位,参照父元素的字体大小计算,1em16pxrem字体尺寸单位,参照根元素的字体大小计算,1rem16px 2、字体属性 介绍 CSS Fonts (字体)属性用于定义字体…...
深入理解Java中的Lambda表达式
在Java 8中,Lambda表达式的引入无疑是一个重大的里程碑。 Lambda表达式以其简洁的语法和强大的功能,极大地改变了Java开发者编写代码的方式。本文将深入探讨Lambda表达式的概念、语法、使用场景以及其在函数式编程中的意义。 一、Lambda表达式的基本概…...
C#里怎么样判断一个数是偶数还是奇数
一般是采用取余的做法。 程序如下: /** C# Program to Check whether the Entered Number is Even or Odd*/ using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace check1 {class Program{static void Main(string[]…...
【论文笔记】Prefix-Tuning: Optimizing Continuous Prompts for Generation
🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: Prefix-Tuning: Optimizin…...
GNN系统学习:消息传递图神经网络
引言 在开篇中我们介绍了,为节点生成节点表征(Node Representation)是图计算任务成功的关键,我们要利用神经网络来学习节点表征。 消息传递范式是一种聚合邻接节点信息来更新中心节点信息的范式,它将卷积算子推广到了…...
基于gewe制作第一个微信聊天机器人
现在我们制作一个微信智能聊天机器人。发送文字它可以回复一段话,或一张图片,是不是有点小酷! 当然,这种智能回复的算法和数据库我们自己肯定是没有的,所以我们借助于gewe框架的开放API接口来完成我们的功能。 请求参…...
【Python】python使用Moviepy库对mp3文件进行剪切,并设置输出文件的码率
【Python】python使用Moviepy库对mp3文件进行剪切,设置输出文件的码率 一、安装Moviepy库二、代码 一、安装Moviepy库 pip install -i https://mirrors.aliyun.com/pypi/simple/ moviepy二、代码 #!/usr/bin/python # -*- coding: UTF-8 -*- from moviepy.editor …...
海外云手机在出海业务中的优势有哪些?
随着互联网技术的快速发展,海外云手机已在出海电商、海外媒体推广和游戏行业都拥有广泛的应用。对于国内的出海电商企业来说,短视频引流和社交平台推广是带来有效流量的重要手段。借助云手机,企业能够更高效地在新兴社交平台上推广产品和品牌…...
这10款PDF转Word在线转换工具的个人使用经历!!
身为现代办公室中的一位经常需要处理各种文件格式的牛马,在PDF和Word之间转换文件是我时常要处理的事。我试过不少PDF转Word的在线工具,前前后后尝试了10款左右的PDF转word转换工具,其中有四大霸主,深深占据了我对这方面的印象。下…...
认识QT以及QT的环境搭建
认识QT 什么是QT? Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 。 认识客户端 现在我们所说的客户端开发其实大致分为三种: 1.网页前端开发。 2.桌面应用开发(电脑的应用层序) 3.移动应用开发。 而我们的QT的主战场就是在…...
Rollup failed to resolve import “destr“ from ***/node_modules/pinia-plugin-pers
在使用uni-appvuu3piniapinia-plugin-persistedstate开发中, 使用pinia-plugin-persistedstate 一直在报错,其实代码也是比较简单的, import { createPinia } from pinia // 创建 pinia 实例 const pinia createPinia(); import piniaPlugi…...
Python小白学习教程从入门到入坑------第三十课 文件定位操作(语法进阶)
一、文件指针 python中严格来说没有指针这个说法,但有指针这个用法的体现。指针概念常用于c语言、c语言中 在Python的文件操作中,文件指针(也称为文件游标或文件句柄的位置)是一个内部标记,它指示了当前文件操作的读…...
人工智能、机器学习与深度学习:层层递进的技术解读
引言 在当今科技快速发展的时代,人工智能(AI)已经成为一个热门话题,几乎渗透到了我们生活的方方面面。从智能手机的语音助手,到自动驾驶汽车,再到医疗诊断中的图像识别,人工智能的应用正在改变我…...
Code Inspector——页面开发提效的神器
写在前面 优点: 开发提效:点击页面上的 DOM 元素,它能自动打开 IDE 并将光标定位至 DOM 的源代码位置,大幅提升开发体验和效率简单易用:对源代码无任何侵入,只需要在打包工具中引入就能够生效,…...
如何定制RockyLinux ISO
目标 基于Rocky9官方ISO做定制,构建自己的ISO 可以添加非官方预装的RPM包实现Kickstart自动化安装, 完成分区等操作ISO安装后,可以执行自定义脚本,比如安装你手动添加的RPM包 Rocky9 官方ISO内容分析 挂载Rocky9 ISO,得到如下…...
成都网站改版/找客户资源的软件免费的
桌面图标带有蓝色问号解决办法 今天用svn更新了一下代码,发现桌面图标都带有一个蓝色的问号,一下子不知所措了,于是百度写了个文件,运行一下就好了。特此记录一下 1,首先在桌面创建一个.txt的文本 2,在文本…...
电子图书网站开发的目的/网上电商平台开发
Stata版本目前已经更新到17了,外观也精美了许多,很增加了许多新的功能,如制作表格导出,双重差分法。自从更新到了16版本后自带了lasso回归功能,到了17以后功能更加强大了,多了可使用 “贝叶斯信息准则”&am…...
网站想要被收录要怎么做/广点通推广登录入口
现在越来越多的电脑使用 windows10 操作系统,大家都知道 windows 系统自带有隐藏文件、文件夹功能,只要把文件或文件夹设置为隐藏属性就可以隐藏了,一定程度上保护文件安全,同时也可以防止误删除操作。个人也可以把文件或文件夹设…...
马云做一网站 只作一次/app开发
经常会碰到你的页面无法打开,原因有很多,通常系统会反馈一个错误信息代码 一般来说,您可以使用IIS来完成自定义的操作。(如要先检测花生壳,请在本机用127.0.0.1访问一个静态页面或用命令 nslookup ***.com 检查&#…...
网站建设三网/什么推广软件效果好
------------------ --------1 执行不带参数的hql文件---------------------------- hive -f 文件名.后缀 实例:hive -f chensq_test1.hql------------------ -----2 执行带1个普通参数的hql文件---------------------------- ----- 直接在hive中执行----select co…...
科学数据分析网站html5/东莞市网络seo推广价格
1. Linux系统几种常见软件包: Debian(扩展名.deb) ubuntu主要支持的软件包,Ubuntu软件仓库中提供的软件包均采用这种封装 Red Hat(扩展名.rpm) Fedora支持的一种软件包 TarBall (扩展名.tar.gz / .tar.bz2),类似与win的.zip,可以只…...