Files
fvh_vezbe/code/vezba10/verif/Sequences/calc_seq_lib.sv
2026-06-12 07:53:32 +02:00

199 lines
9.4 KiB
Systemverilog

`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