序
當惱人的情緒來襲時,如何重拾愉快的心情?
禪的態度是:知道事實,面對事實,處理事實,然後就把它放下。簡而言之:面對它、接受它、處理它、放下它。人生,真的有很多不公平要去接受。生活,難免出 現逆境。逃避解決不了問題,只有用智慧把責任負擔起來,才能真正地從困擾的問題中獲得解脫。因此,放下的幸福,簡單而深沉。
面對它、接受它、處理它、放下它
面對它:即是告訴自己,任何事物、現象的發生,都有它一定的原因。我們不須追究原因,也無暇追究原因,唯有面對它、改善它,才是最直接、最要緊的。當問題 發生時,逃避並不能阻止它不出現;只有坦然以對,把它當做是一種應對危機處理的鍛煉,或者是另一種讓自己成長的助力。不要害怕承擔做錯的後果,努力從中累 積人生的經驗。不做鴕鳥,直面人生。面對是幸福的第一步。
接受它:很多人在問題發生後,都很難接受這個令人失望而意外的結果,但是人生本來就是一連串的起伏波折,得失是很平常的事,我們不可能永遠處在順境之中,所以,遭遇逆境時,也要勇敢接受,就是一種智慧。
處理它:因果必須配合因緣。對於任何不好的情況,如果能夠改善它,當即予以改善;若不能改善,也不必失望,繼續努力,下次還有成功的機會。
放下它:「逝者如斯夫,不捨晝夜。」過去的事情已然過去,繁華似錦也罷,一塌糊塗也罷,歸零是必然的。現實早在重啟,你還戀戀不捨,耿耿於懷。心裡放不下,又是何苦?
放下自己也放下別人
禪的最高境界,緣於「放下」。「放下」的禪理類同於「得與失」的智慧。失即是得,是一種痛苦,也是幸福。因為只有失去,空下的雙手,才能拾起新來的幸福。
能作如此想的人,對一切都會生起同情心與尊敬心。同情人家也是具縛的凡夫,尊敬人家也有獨立的人格。無論遭遇任何狀況,都不會認為它是一件了不得的事,如 果已經知道可能會發生什麼不如意的事,能讓它不發生是最好的;如果它一定要發生,擔心又有什麼用?擔心、憂慮不僅幫不了忙,可能還會令情況變得更嚴重,唯 有面對,最後放下,才是最好的辦法。
對感情的問題,宜用理智來處理;對家族的問題,宜用倫理來處理;即使發生了不得了的大事,也應用時間來化解、淡化。能夠面對、接受,就等於是在處理;既然已經處理了,也就不必再擔心,應該放下了。睡覺時照樣睡覺,吃飯時照樣吃飯,該怎麼生活就怎樣生活。
放不下自己是沒有智慧,放不下別人是沒有慈悲,每一個人都要懂得放自己一馬,也要放別人一馬,不要把生命浪費在鑽牛角尖上。生命的路很長、還寬敞,塞翁失馬焉知非福。
2011年6月18日 星期六
UVM callback(二)
另一個簡單的UVM callback
就原來的例子加了另一個CB
可以看到兩個依序執行
//
`include "uvm.svh"
import uvm_pkg::*;
`include "uvm_macros.svh"
class Driver_callback extends uvm_callback;
function new (string name = "Driver_callback");
super.new(name);
endfunction
static string type_name = "Driver_callback";
virtual function string get_type_name();
return type_name;
endfunction
virtual task pre_send(); endtask
virtual task post_send(); endtask
endclass : Driver_callback
class Driver extends uvm_component;
`uvm_component_utils(Driver)
`uvm_register_cb(Driver,Driver_callback)
function new (string name, uvm_component parent=null);
super.new(name,parent);
endfunction
virtual task run();
repeat(2) begin
`uvm_do_callbacks(Driver,Driver_callback,pre_send())
$display(" Driver: Started Driving the packet ...... %d",$time);
// Logic to drive the packet goes hear
// let's consider that it takes 40 time units to drive a packet.
#40;
$display(" Driver: Finished Driving the packet ...... %d",$time);
`uvm_do_callbacks(Driver,Driver_callback,post_send())
end
#100;
$finish;
endtask
endclass
class Custom_Driver_callbacks_1 extends Driver_callback;
function new (string name = "Driver_callback");
super.new(name);
endfunction
virtual task pre_send();
$display("CB_1:pre_send: Delaying the packet driving by 20 time units. %d",$time);
#20;
endtask
virtual task post_send();
#15;
$display("CB_1:post_send: Just a message from post send callback method \n");
endtask
endclass
class My_Driver_callbacks extends Driver_callback;
function new (string name = "My_Driver_callbacks");
super.new(name);
endfunction
virtual task pre_send();
$display("My_CB:pre_send: Delaying the packet driving by 6 time units. %d",$time);
#6;
endtask
virtual task post_send();
#3;
$display("My_CB:post_send: Delay 3 for post send callback method \n");
endtask
endclass
class My_Driver_callbacks2 extends Driver_callback;
function new (string name = "My_Driver_callbacks2");
super.new(name);
endfunction
virtual task pre_send();
$display("My_CB2:pre_send: Delaying the packet driving by 12 time units. %d",$time);
#12;
endtask
virtual task post_send2(); // 不存在原來的class,所以不會執行到
#5;
$display("My_CB2:post_send2: Delay 5 for post send callback method \n");
endtask
endclass
module test;
initial begin
Driver drvr;
Driver_callback cb_2;
My_Driver_callbacks my_cb;
My_Driver_callbacks2 my_cb2;
drvr = new("drvr");
cb_2 = new("cb_2");
my_cb = new("my_cb");
my_cb2 = new("my_cb2"); //加了另一個my_cb
uvm_callbacks #(Driver,Driver_callback)::add(drvr,my_cb);
uvm_callbacks #(Driver,Driver_callback)::add(drvr,my_cb2);
uvm_callbacks #(Driver,Driver_callback)::display();
run_test();
end
endmodule
就原來的例子加了另一個CB
可以看到兩個依序執行
//
`include "uvm.svh"
import uvm_pkg::*;
`include "uvm_macros.svh"
class Driver_callback extends uvm_callback;
function new (string name = "Driver_callback");
super.new(name);
endfunction
static string type_name = "Driver_callback";
virtual function string get_type_name();
return type_name;
endfunction
virtual task pre_send(); endtask
virtual task post_send(); endtask
endclass : Driver_callback
class Driver extends uvm_component;
`uvm_component_utils(Driver)
`uvm_register_cb(Driver,Driver_callback)
function new (string name, uvm_component parent=null);
super.new(name,parent);
endfunction
virtual task run();
repeat(2) begin
`uvm_do_callbacks(Driver,Driver_callback,pre_send())
$display(" Driver: Started Driving the packet ...... %d",$time);
// Logic to drive the packet goes hear
// let's consider that it takes 40 time units to drive a packet.
#40;
$display(" Driver: Finished Driving the packet ...... %d",$time);
`uvm_do_callbacks(Driver,Driver_callback,post_send())
end
#100;
$finish;
endtask
endclass
class Custom_Driver_callbacks_1 extends Driver_callback;
function new (string name = "Driver_callback");
super.new(name);
endfunction
virtual task pre_send();
$display("CB_1:pre_send: Delaying the packet driving by 20 time units. %d",$time);
#20;
endtask
virtual task post_send();
#15;
$display("CB_1:post_send: Just a message from post send callback method \n");
endtask
endclass
class My_Driver_callbacks extends Driver_callback;
function new (string name = "My_Driver_callbacks");
super.new(name);
endfunction
virtual task pre_send();
$display("My_CB:pre_send: Delaying the packet driving by 6 time units. %d",$time);
#6;
endtask
virtual task post_send();
#3;
$display("My_CB:post_send: Delay 3 for post send callback method \n");
endtask
endclass
class My_Driver_callbacks2 extends Driver_callback;
function new (string name = "My_Driver_callbacks2");
super.new(name);
endfunction
virtual task pre_send();
$display("My_CB2:pre_send: Delaying the packet driving by 12 time units. %d",$time);
#12;
endtask
virtual task post_send2(); // 不存在原來的class,所以不會執行到
#5;
$display("My_CB2:post_send2: Delay 5 for post send callback method \n");
endtask
endclass
module test;
initial begin
Driver drvr;
Driver_callback cb_2;
My_Driver_callbacks my_cb;
My_Driver_callbacks2 my_cb2;
drvr = new("drvr");
cb_2 = new("cb_2");
my_cb = new("my_cb");
my_cb2 = new("my_cb2"); //加了另一個my_cb
uvm_callbacks #(Driver,Driver_callback)::add(drvr,my_cb);
uvm_callbacks #(Driver,Driver_callback)::add(drvr,my_cb2);
uvm_callbacks #(Driver,Driver_callback)::display();
run_test();
end
endmodule
UVM callback(一)
一個簡單的UVM callback
////
`include "uvm.svh"
import uvm_pkg::*;
`include "uvm_macros.svh"
class Driver_callback extends uvm_callback;
function new (string name = "Driver_callback");
super.new(name);
endfunction
static string type_name = "Driver_callback";
virtual function string get_type_name();
return type_name;
endfunction
virtual task pre_send(); endtask //預定義的function
virtual task post_send(); endtask
endclass : Driver_callback
class Driver extends uvm_component;
`uvm_component_utils(Driver)
`uvm_register_cb(Driver,Driver_callback) //註冊 callback的class
function new (string name, uvm_component parent=null);
super.new(name,parent);
endfunction
virtual task run();
// 定義driver的動作
repeat(2) begin
`uvm_do_callbacks(Driver,Driver_callback,pre_send())
$display(" Driver: Started Driving the packet ...... %d",$time);
// Logic to drive the packet goes hear
// let's consider that it takes 40 time units to drive a packet.
#40;
$display(" Driver: Finished Driving the packet ...... %d",$time);
`uvm_do_callbacks(Driver,Driver_callback,post_send())
end
#100;
$finish;
endtask
endclass
// 我自己的 callback class
class My_Driver_callbacks extends Driver_callback;
function new (string name = "My_Driver_callbacks");
super.new(name);
endfunction
virtual task pre_send();
$display("My_CB:pre_send: Delaying the packet driving by 6 time units. %d",$time);
#6;
endtask
virtual task post_send();
#3;
$display("My_CB:post_send: (delay 3) Just a message from post send callback method \n\n\n");
endtask
endclass
module test;
initial begin
Driver drvr;
Driver_callback cb_2;
My_Driver_callbacks my_cb;
drvr = new("drvr");
cb_2 = new("cb_2");
my_cb = new("my_cb");
// 告訴simulator要加入一個callback的動作
uvm_callbacks #(Driver,Driver_callback)::add(drvr,my_cb);
///要顯示有啟動callback的訊息
uvm_callbacks #(Driver,Driver_callback)::display();
run_test();
end
endmodule
2011年6月17日 星期五
$value$plusargs與simulation的應用
節錄自
http://www.socvista.com/bbs/archiver/?tid-2539.html
實際使用例請參考
http://kirenenko-tw.blogspot.com/2011/05/valueplusargs.html
另一個參考點有一些例子說明
http://testbench.in/TB_22_COMPILATION_N_SIMULATION_SWITCHS.html
此處另有說明$test$plusargs的使用
1. 我们比较常用的一般还有$value$plusargs这个task,在test_top中:$value$plusargs("casename=%s",casename)
通过脚本在run的时候把casename传递进去(给vcs/nc SIM_ARG: +casename=$Testcase_name.fsdb)
便于如果同时跑多个testcase的时候可以同时dumpfsdb,另外就是跳过一些时间开始dump(SIM_ARG: +time=$start_time)
$value$plusargs("time=%d",skip)
#skip
2. project中每个人关注的module不同,为了频繁去修改test_top的dump,一般也会把需要dump的内容用dumplist的file来实现
$fsdbDumpvarsToFile("dump.list");
比如dump.list内容:(#用于注释)
0 test_top
#1 test_top
#0 test_top.dut
#0 test_top.dut.m1
#0 test_top.dut.m2
像我们用的时候一般是在test_top.v添加相关的语句:
reg [100:0] casename;
integer skip, i;
initial begin
if( $test$plusargs("dumpfsdb") ) begin
if( $value$plusargs("time=%d", skip) )
#skip;
if( $value$plusargs ("casename=%s",casename) )
$fsdbAutoSwitchDumpfile(300, casename, 30);
else
$fsdbAutoSwitchDumpfile(300,"./test_top.fsdb",40);
$fsdbDumpvarsToFile("dump.list");
end
end
1. 跑仿真的时候,对应的如果要从5000ns(时间单位根timescale有关)处开始dump波形,给vcs/nc的参数
+dumpfsdb +time= 5000 +casename= testcase1.fsdb
其中的testcase1一般我们都会在脚本处理后跟case名字关联起来,这样子跑完之后就会从5000开始dump
testcase1_000.fsdb, testcase1_001.fsdb这样子,
2. 另外那个dump.list(名字可以随便取)里面的设定就跟平常的设定dump的层次设置一样了
层次 路径名
0 test_top.dut.m1
http://www.socvista.com/bbs/archiver/?tid-2539.html
實際使用例請參考
http://kirenenko-tw.blogspot.com/2011/05/valueplusargs.html
另一個參考點有一些例子說明
http://testbench.in/TB_22_COMPILATION_N_SIMULATION_SWITCHS.html
此處另有說明$test$plusargs的使用
1. 我们比较常用的一般还有$value$plusargs这个task,在test_top中:$value$plusargs("casename=%s",casename)
通过脚本在run的时候把casename传递进去(给vcs/nc SIM_ARG: +casename=$Testcase_name.fsdb)
便于如果同时跑多个testcase的时候可以同时dumpfsdb,另外就是跳过一些时间开始dump(SIM_ARG: +time=$start_time)
$value$plusargs("time=%d",skip)
#skip
2. project中每个人关注的module不同,为了频繁去修改test_top的dump,一般也会把需要dump的内容用dumplist的file来实现
$fsdbDumpvarsToFile("dump.list");
比如dump.list内容:(#用于注释)
0 test_top
#1 test_top
#0 test_top.dut
#0 test_top.dut.m1
#0 test_top.dut.m2
像我们用的时候一般是在test_top.v添加相关的语句:
reg [100:0] casename;
integer skip, i;
initial begin
if( $test$plusargs("dumpfsdb") ) begin
if( $value$plusargs("time=%d", skip) )
#skip;
if( $value$plusargs ("casename=%s",casename) )
$fsdbAutoSwitchDumpfile(300, casename, 30);
else
$fsdbAutoSwitchDumpfile(300,"./test_top.fsdb",40);
$fsdbDumpvarsToFile("dump.list");
end
end
1. 跑仿真的时候,对应的如果要从5000ns(时间单位根timescale有关)处开始dump波形,给vcs/nc的参数
+dumpfsdb +time= 5000 +casename= testcase1.fsdb
其中的testcase1一般我们都会在脚本处理后跟case名字关联起来,这样子跑完之后就会从5000开始dump
testcase1_000.fsdb, testcase1_001.fsdb这样子,
2. 另外那个dump.list(名字可以随便取)里面的设定就跟平常的设定dump的层次设置一样了
层次 路径名
0 test_top.dut.m1
VCS模擬與Makefile
節錄自
http://www.socvista.com/bbs/archiver/?tid-2539.html
首先工作环境是linux,所有的命令都是用makefile来联系在一起的。
举个简单的例子,
如果需要运行一个vcs 命令 并带一些命令行参数。公司的做法如下。
在某个固定的地方创建一个vcs.makefile 作为通用的makefile,所有人需要用到vcs的,那么在自己项目的makefile中 include 这个vcs.makefile.
vcs.makefile
VCS_EXE = $(VCS_HOME)/bin/vcs
$(VCS_EXE) ${VCS_FLAGS} \
-l $(vcs_logfile $@) +libverbose \
-LDFLAGS "${VCS_LDFLAGS} ${VCS_LIB_PATHS} -g"
………………
拿其中的VCS_FLAGA来详细说明:
VCS_FLAGS += +define+NO_DUMPS
VCS_FLAGS += -Mupdate -Mmakep="gmake"
VCS_FLAGS += -cc $(GCC_PATH)/bin/gcc -cpp $(GCC_PATH)/bin/g++ -ld $(GCC_PATH)/bin/g++
VCS_FLAGS += $(VCS_VERSION_ARGS)
VCS_FLAGS += ${VCS_EXTRA_ARGS}
VCS_FLAGS += +define+NO_FSDB=1
这个common的 vcs.makefile可以被任意项目调用,我们自己锁需要做的事情就是创建一个自己模块的module_name.makefile 在其中include这个vcs.makefile, 然后将需要的参数传递给vcs.makefile
我们一般利用${VCS_EXTRA_ARGS} 变量,将我们需要为项目专门添加和修改的参数传递
比如,在自己模块的module_name.makefile中:
# vcs argument
VCS_EXTRA_ARGS += +notimingcheck +nospecify +udpsched +vcsevalorder $(STANDSIM_DIR)/dini_sodimm/glbl.v
VCS_EXTRA_ARGS += +define+M512+S667+X8 $(STANDSIM_DIR)/dini_sodimm/ddr2_vcs.vp
VCS_EXTRA_ARGS += +dump_multi_fsdb
VCS_EXTRA_ARGS += +dmp_siloti +dmp_top=0
这样我们就添加额外的vcs command line argument。
以后需要跑vcs的时候,只需要敲一下make就可以。
vcs.makefile把大部分需要设定的参数都会设置好,并有初始值。可以允许我们在各自模块的makefile中覆盖,用以执行自己special 的情况。当然大部分参数都会用设置好的值,在运行之前,我们甚至多数时候都不知道自己用了哪些vcs的参数,只有test跑完,看logfile的时候, 才会发现原来vcs.makefile把我们加了一大堆的参数,包括vcs的版本、路径、项目默认需要包含的很多头文件、使用v2k、使用-ssy -ssv、等等,可能有30~40个默认的参数会被添加。
如果需要使用siloti,那么我们只需要项目文件夹下执行 make siloti,那么和siloti有关的所有参数vcs.makefile都会帮我们自动配置好。 出来的波形都是经过siloti的。
http://www.socvista.com/bbs/archiver/?tid-2539.html
首先工作环境是linux,所有的命令都是用makefile来联系在一起的。
举个简单的例子,
如果需要运行一个vcs 命令 并带一些命令行参数。公司的做法如下。
在某个固定的地方创建一个vcs.makefile 作为通用的makefile,所有人需要用到vcs的,那么在自己项目的makefile中 include 这个vcs.makefile.
vcs.makefile
VCS_EXE = $(VCS_HOME)/bin/vcs
$(VCS_EXE) ${VCS_FLAGS} \
-l $(vcs_logfile $@) +libverbose \
-LDFLAGS "${VCS_LDFLAGS} ${VCS_LIB_PATHS} -g"
………………
拿其中的VCS_FLAGA来详细说明:
VCS_FLAGS += +define+NO_DUMPS
VCS_FLAGS += -Mupdate -Mmakep="gmake"
VCS_FLAGS += -cc $(GCC_PATH)/bin/gcc -cpp $(GCC_PATH)/bin/g++ -ld $(GCC_PATH)/bin/g++
VCS_FLAGS += $(VCS_VERSION_ARGS)
VCS_FLAGS += ${VCS_EXTRA_ARGS}
VCS_FLAGS += +define+NO_FSDB=1
这个common的 vcs.makefile可以被任意项目调用,我们自己锁需要做的事情就是创建一个自己模块的module_name.makefile 在其中include这个vcs.makefile, 然后将需要的参数传递给vcs.makefile
我们一般利用${VCS_EXTRA_ARGS} 变量,将我们需要为项目专门添加和修改的参数传递
比如,在自己模块的module_name.makefile中:
# vcs argument
VCS_EXTRA_ARGS += +notimingcheck +nospecify +udpsched +vcsevalorder $(STANDSIM_DIR)/dini_sodimm/glbl.v
VCS_EXTRA_ARGS += +define+M512+S667+X8 $(STANDSIM_DIR)/dini_sodimm/ddr2_vcs.vp
VCS_EXTRA_ARGS += +dump_multi_fsdb
VCS_EXTRA_ARGS += +dmp_siloti +dmp_top=0
这样我们就添加额外的vcs command line argument。
以后需要跑vcs的时候,只需要敲一下make就可以。
vcs.makefile把大部分需要设定的参数都会设置好,并有初始值。可以允许我们在各自模块的makefile中覆盖,用以执行自己special 的情况。当然大部分参数都会用设置好的值,在运行之前,我们甚至多数时候都不知道自己用了哪些vcs的参数,只有test跑完,看logfile的时候, 才会发现原来vcs.makefile把我们加了一大堆的参数,包括vcs的版本、路径、项目默认需要包含的很多头文件、使用v2k、使用-ssy -ssv、等等,可能有30~40个默认的参数会被添加。
如果需要使用siloti,那么我们只需要项目文件夹下执行 make siloti,那么和siloti有关的所有参数vcs.makefile都会帮我们自动配置好。 出来的波形都是经过siloti的。
fsdb技巧(一)
這些是舊版的指令
節錄自
http://www.socvista.com/bbs/archiver/?tid-2539.html
-- $fsdbDumpvars([], *)
fsdbDumpfile - 指定FSDB文件名
-- $fsdbDumpfile(“”)
fsdbDumpvars - Dump指定的变量
--
fsdbDumpSingle - Dump指定的信号
fsdbDumpvariable - Dump指定的VHDL变量
fsdbSwitchDumpFile - 将dumping切换到另一个FSDB文件
-- $fsdbSwitchDumpFile(“”)
fsdbAutoSwitchDumpfile - 限制文件大小并在数据量过大时自动创建新的FSDB文件
-- $fsdbAutoSwitchDumpfile(, “”,< number of file>)
fsdbDumpflush - Force to Dump Result to FSDB file
fsdbDumpMem - Dump 指定的memory的内容
-- $fsdbDumpMem(, [, []])
現在已換成 fsdbDumpMDA了
$fsdbDumpon - 打开 FSDB dumping
$fsdbDumpoff - 关闭 FSDB dumping
有时候要运行很长时间的仿真,但是关心的波形却只是其中一小段。这个时候怎么来开关波形,使文件不至于太过庞大呢?这里介绍一个方法。
initial begin
$timeformat(...);
$fsdbAutoSwitchDumpfile(...);
$fsdbDumpvars(...);
// 条件表达式1
$fsdbDumpoff;
// 条件表达式2
$fsdbDumpon;
end
節錄自
http://www.socvista.com/bbs/archiver/?tid-2539.html
产生FSDB波形文件的若干技巧
fsdbDumplimit - 限制FSDB文件size-- $fsdbDumpvars([
fsdbDumpfile - 指定FSDB文件名
-- $fsdbDumpfile(“
fsdbDumpvars - Dump指定的变量
--
fsdbDumpSingle - Dump指定的信号
fsdbDumpvariable - Dump指定的VHDL变量
fsdbSwitchDumpFile - 将dumping切换到另一个FSDB文件
-- $fsdbSwitchDumpFile(“
fsdbAutoSwitchDumpfile - 限制文件大小并在数据量过大时自动创建新的FSDB文件
-- $fsdbAutoSwitchDumpfile(
fsdbDumpflush - Force to Dump Result to FSDB file
fsdbDumpMem - Dump 指定的memory的内容
-- $fsdbDumpMem(
現在已換成
$fsdbDumpon - 打开 FSDB dumping
$fsdbDumpoff - 关闭 FSDB dumping
有时候要运行很长时间的仿真,但是关心的波形却只是其中一小段。这个时候怎么来开关波形,使文件不至于太过庞大呢?这里介绍一个方法。
initial begin
$timeformat(...);
$fsdbAutoSwitchDumpfile(...);
$fsdbDumpvars(...);
// 条件表达式1
$fsdbDumpoff;
// 条件表达式2
$fsdbDumpon;
end
2011年6月16日 星期四
UVM Sequence再了解(七)
關於Sequence Action Macro
一般我們會用的大概就是
`uvm_do或是`uvm_do_with
其它的使用機會就少的多了
List Of Sequence Action Macros:
整理自http://testbench.in/UT_08_UVM_SEQUENCE_2.html
These macros are used to start sequences and sequence items that were either registered with a <`uvm-sequence_utils> macro or whose associated sequencer was already set using the method.
`uvm_create(item/sequence)
This action creates the item or sequence using the factory. Only the create phase will be executed.
`uvm_do(item/sequence)
This macro takes as an argument a uvm_sequence_item variable or sequence . All the above defined 7 phases will be executed.
`uvm_do_with(item/sequence, Constraint block)
This is the same as `uvm_do except that the constraint block in the 2nd argument is applied to the item or sequence in a randomize with statement before execution.
`uvm_send(item/sequence)
Create phase and randomize phases are skipped, rest all the phases will be executed. Using `uvm_create, create phase can be executed. Essentially, an `uvm_do without the create or randomization.
`uvm_rand_send(item/sequence)
Only create phase is skipped. rest of all the phases will be executed. User should use `uvm_create to create the sequence or item.
`uvm_rand_send_with(item/sequence , Constraint block)
Only create phase is skipped. rest of all the phases will be executed. User should use `uvm_create to create the sequence or item. Constraint block will be applied which randomization.
`uvm_do_pri(item/sequence, priority )
This is the same as `uvm_do except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_do_pri_with(item/sequence , constraint block , priority)
This is the same as `uvm_do_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution.
`uvm_send_pri(item/sequence,priority)
This is the same as `uvm_send except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_rand_send_pri(item/sequence,priority)
This is the same as `uvm_rand_send except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_rand_send_pri_with(item/sequence,priority,constraint block)
This is the same as `uvm_rand_send_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution.
Following macros are used on sequence or sequence items on a different sequencer.
`uvm_create_on(item/sequence,sequencer)
This is the same as `uvm_create except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on(item/sequence,sequencer)
This is the same as `uvm_do except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on_pri(item/sequence,sequencer, priority)
This is the same as `uvm_do_pri except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on_with(item/sequence,sequencer, constraint block)
This is the same as `uvm_do_with except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument. The user must supply brackets around the constraints.
`uvm_do_on_pri_with(item/sequence,sequencer,priority,constraint block)
This is the same as `uvm_do_pri_with except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
Examples With Sequence Action Macros:
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_do",UVM_LOW);
`uvm_do(req)
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_do_with ",UVM_LOW);
`uvm_do_with(req,{ inst == ADD; })
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_create and uvm_send",UVM_LOW);
`uvm_create(req)
req.inst = instruction::PUSH_B;
`uvm_send(req)
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_create and uvm_rand_send",UVM_LOW);
`uvm_create(req)
`uvm_rand_send(req)
endtask
一般我們會用的大概就是
`uvm_do或是`uvm_do_with
其它的使用機會就少的多了
List Of Sequence Action Macros:
整理自http://testbench.in/UT_08_UVM_SEQUENCE_2.html
These macros are used to start sequences and sequence items that were either registered with a <`uvm-sequence_utils> macro or whose associated sequencer was already set using the
`uvm_create(item/sequence)
This action creates the item or sequence using the factory. Only the create phase will be executed.
`uvm_do(item/sequence)
This macro takes as an argument a uvm_sequence_item variable or sequence . All the above defined 7 phases will be executed.
`uvm_do_with(item/sequence, Constraint block)
This is the same as `uvm_do except that the constraint block in the 2nd argument is applied to the item or sequence in a randomize with statement before execution.
`uvm_send(item/sequence)
Create phase and randomize phases are skipped, rest all the phases will be executed. Using `uvm_create, create phase can be executed. Essentially, an `uvm_do without the create or randomization.
`uvm_rand_send(item/sequence)
Only create phase is skipped. rest of all the phases will be executed. User should use `uvm_create to create the sequence or item.
`uvm_rand_send_with(item/sequence , Constraint block)
Only create phase is skipped. rest of all the phases will be executed. User should use `uvm_create to create the sequence or item. Constraint block will be applied which randomization.
`uvm_do_pri(item/sequence, priority )
This is the same as `uvm_do except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_do_pri_with(item/sequence , constraint block , priority)
This is the same as `uvm_do_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution.
`uvm_send_pri(item/sequence,priority)
This is the same as `uvm_send except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_rand_send_pri(item/sequence,priority)
This is the same as `uvm_rand_send except that the sequence item or sequence is executed with the priority specified in the argument.
`uvm_rand_send_pri_with(item/sequence,priority,constraint block)
This is the same as `uvm_rand_send_pri except that the given constraint block is applied to the item or sequence in a randomize with statement before execution.
Following macros are used on sequence or sequence items on a different sequencer.
`uvm_create_on(item/sequence,sequencer)
This is the same as `uvm_create except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on(item/sequence,sequencer)
This is the same as `uvm_do except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on_pri(item/sequence,sequencer, priority)
This is the same as `uvm_do_pri except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
`uvm_do_on_with(item/sequence,sequencer, constraint block)
This is the same as `uvm_do_with except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument. The user must supply brackets around the constraints.
`uvm_do_on_pri_with(item/sequence,sequencer,priority,constraint block)
This is the same as `uvm_do_pri_with except that it also sets the parent sequence to the sequence in which the macro is invoked, and it sets the sequencer to the specified sequencer argument.
Examples With Sequence Action Macros:
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_do",UVM_LOW);
`uvm_do(req)
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_do_with ",UVM_LOW);
`uvm_do_with(req,{ inst == ADD; })
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_create and uvm_send",UVM_LOW);
`uvm_create(req)
req.inst = instruction::PUSH_B;
`uvm_send(req)
endtask
virtual task body();
uvm_report_info(get_full_name(),
"Executing Sequence Action Macro uvm_create and uvm_rand_send",UVM_LOW);
`uvm_create(req)
`uvm_rand_send(req)
endtask
UVM Sequence再了解(六)
UVM初始的三個Sequence(0,1,2)

UVM初始的三個Sequence
uvm_random_sequence :
This sequence randomly selects and executes a sequence from the sequencer sequence library, excluding uvm_random_sequence itself, and uvm_exhaustive_sequence. From the above image, from sequence id 2 to till the last sequence, all the sequences are executed randomly. If the "count" variable of the sequencer is set to 0, then non of the sequence is executed. If the "count" variable of the sequencer is set to -1, then some random number of sequences from 0 to "max_random_count" are executed. By default "max_random_count" is set to 10. "Count" and "max_random_count" can be changed using set_config_int().
The sequencer when automatically started executes the sequence which is point by default_sequence. By default default_sequence variable points to uvm_random_sequence.
uvm_exhaustive_sequence:
This sequence randomly selects and executes each sequence from the sequencers sequence library once in a randc style, excluding itself and uvm_random_sequence.
uvm_simple_sequence:
This sequence simply executes a single sequence item.
注意事項
一.
Setting the count config property, using uvm_config_int(, “count”,
) will result in a deprecation warning. This variable is only used for
controlling the string-based “default_sequence” and the built-in random
sequence, so it can safely be removed if the alternative default sequence in 1 is
used (and random sequence is not being used). A count setting of 0 may be
safely removed because the uvm_random_sequence is no longer started by default
if the user does not specify a default sequence.
二.
Message: “count config parameter is deprecated and not part of the UVM
standard"
Reason: The max_random_count configuration parameter was used in a set_config_int
call in order control the number of iterations of the uvm_random_sequence (the old
default sequence if no user default sequence was set).
Example:
function void mytest::build();
//設定uvm_random_sequence的執行數目
set_config_int(“agent.seqr”, “max_random_count”, 10);
…
endfunction
Resolution: A sequence library object should be used to generate the random
sequence; the sequence library object can be set as the run phase’s default sequence
with an appropriate setting for the number of iterations.
三.
Message: “max_random_depth config parameter is deprecated and not part of the
UVM standard"
Reason: The max_random_depth configuration parameter was used in a set_config_int
call in order control the maximum sequence depth when uvm_random_sequence is
being used (e.g. the number of times that a random sequence is itself allowed to create
a uvm_random_sequence as a sub sequence).
Example:
function void mytest::build();
set_config_int(“agent.seqr”, “max_random_depth”, 3);
…
endfunction
Resolution: A sequence library object should be used to generate the random
sequence; the sequence library object can be set as the run phase’s default sequence
with an appropriate settings to contain the subsequence depth.
UVM初始的三個Sequence
uvm_random_sequence :
This sequence randomly selects and executes a sequence from the sequencer sequence library, excluding uvm_random_sequence itself, and uvm_exhaustive_sequence. From the above image, from sequence id 2 to till the last sequence, all the sequences are executed randomly. If the "count" variable of the sequencer is set to 0, then non of the sequence is executed. If the "count" variable of the sequencer is set to -1, then some random number of sequences from 0 to "max_random_count" are executed. By default "max_random_count" is set to 10. "Count" and "max_random_count" can be changed using set_config_int().
The sequencer when automatically started executes the sequence which is point by default_sequence. By default default_sequence variable points to uvm_random_sequence.
uvm_exhaustive_sequence:
This sequence randomly selects and executes each sequence from the sequencers sequence library once in a randc style, excluding itself and uvm_random_sequence.
uvm_simple_sequence:
This sequence simply executes a single sequence item.
注意事項
一.
Setting the count config property, using uvm_config_int(
controlling the string-based “default_sequence” and the built-in random
sequence, so it can safely be removed if the alternative default sequence in 1 is
used (and random sequence is not being used). A count setting of 0 may be
safely removed because the uvm_random_sequence is no longer started by default
if the user does not specify a default sequence.
二.
Message: “count config parameter is deprecated and not part of the UVM
standard"
Reason: The max_random_count configuration parameter was used in a set_config_int
call in order control the number of iterations of the uvm_random_sequence (the old
default sequence if no user default sequence was set).
Example:
function void mytest::build();
//設定uvm_random_sequence的執行數目
set_config_int(“agent.seqr”, “max_random_count”, 10);
…
endfunction
Resolution: A sequence library object should be used to generate the random
sequence; the sequence library object can be set as the run phase’s default sequence
with an appropriate setting for the number of iterations.
三.
Message: “max_random_depth config parameter is deprecated and not part of the
UVM standard"
Reason: The max_random_depth configuration parameter was used in a set_config_int
call in order control the maximum sequence depth when uvm_random_sequence is
being used (e.g. the number of times that a random sequence is itself allowed to create
a uvm_random_sequence as a sub sequence).
Example:
function void mytest::build();
set_config_int(“agent.seqr”, “max_random_depth”, 3);
…
endfunction
Resolution: A sequence library object should be used to generate the random
sequence; the sequence library object can be set as the run phase’s default sequence
with an appropriate settings to contain the subsequence depth.
UVM Sequence再了解(五)
一個基本的sequence例子
這是從http://testbench.in/UT_07_UVM_SEQUENCE_1.html
整理出來
`include "uvm.svh"
import uvm_pkg::*;
class instruction extends uvm_sequence_item;
typedef enum {PUSH_A,PUSH_B,ADD,SUB,MUL,DIV,POP_C} inst_t;
rand inst_t inst;
`uvm_object_utils_begin(instruction)
`uvm_field_enum(inst_t,inst, UVM_ALL_ON)
`uvm_object_utils_end
function new (string name = "instruction");
super.new(name);
endfunction
endclass
class instruction_sequencer extends uvm_sequencer #(instruction);
function new (string name, uvm_component parent);
super.new(name, parent);
`uvm_update_sequence_lib_and_item(instruction)
endfunction
`uvm_sequencer_utils(instruction_sequencer)
endclass
class operation_addition extends uvm_sequence #(instruction);
instruction req;
function new(string name="operation_addition");
super.new(name);
endfunction
`uvm_sequence_utils(operation_addition, instruction_sequencer)
virtual task body();
req = instruction::type_id::create("req");
wait_for_grant();
assert(req.randomize() with {
inst == instruction::PUSH_A;
});
send_request(req);
wait_for_item_done();
//get_response(res); This is optional. Not using in this example.
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::PUSH_B;
send_request(req);
wait_for_item_done();
//get_response(res);
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::ADD;
send_request(req);
wait_for_item_done();
//get_response(res);
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::POP_C;
send_request(req);
wait_for_item_done();
//get_response(res);
endtask
endclass
class instruction_driver extends uvm_driver #(instruction);
// Provide implementations of virtual methods such as get_type_name and create
`uvm_component_utils(instruction_driver)
// Constructor
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
task run ();
forever begin
seq_item_port.get_next_item(req);
$display("%0d: Driving Instruction %s",$time,req.inst.name());
#10;
// rsp.set_id_info(req); These two steps are required only if
// seq_item_port.put(esp); responce needs to be sent back to sequence
seq_item_port.item_done();
end
endtask
endclass
module test;
instruction_sequencer sequencer;
instruction_driver driver;
initial begin
set_config_string("sequencer", "default_sequence", "operation_addition");
sequencer = new("sequencer", null);
sequencer.build();
driver = new("driver", null);
driver.build();
driver.seq_item_port.connect(sequencer.seq_item_export);
sequencer.print();
fork
begin
run_test();
sequencer.start_default_sequence();
end
#2000 global_stop_request();
join
end
endmodule
----------------------------------------------------------------------
Name Type Size Value
----------------------------------------------------------------------
sequencer instruction_sequen+ - @614
rsp_export uvm_analysis_export - @703
seq_item_export uvm_seq_item_pull_+ - @1472
default_sequence string 18 operation_addition
count integral 32 -1
max_random_count integral 32 'd10
sequences array 4 -
//這三個是原本UVM初始的三個的sequence
[0] string 19 uvm_random_sequence
[1] string 23 uvm_exhaustive_sequ+
[2] string 19 uvm_simple_sequence
[3] string 18 operation_addition
max_random_depth integral 32 'd4
num_last_reqs integral 32 'd1
num_last_rsps integral 32 'd1
----------------------------------------------------------------------
// 因為對sequence item沒有作random,所以照原本設定的出現
UVM_INFO @ 0: reporter [RNTST] Running test ...
0: Driving Instruction PUSH_A
10: Driving Instruction PUSH_B
20: Driving Instruction ADD
30: Driving Instruction POP_C
這是從http://testbench.in/UT_07_UVM_SEQUENCE_1.html
整理出來
`include "uvm.svh"
import uvm_pkg::*;
class instruction extends uvm_sequence_item;
typedef enum {PUSH_A,PUSH_B,ADD,SUB,MUL,DIV,POP_C} inst_t;
rand inst_t inst;
`uvm_object_utils_begin(instruction)
`uvm_field_enum(inst_t,inst, UVM_ALL_ON)
`uvm_object_utils_end
function new (string name = "instruction");
super.new(name);
endfunction
endclass
class instruction_sequencer extends uvm_sequencer #(instruction);
function new (string name, uvm_component parent);
super.new(name, parent);
`uvm_update_sequence_lib_and_item(instruction)
endfunction
`uvm_sequencer_utils(instruction_sequencer)
endclass
class operation_addition extends uvm_sequence #(instruction);
instruction req;
function new(string name="operation_addition");
super.new(name);
endfunction
`uvm_sequence_utils(operation_addition, instruction_sequencer)
virtual task body();
req = instruction::type_id::create("req");
wait_for_grant();
assert(req.randomize() with {
inst == instruction::PUSH_A;
});
send_request(req);
wait_for_item_done();
//get_response(res); This is optional. Not using in this example.
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::PUSH_B;
send_request(req);
wait_for_item_done();
//get_response(res);
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::ADD;
send_request(req);
wait_for_item_done();
//get_response(res);
req = instruction::type_id::create("req");
wait_for_grant();
req.inst = instruction::POP_C;
send_request(req);
wait_for_item_done();
//get_response(res);
endtask
endclass
class instruction_driver extends uvm_driver #(instruction);
// Provide implementations of virtual methods such as get_type_name and create
`uvm_component_utils(instruction_driver)
// Constructor
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction
task run ();
forever begin
seq_item_port.get_next_item(req);
$display("%0d: Driving Instruction %s",$time,req.inst.name());
#10;
// rsp.set_id_info(req); These two steps are required only if
// seq_item_port.put(esp); responce needs to be sent back to sequence
seq_item_port.item_done();
end
endtask
endclass
module test;
instruction_sequencer sequencer;
instruction_driver driver;
initial begin
set_config_string("sequencer", "default_sequence", "operation_addition");
sequencer = new("sequencer", null);
sequencer.build();
driver = new("driver", null);
driver.build();
driver.seq_item_port.connect(sequencer.seq_item_export);
sequencer.print();
fork
begin
run_test();
sequencer.start_default_sequence();
end
#2000 global_stop_request();
join
end
endmodule
----------------------------------------------------------------------
Name Type Size Value
----------------------------------------------------------------------
sequencer instruction_sequen+ - @614
rsp_export uvm_analysis_export - @703
seq_item_export uvm_seq_item_pull_+ - @1472
default_sequence string 18 operation_addition
count integral 32 -1
max_random_count integral 32 'd10
sequences array 4 -
//這三個是原本UVM初始的三個的sequence
[0] string 19 uvm_random_sequence
[1] string 23 uvm_exhaustive_sequ+
[2] string 19 uvm_simple_sequence
[3] string 18 operation_addition
max_random_depth integral 32 'd4
num_last_reqs integral 32 'd1
num_last_rsps integral 32 'd1
----------------------------------------------------------------------
// 因為對sequence item沒有作random,所以照原本設定的出現
UVM_INFO @ 0: reporter [RNTST] Running test ...
0: Driving Instruction PUSH_A
10: Driving Instruction PUSH_B
20: Driving Instruction ADD
30: Driving Instruction POP_C
2011年6月15日 星期三
UVM Sequence再了解(四)
這是從http://testbench.in/UT_08_UVM_SEQUENCE_2.html
整理出來
有些時候,比較複雜的Sequence需要用到這些function/task,
來制定特殊的流程
參考用法
virtual task pre_do(bit is_item)
virtual function void mid_do(uvm_sequence_item this_item)
virtual function void post_do(uvm_sequence_item this_item)
Sequence Action Macro參考表

至於為甚麼叫做Macro,這就要看看制定UVM時,
這種function/task的原意是甚麼
整理出來
有些時候,比較複雜的Sequence需要用到這些function/task,
來制定特殊的流程
參考用法
virtual task pre_do(bit is_item)
virtual function void mid_do(uvm_sequence_item this_item)
virtual function void post_do(uvm_sequence_item this_item)
Sequence Action Macro參考表
至於為甚麼叫做Macro,這就要看看制定UVM時,
這種function/task的原意是甚麼
2011年6月14日 星期二
UVM Sequence再了解(一)
2011年6月13日 星期一
set_inst_override_by_type與set_type_override_by_type
The set_*_overrides are utilized by a component or test to change the type of class instantiated at a lower level.
For instance, if you create a new driver class by extending a current driver class, you can replace the lower level instance when the driver is built. When the driver is built in the build phase, it asks the factory to create an instance of the driver component. Since the component has been overridden from above, the factory will instead return an instance of the new driver.
You can not change or configure the new driver, just use it in place of the original driver.
語法如下
The first component override replaces all components of the specified type with the new specified type. The prototype is.
set_type_override_by_type(orig_type, override_type, bit replace = 1);
這個set_type_override_by_type 在testcase中使用的價值,我比較看不出。
使用例請參考我前面的文章
http://kirenenko-tw.blogspot.com/2011/06/uvm-factory-usage-in.html
this method registers a factory override for components and objects created at this level of hierarchy or below. In typical usage, this method is equivalent to:
另外兩個小例子,在不同的層級,使用不同的覆載方式
set_inst_override_by_type("a.b.c", mytype::get_type(),
different_type::get_type());
set_inst_override_by_type("a.b.*", mytype::get_type(),
newtype::get_type());
For instance, if you create a new driver class by extending a current driver class, you can replace the lower level instance when the driver is built. When the driver is built in the build phase, it asks the factory to create an instance of the driver component. Since the component has been overridden from above, the factory will instead return an instance of the new driver.
You can not change or configure the new driver, just use it in place of the original driver.
語法如下
| static function void set_type_override_by_type ( | ||||
| uvm_object_wrapper | original_type, | |||
| uvm_object_wrapper | override_type, | |||
| bit | replace | = | 1 | |
| ) | ||||
The first component override replaces all components of the specified type with the new specified type. The prototype is.
set_type_override_by_type(orig_type, override_type, bit replace = 1);
這個set_type_override_by_type 在testcase中使用的價值,我比較看不出。
使用例請參考我前面的文章
http://kirenenko-tw.blogspot.com/2011/06/uvm-factory-usage-in.html
| function void set_inst_override_by_type( | string | relative_inst_path, | |
| uvm_object_wrapper | original_type, | ||
| uvm_object_wrapper | override_type | ) |
this method registers a factory override for components and objects created at this level of hierarchy or below. In typical usage, this method is equivalent to:
factory.set_inst_override_by_type({get_full_name(),".", relative_inst_path}, original_type, override_type);
實際應用
class comp extends uvm_component; `uvm_component_utils(comp)//已註冊
... endclass
class mycomp extends uvm_component;
`uvm_component_utils(mycomp)//已註冊
... endclass
class block extends uvm_component;
`uvm_component_utils(block) comp c_inst;
virtual function void build_phase(uvm_phase phase);
set_inst_override_by_type("c_inst",comp::get_type(), mycomp::get_type()); endfunction ... endclass
另外兩個小例子,在不同的層級,使用不同的覆載方式
set_inst_override_by_type("a.b.c", mytype::get_type(),
different_type::get_type());
set_inst_override_by_type("a.b.*", mytype::get_type(),
newtype::get_type());
UVM Virtual Sequences(一)
一個virtual sequence
A virtual sequence use `uvm_do_on or `uvm_do_on_with to execute sequences on any of the
subsequencers connected to the current virtual sequencer.
A virtual sequence uses `uvm_do or `uvm_do_with to execute other virtual sequences of this
sequencer. A virtual sequence cannot use `uvm_do or `uvm_do_with to execute items. Virtual sequencers do not have items associated with them, only sequences.
examle
class simple_virt_seq extends uvm_sequence;
... // Constructor and UVM automation macros
// Required to be able to use p_sequencer
`uvm_declare_p_sequencer(simple_virtual_sequencer)
// A sequence from the cpu sequencer library
cpu_config_seq conf_seq;
// A sequence from the ethernet subsequencer library
eth_large_payload_seq frame_seq;
// A virtual sequence from this sequencer's library
random_traffic_virt_seq rand_virt_seq;
virtual task body();
// Invoke a sequence in the cpu subsequencer.
`uvm_do_on(conf_seq, p_sequencer.cpu_seqr)
// Invoke a sequence in the ethernet subsequencer.
`uvm_do_on(frame_seq, p_sequencer.eth_seqr) //執行其它普通的sequence
// Invoke another virtual sequence in this sequencer.
`uvm_do(rand_virt_seq) //執行另一個virtual sequence
endtask : body
endclass : simple_virt_seq
A virtual sequence use `uvm_do_on or `uvm_do_on_with to execute sequences on any of the
subsequencers connected to the current virtual sequencer.
A virtual sequence uses `uvm_do or `uvm_do_with to execute other virtual sequences of this
sequencer. A virtual sequence cannot use `uvm_do or `uvm_do_with to execute items. Virtual sequencers do not have items associated with them, only sequences.
examle
class simple_virt_seq extends uvm_sequence;
... // Constructor and UVM automation macros
// Required to be able to use p_sequencer
`uvm_declare_p_sequencer(simple_virtual_sequencer)
// A sequence from the cpu sequencer library
cpu_config_seq conf_seq;
// A sequence from the ethernet subsequencer library
eth_large_payload_seq frame_seq;
// A virtual sequence from this sequencer's library
random_traffic_virt_seq rand_virt_seq;
virtual task body();
// Invoke a sequence in the cpu subsequencer.
`uvm_do_on(conf_seq, p_sequencer.cpu_seqr)
// Invoke a sequence in the ethernet subsequencer.
`uvm_do_on(frame_seq, p_sequencer.eth_seqr) //執行其它普通的sequence
// Invoke another virtual sequence in this sequencer.
`uvm_do(rand_virt_seq) //執行另一個virtual sequence
endtask : body
endclass : simple_virt_seq
2011年6月12日 星期日
uvm_config_db的使用(五)
uvm_config_db與uvm_resource_db的差異
uvm_config_db是繼承自uvm_resource_db
The uvm_config_db is a type-specific configuration mechanism, offering a robust facility for specifying hierarchical configuration values of desired parameters
uvm_config_db#(virtual ubus_if)::set(this,"ubus_example_tb0.*","vif",vif);
uvm_resource_db provides side-band (non-hierarchical) data sharing for general purpose
uvm_resource_db#(myobject)::set(“anyobject”, “shared_config”, data, this);
所以使用的時機在
當需要確定階程及繼承性時請使用uvm_config_db
當不需要考慮到階程性時就使用uvm_resource_db比較方便
uvm_config_db是繼承自uvm_resource_db
The uvm_config_db is a type-specific configuration mechanism, offering a robust facility for specifying hierarchical configuration values of desired parameters
uvm_config_db#(virtual ubus_if)::set(this,"ubus_example_tb0.*","vif",vif);
uvm_resource_db provides side-band (non-hierarchical) data sharing for general purpose
uvm_resource_db#(myobject)::set(“anyobject”, “shared_config”, data, this);
所以使用的時機在
當需要確定階程及繼承性時請使用uvm_config_db
當不需要考慮到階程性時就使用uvm_resource_db比較方便
uvm_config_db的使用(四)
使用在testcase上
設定master使用read_modify_write_seq sequence
slave使用slave_memory_seq sequence
uvm_config_db#(uvm_object_wrapper)::
set(this, “ubus0.masters[0].sequencer.run_phase",
"default_sequence", read_modify_write_seq::type_id::get());
uvm_config_db#(uvm_object_wrapper)::
set(this, “ubus0.slaves[0].sequencer.run_phase",
"default_sequence",slave_memory_seq::type_id::get());
設定master使用read_modify_write_seq sequence
slave使用slave_memory_seq sequence
uvm_config_db#(uvm_object_wrapper)::
set(this, “ubus0.masters[0].sequencer.run_phase",
"default_sequence", read_modify_write_seq::type_id::get());
uvm_config_db#(uvm_object_wrapper)::
set(this, “ubus0.slaves[0].sequencer.run_phase",
"default_sequence",slave_memory_seq::type_id::get());
訂閱:
文章 (Atom)



