`ifndef CALC_SEQ_LIB_SV `define CALC_SEQ_LIB_SV //============================================================================= // Library of Calc1 sequences (Vezba 6, Zadaci). //============================================================================= //----------------------------------------------------------------------------- // One single random transaction on a random port. //----------------------------------------------------------------------------- class calc_single_seq extends calc_base_seq; `uvm_object_utils(calc_single_seq) function new(string name = "calc_single_seq"); super.new(name); endfunction virtual task body(); `uvm_do(req) endtask endclass : calc_single_seq //----------------------------------------------------------------------------- // Several transactions, all on the same (randomly chosen) port. //----------------------------------------------------------------------------- class calc_same_port_seq extends calc_base_seq; `uvm_object_utils(calc_same_port_seq) rand int unsigned num_of_tr = 5; rand bit [1:0] the_port; constraint c_num { num_of_tr inside {[2:10]}; } function new(string name = "calc_same_port_seq"); super.new(name); endfunction virtual task body(); `uvm_info(get_type_name(), $sformatf("%0d transactions on port %0d", num_of_tr, the_port+1), UVM_LOW) repeat (num_of_tr) `uvm_do_with(req, { req.port == the_port; }) endtask endclass : calc_same_port_seq //----------------------------------------------------------------------------- // 1..10 transactions, each one on a port different from the previous one. //----------------------------------------------------------------------------- class calc_diff_port_seq extends calc_base_seq; `uvm_object_utils(calc_diff_port_seq) rand int unsigned num_of_tr = 6; constraint c_num { num_of_tr inside {[1:10]}; } function new(string name = "calc_diff_port_seq"); super.new(name); endfunction virtual task body(); bit [1:0] prev = 2'd0; bit first = 1; repeat (num_of_tr) begin if (first) begin `uvm_do(req) first = 0; end else begin `uvm_do_with(req, { req.port != prev; }) end prev = req.port; end endtask endclass : calc_diff_port_seq //----------------------------------------------------------------------------- // Back-to-back commands aimed only at the adder/subtractor ALU, no idle gap. //----------------------------------------------------------------------------- class calc_alu_seq extends calc_base_seq; `uvm_object_utils(calc_alu_seq) rand int unsigned num_of_tr = 10; constraint c_num { num_of_tr inside {[5:15]}; } function new(string name = "calc_alu_seq"); super.new(name); endfunction virtual task body(); repeat (num_of_tr) `uvm_do_with(req, { req.cmd inside {CMD_ADD, CMD_SUB}; req.delay == 0; }) endtask endclass : calc_alu_seq //----------------------------------------------------------------------------- // Back-to-back commands aimed only at the shifter ALU. //----------------------------------------------------------------------------- class calc_shift_seq extends calc_base_seq; `uvm_object_utils(calc_shift_seq) rand int unsigned num_of_tr = 10; constraint c_num { num_of_tr inside {[5:15]}; } function new(string name = "calc_shift_seq"); super.new(name); endfunction virtual task body(); repeat (num_of_tr) `uvm_do_with(req, { req.cmd inside {CMD_SHL, CMD_SHR}; req.delay == 0; }) endtask endclass : calc_shift_seq //----------------------------------------------------------------------------- // Directed corner cases: add overflow, sub underflow, sub of equal numbers. //----------------------------------------------------------------------------- class calc_corner_seq extends calc_base_seq; `uvm_object_utils(calc_corner_seq) function new(string name = "calc_corner_seq"); super.new(name); endfunction virtual task body(); // add overflow: FFFFFFFF + 1 `uvm_do_with(req, { req.cmd==CMD_ADD; req.op1==32'hFFFF_FFFF; req.op2==32'h0000_0001; }) // add overflow: 80002345 + 80010000 `uvm_do_with(req, { req.cmd==CMD_ADD; req.op1==32'h8000_2345; req.op2==32'h8001_0000; }) // sub underflow: 11111111 - 20000000 `uvm_do_with(req, { req.cmd==CMD_SUB; req.op1==32'h1111_1111; req.op2==32'h2000_0000; }) // sub of two equal numbers -> 0, success `uvm_do_with(req, { req.cmd==CMD_SUB; req.op1==req.op2; }) // add at the success boundary: 80002345 + 00010000 (Tabela 9) `uvm_do_with(req, { req.cmd==CMD_ADD; req.op1==32'h8000_2345; req.op2==32'h0001_0000; }) // sub success: FFFFFFFF - 11111111 = EEEEEEEE (Tabela 9) `uvm_do_with(req, { req.cmd==CMD_SUB; req.op1==32'hFFFF_FFFF; req.op2==32'h1111_1111; }) endtask endclass : calc_corner_seq //----------------------------------------------------------------------------- // Directed invalid commands (must produce the error response). //----------------------------------------------------------------------------- class calc_invalid_seq extends calc_base_seq; `uvm_object_utils(calc_invalid_seq) function new(string name = "calc_invalid_seq"); super.new(name); endfunction virtual task body(); bit [3:0] inv [$] = '{4'h3, 4'h4, 4'h7, 4'h8, 4'hF}; foreach (inv[i]) `uvm_do_with(req, { req.cmd == inv[i]; }) endtask endclass : calc_invalid_seq //----------------------------------------------------------------------------- // "Clean" sequence: only spec-conformant traffic that the DUT handles exactly // as specified (no add overflow, no sub underflow, no shift-by-zero, no illegal // commands). Used by test_sanity to prove the environment reports ZERO errors // on a correctly behaving stimulus - i.e. the checker has no false positives. //----------------------------------------------------------------------------- class calc_clean_seq extends calc_base_seq; `uvm_object_utils(calc_clean_seq) rand int unsigned num_of_tr = 20; constraint c_num { num_of_tr inside {[10:40]}; } function new(string name = "calc_clean_seq"); super.new(name); endfunction virtual task body(); repeat (num_of_tr) `uvm_do_with(req, { req.cmd inside {CMD_ADD, CMD_SUB, CMD_SHL, CMD_SHR}; (req.cmd == CMD_ADD) -> (req.op1[31] == 1'b0 && req.op2[31] == 1'b0); (req.cmd == CMD_SUB) -> (req.op1 >= req.op2); (req.cmd inside {CMD_SHL,CMD_SHR}) -> (req.op2[4:0] != 5'b0); // port 4 (id 3) add/sub is a known DUT defect (never responds) - the // clean stimulus avoids it so test_sanity stays green (req.cmd inside {CMD_ADD,CMD_SUB}) -> (req.port != 2'd3); }) endtask endclass : calc_clean_seq //----------------------------------------------------------------------------- // Directed "known-good" vectors: operand/command/port combinations that this // RTL computes exactly per the specification (verified against the DUT). They // cover every port and every command, so a run produces ZERO scoreboard errors // - proving the environment/reference model has no false positives. (The DUT // also has data-dependent arithmetic defects, so an unconstrained random run is // NOT error-free; that is the DUT, not the testbench.) //----------------------------------------------------------------------------- class calc_known_good_seq extends calc_base_seq; `uvm_object_utils(calc_known_good_seq) function new(string name = "calc_known_good_seq"); super.new(name); endfunction task send(bit [1:0] p, bit [3:0] c, bit [31:0] a, bit [31:0] b); `uvm_do_with(req, { req.port==p; req.cmd==c; req.op1==a; req.op2==b; req.delay==1; }) endtask virtual task body(); // ADD (ports 1-3) send(2'd0, CMD_ADD, 32'h0000_0001, 32'h0000_0002); // -> 0000_0003 send(2'd1, CMD_ADD, 32'h0000_000A, 32'h0000_0005); // -> 0000_000F send(2'd2, CMD_ADD, 32'h0000_000F, 32'h0000_00F0); // -> 0000_00FF // SUB (ports 1-3) send(2'd0, CMD_SUB, 32'hFFFF_FFFF, 32'h1111_1111); // -> EEEE_EEEE send(2'd1, CMD_SUB, 32'h0000_ABCD, 32'h0000_0CD0); // -> 0000_9EFD send(2'd2, CMD_SUB, 32'h7FFF_FFFF, 32'h0000_0001); // -> 7FFF_FFFE // SHL send(2'd0, CMD_SHL, 32'h0000_0001, 32'h0000_0004); // -> 0000_0010 send(2'd1, CMD_SHL, 32'h0000_00FF, 32'h0000_0008); // -> 0000_FF00 send(2'd3, CMD_SHL, 32'h0000_00FF, 32'h0000_0004); // port4 -> 0000_0FF0 // SHR send(2'd2, CMD_SHR, 32'hFF00_0000, 32'h0000_0004); // -> 0FF0_0000 send(2'd0, CMD_SHR, 32'h8000_0000, 32'h0000_000F); // -> 0001_0000 send(2'd3, CMD_SHR, 32'hFF00_0000, 32'h0000_0008); // port4 -> 00FF_0000 endtask endclass : calc_known_good_seq //----------------------------------------------------------------------------- // Shift coverage helper: hit shift amounts 0, 1, 31 on both shift directions. //----------------------------------------------------------------------------- class calc_shift_amounts_seq extends calc_base_seq; `uvm_object_utils(calc_shift_amounts_seq) function new(string name = "calc_shift_amounts_seq"); super.new(name); endfunction virtual task body(); bit [4:0] amt [$] = '{5'd0, 5'd1, 5'd4, 5'd16, 5'd31}; foreach (amt[i]) begin `uvm_do_with(req, { req.cmd==CMD_SHL; req.op1==32'h0000_00FF; req.op2=={27'b0, amt[i]}; }) `uvm_do_with(req, { req.cmd==CMD_SHR; req.op1==32'hFF00_0000; req.op2=={27'b0, amt[i]}; }) end endtask endclass : calc_shift_amounts_seq `endif