0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

UVM中的虛擬序列:為什么,如何?

星星科技指導(dǎo)員 ? 來(lái)源:synopsys ? 作者:Hari Balisetty,Broa ? 2023-05-29 09:46 ? 次閱讀

大多數(shù)UVM測(cè)試平臺(tái)由可重復(fù)使用的驗(yàn)證組件組成,除非我們正在對(duì)像MIPI-CSI這樣的簡(jiǎn)單協(xié)議進(jìn)行塊級(jí)驗(yàn)證??紤]驗(yàn)證簡(jiǎn)單協(xié)議的場(chǎng)景;在這種情況下,我們可以忍受只有一個(gè)音序器將刺激發(fā)送給驅(qū)動(dòng)器。頂級(jí)測(cè)試將使用此序列器來(lái)處理序列(如上一篇博客文章中所述)。在這里,我們可能不需要虛擬序列(或虛擬序列器)。

但是,當(dāng)我們嘗試將此IP集成到我們的SOC(或頂級(jí)塊)中時(shí),我們肯定要考慮重用用于驗(yàn)證這些塊的測(cè)試平臺(tái)組件。讓我們考慮一個(gè)簡(jiǎn)單的案例,其中我們正在集成兩個(gè)這樣的塊:兩個(gè)音序器驅(qū)動(dòng)這兩個(gè)塊。從頂級(jí)測(cè)試來(lái)看,我們需要一種方法來(lái)控制這兩個(gè)音序器。

這可以通過(guò)使用虛擬序列器和虛擬序列來(lái)實(shí)現(xiàn)。另一種方法是通過(guò)將序列器傳遞給啟動(dòng)方法,從頂級(jí)測(cè)試顯式調(diào)用序列的啟動(dòng)方法。

我將通過(guò)一個(gè)例子來(lái)解釋這種用法,其中 USB 主機(jī)集成在 AXI 環(huán)境中。讓我們看看如何從頂級(jí)測(cè)試中控制USB音序器和AXI音序器。對(duì)于此特定測(cè)試,我想配置 AXI 寄存器,然后發(fā)送 USB 傳輸。對(duì)于配置 AXI 寄存器,我使用序列說(shuō)axi_cfg_reg_sequence,對(duì)于發(fā)送 USB 傳輸,我使用我在上一篇博客文章中使用的序列 (usb_complex_sequence)。下面是一個(gè)示例,其中在不使用虛擬序列的情況下控制多個(gè)序列器。

