UVM-使用start发送item,sequence
當(dāng)sequence得知自己掛載的sequencer時(shí),他就會調(diào)用sequencer自帶的TLM端口與driver(的TLM端口)進(jìn)行通信
而sequencer在這里就像一個(gè)傀儡
- I sequence中擁有item
- II sequence中擁有item和sequence
- 使用start啟動sequence
- 使用start啟動item
- 發(fā)送item和sequence的小知識總結(jié)
I sequence中擁有item
package pack1; //pack1頭import uvm_pkg::*; //+UVM`include "uvm_macros.svh"//+工廠class item extends uvm_sequence_item;rand int data_auto;rand int data_noauto;//聲明兩個(gè)data,一個(gè)加入自動化域,一個(gè)//不加入`uvm_object_utils_begin(item)`uvm_field_int(data_auto,UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "item");super.new(name);endfunctionendclassclass seq extends uvm_sequence;`uvm_object_utils(seq)function new(string name = "seq");super.new(name);endfunctiontask body();uvm_sequence_item temp;item req,rsp;temp = create_item(item::get_type(),m_sequencer,"req");//create_item:能夠?qū)嵗粋€(gè)繼承于uvm_sequence_item類的類//返回值:uvm_sequence_item句柄//參數(shù)1:指明要例化的繼承于uvm_sequence_item類的類//參數(shù)2:指明這個(gè)對象即將掛載到哪個(gè)sequencer上// (m_sequencer是uvm_sequence類的一個(gè)屬// 性,當(dāng)m_sequencer被掛載到某個(gè)// sequencer上時(shí),m_sequencer會自動指向// 這個(gè)sequencer)//參數(shù)3:這個(gè)對象的名字void'($cast(req,temp));//在上一句話中由于使用create_item方法,導(dǎo)致//父類句柄指向子類對象//(uvm_sequence_item句柄) --> (item對象)//做個(gè)轉(zhuǎn)化使子類對象重新被子類句柄指向start_item(req);void'(req.randomize with{data_auto == 50;data_noauto == 50;});`uvm_info("sequence","sequence request to send item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)req.print();finish_item(req);////seq發(fā)起start告知seqr,我要向driver發(fā)送item//(start會立即返回,然后執(zhí)行下面的語句)//seqr判斷此時(shí)的driver是否已經(jīng)get_next_item,//若否,則繼續(xù)等待。若是,那么driver收到完item//后會執(zhí)行item_done,收到item_done后,//finish_item的阻塞結(jié)束//get_response(temp); //get_response返回的uvm_sequence_item是句柄,//需要做個(gè)中間轉(zhuǎn)化void'($cast(rsp,temp));`uvm_info("sequence","sequence already recive item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)req.print();endtaskendclassclass seqr extends uvm_sequencer;`uvm_component_utils(seqr)function new(string name = "seqr", uvm_component parent = null);super.new(name, parent);endfunctionendclassclass dri extends uvm_driver;`uvm_component_utils(dri)function new(string name = "dri", uvm_component parent = null);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);uvm_sequence_item temp ;uvm_object temp1;item req,rsp;phase.raise_objection(this);//進(jìn)入run_phase需要先舉手seq_item_port.get_next_item(temp);void'($cast(req,temp));`uvm_info("driver","driver already recive item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)req.print();//driver使用自帶的TLM端口,向seqr的TLM端口使用get_next_item//來獲取一個(gè)對象,(get_next_item返回的是uvm_sequence_item//句柄需要類型轉(zhuǎn)換)#1us;//---------------------------------------------//--此處省略driver解析item并向interface進(jìn)行驅(qū)動//---------------------------------------------temp1 = req.clone();void'($cast(rsp,temp1));`uvm_info("clone:data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)`uvm_info("clone:data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)//克隆一個(gè)上一步接收到的對象//(clone返回的居然是uvm_object的句柄,需要類型轉(zhuǎn)換)//!!clone只會克隆已經(jīng)加入自動化域的屬性的值,//data_noauto不在自動化域內(nèi),在克隆時(shí)候,類聲明時(shí)候的//默認(rèn)值0,而不是req的對象值50//同樣‘req’的sequence_id也不會被克隆,克隆時(shí)候得到的也//是類中的聲明初始值rsp.set_sequence_id(req.get_sequence_id());rsp.data_auto = rsp.data_auto + 100;rsp.data_noauto = rsp.data_noauto + 100;seq_item_port.item_done(rsp);//get_sequence_id用于獲取‘req’這個(gè)item所在sequence的id好//然后使用set_sequence_id把id號交給‘rsp’這個(gè)item//這樣item_done這個(gè)方法就知道要把‘rsp’這個(gè)item發(fā)送給誰//了//細(xì)節(jié)來說,item_done這個(gè)方法的作用有兩個(gè)//1是:告知seq的finish_item,你別在那阻塞了,我都消化// 掉了//2是:向seqr的rspfifo中傳遞rsp這個(gè)對象// 這樣sequence里的get_response才能得到對象// 要不然是得不到對象的`uvm_info("driver","driver already send item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)phase.drop_objection(this);//退出run_phase需要先落手endtaskendclassclass env extends uvm_env;seqr seqr0;dri dri0;`uvm_component_utils(env)function new(string name="env" ,uvm_component parent = null);super.new(name,parent);endfunction//buildphase中例化sequencer 和 driverfunction void build_phase(uvm_phase phase);seqr0 = seqr::type_id::create("seqr0",this); dri0 = dri::type_id::create("dri0",this); endfunction//connect_phase中連接sequencer和driver自帶的一組TLM端口function void connect_phase(uvm_phase phase);dri0.seq_item_port.connect(seqr0.seq_item_export);endfunctionendclassclass test1 extends uvm_test;env env0;`uvm_component_utils(test1)function new(string name = "test1", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env0 = env::type_id::create("env0",this);`uvm_info("test1",$sformatf("build"), UVM_LOW)endfunctiontask run_phase(uvm_phase phase);seq seq0;phase.raise_objection(this);//進(jìn)入run_phase需要先舉手`uvm_info("test1",$sformatf("run"), UVM_LOW)seq0 = new();seq0.start(env0.seqr0);//將seq0掛載到 env0的seqr0上//一旦seq被掛載到了seqr上,那么這個(gè)seq就知道了他的m_seqencer是誰//他的body任務(wù)也會自動執(zhí)行phase.drop_objection(this);//退出run_phase需要先落手endtaskendclassendpackage//--------------------------------------module--------------------------------- module hardware1;import pack1::*;import uvm_pkg::*; //+UVMinitial beginrun_test("test1"); endendmoduleII sequence中擁有item和sequence
package pack1; //pack1頭import uvm_pkg::*; //+UVM`include "uvm_macros.svh"//+工廠class item extends uvm_sequence_item;rand int data_auto;`uvm_object_utils_begin(item)`uvm_field_int(data_auto,UVM_ALL_ON)`uvm_object_utils_endfunction new(string name = "item");super.new(name);endfunctionendclass//底層sequenceclass child_seq extends uvm_sequence;`uvm_object_utils(child_seq)function new(string name = "child_seq");super.new(name);endfunctiontask body();uvm_sequence_item temp;item req;temp = create_item(item::get_type(),m_sequencer,"req");void'($cast(req,temp));start_item(req);void'(req.randomize with{data_auto == 99;});`uvm_info("child_seq","i want to send item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)finish_item(req);//不get responseendtaskendclass//頂層sequenceclass top_seq extends uvm_sequence;`uvm_object_utils(top_seq)function new(string name = "top_seq");super.new(name);endfunctiontask body();uvm_sequence_item temp;item req;child_seq cseq;//創(chuàng)建一個(gè)sequcence和一個(gè)item對象cseq = child_seq::type_id::create("cseq");temp = create_item(item::get_type(),m_sequencer,"req");void'($cast(req,temp));//發(fā)送sequencecseq.start(m_sequencer,this);//start任務(wù)的入口參數(shù)有4個(gè)(這里使用兩個(gè))://參數(shù)1指定了掛載的是哪個(gè)sequencer,//(m_sequencer是什么請看第一節(jié)的代碼)//參數(shù)2是如果你start這個(gè)sequence不是最頂層的sequence,那么請你為他指定上級//發(fā)送itemstart_item(req);void'(req.randomize with{data_auto == 66;});`uvm_info("top_seq","i want to send item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)finish_item(req);//不get responceendtaskendclassclass seqr extends uvm_sequencer;`uvm_component_utils(seqr)function new(string name = "seqr", uvm_component parent = null);super.new(name, parent);endfunctionendclassclass dri extends uvm_driver;`uvm_component_utils(dri)function new(string name = "dri", uvm_component parent = null);super.new(name, parent);endfunctiontask run_phase(uvm_phase phase);uvm_sequence_item temp ;item req;forever beginseq_item_port.get_next_item(temp);void'($cast(req,temp));`uvm_info("driver","driver already recive item", UVM_LOW)`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)//只告訴完成,不發(fā)送響應(yīng)(response)seq_item_port.item_done();endendtaskendclassclass env extends uvm_env;seqr seqr0;dri dri0;`uvm_component_utils(env)function new(string name="env" ,uvm_component parent = null);super.new(name,parent);endfunctionfunction void build_phase(uvm_phase phase);seqr0 = seqr::type_id::create("seqr0",this); dri0 = dri::type_id::create("dri0",this); endfunctionfunction void connect_phase(uvm_phase phase);dri0.seq_item_port.connect(seqr0.seq_item_export);endfunctionendclassclass test1 extends uvm_test;env env0;`uvm_component_utils(test1)function new(string name = "test1", uvm_component parent = null);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);env0 = env::type_id::create("env0",this);`uvm_info("test1",$sformatf("build"), UVM_LOW)endfunctiontask run_phase(uvm_phase phase);top_seq seq0;phase.raise_objection(this);`uvm_info("test1",$sformatf("run"), UVM_LOW)seq0 = new();seq0.start(env0.seqr0);phase.drop_objection(this);//退出run_phase需要先落手endtaskendclassendpackage//--------------------------------------module--------------------------------- module hardware1;import pack1::*;import uvm_pkg::*; //+UVMinitial beginrun_test("test1"); endendmodule使用start啟動sequence
啟動sequence的start可以在另一個(gè)sequence內(nèi)部,如 II 中的topseq 和 childseq (sequence嵌套sequence)
也可以在別的地方使用,如I 和 II 中的test
函數(shù)原型:
virtual task start (uvm_sequencer_base sequencer,
uvm_sequence_base parent_sequence = null,
int this_priority = -1,
bit call_pre_post = 1);
sequencer:指定了當(dāng)前sequence要掛載的是哪個(gè)sequencer
parent_sequence :如果要start的這個(gè)sequence是個(gè)底層sequence(sequence套sequence)
就可以來為他指定parent。指定后會在這個(gè)start的過程中,調(diào)用父類的pre_do、mid_do、post_do
this_priority : 指明產(chǎn)生transaction的優(yōu)先級,sequencer在某些條件下會根據(jù)優(yōu)先級來將transaction發(fā)送給sequence。
call_pre_post :如果為1, 要啟動的這個(gè)sequence的 pre_do(), mid_do(), post_do() 將會被調(diào)用。
調(diào)用順序如下:
(sub指此sequence,parent即參數(shù)2)
使用start啟動item
啟動item的start只能在sequence中使用,
通常只使用第一個(gè)參數(shù)(想發(fā)送的item句柄)
調(diào)用順序如下:
(sequencer是該item掛載的sequencer,parent_seq是該item所在的sequence)
發(fā)送item和sequence的小知識總結(jié)
1:sequence和item都有自身的優(yōu)先級,可以決定什么時(shí)刻可以獲得sequencer的授權(quán)
2:在發(fā)送item 或者在發(fā)送底層sequence的過程中,會調(diào)用上層sequence的一些方法:pre_do,mid_do,post_do,但一般情況都是讓上層的這些方法為空,不然驗(yàn)證環(huán)境的可讀性會變差。
3:在發(fā)送sequence的過程中,在執(zhí)行body任務(wù)的前后,還會執(zhí)行pre_body()和post_body(),但這個(gè)機(jī)制可以通過將start函數(shù)的第四個(gè)參數(shù)call_pre_post置0來關(guān)閉掉。
總結(jié)
以上是生活随笔為你收集整理的UVM-使用start发送item,sequence的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序中自定义函数的学习使用
- 下一篇: 配置AutoFac(IOC容器)