原文地址:uvm sequence 几种用法总结http://blog.sina.com.cn/s/blog_8de2be440101dboj.html作者:myshitshit
sequence用来描述发送到agent上的数据流,是写test的关键,以下是几种常见用法。
1 一般的可配置sequence
task body;
ex_seq_item item = ex_seq_item::type_id::create("item");
start_item(item);
// Randomize with shaped data
if(!item.randomize() with {addr == local::addr;
rnw == local::rnw;
length == local::length;})
。。。。。
可以根据需求改变其中的几个变量。
2 由config配置的sequence
task body;
ex_seq_item item = ex_seq_item::type_id::create("item");
//
Item constrained to be within protocol subset
// Driver supports the whole protocol
start_item(item);
if(!item.randomize() with
{addr == start_addr;
wdata == wdata;
rnw == rnw;
// Protocol subset constraints
burst_length inside
{cfg.burst_length};
valid_bursts inside {cfg.valid_bursts};
// ... Other protocol subset constraints
protection inside {cfg.prot};
}
)
.。。。。。
这种sequence的配置数据放在一个config中,方便统一调度。
3. 由config_db配置的sequence
task body;
if(!uvm_config_db #(env_config)::get(m_sequencer, "",
"env_config", cfg))
。。。。
rm = cfg.rm
rm.cfg.write(status, 32'hdeadbeef,.parent(this));
这种一般用来实现reg读写的sequence,因为reg model只能用config_db与seqeucne互动
4. Virtual Sequence
task body;
// Sub sequences:
t1_setup setup_1 = t1_setup::type_id::create("setup_1");
t3_setup setup_3 = t3_setup::type_id::create("setup_3");
t2_slave slave_2 = t2_slave::type_id::create("slave_2");
t
1_t2_transfer t1_t2 =
t1_t2_transfer::type_id::create("t1_t2");
t2_t3_transfer t2_t3 =
t2_t3_transfer::type_id::create("t2_t3");
setup_1.rm = rm;
setup_2.rm = rm;
slave_2.rm = rm;
t1_t2.rm = rm;
t2_t3.rm = rm;
fork
t1_setup.start(t1);
t3_setup.start(t3);
join
fork
slave_2.start(t2);
begin
t1_t2.start(t1);
t2_t3.start(t3);
end
join_any;
endtask: body
这种用的最多,为了一个sequence可以管控多个子sequence在不同接口操作。
5. Hierarchical层次化 Sequence
class write_burst_16 extends bus_base;
。。。
class setup_ch1 extends bus_base;
task body;
single_write write =
single_write::type_id::crea
te("write");
write_burst_16 write_16 =
write_burst_16::type_id::create("write_16");
write.addr = `BUFFER1_START;
write.data[0] = addr;
write.start(m_sequencer);
write_16.addr = addr;
write
_16
.start(m_sequenc
er);
// ...
endtask: body
这种实现一个接口上复杂seq由简单seq连接起来。
6. Sequence Library
class bus_seq_library
extends bus_seq_base;
`uvm_object_utils(bus_seq_library)
// Associative array of sequences, indexed by string
bus_seq_base lib[string];
bus_seq_base sel_seq;
string sel;
task body
lib["read_burst"] =
read_burst_seq::type_id::create("read_burst");
lib["write_burst"] =
write_burst_seq::type_id::create("write_burst");
lib["read_mod_write"] =
r
ead_modify_write_s
eq::type_id::create("read_mod
_write");
lib["write_ch
k_read"] =
write_check_read_
seq::type_id::create("write_ch
k_read");
lib["rea
d_block"] =
read_block_seq::type_id::create("read_block");
lib["write_block"] =
write_block_seq::type_id::create("write_block");
// Choose a sequence at random by shuffling the array:
lib.shuffle();
// Take the sequence at the top of the pil
e and start
sel_seq = lib.first(sel);
sel_seq.start(m_sequencer);
endtask: body
这个实现从一系列seq中任意选取一个运行,可以用来做seq顺序的随机化
7. Layering Sequence 层次化seq
把高层次protocal映射到底层protocal,不同于5.需要seq convert
class layering_sequence extends uvm_sequence #(usb_item);
`uvm_object_utils(layering_sequence)
// Upper
-
layer seq
uencer handle:
uvm_sequencer #(audio_item) voice_sequencer;
// Get a audio_item
, start a usb_item
// Translate the audio_item to the usb_item
// finish the usb_item
// Call item_done() on the audio_item
task body;
audio_item voc;
usb_item usb = usb_
item::type_id::create("usb");
forever begin
voice_sequencer.get_next_item(voc);
start_item(usb);
convert_voc_2_usb(usb, voc);
finish_item(usb);
voice_sequencer.item_done();
end
endtask body;
endclass: layering_sequence
task run_phase(uvm_phase phase);
layering_sequence audio_2_usb =
layering_sequence::type_id::create("audio_2_usb");
audio_2_usb
.voice_sequencer = audio.m_sequencer;
audio_2_usb
.start(usb._m_sequencer);
endtask: run_phase
这种转接方便做协议验证
以上源自
https://s3.amazonaws.com/verificationacademy-news/DVCon2013/Papers/MGC_DVCon_13_Seven_Separate_Sequence_Styles_Speed_Stimulus_Scenarios.pdf