//Top-level test where multiple sequencers are controlled from the
//phase method.
class axi_cfg_usb_bulk_test extends uvm_test;
  `uvm_component_utils(usb_ltssm_bulk_test)

  //Sequences which needs to be exercised
  usb_reset_sequence u_reset_seq;
  axi_reset_sequence a_reset_seq;
  usb_complex_sequence u_bulk_seq;
  axi_cfg_reg_sequence a_cfg_reg_seq;

  function new (strint name=”axi_cfg_usb_bulk_test”,
                uvm_component parent=null);
    …
  endfunction: new

  //Call the reset sequences in the reset_phase
  virtual task reset_phase (uvm_phase phase);
    phase.raise_objections(this);
    …
    //Executing sequences by calling the start method directly by passing the
    //corresponding sequencer
    a_reset_seq.start(env.axi_master_agent_obj.sequencer);
    u_reset_seq.start(env.usb_host_agent_obj.sequencer);
    …
    phase.drop_objections(this);
  endtask:reset_phase

  virtual task main_phase (uvm_phase phase);
    phase.raise_objections(this);
    …
    //Executing sequences by calling the start method directly by passing the
    //corresponding sequencer
    a_cfg_reg_seq.start(env.axi_master_agent_obj.sequencer);
    u_bulk_seq.start(env.usb_host_agent_obj.sequencer);
    …
    phase.drop_objections(this);
  endtask:main_phase
endclass: axi_cfg_usb_bulk_test

這不是控制序列器的最有效方法,因?yàn)槲覀冎苯釉跍y(cè)試中使用簡(jiǎn)單的序列并使其變得復(fù)雜。通過(guò)這樣做,我們無(wú)法進(jìn)一步重用這些復(fù)雜的場(chǎng)景來(lái)開(kāi)發(fā)更復(fù)雜的場(chǎng)景。相反,如果我們嘗試創(chuàng)建一個(gè)序列并在測(cè)試中使用該序列,那么我們也可以在其他測(cè)試(或序列)中重用這些序列。此外,與在頂級(jí)測(cè)試中創(chuàng)建整個(gè)方案相比,維護(hù)和調(diào)試這些序列將更容易。

在理解了為什么我們需要虛擬序列和虛擬序列器之后,讓我們看看如何通過(guò)上面顯示的相同示例來(lái)實(shí)現(xiàn)這一點(diǎn)。

我們需要做的第一件事是創(chuàng)建一個(gè)虛擬序列器。請(qǐng)注意,虛擬序列只能與虛擬序列器關(guān)聯(lián)(但不能與非虛擬序列器關(guān)聯(lián))。虛擬排序器也像任何其他非虛擬排序器一樣派生自u(píng)vm_sequencer,但不附加到任何驅(qū)動(dòng)程序。虛擬音序器引用了我們嘗試控制的音序器。這些引用從頂部環(huán)境分配給非虛擬序列器。

//Virtual sequencer having references to non-virtual sequencers
Class system_virtual_sequencer extends uvm_sequencer;
  //References to non-virtual sequencer
  usb_sequencer usb_seqr;
  axi_sequencer axi_seqr;

  function new (string name=”usb_ltssm_bulk_test”,
                uvm_component parent=null);
    …
  endfunction: new

  `uvm_component_utils(system_virtual_sequencer)

endclass: system_virtual_sequencer

//Top level environment, where virtual sequencer’s references
//are connected to non-virtual sequencers
class system_env extends uvm_env;
  //Agents where the non-virtual sequencers are present
  usb_host_agent usb_host_agent_obj;
  axi_master_agent axi_master_agent_obj;
  //Virtual sequencer
  system_virtual_sequencer sys_vir_seqr;

  `uvm_component_utils(system_env)

  function new (string name=”system_env”, uvm_component parent=null);
   …
  endfunction: new

  function void connect_phase(uvm_phase phase);
    //Assigning the virtual sequencer’s references to non-virtual sequencers
    sys_vir_seqr.usb_seqr = usb_host_agent_obj.sequencer;
    sys_vir_seqr.axi_seqr = axi_master_agent_obj.sequencer;
  endfunction: connect_phase

endclass: system_virtual_sequencer

現(xiàn)在我們有虛擬序列器,其中包含對(duì)非虛擬序列器的引用,我們想要控制這些序列,讓我們看看如何使用虛擬序列控制這些非虛擬序列器。

虛擬序列與任何其他序列相同,但與非虛擬序列不同,它與虛擬序列器相關(guān)聯(lián),因此它需要指示它必須使用哪個(gè)非虛擬序列來(lái)執(zhí)行基礎(chǔ)序列。另請(qǐng)注意,虛擬序列只能執(zhí)行序列或其他虛擬序列,而不能執(zhí)行項(xiàng)目。使用“uvm_do_on/”uvm_do_on_with執(zhí)行非虛擬序列,使用“uvm_do/”uvm_do_with執(zhí)行其他虛擬序列。

//virtual sequence for reset operation
class axi_usb_reset_virtual_sequence extends uvm_sequence;

  `uvm_object_utils(axi_usb_reset_virtual_sequence)

  //non-virtual reset sequences
  usb_reset_sequence u_reset_seq;
  axi_reset_sequence a_reset_seq;

  function new (string name=” axi_usb_reset_virtual_sequence”,
                uvm_component parent=null);
    …
  endfunction: new

  …

  task body();
    …
    //executingnon-virtual sequence on the corresponding
    //non-virtual sequencer using `uvm_do_on
    `uvm_do_on(a_reset_seq, p_sequencer.axi_seqr)
    a_reset_seq.get_response();
    `uvm_do_on(u_reset_seq, p_sequencer.usb_seqr)
    u_reset_seq.get_response();
  endtask: body

