请教各位:UVM中如何模拟中断操作?
打算用UVM设计一个验证环境,但是DUT要求在它给出中断的时候,验证环境要识别是哪种中断,并且给出相应的响应,比如配一些寄存器或者发送一些数据包。我只是刚开始接触UVM,简单的接口的话可以实现,但是这种交互比较多的,接口又不是很标准的,完全没经验,因此,我想来问问大家,UVM有什么办法处理中断操作么?
To handle interrupts using sequences:
a)Define an interrupt handler sequence that will do the following:
Wait for the interrupt event to occur.
Grab the sequencer for exclusive access.
Execute the interrupt service operations using the proper items or sequences.
Ungrab the sequencer.
b)Start the interrupt-handler sequence in the sequencer or in the default sequence.
Example
Define an interrupt handler sequence.
// Upon an interrupt, grab the sequencer, and execute a
// read_status_seq sequence.
class interrupt_handler_seq extends uvm_sequence #(bus_transfer);
... // Constructor and UVM automation macros here
read_status_seq interrupt_clear_seq;
virtual task body();
forever begin // Initialize the sequence variables with the factory.
@p_sequencer.interrupt;
grab(p_sequencer);
`uvm_do(interrupt_clear_seq)
ungrab(p_sequencer);
end endtask : body
endclass : interrupt_handler_seq
Then, start the interrupt handler sequence in the sequencer. The example below does this in the sequencer itself at the run phase:
class my_sequncer extends uvm_sequencer;
... // Constructor and UVM automation macros here
interrupt_handler_seq interrupt_seq;
virtual task run_phase(uvm_phase phase);
interrupt_seq = interrupt_handler_seq::type_id::create("interrupt_seq");
fork
interrupt_seq.start(this);
join_none
super.run();
endtask : run
endclass : my_sequncer
那个,我想问一下,“@p_sequencer.interrupt"这个东西是需要定义的么,还是UVM自带的呀?
另外,我这边的实际情况稍微复杂一点,DUT有两种接口:apb与ahb,apb是用来配置寄存器的,而ahb是给DUT传递数据的,以前DUT没加中断的时候是先使用apb配置,然后再用ahb传递数据。现在加了中断之后,需要验证环境在接受到中断请求之后再用apb重新配置一遍寄存器,同时ahb那边的数据传输是不间断的。
这样的话,我要有三个不同的sequence,config_seq、data_seq与interrupt_seq,但是interrupt_seq就不能grap p_sequencer,只能跟config_seq抢,那,在apb_sequencer中,如何能接受到interrupt呢?也是”@apb_sequencer.interrupt"么?
恩,还有,因为这次的中断只有一种情况,因此,DUT只提供给我一个intr信号,如果有个高电平脉冲,那就是有中断了。那么我该把这个信号放入apb的interface中么,还是用其他办法?恩,反正就是apb_sequencer如何通过这个信号来识别中断的问题。
原谅我是小白呀。
解决方案:
(1)把DUT的中断port通过virtual interface连接到apb sequencer的interrupt上,
电平触发可以直接 wait(interrupt === 1'b1);
沿触发只可以直接@(posedge interrupt);
(2)要想不让apb中断ahb的现有操作,可以把apb sequencer和ahb sequencer分开。
lock和grab是排他性的
非常感谢asic_wang的指教!
我还是有些问题不大明白。以下是我目前的apb_sequencer的代码:
- class apb_master_sequencer extends uvm_sequencer #(apb_transfer);
- // Config in case it is needed by the sequencer
- apb_config cfg;
- // Provide implementations of virtual methods such as get_type_name and create
- `uvm_component_utils_begin(apb_master_sequencer)
- `uvm_field_object(cfg, UVM_DEFAULT|UVM_REFERENCE)
- `uvm_component_utils_end
- // Constructor
- function new (string name, uvm_component parent);
- super.new(name, parent);
- endfunction : new
- // UVM build_phase
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- if (cfg == null)
- if (!uvm_config_db#(apb_config)::get(this, "", "cfg", cfg))
- `uvm_warning("NOCONFIG", "apb_config not set for this component")
- endfunction : build_phase
- endclass : apb_master_sequencer
- class multiple_read_after_write_test extends base_test;
- `uvm_component_utils(multiple_read_after_write_test)
- function new(string name="multiple_read_after_write_test",uvm_component parent);
- super.new(name,parent);
- endfunction : new
- virtual function void build_phase(uvm_phase phase);
- super.build_phase(phase);
- uvm_config_db#(uvm_object_wrapper)::set(this,"demo_tb0.apb0.master.sequencer.run_phase","default_sequence",multiple_read_after_write_seq::type_id::get());
- endfunction : build_phase
- endclass : multiple_read_after_write_test
是否我应该在apb_sequencer中添加一个interrupt的变量(还是wire?)
(2)我看grab和ungrab的时候都使用了指针p_sequencer,嗯,如果只grab apb_sequencer的使用权的话,是否是应该是“grab(p_sequencer.apb_sqr)"?
另外,关于interrupt和grab的使用,我还有些一知半解,懵懵懂懂的,能否指明哪份资料里面有详细说明,我查了UVM_1.1_class_reference中没有interrupt相关的东西,而uvm_users_guide_1.1中也只有那么一点点。关于这部分我还是从头补齐比较好。
学习了
那么,(1)把DUT的中断port通过virtual interface连接到apb sequencer的interrupt上
是否我应该在apb_sequencer中添加一个interrupt的变量(还是wire?)
(2)我看grab和ungrab的时候都使用了指针p_sequencer,嗯,如果只grab apb_sequencer的使用权的话,是否是应该是“grab(p_sequencer.apb_sqr)"?
1. 感觉asic兄的意思是把interrupt相关的port,单独封装成一个virtual interface,连接/传递到sequencer,
2. p_sequencer就是启动当前sequence的seqr啊,为什么还套了一个apb_sqr,变成p_sequencer.apb_sqr? asic兄的意思大概是用两个apb_seqr,ahb_seqr来控制各自的sequence吧,那样也许需要加一个virtual_sequencer/virtual_sequence.
大家多讨论
1.我理解了,应该是这样
2.我觉得要再包一层到apb_sqr吧,因为grab是排他性的,我是要求中断进行的时候,ahb那边的数据不要间断。p_sequencer不是指向virtual sequencer的指针么,如果中断那边grab了virtual sequencer,那么ahb那里怎么办?
2 p_sequser.seqr的操作一般是用在virtual_seq里面。而我感觉grab操作一般还是放在具体sequence的body里面。其作为参数的sequencer自然就是它关联的p_sequencer,也就是它的parent sequencer
[code][/code]
传到sqr中控制,好方案,在UT中对中断的验证很有必要吗?通过直接读状态寄存器等标志位配置相关的寄存器不是也挺好吗?小白好累