Cleaning out Your Pipes – Pipeline Debug in UVM Testbenches Rich Edelman and Neil Bulman Mentor, a Siemens Company, Fremont, CA Arm Limited, Cambridge, UK
Total Page:16
File Type:pdf, Size:1020Kb
Cleaning Out Your Pipes – Pipeline Debug in UVM Testbenches Rich Edelman and Neil Bulman Mentor, A Siemens Company, Fremont, CA Arm Limited, Cambridge, UK The Testbench $display Breakpoint Classes in the Wave Window my_transaction t; Driver The motivation and example used “I just use $display”. Don’t forget to Problem: Testbench code is doing take them all out again. something wrong. Set a breakpoint. forever begin for this paper was a sub-section of seq_item_port.get_next_item(t); an Arm® Cortex-M33, which was BP1: begin Breakpoint $stop; … `ifdef VERBOSE announced October 2016. end end $display(“Debug: %0d”, • Characteristics of the Cortex-M4 BP2: begin Transaction loop_count); Conditional if (!reset_mode && class my_transaction_t extends ...; plus TrustZone security and 3- `endif stage instruction pipeline. nreads > 10 && rand bit rw ; nwrites > 10) rand bit [31:0]addr; • Design code Fancy $display with %p $stop; rand bit [31:0]data; – 62 files, 100,000 lines of code end BP3: begin • Testbench code Using $display can be cumbersome Counted and time-consuming when printing a if ( counter++ > LIMIT) – 95 files, 12,000 lines of code $stop; complex object, list a class or an • A typical test end array. Use the %p format type. BP4: begin Instance Specific – a minute with random seeds if(get_full_name() == class base; int id; “uvm_test_top.i2...A_seq”) SCOREBOARD int x; $stop; endclass end class extended extends base; AGENT AGENT int x, y, z; Break-on-Change base b; `define STOP_ON_CHANGE(obj,name) \ AGENT DUT AGENT fork \ int my_queue[$]; forever begin \ int my_associative_array[int]; @(obj.name); \ Sequences, Threads and Classes function void print(); $stop; \ b = new(); end \ Testbench Debug $display("This = %p", this); join_none $display("B = %p", b); Data structures $display("Queue = %p", In the testbench, execute the follow • A testbench typically will use my_queue); code, which creates a “stop-on- $display("Associative = %p", many types of SystemVerilog my_associative_array); change” monitor. data structures, including endfunction dynamic arrays, associative `STOP_ON_CHANGE(this, loop_count) arrays and queues. The print() routine will print the classes (this & b), a queue and an Break-on-Change – Dynamic Array or Queue my_queue[$]; associative array. int task wait_all_q(); my_associative_array[ ]; int string forever begin my_dynamic_array[]; This ='{id:10, x:0, x:0, y:0, z:0, int int size; b:@base@10, size = all_q.size(); my_queue:'{57, 74, 40, 79, Transaction Debug wait (all_q.size() != size); • It will contain lists of lists and 87, 100, 61}, $display("size=%0d, q=%p", arrays of arrays and arrays of my_associative_array:'{0:61, all_q.size(), all_q); Use UVM Transactions or create lists. 1:100, 2:87, 3:79, if (count++ > 5) break; your own using PLI calls 4:40, 5:74, 6:57 }} • The job of the scoreboard is to end ... – keep track of history B = '{id:10, x:0} endtask – model behavior Queue='{57, 74, 40, 79, 87, 100, 61} ... Associative Array = '{0:61, 1:100, • code task run_phase(...); 2:87, 3:79, 4:40, 5:74, 6:57 } • data structures fork wait_all_q(); Coding Styles join_none ... • SystemVerilog Scoreboards Monitoring RAM Usage – Memory HOGS endtask – UVM OUTPUT FILE: Other Debug – macros Every “Push” is checked. # size=1, q='{@sequence_item_A@3} – threads Queue size > 10,000 is likely a bug. # size=2, q='{@sequence_item_A@7, @sequence_item_A@3} `define Q_PUSH_FRONT(q, item) \ – if-then-else # size=3, q='{@sequence_item_A@11, Checkpoint / Restart – case statements if (q.size() > Q_LIMIT) begin \ @sequence_item_A@7, SEARCH Better visibility ... \ @sequence_item_A@3} end \ # size=4, q='{@sequence_item_A@15, UVM Config Debug q.push_front(item); @sequence_item_A@11, • +UVM_RESOURCE_DB_TRACE • The code is usually written at a @sequence_item_A@7, “higher abstraction” level: Change the push() calls @sequence_item_A@3} • +UVM_CONFIG_DB_TRACE – pushing and popping a queue q.push_front(item) Macro Debug – comparing the items from two different queues. `Q_PUSH_FRONT(q, item). Color Highlights Contact Authors my_transaction_t transaction_h; my_transaction_t my_q[$]; Rich Edelman begin [email protected] ... Neil Bulman `Q_PUSH_FRONT(my_q, transaction_h) ... [email protected] https://en.wikipedia.org/wiki/ARM_Cortex-M end.