`ifndef TEST_LIB_SV
 `define TEST_LIB_SV

//=============================================================================
// Additional Calc1 tests, built on top of test_base.
//=============================================================================

//-----------------------------------------------------------------------------
// Broad random regression: exercises every command, every port, both ALUs,
// corner cases and a few illegal commands.  Good for coverage closure.
//-----------------------------------------------------------------------------
class test_random extends test_base;
   `uvm_component_utils(test_random)

   function new(string name = "test_random", uvm_component parent = null);
      super.new(name,parent);
   endfunction : new

   task main_phase(uvm_phase phase);
      calc_simple_seq        rnd;
      calc_alu_seq           alu;
      calc_shift_seq         sh;
      calc_diff_port_seq     dp;
      calc_same_port_seq     sp;
      calc_shift_amounts_seq sa;
      calc_corner_seq        cor;

      phase.raise_objection(this);
      `uvm_info(get_type_name(), "Starting random regression", UVM_LOW)

      repeat (3) begin
         rnd = calc_simple_seq::type_id::create("rnd");
         void'(rnd.randomize());
         rnd.start(env.agent.seqr);
      end
      alu = calc_alu_seq::type_id::create("alu");        void'(alu.randomize()); alu.start(env.agent.seqr);
      sh  = calc_shift_seq::type_id::create("sh");       void'(sh.randomize());  sh.start(env.agent.seqr);
      dp  = calc_diff_port_seq::type_id::create("dp");   void'(dp.randomize());  dp.start(env.agent.seqr);
      sp  = calc_same_port_seq::type_id::create("sp");   void'(sp.randomize());  sp.start(env.agent.seqr);
      sa  = calc_shift_amounts_seq::type_id::create("sa"); sa.start(env.agent.seqr);
      cor = calc_corner_seq::type_id::create("cor");     cor.start(env.agent.seqr);

      phase.drop_objection(this);
   endtask : main_phase
endclass : test_random

//-----------------------------------------------------------------------------
// Sanity test: only spec-conformant traffic.  Expected result: 0 UVM_ERRORs.
// Proves the environment (driver/monitor/scoreboard/reference model) is sound
// and free of false positives.
//-----------------------------------------------------------------------------
class test_sanity extends test_base;
   `uvm_component_utils(test_sanity)

   function new(string name = "test_sanity", uvm_component parent = null);
      super.new(name,parent);
   endfunction : new

   task main_phase(uvm_phase phase);
      calc_known_good_seq good;
      phase.raise_objection(this);
      `uvm_info(get_type_name(), "Running directed known-good vectors (expect 0 errors)", UVM_LOW)
      repeat (3) begin
         good = calc_known_good_seq::type_id::create("good");
         good.start(env.agent.seqr);
      end
      phase.drop_objection(this);
   endtask : main_phase
endclass : test_sanity

//-----------------------------------------------------------------------------
// Directed corner / error test: overflow, underflow, equal-subtract, invalid.
//-----------------------------------------------------------------------------
class test_corner extends test_base;
   `uvm_component_utils(test_corner)

   function new(string name = "test_corner", uvm_component parent = null);
      super.new(name,parent);
   endfunction : new

   task main_phase(uvm_phase phase);
      calc_corner_seq        cor;
      calc_invalid_seq       inv;
      calc_shift_amounts_seq sa;

      phase.raise_objection(this);
      cor = calc_corner_seq::type_id::create("cor");          cor.start(env.agent.seqr);
      inv = calc_invalid_seq::type_id::create("inv");         inv.start(env.agent.seqr);
      sa  = calc_shift_amounts_seq::type_id::create("sa");    sa.start(env.agent.seqr);
      phase.drop_objection(this);
   endtask : main_phase
endclass : test_corner

//-----------------------------------------------------------------------------
// Factory-override demo (Vezba 9, Zadatak): a transaction that never uses SUB.
//-----------------------------------------------------------------------------
class calc_seq_item_no_sub extends calc_seq_item;
   `uvm_object_utils(calc_seq_item_no_sub)
   constraint c_no_sub { cmd != CMD_SUB; }
   function new(string name = "calc_seq_item_no_sub");
      super.new(name);
   endfunction
endclass : calc_seq_item_no_sub

class test_no_sub extends test_base;
   `uvm_component_utils(test_no_sub)

   calc_simple_seq simple_seq;

   function new(string name = "test_no_sub", uvm_component parent = null);
      super.new(name,parent);
   endfunction : new

   function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      // every calc_seq_item created in the environment becomes a no-sub item
      calc_seq_item::type_id::set_type_override(calc_seq_item_no_sub::get_type());
      simple_seq = calc_simple_seq::type_id::create("simple_seq");
   endfunction : build_phase

   task main_phase(uvm_phase phase);
      phase.raise_objection(this);
      void'(simple_seq.randomize());
      simple_seq.start(env.agent.seqr);
      phase.drop_objection(this);
   endtask : main_phase
endclass : test_no_sub

`endif
