日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UVM-使用start发送item,sequence

發布時間:2023/12/29 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UVM-使用start发送item,sequence 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當sequence得知自己掛載的sequencer時,他就會調用sequencer自帶的TLM端口與driver(的TLM端口)進行通信
而sequencer在這里就像一個傀儡

  • I sequence中擁有item
  • II sequence中擁有item和sequence
    • 使用start啟動sequence
    • 使用start啟動item
    • 發送item和sequence的小知識總結

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;//聲明兩個data,一個加入自動化域,一個//不加入`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:能夠實例化一個繼承于uvm_sequence_item類的類//返回值:uvm_sequence_item句柄//參數1:指明要例化的繼承于uvm_sequence_item類的類//參數2:指明這個對象即將掛載到哪個sequencer上// (m_sequencer是uvm_sequence類的一個屬// 性,當m_sequencer被掛載到某個// sequencer上時,m_sequencer會自動指向// 這個sequencer)//參數3:這個對象的名字void'($cast(req,temp));//在上一句話中由于使用create_item方法,導致//父類句柄指向子類對象//(uvm_sequence_item句柄) --> (item對象)//做個轉化使子類對象重新被子類句柄指向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發起start告知seqr,我要向driver發送item//(start會立即返回,然后執行下面的語句)//seqr判斷此時的driver是否已經get_next_item,//若否,則繼續等待。若是,那么driver收到完item//后會執行item_done,收到item_done后,//finish_item的阻塞結束//get_response(temp); //get_response返回的uvm_sequence_item是句柄,//需要做個中間轉化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);//進入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//來獲取一個對象,(get_next_item返回的是uvm_sequence_item//句柄需要類型轉換)#1us;//---------------------------------------------//--此處省略driver解析item并向interface進行驅動//---------------------------------------------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)//克隆一個上一步接收到的對象//(clone返回的居然是uvm_object的句柄,需要類型轉換)//!!clone只會克隆已經加入自動化域的屬性的值,//data_noauto不在自動化域內,在克隆時候,類聲明時候的//默認值0,而不是req的對象值50//同樣‘req’的sequence_id也不會被克隆,克隆時候得到的也//是類中的聲明初始值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’這個item所在sequence的id好//然后使用set_sequence_id把id號交給‘rsp’這個item//這樣item_done這個方法就知道要把‘rsp’這個item發送給誰//了//細節來說,item_done這個方法的作用有兩個//1是:告知seq的finish_item,你別在那阻塞了,我都消化// 掉了//2是:向seqr的rspfifo中傳遞rsp這個對象// 這樣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);//進入run_phase需要先舉手`uvm_info("test1",$sformatf("run"), UVM_LOW)seq0 = new();seq0.start(env0.seqr0);//將seq0掛載到 env0的seqr0上//一旦seq被掛載到了seqr上,那么這個seq就知道了他的m_seqencer是誰//他的body任務也會自動執行phase.drop_objection(this);//退出run_phase需要先落手endtaskendclassendpackage//--------------------------------------module--------------------------------- module hardware1;import pack1::*;import uvm_pkg::*; //+UVMinitial beginrun_test("test1"); endendmodule

II 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;//創建一個sequcence和一個item對象cseq = child_seq::type_id::create("cseq");temp = create_item(item::get_type(),m_sequencer,"req");void'($cast(req,temp));//發送sequencecseq.start(m_sequencer,this);//start任務的入口參數有4個(這里使用兩個)://參數1指定了掛載的是哪個sequencer,//(m_sequencer是什么請看第一節的代碼)//參數2是如果你start這個sequence不是最頂層的sequence,那么請你為他指定上級//發送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)//只告訴完成,不發送響應(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可以在另一個sequence內部,如 II 中的topseq 和 childseq (sequence嵌套sequence)
也可以在別的地方使用,如I 和 II 中的test

函數原型:
virtual task start (uvm_sequencer_base sequencer,

uvm_sequence_base parent_sequence = null,

int this_priority = -1,

bit call_pre_post = 1);
sequencer:指定了當前sequence要掛載的是哪個sequencer
parent_sequence :如果要start的這個sequence是個底層sequence(sequence套sequence)
就可以來為他指定parent。指定后會在這個start的過程中,調用父類的pre_do、mid_do、post_do
this_priority : 指明產生transaction的優先級,sequencer在某些條件下會根據優先級來將transaction發送給sequence。
call_pre_post :如果為1, 要啟動的這個sequence的 pre_do(), mid_do(), post_do() 將會被調用。
調用順序如下:
(sub指此sequence,parent即參數2)

使用start啟動item

啟動item的start只能在sequence中使用,

通常只使用第一個參數(想發送的item句柄)
調用順序如下:
(sequencer是該item掛載的sequencer,parent_seq是該item所在的sequence)

發送item和sequence的小知識總結

1:sequence和item都有自身的優先級,可以決定什么時刻可以獲得sequencer的授權
2:在發送item 或者在發送底層sequence的過程中,會調用上層sequence的一些方法:pre_do,mid_do,post_do,但一般情況都是讓上層的這些方法為空,不然驗證環境的可讀性會變差。
3:在發送sequence的過程中,在執行body任務的前后,還會執行pre_body()和post_body(),但這個機制可以通過將start函數的第四個參數call_pre_post置0來關閉掉。

總結

以上是生活随笔為你收集整理的UVM-使用start发送item,sequence的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。