• UVM sequence 3种启动方式


    start():

    在这里插入图片描述

    • sequence.strat(sequencer,parent_sequence,优先级) ,第一个参数是需要挂载的sequencer;第二个是parent_sequence,一般传入this或者不传入;第三个是优先级;第四个call_pre_post默认为1,则自动执行pre_body/ post_body()函数
    • start 执行 pre_start,body等函数。此时就完成了sequence的启动过程。
    • 所有sequence都要在sequencer中启动,当sequence启动的时候, 在sequence的 task start 内,会调用 set_item_context() 函数,在 set_item_context() 函数内,会调用 set_sequencer() 函数完成挂载,给m_sequencer赋值
    • set_sequencer 函数 会使m_sequencer 句柄指向执行当前 sequence 的 sequencer,即指向 env.vsqr
    • 如果没有指定挂载的sequencer,则挂载到parent_sequence的sequencer上

    `uvm_do() 宏:

    相比直接调用start函数,uvm_do()宏节省了sequence的实例化和随机化的步骤

    在这里插入图片描述

    uvm_do系列宏:

    在这里插入图片描述

    第一类:uvm_do类

    • uvm_do:只有一个参数,即产生的transaction
    • uvm_do_pri(ority):除了第一个参数transaction外,还有一个参数priority优先级,sequencer的仲裁机制根据transaction的优先级来进行选择。没指定优先级时默认为-1,指定时的数值是大于等于-1的整数,数字越大,优先级越高
    • uvm_do_with:第一个参数transaction,第二个参数constraints,在随机化时对transaction的某些字段进行约束
    • uvm_do_pri_with:前两者的结合

    第二类:uvm_do_on类

    • uvm_do_on:on表示展示出来,就是显式地指定产生的这个transaction具体是哪个sequencer来发送。它有两个参数,对应的就是transaction的指针和sequencer的指针。而对于uvm_do而言,它默认的sequencer就是调用uvm_do宏的这个sequence在启动时指定的sequencer

    在同一sequencer上启动多个sequence

    UVM支持同一时刻在同一sequencer上启动多个sequence,并使用sequence的仲裁机制决定发送顺序

    uvm_do 宏 设置 transaction 优先级

    • uvm_do 或 uvm_do_with 宏时,产生的 transaction 优先级是默认的优先级(即1)。可通过 uvm_do_pri 及uvm_do_pri_with 改变所产生的 transaction 的优先级
    • uvm_do_pri 与 uvm_do_pri_with 的第二个参数是优先级,其数值必须是一个大于等于-1的整数。数字越大优先级越高
    • 要使优先级起作用,应设置 sqr 为 SEQ_ARB_STRICT_FIFO 或 SEQ_ARB_STRICT_RANDOM

    sequencer的仲裁算法:

    • SEQ_ARB_FIFO 默认算法,按照“先入先出”的顺序,不考虑优先级
      SEQ_ARB_WEIGHTED 加权的仲裁
      SEQ_ARB_RANDOM 完全随机选择
      SEQ_ARB_STRICT_FIFO 严格按照优先级,同一优先级的sequence按先入先出的顺序
      SEQ_ARB_STRICT_RANDOM 严格按照优先级,同一优先级的sequence随机从最高优先级中选择
      SEQ_ARB_USER 用户可以自定义
    // sequence
    
    class sequence0 extends uvm_sequence #(my_transaction);
    	...
    	virtual task body();
    		...
    		repeat (5) begin
    			`uvm_do_pri(m_trans, 100)  // 设置优先级为100
    			`uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
    	end
    	#100;
    	...
    	endtask
    	...
    endclass
    
    class sequence1 extends uvm_sequence #(my_transaction);
    	...
    	virtual task body();
    		...
    		repeat (5) begin
    			`uvm_do_pri_with(m_trans, 200, {m_trans.pload.size < 500;})  // 设置优先级为200
    			`uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
    		end
    		...
    	endtask
    	...
    endclass
    
    // case
    
    task my_case0::main_phase(uvm_phase phase);
    	sequence0 seq0;
    	sequence1 seq1;
    	seq0 = new("seq0");
    	seq0.starting_phase = phase;
    	seq1 = new("seq1");
    	seq1.starting_phase = phase
    	
    	env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);  // 启动优先级配置
    	
    	fork
    		seq0.start(env.i_agt.sqr);
    		seq1.start(env.i_agt.sqr);
    	join
    endtask
    
    

    seq.start(sqr) 设置 sequence 优先级

    sequence启动时指定其优先级

     task my_case0::main_phase(uvm_phase phase);
    	... 
    	
    	env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);   // 启动优先级配置
    	
    	fork
    		seq0.start(env.i_agt.sqr, null, 100);  // 第一个参数是sequencer,第二个参数是parent sequence(可设为null),第三个参数是优先级,不指定则此值为-1,不能设置为小于-1的数字。
    		seq1.start(env.i_agt.sqr, null, 200);
    	join
    endtask
    
    

    default_sequence:

    test中将sequence通过config_db机制set到相应的sequencer(virtual sequencer)的main_phase中

    在build_phase中将某个sequence配置成某个sequencer的动态运行的phase中(如main_phase)的default_sequence, 那么在仿真执行到main_phase的时候,squencer的default_sequence就会启动

    实际上default_sequence会调用start任务,有两种调用方式:

    // 方式一
    
    function void my_case0::build_phase(uvm_phase phase);
    	super.build_phase(phase);
    	`uvm_config_db#(ubm_object_wrapper)::set(this,  // 第一个参数是指定seqr的路径        
    										 "env.in_agent.sqr.main_phase",  // 第二个参数是指定要执行的phase阶段
    					  					 "default_sequence",  // 第三个参数是指定你的seq
    										 sequence_base::type_id::get());  // uvm_config_db设置default_sequencer
    endfunction
    
    // 方式二
    
    function void my_case0::build_phase(uvm_phase phase);
       case0_sequence cseq;                                              //
       super.build_phase(phase);
       cseq = new("cseq");                                               //
       uvm_config_db#(uvm_sequence_base)::set(this,                      //
                                             "env.i_agt.sqr.main_phase", //
                                             "default_sequence",         //
                                              cseq);                     //
    endfunction
    

    start_item/finish_item封装函数以及sequence,sequencer,driver的握手关系如下图:

    在这里插入图片描述


  • 相关阅读:
    个人云服务器已经被安全合规等卡脖子 建议不要买 买了必定后悔 安全是个大问题 没有能力维护
    是机遇还是挑战?AI 2022五大预测
    Date对象
    debian 9 ssh root权限登录
    (生物信息学)R语言绘图初级——3-5分文章必备——小提琴图
    延迟队列实现订单超时自动取消
    C++入门学习笔记
    tsconfig编译属性isolatedModules的作用
    营销文案的“瑞士军刀”:阿里妈妈智能文案多模态、多场景探索
    针对公网IP签发的IP地址SSL证书
  • 原文地址:https://blog.csdn.net/qq_40456702/article/details/126922927