endclass: axi_usb_reset_virtual_sequence

//virtual sequence for doing axi register configuration
//followed by USB transfer
class axi_cfg_usb_bulk_virtual_sequence extends uvm_sequence;

  `uvm_object_utils(axi_cfg_usb_bulk_virtual_sequence)
  `uvm_declare_p_sequencer(system_virtual_sequencer)

  //Re-using the non-virtual sequences
  usb_complex_sequence u_bulk_seq;
  axi_cfg_reg_sequence a_cfg_reg_seq;

  function new (string name=” axi_cfg_usb_bulk_virtual_sequence”,
                uvm_component parent=null);
    …
  endfunction: new

  task body();
    …
    //executingnon-virtual sequence on the corresponding
    //non-virtual sequencer using `uvm_do_on
    `uvm_do_on(a_cfg_reg_seq, p_sequencer.axi_seqr)
    a_cfg_req_seq.get_response();
    `uvm_do_on(u_bulk_seq, p_sequencer.usb_seqr)
    u_bulk_seq.get_response();
  endtask: body

endclass: axi_cfg_usb_bulk_virtual_sequence

在上面的虛擬序列中,我們執(zhí)行axi_cfg_reg_sequence然后執(zhí)行usb_complex_sequence?,F(xiàn)在虛擬序列和虛擬序列器已經(jīng)準(zhǔn)備就緒,讓我們看看如何從頂級(jí)測(cè)試中執(zhí)行此虛擬序列。

//virtual sequence for reset operation
class axi_usb_reset_virtual_sequence extends uvm_sequence;

  `uvm_object_utils(axi_usb_reset_virtual_sequence)

  //non-virtual reset sequences
  usb_reset_sequence u_reset_seq;
  axi_reset_sequence a_reset_seq;

  function new (string name=” axi_usb_reset_virtual_sequence”,
                uvm_component parent=null);
    …
  endfunction: new

  …

  task body();
    …
    //executingnon-virtual sequence on the corresponding
    //non-virtual sequencer using `uvm_do_on
    `uvm_do_on(a_reset_seq, p_sequencer.axi_seqr)
    a_reset_seq.get_response();
    `uvm_do_on(u_reset_seq, p_sequencer.usb_seqr)
    u_reset_seq.get_response();
  endtask: body

endclass: axi_usb_reset_virtual_sequence

//virtual sequence for doing axi register configuration
//followed by USB transfer
class axi_cfg_usb_bulk_virtual_sequence extends uvm_sequence;

  `uvm_object_utils(axi_cfg_usb_bulk_virtual_sequence)
  `uvm_declare_p_sequencer(system_virtual_sequencer)

  //Re-using the non-virtual sequences
  usb_complex_sequence u_bulk_seq;
  axi_cfg_reg_sequence a_cfg_reg_seq;

  function new (string name=” axi_cfg_usb_bulk_virtual_sequence”,
                uvm_component parent=null);
    …
  endfunction: new

  task body();
    …
    //executingnon-virtual sequence on the corresponding
    //non-virtual sequencer using `uvm_do_on
    `uvm_do_on(a_cfg_reg_seq, p_sequencer.axi_seqr)
    a_cfg_req_seq.get_response();
    `uvm_do_on(u_bulk_seq, p_sequencer.usb_seqr)
    u_bulk_seq.get_response();
  endtask: body

endclass: axi_cfg_usb_bulk_virtual_sequence

到目前為止,我們了解為什么以及如何使用虛擬序列。在使用虛擬序列和虛擬序列器時(shí),我們還應(yīng)該記住一些事情,以節(jié)省大量的調(diào)試時(shí)間。

