uvm_heartbeat example
Table of Contents
Adding uvm_heratbeat logic to the testbench
- The testbench in the below example consists of a component comp_a
- In the run phase of comp_a, a loop is running with a delay of 50
- This example shows the implementation of the uvm heartbeat, to monitor the idle condition of comp_a
———————————————–
Name Type
———————————————–
uvm_test_top basic_test
env environment
comp_a component_a
———————————————–
component_a code
Below is the complete code of component_a,
which has a loop in run_phase which raises the objection with a 50ns delay between the iterations.
*Objection is declared in the top file.
class component_a extends uvm_component; `uvm_component_utils(component_a) //--------------------------------------- // Constructor //--------------------------------------- function new(string name, uvm_component parent); super.new(name, parent); endfunction : new //--------------------------------------- // run_phase //--------------------------------------- virtual task run_phase(uvm_phase phase); phase.raise_objection(this); `uvm_info(get_type_name(),$sformatf(" [ Comp-A ] Objection raised "),UVM_LOW) for(int i=0;i<10;i++) begin //{ `uvm_info(get_type_name(),$sformatf(" [ Comp-A ] Idx-%0d raising obje objection",i),UVM_LOW) obje.raise_objection(this); #50; end //} phase.drop_objection(this); endtask : run_phase endclass : component_a
env code without a heartbeat logic
Below is the environment code without heartbeat logic.
class environment extends uvm_env; //--------------------------------------- // Components Instantiation //--------------------------------------- component_a comp_a; `uvm_component_utils(environment) //--------------------------------------- // Constructor //--------------------------------------- function new(string name, uvm_component parent); super.new(name, parent); endfunction : new //--------------------------------------- // build_phase - Create the components //--------------------------------------- function void build_phase(uvm_phase phase); super.build_phase(phase); comp_a = component_a::type_id::create("comp_a", this); endfunction : build_phase endclass : environment
env code with a heartbeat logic
Below are the steps to set up the uvm heartbeat,
Declare the heartbeat and event
The event is the event at which the heartbeat monitor looks for idleness of components
uvm_heartbeat heart_beat; uvm_event hb_event;
Create the heartbeat and event
heart_beat = new("heart_beat", this, obje); hb_event = new("hb_event");
Set the mode
This will tell the heartbeat about the active condition of the testbench
UVM_ALL_ACTIVE – all components
UVM_ONE_ACTIVE – exactly one component
UVM_ANY_ACTIVE – any component
heart_beat.set_mode(UVM_ALL_ACTIVE);
Setup the heartbeat event
heart_beat.set_heartbeat(hb_event,hb);
Add the components to be monitored
By using the add method, the component can be added for monitoring.
heart_beat.add(comp_a);
Start the heartbeat
heart_beat.start(hb_event);
Trigger the event to monitor
virtual task run_phase(uvm_phase phase); heart_beat.start(hb_event); repeat(10) begin //{ #100; `uvm_info(get_type_name(),$sformatf(" [ Env ] Triggering hb_event"),UVM_LOW) hb_event.trigger(); end //} endtask : run_phase
Complete env code,
class environment extends uvm_env; //--------------------------------------- // Components Instantiation //--------------------------------------- component_a comp_a; uvm_heartbeat heart_beat; uvm_event hb_event; `uvm_component_utils(environment) //--------------------------------------- // Constructor //--------------------------------------- function new(string name, uvm_component parent); super.new(name, parent); endfunction : new //--------------------------------------- // build_phase - Create the components //--------------------------------------- function void build_phase(uvm_phase phase); super.build_phase(phase); comp_a = component_a::type_id::create("comp_a", this); heart_beat = new("heart_beat", this, obje); hb_event = new("hb_event"); endfunction : build_phase //--------------------------------------- // Connect_phase //--------------------------------------- function void connect_phase(uvm_phase phase); uvm_component hb[$]; heart_beat.set_mode(UVM_ALL_ACTIVE); heart_beat.set_heartbeat(hb_event,hb); heart_beat.add(comp_a); endfunction : connect_phase //--------------------------------------- // run_phase //--------------------------------------- virtual task run_phase(uvm_phase phase); heart_beat.start(hb_event); repeat(10) begin //{ #100; `uvm_info(get_type_name(),$sformatf(" [ Env ] Triggering hb_event"),UVM_LOW) hb_event.trigger(); end //} endtask : run_phase endclass : environment
Simulator Output
UVM_INFO @ 0: reporter [RNTST] Running test basic_test... -------------------------------------- Name Type Size Value -------------------------------------- uvm_test_top basic_test - @1858 env environment - @1927 comp_a component_a - @1959 -------------------------------------- UVM_INFO component_a.sv(21) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Objection raised UVM_INFO component_a.sv(24) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-0 raising obje objection UVM_INFO component_a.sv(24) @ 50: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-1 raising obje objection UVM_INFO environment.sv(55) @ 100: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 100: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-2 raising obje objection UVM_INFO component_a.sv(24) @ 150: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-3 raising obje objection UVM_INFO environment.sv(55) @ 200: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 200: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-4 raising obje objection UVM_INFO component_a.sv(24) @ 250: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-5 raising obje objection UVM_INFO environment.sv(55) @ 300: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 300: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-6 raising obje objection UVM_INFO component_a.sv(24) @ 350: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-7 raising obje objection UVM_INFO environment.sv(55) @ 400: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 400: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-8 raising obje objection UVM_INFO component_a.sv(24) @ 450: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-9 raising obje objection UVM_INFO environment.sv(55) @ 500: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 500: reporter [TEST_DONE] UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 500: reporter [UVM/REPORT/SERVER]
Output Analysis
In the above simulation result, we could see that there is no FATAL message from the uvm_heartbeat, this is because the comp_a is always active between the heartbeat the event triggers.
comp_a loop delay value is 50 and the event trigger interval is 100.
So between the heartbeat event trigger, there will be one iteration of the loop.
Fatal From HeartBeat Monitor / Detecting Inactive condition of the testbench
This example is same as the previous example, the comp_a is shown as inactive to the uvm heartbeat so that the uvm heartbeat should detect the same.
As mentioned before, UVM_heartbeat watches for an activity in the comp_a and if it finds that there is no activity in the specified interval of time (between the event triggering), then uvm_heratbeat issue a fatal message which leads to the end of the simulation.
In order to make no activity within the heartbeat event triggering time, let’s make the delay of loop more than the heartbeat event triggering time.
comp_a delay modification
virtual task run_phase(uvm_phase phase); phase.raise_objection(this); `uvm_info(get_type_name(),$sformatf(" [ Comp-A ] Objection raised "),UVM_LOW) for(int i=0;i< 10;i++) begin //{ `uvm_info(get_type_name(),$sformatf(" [ Comp-A ] Idx-%0d raising obje objection",i),UVM_LOW) obje.raise_objection(this); //Variable delay #(50*i); end //} phase.drop_objection(this); endtask : run_phase
Simulator Output
UVM_INFO @ 0: reporter [RNTST] Running test basic_test... -------------------------------------- Name Type Size Value -------------------------------------- uvm_test_top basic_test - @1858 env environment - @1927 comp_a component_a - @1959 -------------------------------------- UVM_INFO component_a.sv(21) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Objection raised UVM_INFO component_a.sv(24) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-0 raising obje objection UVM_INFO component_a.sv(24) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-1 raising obje objection UVM_INFO component_a.sv(24) @ 50: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-2 raising obje objection UVM_INFO environment.sv(55) @ 100: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 150: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-3 raising obje objection UVM_INFO environment.sv(55) @ 200: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_a.sv(24) @ 300: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-4 raising obje objection UVM_INFO environment.sv(55) @ 300: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO environment.sv(55) @ 400: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_FATAL @ 400: uvm_test_top.env [HBFAIL] Did not recieve an update of obje for component uvm_test_top.env.comp_a since last event trigger at time 300 : last update time was 300 UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 400: reporter [UVM/REPORT/SERVER]
Adding multiple components to uvm_heartbeat
In the previous example, only one component comp_a is monitored by the uvm_heartbeat. In this example along with the comp_a will add one more component comp_b to the heartbeat monitor.
———————————————–
Name Type
———————————————–
uvm_test_top basic_test
env environment
comp_a component_a
comp_b component_b
———————————————–
On comparing to the previous example, the only extra code w.r.t heartbeat is adding comp_b to monitor.
By using the add method, component comp_b can be added for monitoring.
heart_beat.add(comp_b);
As there are two components, we will set the mode as any component is active,
heart_beat.set_mode(UVM_ANY_ACTIVE);
Complete env code,
class environment extends uvm_env; //--------------------------------------- // Components Instantiation //--------------------------------------- component_a comp_a; component_b comp_b; uvm_heartbeat heart_beat; uvm_event hb_event; `uvm_component_utils(environment) //--------------------------------------- // Constructor //--------------------------------------- function new(string name, uvm_component parent); super.new(name, parent); endfunction : new //--------------------------------------- // build_phase - Create the components //--------------------------------------- function void build_phase(uvm_phase phase); super.build_phase(phase); comp_a = component_a::type_id::create("comp_a", this); comp_b = component_b::type_id::create("comp_b", this); heart_beat = new("heart_beat", this, obje); hb_event = new("hb_event"); endfunction : build_phase //--------------------------------------- // Connect_phase //--------------------------------------- function void connect_phase(uvm_phase phase); uvm_component hb[$]; heart_beat.set_mode(UVM_ANY_ACTIVE); heart_beat.set_heartbeat(hb_event,hb); heart_beat.add(comp_a); heart_beat.add(comp_b); endfunction : connect_phase //--------------------------------------- // run_phase //--------------------------------------- virtual task run_phase(uvm_phase phase); heart_beat.start(hb_event); repeat(20) begin //{ #60; hb_event.trigger(); `uvm_info(get_type_name(),$sformatf(" [ Env ] Triggering hb_event"),UVM_LOW) end //} endtask : run_phase endclass : environment
Simulator Output
UVM_INFO @ 0: reporter [RNTST] Running test basic_test... -------------------------------------- Name Type Size Value -------------------------------------- uvm_test_top basic_test - @1861 env environment - @1930 comp_a component_a - @1962 comp_b component_b - @1993 -------------------------------------- UVM_INFO component_b.sv(21) @ 0: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Objection raised UVM_INFO component_b.sv(24) @ 0: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-0 raising obje objection UVM_INFO component_a.sv(21) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Objection raised UVM_INFO component_a.sv(24) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-0 raising obje objection UVM_INFO component_b.sv(24) @ 30: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-1 raising obje objection UVM_INFO component_a.sv(24) @ 50: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-1 raising obje objection UVM_INFO environment.sv(61) @ 60: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 60: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-2 raising obje objection UVM_INFO component_b.sv(24) @ 90: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-3 raising obje objection UVM_INFO component_a.sv(24) @ 100: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-2 raising obje objection UVM_INFO environment.sv(61) @ 120: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 120: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-4 raising obje objection UVM_INFO component_a.sv(24) @ 150: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-3 raising obje objection UVM_INFO component_b.sv(24) @ 150: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-5 raising obje objection UVM_INFO environment.sv(61) @ 180: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 180: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-6 raising obje objection UVM_INFO component_a.sv(24) @ 200: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-4 raising obje objection UVM_INFO component_b.sv(24) @ 210: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-7 raising obje objection UVM_INFO environment.sv(61) @ 240: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 240: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-8 raising obje objection UVM_INFO component_b.sv(24) @ 270: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-9 raising obje objection UVM_INFO environment.sv(61) @ 300: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 300: reporter [TEST_DONE] UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 300: reporter [UVM/REPORT/SERVER]
Heartbeat with All Components active mode
This example is same as the previous example, the only change is monitoring mode.
The monitoring mode is changed to monitor all the components. i.e, comp_a and comp_b if one of the components is inactive then the heartbeat will give the FATAL message.
Setting the heartbeat mode as ALL_ACTIVE.
heart_beat.set_mode(UVM_ALL_ACTIVE);
Complete env code,
class environment extends uvm_env; //--------------------------------------- // Components Instantiation //--------------------------------------- component_a comp_a; component_b comp_b; uvm_heartbeat heart_beat; uvm_event hb_event; `uvm_component_utils(environment) //--------------------------------------- // Constructor //--------------------------------------- function new(string name, uvm_component parent); super.new(name, parent); endfunction : new //--------------------------------------- // build_phase - Create the components //--------------------------------------- function void build_phase(uvm_phase phase); super.build_phase(phase); comp_a = component_a::type_id::create("comp_a", this); comp_b = component_b::type_id::create("comp_b", this); heart_beat = new("heart_beat", this, obje); hb_event = new("hb_event"); endfunction : build_phase //--------------------------------------- // Connect_phase //--------------------------------------- function void connect_phase(uvm_phase phase); uvm_component hb[$]; heart_beat.set_mode(UVM_ALL_ACTIVE); heart_beat.set_heartbeat(hb_event,hb); heart_beat.add(comp_a); heart_beat.add(comp_b); endfunction : connect_phase //--------------------------------------- // run_phase //--------------------------------------- virtual task run_phase(uvm_phase phase); heart_beat.start(hb_event); repeat(20) begin //{ #60; hb_event.trigger(); `uvm_info(get_type_name(),$sformatf(" [ Env ] Triggering hb_event"),UVM_LOW) end //} endtask : run_phase endclass : environment
Simulator Output
UVM_INFO @ 0: reporter [RNTST] Running test basic_test... -------------------------------------- Name Type Size Value -------------------------------------- uvm_test_top basic_test - @1861 env environment - @1930 comp_a component_a - @1962 comp_b component_b - @1993 -------------------------------------- UVM_INFO component_b.sv(21) @ 0: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Objection raised UVM_INFO component_b.sv(24) @ 0: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-0 raising obje objection UVM_INFO component_a.sv(21) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Objection raised UVM_INFO component_a.sv(24) @ 0: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-0 raising obje objection UVM_INFO component_b.sv(24) @ 30: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-1 raising obje objection UVM_INFO component_a.sv(24) @ 50: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-1 raising obje objection UVM_INFO environment.sv(61) @ 60: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 60: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-2 raising obje objection UVM_INFO component_b.sv(24) @ 90: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-3 raising obje objection UVM_INFO component_a.sv(24) @ 100: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-2 raising obje objection UVM_INFO environment.sv(61) @ 120: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 120: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-4 raising obje objection UVM_INFO component_a.sv(24) @ 150: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-3 raising obje objection UVM_INFO component_b.sv(24) @ 150: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-5 raising obje objection UVM_INFO environment.sv(61) @ 180: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 180: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-6 raising obje objection UVM_INFO component_a.sv(24) @ 200: uvm_test_top.env.comp_a [component_a] [ Comp-A ] Idx-4 raising obje objection UVM_INFO component_b.sv(24) @ 210: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-7 raising obje objection UVM_INFO environment.sv(61) @ 240: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_INFO component_b.sv(24) @ 240: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-8 raising obje objection UVM_INFO component_b.sv(24) @ 270: uvm_test_top.env.comp_b [component_b] [ Comp-B ] Idx-9 raising obje objection UVM_INFO environment.sv(61) @ 300: uvm_test_top.env [environment] [ Env ] Triggering hb_event UVM_FATAL @ 300: uvm_test_top.env [HBFAIL] Did not recieve an update of obje for component uvm_test_top.env.comp_a since last event trigger at time 240 : last update time was 200 UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 300: reporter [UVM/REPORT/SERVER]