sequence,sequencer的使用(完整的uvm验证平台)
资料来源
(1) 《The UVM Primer》第23章
1.top.sv
1 module top; 2 import uvm_pkg::*; 3 import tinyalu_pkg::*; 4 `include "tinyalu_macros.svh" 5 `include "uvm_macros.svh" 6 7 tinyalu_bfm bfm(); 8 tinyalu DUT (.A(bfm.A), .B(bfm.B), .op(bfm.op), 9 .clk(bfm.clk), .reset_n(bfm.reset_n), 10 .start(bfm.start), .done(bfm.done), .result(bfm.result)); 11 12 13 initial begin 14 uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm); 15 run_test(); 16 end 17 18 endmodule : top
2.tinyalu_bfm.sv
1 interface tinyalu_bfm; 2 import tinyalu_pkg::*; 3 4 byte unsigned A; 5 byte unsigned B; 6 bit clk; 7 bit reset_n; 8 wire [2:0] op; 9 bit start; 10 wire done; 11 wire [15:0] result; 12 operation_t op_set; 13 14 15 assign op = op_set; 16 17 task reset_alu(); 18 reset_n = 1'b0; 19 @(negedge clk); 20 @(negedge clk); 21 reset_n = 1'b1; 22 start = 1'b0; 23 endtask : reset_alu 24 25 26 27 task send_op(input byte iA, input byte iB, input operation_t iop, output shortint alu_result); 28 if (iop == rst_op) begin 29 @(posedge clk); 30 reset_n = 1'b0; 31 start = 1'b0; 32 @(posedge clk); 33 #1; 34 reset_n = 1'b1; 35 end else begin 36 @(negedge clk); 37 op_set = iop; 38 A = iA; 39 B = iB; 40 start = 1'b1; 41 if (iop == no_op) begin 42 @(posedge clk); 43 #1; 44 start = 1'b0; 45 end else begin 46 do 47 @(negedge clk); 48 while (done == 0); 49 alu_result = result; 50 start = 1'b0; 51 end 52 end // else: !if(iop == rst_op) 53 54 endtask : send_op 55 56 command_monitor command_monitor_h; 57 58 function operation_t op2enum(); 59 case(op) 60 3'b000 : return no_op; 61 3'b001 : return add_op; 62 3'b010 : return and_op; 63 3'b011 : return xor_op; 64 3'b100 : return mul_op; 65 default : $fatal("Illegal operation on op bus"); 66 endcase // case (op) 67 endfunction : op2enum 68 69 70 always @(posedge clk) begin : op_monitor 71 static bit in_command = 0; 72 if (start) begin : start_high 73 if (!in_command) begin : new_command 74 command_monitor_h.write_to_monitor(A, B, op2enum()); 75 in_command = (op2enum() != no_op); 76 end : new_command 77 end : start_high 78 else // start low 79 in_command = 0; 80 end : op_monitor 81 82 always @(negedge reset_n) begin : rst_monitor 83 if (command_monitor_h != null) //guard against VCS time 0 negedge 84 command_monitor_h.write_to_monitor($random,0,rst_op); 85 end : rst_monitor 86 87 result_monitor result_monitor_h; 88 89 initial begin : result_monitor_thread 90 forever begin : result_monitor_block 91 @(posedge clk) ; 92 if (done) 93 result_monitor_h.write_to_monitor(result); 94 end : result_monitor_block 95 end : result_monitor_thread 96 97 98 initial begin 99 clk = 0; 100 fork 101 forever begin 102 #10; 103 clk = ~clk; 104 end 105 join_none 106 end 107 108 109 endinterface : tinyalu_bfm
3.tinyalu_pkg.sv
1 package tinyalu_pkg; 2 import uvm_pkg::*; 3 `include "uvm_macros.svh" 4 5 typedef enum bit[2:0] { 6 no_op = 3'b000, 7 add_op = 3'b001, 8 and_op = 3'b010, 9 xor_op = 3'b011, 10 mul_op = 3'b100, 11 rst_op = 3'b111} operation_t; 12 13 `include "sequence_item.svh" 14 typedef uvm_sequencer #(sequence_item) sequencer; 15 16 `include "add_sequence_item.svh" 17 `include "random_sequence.svh" 18 `include "maxmult_sequence.svh" 19 `include "reset_sequence.svh" 20 `include "runall_sequence.svh" 21 `include "add_sequence.svh" 22 `include "fibonacci_sequence.svh" 23 `include "short_random_sequence.svh" 24 25 26 `include "result_transaction.svh" 27 `include "coverage.svh" 28 `include "scoreboard.svh" 29 `include "driver.svh" 30 `include "command_monitor.svh" 31 `include "result_monitor.svh" 32 33 `include "env.svh" 34 `include "parallel_sequence.svh" 35 36 `include "tinyalu_base_test.svh" 37 `include "full_test.svh" 38 `include "fibonacci_test.svh" 39 `include "parallel_test.svh" 40 41 42 43 44 45 endpackage : tinyalu_pkg
4.sequence_item.svh
1 class sequence_item extends uvm_sequence_item; 2 `uvm_object_utils(sequence_item); 3 4 function new(string name = ""); 5 super.new(name); 6 endfunction : new 7 8 rand byte unsigned A; 9 rand byte unsigned B; 10 rand operation_t op; 11 shortint unsigned result; 12 13 constraint op_con {op dist {no_op := 1, add_op := 5, and_op:=5, 14 xor_op:=5,mul_op:=5, rst_op:=1};} 15 16 constraint data { A dist {8'h00:=1, [8'h01 : 8'hFE]:=1, 8'hFF:=1}; 17 B dist {8'h00:=1, [8'h01 : 8'hFE]:=1, 8'hFF:=1};} 18 19 function bit do_compare(uvm_object rhs, uvm_comparer comparer); 20 sequence_item tested; 21 bit same; 22 23 if (rhs==null) `uvm_fatal(get_type_name(), 24 "Tried to do comparison to a null pointer"); 25 26 if (!$cast(tested,rhs)) 27 same = 0; 28 else 29 same = super.do_compare(rhs, comparer) && 30 (tested.A == A) && 31 (tested.B == B) && 32 (tested.op == op) && 33 (tested.result == result); 34 return same; 35 endfunction : do_compare 36 37 function void do_copy(uvm_object rhs); 38 sequence_item RHS; 39 assert(rhs != null) else 40 $fatal(1,"Tried to copy null transaction"); 41 super.do_copy(rhs); 42 assert($cast(RHS,rhs)) else 43 $fatal(1,"Faied cast in do_copy"); 44 A = RHS.A; 45 B = RHS.B; 46 op = RHS.op; 47 result = RHS.result; 48 endfunction : do_copy 49 50 function string convert2string(); 51 string s; 52 s = $sformatf("A: %2h B: %2h op: %s = %4h", 53 A, B, op.name(), result); 54 return s; 55 endfunction : convert2string 56 57 endclass : sequence_item
5.base_test & tests
1 `ifdef QUESTA 2 virtual class tinyalu_base_test extends uvm_test; 3 `else 4 class tinyalu_base_test extends uvm_test; 5 `endif 6 7 env env_h; 8 sequencer sequencer_h; 9 10 function void build_phase(uvm_phase phase); 11 env_h = env::type_id::create("env_h",this); 12 endfunction : build_phase 13 14 function void end_of_elaboration_phase(uvm_phase phase); 15 sequencer_h = env_h.sequencer_h; 16 endfunction : end_of_elaboration_phase 17 18 function new (string name, uvm_component parent); 19 super.new(name,parent); 20 endfunction : new 21 22 endclass 23 24 class fibonacci_test extends tinyalu_base_test; 25 `uvm_component_utils(fibonacci_test); 26 27 task run_phase(uvm_phase phase); 28 fibonacci_sequence fibonacci; 29 fibonacci = new("fibonacci"); 30 31 phase.raise_objection(this); 32 fibonacci.start(sequencer_h); 33 phase.drop_objection(this); 34 endtask : run_phase 35 36 function new(string name, uvm_component parent); 37 super.new(name,parent); 38 endfunction : new 39 40 endclass 41 42 class parallel_test extends tinyalu_base_test; 43 `uvm_component_utils(parallel_test); 44 45 parallel_sequence parallel_h; 46 47 function new(string name, uvm_component parent); 48 super.new(name,parent); 49 parallel_h = new("parallel_h"); 50 endfunction : new 51 52 task run_phase(uvm_phase phase); 53 phase.raise_objection(this); 54 parallel_h.start(sequencer_h); 55 phase.drop_objection(this); 56 endtask : run_phase 57 58 endclass 59 60 class full_test extends tinyalu_base_test; 61 `uvm_component_utils(full_test); 62 63 runall_sequence runall_seq; 64 65 task run_phase(uvm_phase phase); 66 runall_seq = new("runall_seq"); 67 phase.raise_objection(this); 68 runall_seq.start(null); //virtual sequence; 69 phase.drop_objection(this); 70 endtask : run_phase 71 72 73 function new (string name, uvm_component parent); 74 super.new(name,parent); 75 endfunction : new 76 77 endclass
6.env.svh
1 class env extends uvm_env; 2 `uvm_component_utils(env); 3 4 sequencer sequencer_h; 5 coverage coverage_h; 6 scoreboard scoreboard_h; 7 driver driver_h; 8 command_monitor command_monitor_h; 9 result_monitor result_monitor_h; 10 11 function new (string name, uvm_component parent); 12 super.new(name,parent); 13 endfunction : new 14 15 function void build_phase(uvm_phase phase); 16 // stimulus 17 sequencer_h = new("sequencer_h",this); 18 driver_h = driver::type_id::create("driver_h",this); 19 // monitors 20 command_monitor_h = command_monitor::type_id::create("command_monitor_h",this); 21 result_monitor_h = result_monitor::type_id::create("result_monitor",this); 22 // analysis 23 coverage_h = coverage::type_id::create ("coverage_h",this); 24 scoreboard_h = scoreboard::type_id::create("scoreboard",this); 25 endfunction : build_phase 26 27 function void connect_phase(uvm_phase phase); 28 29 driver_h.seq_item_port.connect(sequencer_h.seq_item_export); 30 31 command_monitor_h.ap.connect(coverage_h.analysis_export); 32 command_monitor_h.ap.connect(scoreboard_h.cmd_f.analysis_export); 33 result_monitor_h.ap.connect(scoreboard_h.analysis_export); 34 endfunction : connect_phase 35 36 endclass : env
7.driver,coverage,scoreboard略
8.fibonacci_sequence.svh
1 class fibonacci_sequence extends uvm_sequence #(sequence_item); 2 `uvm_object_utils(fibonacci_sequence); 3 4 function new(string name = "fibonacci"); 5 super.new(name); 6 endfunction : new 7 8 9 task body(); 10 byte unsigned n_minus_2=0; 11 byte unsigned n_minus_1=1; 12 sequence_item command; 13 14 command = sequence_item::type_id::create("command"); 15 16 start_item(command); 17 command.op = rst_op; 18 finish_item(command); 19 20 `uvm_info("FIBONACCI", " Fib(01) = 00", UVM_MEDIUM); 21 `uvm_info("FIBONACCI", " Fib(02) = 01", UVM_MEDIUM); 22 for(int ff = 3; ff<=14; ff++) begin //斐波那契数列 23 start_item(command); 24 command.A = n_minus_2; 25 command.B = n_minus_1; 26 command.op = add_op; 27 finish_item(command); 28 n_minus_2 = n_minus_1; 29 n_minus_1 = command.result; //command.result=command.A+command.B; 30 `uvm_info("FIBONACCI", $sformatf("Fib(%02d) = %02d", ff, n_minus_1), 31 UVM_MEDIUM); 32 end 33 endtask : body 34 endclass : fibonacci_sequence
9.reset_sequence.svh
1 class reset_sequence extends uvm_sequence #(sequence_item); 2 `uvm_object_utils(reset_sequence) 3 4 sequence_item command; 5 6 function new(string name = "reset"); 7 super.new(name); 8 endfunction : new 9 10 task body(); 11 command = sequence_item::type_id::create("command"); 12 start_item(command); 13 command.op = rst_op; 14 finish_item(command); 15 endtask : body 16 endclass : reset_sequence
10.short_random_sequence.svh
1 class short_random_sequence extends uvm_sequence #(sequence_item); 2 `uvm_object_utils(short_random_sequence); 3 4 sequence_item command; 5 6 function new(string name = "short_random_sequence"); 7 super.new(name); 8 endfunction : new 9 10 11 12 task body(); 13 repeat (14) begin : short_random_loop 14 command = sequence_item::type_id::create("command"); 15 start_item(command); 16 assert(command.randomize()); 17 finish_item(command); 18 // Moved relative to the book example so as to show result 19 `uvm_info("SHORT RANDOM", $sformatf("random command: %s", command.convert2string), UVM_MEDIUM) 20 end : short_random_loop 21 endtask : body 22 endclass : short_random_sequence
11.parallel_sequence.svh
1 class parallel_sequence extends uvm_sequence #(uvm_sequence_item); 2 `uvm_object_utils(parallel_sequence); 3 4 protected reset_sequence reset; 5 protected short_random_sequence short_random; 6 protected fibonacci_sequence fibonacci; 7 8 function new(string name = "parallel_sequence"); 9 super.new(name); 10 reset = reset_sequence::type_id::create("reset"); 11 fibonacci = fibonacci_sequence::type_id::create("fibonacci"); 12 short_random = short_random_sequence::type_id::create("short_random"); 13 endfunction : new 14 15 task body(); 16 reset.start(m_sequencer); 17 fork 18 fibonacci.start(m_sequencer); 19 short_random.start(m_sequencer); 20 join 21 endtask : body 22 endclass : parallel_sequence