• UVM driver和sequencer握手机制 get_next_item() 和 get() and put()


    参考链接:UVM 源码

    driver 和 sequencer 握手机制一:get_next_item():

    在这里插入图片描述

    // transaction 
    
    class my_data extends uvm_sequence_item;  // 创建自己的transaction一般是从uvm_sequence_item,而不是uvm_transaction
      	rand bit [7:0]   data;
      	rand bit [7:0]   addr;
    
    	// Rest of the class contents come here ...
    endclass
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    // driver 
    
    class my_driver extends uvm_driver #(my_data);  // my_driver被参数化为仅接受“my_data”类型的对象
    	`uvm_component_utils (my_driver)
    	
       	virtual task run_phase(uvm_phase phase);
          	super.run_phase(phase);
          
          	// 1. driver用get_next_item()从sequencer拿到item 
          	`uvm_info ("DRIVER", $sformatf ("Waiting for data from sequencer"), UVM_MEDIUM)
          	seq_item_port.get_next_item(req);
          
          	`uvm_info ("DRIVER", $sformatf ("Start driving tx addr=0x%0h data=0x%0h", req.addr, req.data), UVM_MEDIUM)
          	#20;  // 2.假设driver把接收到的数据包发给dut需要20ns
          
          	// 3. driver 调用 item_done() 让 sequencer 知道 driver 发送完 item
         	`uvm_info ("DRIVER", $sformatf ("Finish driving tx addr=0x%0h data=0x%0h", req.addr, req.data), UVM_MEDIUM)
         	seq_item_port.item_done();   // driver完成对item的处理
       endtask
       
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    // sequence
    class my_sequence extends uvm_sequence #(my_data);  // my_sequence被参数化为仅接受“my_data”类型的对象
    	`uvm_object_utils (my_sequence)
    	
      	virtual task body();
      		// 1. 在 sequence body 中实例化item: create item 
      		my_data tx = my_data::type_id::create("tx");
    	   	`uvm_info ("SEQ", $sformatf("About to call start_item"), UVM_MEDIUM)
        
        	// 2. 调用 start_item() ,将这个 item 发送给 driver 
        	start_item(tx);
        	`uvm_info ("SEQ", $sformatf("start_item() fn call done"), UVM_MEDIUM)
        
        	// 3. 因为传递给driver的类句柄指向同一个对象,可以先create再随机? 后随机
        	tx.randomize();
        	`uvm_info ("SEQ", $sformatf("tx randomized with addr=0x%0h data=0x%0h", tx.addr, tx.data), UVM_MEDIUM)
        
        	// 4. 调用 finish_item ,以便sequence等待,直到驱driver让sequencer知道该item已完成
        	finish_item(tx);
        	`uvm_info ("SEQ", $sformatf("finish_item() fn call done"), UVM_MEDIUM)
      	endtask
      
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Driver 和 Sequencer 应该在 agent 实例化,agent 在 env 中实例化,env 在 test 中实例化

    // test
    
    class base_test extends uvm_test;
    
      	my_driver                	m_drv0;
      	uvm_sequencer #(my_data) 	m_seqr0;  // sequencer 被参数化为仅接受“my_data”类型的对象
      	my_sequence   				m_seq;
    
    	// 在 build_phase 用 create 实例化 sequencer/driver 组件
      	virtual function void build_phase(uvm_phase phase);
         	super.build_phase(phase);
         	m_drv0 = my_driver::type_id::create ("m_drv0", this);
         	m_seqr0 = uvm_sequencer#(my_data)::type_id::create ("m_seqr0", this);
      	endfunction
      
       	// 在 connect_phase 连接 driver 的 port(seq_item_port) 到 sequencer 的 export(seq_item_export)
       	virtual function void connect_phase (uvm_phase phase);
         	super.connect_phase (phase);
         	m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
       	endfunction
    
    	// 在run_phase中实例化sequence;  在sequencer上启动sequence
      	virtual task run_phase(uvm_phase phase);
        	m_seq = my_sequence::type_id::create("m_seq");   // 实例化sequence
        	phase.raise_objection(this);
        	m_seq.start(m_seqr0);  // 在sequencer上启动sequence
        	phase.drop_objection(this);
      	endtask
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    - [ ] 一周掌握 Java 入门知识


    driver 和 sequencer 握手机制二: get() and put():

    在这里插入图片描述

    // transaction item 
    
    class my_data extends uvm_sequence_item;
      	rand bit [7:0]   data;
      	rand bit [7:0]   addr;
    
    	// Rest of the class contents come here ...
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // driver
    
    class my_driver extends uvm_driver #(my_data);  // driver 被参数化为仅接受“my_data”类型的对象
       `uvm_component_utils (my_driver)
    
       virtual task run_phase(uvm_phase phase);
          super.run_phase(phase);
          
          // 1.driver 使用get从sequencer拿到item,req是uvm_driver类的pre-defined变量
          `uvm_info ("DRIVER", $sformatf ("Waiting for data from sequencer"), UVM_MEDIUM)
          seq_item_port.get(req);
          
          // 2.假设的driver处理该item需要10ns
          uvm_info ("DRIVER", $sformatf ("Start driving tx addr=0x%0h data=0x%0h", req.addr, req.data), UVM_MEDIUM)
          #20;
          
          // 3. 假设 DUT 将一些读取数据返回给driver,这些数据需要发送回到sequence。 请注意,读取的数据被放入相同的request的对象句柄中
          `uvm_info ("DRIVER", $sformatf ("#20 delay over, curr data=0x%0h", req.data), UVM_MEDIUM)
          req.data = 8'hAA;  // 假设driver从dut拿到的响应数据是8'hAA
          
          // 4. driver调用put,并将响应数据发送回sequencer
          `uvm_info ("DRIVER", $sformatf ("About to call put() with new data=0x%0h", req.data), UVM_MEDIUM)
          seq_item_port.put(req);   // driver发回响应数据给sequencer
          `uvm_info ("DRIVER", $sformatf ("Finish driving tx addr=0x%0h data=0x%0h", req.addr, req.data), UVM_MEDIUM)
       endtask
       
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    // sequence
    
    class my_sequence extends uvm_sequence #(my_data);  // sequence 被参数化为仅接受“my_data”类型的对象
    
      	virtual task body();
      		// 1. 实例化item 
      		my_data tx = my_data::type_id::create("tx");
        	`uvm_info ("SEQ", $sformatf("About to call start_item"), UVM_MEDIUM)
        	
        	// 2. sequence 启动item 
        	start_item(tx);
        	`uvm_info ("SEQ", $sformatf("start_item() fn call done"), UVM_MEDIUM)
        	
        	// 3. 对item后随机 (先create再随机?)
        	tx.randomize();
        	`uvm_info ("SEQ", $sformatf("tx randomized with addr=0x%0h data=0x%0h", tx.addr, tx.data), UVM_MEDIUM)
        	
        	// 4. sequence 调用 finish_item
        	finish_item(tx);
        	`uvm_info ("SEQ", $sformatf("finish_item() fn call done, wait for rsp"), UVM_MEDIUM)
        	
        	// 阻塞型get_response会等到driver发回数据响应
        	get_response(tx);
        	`uvm_info ("SEQ", $sformatf("get_response() fn call done rsp addr=0x%0h data=0x%0h, exit seq", tx.addr, tx.data), UVM_MEDIUM)
      	endtask
      	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    // test
    
    class base_test extends uvm_test;
    
    	// sequencer 被参数化为仅接受“my_data”类型的对象
      	my_driver                	m_drv0;
      	uvm_sequencer #(my_data) 	m_seqr0;  // 使用了uvm自带的uvm_sequencer类,而没有自定义uvm_sequencer子类
      	my_sequence   				m_seq;
    
    	// 在 build_phase 用 create 实例化 sequencer/driver 组件
      	virtual function void build_phase(uvm_phase phase);
         	super.build_phase(phase);
         	m_drv0 = my_driver::type_id::create ("m_drv0", this);
         	m_seqr0 = uvm_sequencer#(my_data)::type_id::create ("m_seqr0", this);
      	endfunction
      
       	// 在 connect_phase 连接 driver 的 port(seq_item_port) 到 sequencer 的 export(seq_item_export)
       	virtual function void connect_phase (uvm_phase phase);
         	super.connect_phase (phase);
         	m_drv0.seq_item_port.connect (m_seqr0.seq_item_export);
       	endfunction
    
    	// 在run_phase中实例化sequence;  在sequencer上启动sequence
      	virtual task run_phase(uvm_phase phase);
        	m_seq = my_sequence::type_id::create("m_seq");  // 在run phase实例化sequence
        	phase.raise_objection(this);
        	m_seq.start(m_seqr0);
        	phase.drop_objection(this);
      	endtask
      	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述


    driver seq_item_port TLM端口:

    • seq_item_port.get(req)
    • seq_item_port.put(req)
    • seq_item_port.get_next_item(req)
    • seq_item_port.item_done()
    • 一个 seq_item_port 只能 connect 一个 seq_item_export
    • 可以在一个 driver 中用数组的形式定义多个 uvm_seq_item_pull_port,用来连接多个 sequencer

    get()和get_next_item()的区别在于get()中调用了item_done()函数,所以可以发现在上面的代码中,get到了transaction后并没有item_done()操作

  • 相关阅读:
    [Pandas] 按轴标签.loc VS 按数字索引.iloc
    Tempo数据分析平台,助力企业高效完成数据预处理工作
    CockroachDB集群部署
    Docker基础组件、安装启动和Docker生命周期
    Springboot毕业设计毕设作品,个人博客系统设计与实现
    电力物联网关智能通讯管理机-安科瑞黄安南
    DBCO-PEG-carboxyl COOH-PEG-DBCO 二苯并环辛炔-聚乙二醇-羧酸 羧酸修饰PEG二苯并环辛炔
    中国人民大学加拿大女王金融硕士项目——只有不断提升自己,才能立于不败之地
    记录一些 PostgreSQL问题分析思路
    最远点采样(Farthest Point Sampling,FPS)算法详解
  • 原文地址:https://blog.csdn.net/qq_40456702/article/details/126796995