1. 在配置序列中的變量(使用虛擬序列執(zhí)行)時(shí),我們必須使用通過(guò)虛擬序列的路徑。在上面的示例中,使用非虛擬序列器路徑在較低級(jí)別的序列中設(shè)置變量將不起作用。

uvm_config_db#(int unsigned)::set(this,“env.usb_host_agent_obj.sequencer.u_bulk_sequence”,“sequence_length”,10);

即使u_bulk_sequence在 usb_host_agent_obj.sequencer 上運(yùn)行,這也不起作用,因?yàn)榇诵蛄惺怯商摂M序列創(chuàng)建的,因此分層路徑應(yīng)來(lái)自虛擬序列,但不使用非虛擬序列器。因此,設(shè)置變量的正確方法是使用虛擬序列路徑。

uvm_config_db#(int unsigned)::set(this,“env.sys_vir_seqr.axi_cfg_usb_bulk_virtual_sequence.u_bulk_sequence”,“sequence_length”,10);

對(duì)于工廠覆蓋也是如此。例如,由于上述原因相同,下面的工廠覆蓋將不起作用。

set_inst_override_by_type(“env.usb_host_agent_obj.*”,usb_transfer_item::get_type(), cust_usb_transfer_item::get_type());

在上面的示例中,我們嘗試使用頂級(jí)測(cè)試中的新派生類型更改基礎(chǔ)序列項(xiàng)。為此,我們需要使用虛擬序列器路徑。

set_inst_override_by_type(“env.sys_vir_seqr.*”,usb_transfer_item::get_type(), cust_usb_transfer_item::get_type());

經(jīng)驗(yàn)法則是:
? 如果序列是由虛擬序列直接或間接創(chuàng)建的,則工廠覆蓋或配置中的任何分層路徑都應(yīng)使用虛擬序列器的分層路徑。
? 如果序列是由非虛擬序列創(chuàng)建的,則工廠覆蓋或配置中的任何分層路徑都應(yīng)使用非虛擬序列器的分層路徑。

2. 即使我們有虛擬序列器來(lái)控制多個(gè)序列器,在某些測(cè)試中,我們可能只需要一個(gè)序列器(例如單獨(dú)的 USB 序列器)。在這種情況下,我們必須直接使用非虛擬序列器的分層路徑(而不是虛擬序列器的引用路徑)來(lái)配置變量或工廠覆蓋。使用虛擬序列器的引用路徑將不起作用,因?yàn)榉翘摂M序列器的層次結(jié)構(gòu)不正確。

uvm_config_db#(uvm_object_wrapper)::set(this, “env.sys_vir_seqr.usb_seqr.main_phase”, “default_sequence”, usb_complex_sequence::type_id::get());

上述配置將不起作用,因?yàn)榉翘摂M序列器 (usb_seqr/usb_host_agent_obj.sequencer) 實(shí)際上是在代理中創(chuàng)建的,因此此排序器的父級(jí)是代理,而不是虛擬序列器,盡管引用在虛擬序列器中。因此,在嘗試在實(shí)際序列器中設(shè)置變量時(shí),我們不應(yīng)使用虛擬序列器路徑,而是必須使用通過(guò)代理的分層路徑(序列器的實(shí)際父級(jí))。

uvm_config_db#(uvm_object_wrapper)::set(this, “env.usb_host_agent_obj.sequencer.main_phase”, “default_sequence”, usb_complex_sequence::type_id::get());

3. 每當(dāng)我們使用虛擬音序器并希望從虛擬音序器控制非虛擬音序器時(shí),請(qǐng)確保將所有實(shí)際音序器中的default_sequence設(shè)置為 null。

uvm_config_db#(uvm_object_wrapper)::set(this, “env.usb_host_agent_obj.sequencer.main_phase”, “default_sequence”, null);
uvm_config_db#(uvm_object_wrapper)::set(this, “env.axi_master_agent_obj.sequencer.main_phase”, “default_sequence”, null);

