27 Feb Implementing Interrupt in UVM
SoC에서 CPU가 동작 중 예외 상황이 발생하거나, 우선순위가 높아 빠르게 처리되어야 하는 작업이 발생하는 경우 interrupt를 통해 CPU에게 알려준다. CPU는 interrupt를 받으면 interrupt service routine, 즉, ISR이라고 불리는 일련의 작업을 수행하고, 해당 작업이 완료되면 다시 기존 동작으로 되돌아간다. 이러한 interrupt를 UVM에서 구현하는 방법에 대해서 알아보자.
먼저 아래의 code는 interrupt를 처리하는 ISR sequence가 없다는 가정 하에 main sequence만을 수행하는 test를 나타낸다.
task my_test::run_phase(uvm_phase phase); super.run_phase(phase); phase.raise_objection(this); if (!main_seq.randomize()) begin `uvm_fatal(get_type_name(), "randomization fail") end main_seq.start(env.agent.sequencer); phase.drop_objection(this); endtask: run_phase
Main sequence 내에서는 아래와 같이 10개의 transaction을 보내는 동작을 한다고 가정하자. 단, 구분을 쉽게 하기 위하여 main sequence에서 보내는 transaction의 data는 항상 4'hF
보다 작은 값을 갖도록 constraint를 준다.
task my_main_sequence::body(); for (int i = 0; i < n; i ++) begin start_item(req); if (!req.randomize() with { data < 4'hF; }) begin `uvm_fatal(get_name(), "randomization fail"); end `uvm_info(get_type_name(), $sformatf("data = 0x%h", req.data), UVM_MEDIUM) finish_item(req); end endtask: body
이제 test에 interrupt를 처리하기 위한 ISR sequence를 추가해보자. ISR은 main sequence가 진행되는 도중, interrupt event가 발생할 경우 동작해야 하므로 fork
–join_none
구문을 이용하여 background에서 진행되도록 한다.
task my_test::run_phase(uvm_phase phase); // ... // ISR sequence fork isr_seq.start(env.agent.sequencer); join_none // main sequence main_seq.start(env.agent.sequencer); // ... endtask: run_phase
ISR sequence는 interrupt event가 발생할 때마다 동작해야 하므로 forever
구문을 이용하여 반복할 수 있도록 하고, 반복문 내에서 interrupt event를 polling 하도록 한다. Interrupt event가 trigger 되면 3개의 transaction을 보내되, 구분을 쉽게 하기 위하여 data는 항상 4'hF
값을 갖도록 constraint를 준다.
task my_isr_sequence::body(); uvm_event e; e = uvm_event_pool::get_global("INT"); forever begin e.wait_trigger(); `uvm_info(get_type_name(), "ISR started", UVM_MEDIUM) repeat (3) begin start_item(req); if (!req.randomize() with { data == 4'hF; }) begin `uvm_fatal(get_name(), "randomization fail"); end `uvm_info(get_type_name(), $sformatf("data = 0x%h", req.data), UVM_MEDIUM) finish_item(req); end `uvm_info(get_type_name(), "ISR finished", UVM_MEDIUM) e.reset(); end endtask: body
Interrupt event를 polling 하는 부분이 구현되었으므로, 이제 interrupt event를 trigger 하는 부분을 구현해야 한다. 일반적으로 monitor가 이러한 역할을 수행하게 된다. 아래 code에서는 virtual interface를 통해 DUT의 interrupt pin을 monitor 하다가 rising edge가 detect 되면 interrupt event를 trigger 하도록 구현하고 있다.
task my_monitor::run_phase(uvm_phase phase); uvm_event e; e = uvm_event_pool::get_global("INT"); forever begin @(posedge vif.interrupt); e.trigger(); end endtask: run_phase
이제 simulation을 통해 원하는 결과가 출력되는지 확인해보자. DUT가 interrupt pin을 50 ns에 assert 한다고 가정하고, virtual interface를 임의로 control 하였음에 유의하자. Log를 보면 main sequence가 transaction을 4개까지 처리한 이후 interrupt에 의해 ISR sequence가 동작하기 시작하는 것을 확인할 수 있다. 일단 ISR 진입까지는 문제가 없는 셈이다. 하지만 그 이후의 log를 보면 ISR sequence와 main sequence가 번갈아가면서 수행되고 있다. ISR sequence는 main sequence보다 우선하여 처리가 완료되어야 하므로 아직 code 수정이 더 필요하다는 것을 알 수 있다.
UVM_INFO @ 20000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x1 UVM_INFO @ 25000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x9 UVM_INFO @ 35000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xa UVM_INFO @ 45000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x4 UVM_INFO @ 50000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] ISR started UVM_INFO @ 55000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 65000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x5 UVM_INFO @ 75000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 85000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x0 UVM_INFO @ 95000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 105000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] ISR finished UVM_INFO @ 105000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x3 UVM_INFO @ 115000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xe UVM_INFO @ 125000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x2 UVM_INFO @ 135000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xe
ISR 진입 이후 ISR sequence가 모두 처리되기 전까지 main sequence가 끼어들지 않도록 보장하기 위해서는 grab
, ungrab
method를 활용할 수 있다. Interrupt event가 detect 된 이후 grab
method를 이용해 해당 sequencer에 대한 exclusive access 권한을 획득한다. 또한 ISR sequence 처리가 완료되면 ungrab
method를 이용하여 다른 sequence가 해당 sequencer를 사용할 수 있도록 풀어준다.
task my_isr_sequence::body(); forever begin e.wait_trigger(); `uvm_info(get_type_name(), "ISR started", UVM_MEDIUM) grab(); repeat (3) begin start_item(req); if (!req.randomize() with { data == 4'hF; }) begin `uvm_fatal(get_name(), "randomization fail"); end `uvm_info(get_type_name(), $sformatf("data = 0x%h", req.data), UVM_MEDIUM) finish_item(req); end ungrab(); `uvm_info(get_type_name(), "ISR finished", UVM_MEDIUM) e.reset(); end endtask: body
다시 한 번 simulation log를 확인해보자. 이제 ISR sequence가 모두 처리된 이후 비로소 main sequence로 복귀함을 확인할 수 있다.
UVM_INFO @ 20000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x1 UVM_INFO @ 25000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x9 UVM_INFO @ 35000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xa UVM_INFO @ 45000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x4 UVM_INFO @ 50000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] ISR started UVM_INFO @ 55000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 65000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 75000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] data = 0xf UVM_INFO @ 85000: uvm_test_top.env.agent.sequencer@@isr_seq [my_isr_sequence] ISR finished UVM_INFO @ 85000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x5 UVM_INFO @ 95000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x0 UVM_INFO @ 105000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x3 UVM_INFO @ 115000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xe UVM_INFO @ 125000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0x2 UVM_INFO @ 135000: uvm_test_top.env.agent.sequencer@@main_seq [my_main_sequence] data = 0xe
참고로 grab
, ungrab
method 외에 lock
, unlock
method도 존재하는데, grab
은 sequence arbitration 시 queue의 가장 앞(front)에 해당 sequence를 위치시키는 반면 lock
은 queue의 가장 뒤(back)에 해당 sequence를 위치시키는 차이가 있다. 따라서 ISR sequence 작성 시 요구사항에 맞게 적절한 method를 사용하도록 주의해야 한다. 참고로 위 예제와 같이 ISR이 하나만 존재하는 경우는 grab
동작과 lock
동작에 차이가 없다.
마지막으로 UVM register model을 이용하여 ISR sequence를 작성하는 경우 한 가지 유의해야 할 점이 있다. write
, read
와 같은 UVM register method를 사용할 때 반드시 아래와 같이 parent
argument를 설정해야 한다는 점이다. parent
argument는 설정하지 않는 경우 기본적으로 null
값을 가지게 되고, parent sequence로부터 grab 또는 lock에 대한 status를 inherit 받을 수 없기 때문이다.
task my_isr_sequence::body(); forever begin e.wait_trigger(); grab(); regmodel.r0.write( .status(status), .value(value), .parent(this) // required! ); ungrab(); e.reset(); end endtask: body
References
Jung Ik Moon
Verification Engineer
puravive weight loss review
Posted at 17:02h, 27 FebruaryThis stage is incredible. The magnificent information uncovers the administrator’s excitement. I’m shocked and anticipate additional such astonishing presents.
puravive reviews
Posted at 11:08h, 03 MarchThis webpage is outstanding. The site owner’s passion is evident in the excellent content. I’m in awe and anticipate reading more amazing pieces like this one.
https://medium.com/@serkan.koca.1071/
Posted at 22:46h, 12 Aprilhello!,I really like your writing verry much!
proporton wwe communicate more about your
post on AOL? I require an expert in this house to solve my problem.
May be that iss you! Takong a look ahead to see you.
medium.com
Posted at 02:09h, 22 AprilExcellent website you hzve here bbut I was wondering if
you knew of anny user discussion forums that cover the same topics talked about in this article?
I’d realy like to bee a part of community where I can gget opinions from other experienced individuals that share the samke interest.
If yoou have any recommendations, pldase let me know.
Thankss a lot!