AK_K Posted February 13, 2021 Report Posted February 13, 2021 I am facing strange issue with UVM event and threading. I have two threads waiting on one UVM_EVENT. one thread is from the same class where event is getting generated while other thread is called upper parent class. only one thread sees the event while both should see the event. i can no_of_waiters also getting 0 after event triggered and before i can see count 2. I have narrowed down actual problem to following examle code and tried at EDA playground and i dont understand why case 1 does not work. Please explain me if you have any idea. Case 1: Not working code import uvm_pkg::*; `include "uvm_macros.svh" class uvm_top_comp extends uvm_component; `uvm_component_utils(uvm_top_comp) uvm_event msg_seen; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); endfunction task wait_for_match(string sa); `uvm_info("EVENT_ORDER",$sformatf("Wait before trigger %s",sa), UVM_LOW) msg_seen.wait_trigger(); `uvm_info("EVENT_ORDER", $sformatf("wait After trigger %s",sa), UVM_LOW) endtask task message_receiver(); `uvm_info("EVENT_ORDER", $sformatf("Before trigger %0d",msg_seen.get_num_waiters()), UVM_LOW) msg_seen.trigger(); `uvm_info("EVENT_ORDER", $sformatf("After trigger %0d",msg_seen.get_num_waiters()), UVM_LOW) endtask task run_phase(uvm_phase phase); super.run(); msg_seen = new("msg_seen"); fork begin message_receiver(); end join_none wait_for_match("HI"); endtask endclass class uvm_simple_comp extends uvm_component; `uvm_component_utils(uvm_simple_comp) uvm_top_comp u_top_comp; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); u_top_comp = uvm_top_comp::type_id::create("u_top_comp", this); endfunction task s_setup(); u_top_comp.wait_for_match("Hello"); endtask task run_phase(uvm_phase phase); //nothing done here endtask endclass class uvm_top_test extends uvm_test; `uvm_component_utils(uvm_top_test) uvm_simple_comp simple_comp; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); simple_comp = uvm_simple_comp::type_id::create("simple_comp",this); endfunction task run_phase(uvm_phase phase); `uvm_info("PHASE_ORDER", $sformatf("Starting run phase for %s",get_full_name()), UVM_LOW) phase.raise_objection(this); uvm_top.print(); #100; simple_comp.s_setup(); phase.drop_objection(this); `uvm_info("PHASE_ORDER", $sformatf("Ending run phase for %s",get_full_name()), UVM_LOW) endtask endclass module test_module(); initial begin run_test("uvm_top_test"); end endmodule ---------------------- Strange is when i move my event generating method to test, both thread sees the event. what can be wrong with this ? is my expectation not right in above case that both thread should see the event ? ------------------------------------------------------------ Case 2: Working code import uvm_pkg::*; `include "uvm_macros.svh" class uvm_top_comp extends uvm_component; `uvm_component_utils(uvm_top_comp) uvm_event msg_seen; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); endfunction task wait_for_match(string sa); `uvm_info("EVENT_ORDER",$sformatf("Wait before trigger %s",sa), UVM_LOW) msg_seen.wait_trigger(); `uvm_info("EVENT_ORDER", $sformatf("wait After trigger %s",sa), UVM_LOW) endtask task message_receiver(); `uvm_info("EVENT_ORDER", $sformatf("Before trigger %0d",msg_seen.get_num_waiters()), UVM_LOW) msg_seen.trigger(); `uvm_info("EVENT_ORDER", $sformatf("After trigger %0d",msg_seen.get_num_waiters()), UVM_LOW) endtask task run_phase(uvm_phase phase); super.run(); msg_seen = new("msg_seen"); fork begin //message_receiver(); end join_none wait_for_match("HI"); endtask endclass class uvm_simple_comp extends uvm_component; `uvm_component_utils(uvm_simple_comp) uvm_top_comp u_top_comp; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); u_top_comp = uvm_top_comp::type_id::create("u_top_comp", this); endfunction task s_setup(); u_top_comp.wait_for_match("Hello"); endtask task run_phase(uvm_phase phase); //nothing done here endtask endclass class uvm_top_test extends uvm_test; `uvm_component_utils(uvm_top_test) uvm_simple_comp simple_comp; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); simple_comp = uvm_simple_comp::type_id::create("simple_comp",this); endfunction task run_phase(uvm_phase phase); `uvm_info("PHASE_ORDER", $sformatf("Starting run phase for %s",get_full_name()), UVM_LOW) phase.raise_objection(this); uvm_top.print(); #100; fork begin simple_comp.u_top_comp.message_receiver(); end join_none simple_comp.s_setup(); phase.drop_objection(this); `uvm_info("PHASE_ORDER", $sformatf("Ending run phase for %s",get_full_name()), UVM_LOW) endtask endclass module test_module(); initial begin run_test("uvm_top_test"); end endmodule Please explain in detail if you see why case 1 should not work. Quote
chr_sue Posted February 15, 2021 Report Posted February 15, 2021 Both cases do exectly what you are instructing in your code. The fatal in case 1 comes from waiting for the 2nd event which never happens. See the log-file here: UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(215) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.3 # UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(216) @ 0: reporter [Questa UVM] questa_uvm::init(+struct) # UVM_INFO @ 0: reporter [RNTST] Running test uvm_top_test... # UVM_INFO case1-uvm_event.sv(91) @ 0: uvm_test_top [uvm_top_test] Starting run phase for uvm_test_top # ---------------------------------------------- # Name Type Size Value # ---------------------------------------------- # <unnamed> uvm_root - @13 # uvm_test_top uvm_top_test - @466 # simple_comp uvm_simple_comp - @473 # u_top_comp uvm_top_comp - @480 # ---------------------------------------------- # UVM_INFO case1-uvm_event.sv(44) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] calling wait_for_match 1 # UVM_INFO case1-uvm_event.sv(20) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger HI # UVM_INFO case1-uvm_event.sv(40) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] calling message receiver task # UVM_INFO case1-uvm_event.sv(28) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger 1 # UVM_INFO case1-uvm_event.sv(30) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] After trigger 0 # UVM_INFO case1-uvm_event.sv(22) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] After trigger HI run -a # UVM_INFO case1-uvm_event.sv(64) @ 100: uvm_test_top.simple_comp [uvm_simple_comp] calling wait_for_match 2 # UVM_INFO case1-uvm_event.sv(20) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger Hello # UVM_FATAL verilog_src/uvm-1.1d/src/base/uvm_phase.svh(1251) @ 9200000000000: reporter [PH_TIMEOUT] Default timeout of 9200000000000 hit, indicating a probable testbench issue # This is caused by the topdown execution of the components in your hierarchy. case 2 looks differently: # UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(215) @ 0: reporter [Questa UVM] QUESTA_UVM-1.2.3 # UVM_INFO verilog_src/questa_uvm_pkg-1.2/src/questa_uvm_pkg.sv(216) @ 0: reporter [Questa UVM] questa_uvm::init(+struct) # UVM_INFO @ 0: reporter [RNTST] Running test uvm_top_test... # UVM_INFO case2-uvm_event.sv(135) @ 0: uvm_test_top [uvm_top_test] Starting run phase for uvm_test_top # ---------------------------------------------- # Name Type Size Value # ---------------------------------------------- # <unnamed> uvm_root - @13 # uvm_test_top uvm_top_test - @466 # simple_comp uvm_simple_comp - @473 # u_top_comp uvm_top_comp - @480 # ---------------------------------------------- # UVM_INFO case2-uvm_event.sv(67) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] calling wait_for_match 1 # UVM_INFO case2-uvm_event.sv(27) @ 0: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger HI run -a # UVM_INFO case2-uvm_event.sv(98) @ 100: uvm_test_top.simple_comp [uvm_simple_comp] calling wait_for_match 2 # UVM_INFO case2-uvm_event.sv(27) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger Hello # UVM_INFO case2-uvm_event.sv(39) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] Before trigger 2 # UVM_INFO case2-uvm_event.sv(43) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] After trigger 0 # UVM_INFO case2-uvm_event.sv(31) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] After trigger Hello # UVM_INFO case2-uvm_event.sv(157) @ 100: uvm_test_top [uvm_top_test] Ending run phase for uvm_test_top # UVM_INFO case2-uvm_event.sv(31) @ 100: uvm_test_top.simple_comp.u_top_comp [uvm_top_comp] After trigger HI # UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_objection.svh(1267) @ 100: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase case1-uvm_event.sv case2-uvm_event.sv Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.