這很重要,因?yàn)槿绻腥魏蝑efault_sequence集,那么我們的非虛擬序列器將同時(shí)運(yùn)行虛擬序列中的default_sequence和序列。要僅從虛擬序列器控制非虛擬序列器,我們需要將非虛擬序列器的default_sequence設(shè)置為 null。

我希望您發(fā)現(xiàn)這篇文章有助于理解虛擬序列并通過(guò)概述的指南節(jié)省調(diào)試時(shí)間。我相信在使用虛擬序列時(shí)會(huì)還有其他準(zhǔn)則,我們學(xué)習(xí)調(diào)試復(fù)雜環(huán)境的更難的方法;請(qǐng)與我分享任何此類準(zhǔn)則。

審核編輯:郭婷

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • UVM
    UVM
    +關(guān)注

    關(guān)注

    0

    文章

    182

    瀏覽量

    19171
  • MIPI
    +關(guān)注

    關(guān)注

    11

    文章

    310

    瀏覽量

    48630
  • 音序器
    +關(guān)注

    關(guān)注

    0

    文章

    30

    瀏覽量

    3824
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    UVM序列的創(chuàng)建和運(yùn)行及中斷服務(wù)程序?qū)崿F(xiàn)方案

    SystemVerilog通用驗(yàn)證方法(UVM)是一種生成測(cè)試和檢查結(jié)果以進(jìn)行功能驗(yàn)證的有效方法,最適合用于塊級(jí)IC或FPGA或其他“小型”系統(tǒng)。在UVM測(cè)試臺(tái)中,大多數(shù)活動(dòng)是通過(guò)編寫(xiě)序列來(lái)生
    的頭像 發(fā)表于 04-09 16:09 ?4293次閱讀
    <b class='flag-5'>UVM</b><b class='flag-5'>序列</b>的創(chuàng)建和運(yùn)行及中斷服務(wù)程序?qū)崿F(xiàn)方案

    數(shù)字IC驗(yàn)證之“什么是UVM”“UVM的特點(diǎn)”“UVM提供哪些資源”(2)連載...

    原文鏈接:https://zhuanlan.zhihu.com/p/345775995大家好,我是一哥,上章內(nèi)容主要講述兩個(gè)內(nèi)容,芯片驗(yàn)證以及驗(yàn)證計(jì)劃。那本章我們主要講述的內(nèi)容有介紹什么是uvm
    發(fā)表于 01-21 16:00

    什么是uvm?uvm的特點(diǎn)有哪些呢

    直觀的印象,就是uvm驗(yàn)證平臺(tái),它是分層的結(jié)構(gòu)。圖中的每一個(gè)巨型框都代表著平臺(tái)的一個(gè)構(gòu)成元素。這些元素呢,我們稱為平臺(tái)組建,下面來(lái)簡(jiǎn)單的分析一下。從最底層上來(lái)看,agent 包含了driver,monitor和sequencer,其中driver ,monitor
    發(fā)表于 02-14 06:46

    請(qǐng)問(wèn)一下在UVM的UVMsequences是什么意思啊

    UVM方法學(xué),UVMsequences 是壽命有限的對(duì)象。UVM sequences從uvm_sequence_item基類擴(kuò)展得到,uvm
    發(fā)表于 04-11 16:43

    如何構(gòu)建UVM寄存器模型并將寄存器模型集成到驗(yàn)證環(huán)境

    ),通常也叫寄存器模型,顧名思義就是對(duì)寄存器這個(gè)部件的建模。本文要介紹的內(nèi)容,包括對(duì)UVM寄存器模型的概述,如何構(gòu)建寄存器模型,以及如何將寄存器模型集成到驗(yàn)證環(huán)境。篇幅原因,將在下一篇文章再給出寄存器
    發(fā)表于 09-23 14:29

    談?wù)?b class='flag-5'>UVMuvm_info打印

    uvm_report_enabled(xxx),會(huì)分析傳過(guò)來(lái)的severity和id的配置verbosity要大于傳過(guò)來(lái)的verbosity,(get_report_verbosity_level(severity, id
    發(fā)表于 03-17 16:41

    UVMseq.start()和default_sequence執(zhí)行順序

      1. 問(wèn)題  假如用以下兩種方式啟動(dòng)sequence,方法1用sequence的start()方法啟動(dòng)seq1,方法2用UVM的default_sequence機(jī)制啟動(dòng)seq2。那么seq1
    發(fā)表于 04-04 17:15

    UVM的可重用序列

    眾所周知,序列由幾個(gè)數(shù)據(jù)項(xiàng)組成,它們共同構(gòu)成了一個(gè)有趣的場(chǎng)景。序列可以是分層的,從而創(chuàng)建更復(fù)雜的方案。在最簡(jiǎn)單的形式,序列應(yīng)該是 uvm_
    的頭像 發(fā)表于 05-29 09:50 ?686次閱讀

    創(chuàng)建UVM Testcase的步驟

    UVM,Testcase是一個(gè)類,它封裝了測(cè)試用例開(kāi)發(fā)者編寫(xiě)的特定激勵(lì)序列。
    的頭像 發(fā)表于 06-15 09:41 ?1606次閱讀
    創(chuàng)建<b class='flag-5'>UVM</b> Testcase的步驟

    UVMuvm_config_db機(jī)制背后的大功臣

    本次講一下UVMuvm_config_db,在UVM中提供了一個(gè)內(nèi)部數(shù)據(jù)庫(kù),可以在其中存儲(chǔ)給定名稱下的值,之后可以由其它TB組件去檢索。
    的頭像 發(fā)表于 06-20 17:28 ?1426次閱讀

    如何用Verdi查看UVM環(huán)境的變量?

    我們常用的debug UVM的方法是通過(guò)打印log實(shí)現(xiàn)。有沒(méi)有辦法像 debug RTL代碼一樣將 UVM 變量拉到波形上看呢?答案是有的,下面讓我們看看是怎么做到的。
    的頭像 發(fā)表于 06-25 16:01 ?1744次閱讀
    如何用Verdi查看<b class='flag-5'>UVM</b>環(huán)境<b class='flag-5'>中</b>的變量?

    UVMuvm_config_db機(jī)制背后的大功臣

    本次講一下UVMuvm_config_db,在UVM中提供了一個(gè)內(nèi)部數(shù)據(jù)庫(kù),可以在其中存儲(chǔ)給定名稱下的值,之后可以由其它TB組件去檢索。
    的頭像 發(fā)表于 06-29 16:57 ?1305次閱讀

    一文詳解UVM設(shè)計(jì)模式

    本篇是對(duì)UVM設(shè)計(jì)模式 ( 二 ) 參數(shù)化類、靜態(tài)變量/方法/類、單例模式、UVM_ROOT、工廠模式、UVM_FACTORY[1]單例模式的補(bǔ)充,分析靜態(tài)類的使用,
    的頭像 發(fā)表于 08-06 10:38 ?1816次閱讀
    一文詳解<b class='flag-5'>UVM</b>設(shè)計(jì)模式

    行為型設(shè)計(jì)模式在UVM的應(yīng)用

    接下來(lái)介紹行為型設(shè)計(jì)模式在UVM的應(yīng)用。
    的頭像 發(fā)表于 08-09 14:01 ?713次閱讀
    行為型設(shè)計(jì)模式在<b class='flag-5'>UVM</b><b class='flag-5'>中</b>的應(yīng)用

    UVM設(shè)計(jì)的sequence啟動(dòng)方式有哪幾種呢?

    本篇介紹UVM的sequence,這是UVM中最基礎(chǔ)的部分。對(duì)于前面介紹的uvm_callback, uvm_visitor等,很少被使用
    的頭像 發(fā)表于 08-17 10:07 ?4331次閱讀
    <b class='flag-5'>UVM</b>設(shè)計(jì)<b class='flag-5'>中</b>的sequence啟動(dòng)方式有哪幾種呢?