
//----------------------------------------------------------------------
//  Copyright (c) 2011-2012 by Doulos Ltd.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//----------------------------------------------------------------------

// First Steps with UVM - Nested Sequences

// Author: John Aynsley, Doulos
// Date:   13-Sep-2012


`include "uvm_macros.svh"

package my_pkg;

  import uvm_pkg::*;

  class my_transaction extends uvm_sequence_item;
  
    `uvm_object_utils(my_transaction)
  
    rand bit cmd;
    rand int addr;
    rand int data;
  
    constraint c_addr { addr >= 0; addr < 256; }
    constraint c_data { data >= 0; data < 256; }
    
    function new (string name = "");
      super.new(name);
    endfunction
    
    function string convert2string;
      return $sformatf("cmd=%b, addr=%0d, data=%0d", cmd, addr, data);
    endfunction

    function void do_copy(uvm_object rhs);
      my_transaction tx;
      $cast(tx, rhs);
      cmd  = tx.cmd;
      addr = tx.addr;
      data = tx.data;
    endfunction
    
    function bit do_compare(uvm_object rhs, uvm_comparer comparer);
      my_transaction tx;
      bit status = 1;
      $cast(tx, rhs);
      status &= (cmd  == tx.cmd);
      status &= (addr == tx.addr);
      status &= (data == tx.data);
      return status;
    endfunction

  endclass: my_transaction
  
  
  class my_config extends uvm_object;

    rand int count;
    rand int max_addr;
    
    constraint c_count    { count > 0; count < 128; }
    constraint c_max_addr { max_addr > 128; max_addr < 252; }

  endclass: my_config


  typedef uvm_sequencer #(my_transaction) my_sequencer;


  class child_sequence extends uvm_sequence #(my_transaction);
  
    `uvm_object_utils(child_sequence)
    
    rand int start_addr;
    
    constraint c_addr { start_addr >= 0; start_addr < 252; }
    
    function new (string name = "");
      super.new(name);
    endfunction

    task body;
      if (starting_phase != null)
        starting_phase.raise_objection(this);
        
      for (int i = 0; i < 4; i++)
      begin
        req = my_transaction::type_id::create("req");
        start_item(req);
        if( !req.randomize() with { addr == start_addr + i; } )
          `uvm_error("", "Randomize failed")
        finish_item(req);
      end
      
      if (starting_phase != null)
        starting_phase.drop_objection(this);
    endtask: body
   
  endclass: child_sequence
  
  
  class alt_child_sequence extends child_sequence;
  
    `uvm_object_utils(alt_child_sequence)

    rand bit [2:0] fixed_data;
    
    function new (string name = "");
      super.new(name);
    endfunction
    
    function void mid_do(uvm_sequence_item this_item);
      my_transaction tx;
      $cast(tx, this_item);
      tx.data = fixed_data;
    endfunction
    
  endclass: alt_child_sequence
  
    
  class top_sequence extends uvm_sequence #(my_transaction);

    `uvm_object_utils(top_sequence)
    `uvm_declare_p_sequencer(my_sequencer)
    
    function new (string name = "");
      super.new(name);
    endfunction

    task body;
      my_config cfg;
      int count, max_addr;

      if ( uvm_config_db #(my_config)::get(p_sequencer, "", "config", cfg) )
      begin
        count    = cfg.count;
        max_addr = cfg.max_addr;
      end
      else
      begin
        count    = 1;
        max_addr = 256;
      end
      
      if (starting_phase != null)
        starting_phase.raise_objection(this);

      repeat(count)
      begin
        child_sequence seq;
        seq = child_sequence::type_id::create("seq");
        if( !seq.randomize() with { start_addr < max_addr; } )
          `uvm_error("", "Randomize failed")
        seq.start(p_sequencer, this);
      end
      
      if (starting_phase != null)
        starting_phase.drop_objection(this);
    endtask: body
   
  endclass: top_sequence
  

  class my_driver extends uvm_driver #(my_transaction);
  
    `uvm_component_utils(my_driver)

    virtual dut_if dut_vi;

    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
    function void build_phase(uvm_phase phase);
      // Get interface reference from config database
      if( !uvm_config_db #(virtual dut_if)::get(this, "", "dut_if", dut_vi) )
        `uvm_error("", "uvm_config_db::get failed")
    endfunction 

    task run_phase(uvm_phase phase);
      forever
      begin
        seq_item_port.get_next_item(req);

        // Wiggle pins of DUT
        dut_vi.cmd  = req.cmd;
        dut_vi.addr = req.addr;
        dut_vi.data = req.data;
        @(posedge dut_vi.clock);

        seq_item_port.item_done();
      end
    endtask

  endclass: my_driver
  
  
  class my_env extends uvm_env;

    `uvm_component_utils(my_env)
    
    my_sequencer m_seqr;
    my_driver    m_driv;
    
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
 
    function void build_phase(uvm_phase phase);
      m_seqr = my_sequencer::type_id::create("m_seqr", this);
      m_driv = my_driver   ::type_id::create("m_driv", this);
    endfunction
    
    function void connect_phase(uvm_phase phase);
      m_driv.seq_item_port.connect( m_seqr.seq_item_export );
    endfunction
    
  endclass: my_env
  
  
  class my_test extends uvm_test;
  
    `uvm_component_utils(my_test)
    
    my_env m_env;
    
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    
    function void build_phase(uvm_phase phase);
      m_env = my_env::type_id::create("m_env", this);
    endfunction
    
    task run_phase(uvm_phase phase);
      my_config     cfg;
      top_sequence  seq;
      uvm_component component;
      my_sequencer  sequencer;
      
      cfg = new;
      if ( !cfg.randomize() with { count == 3; } )
        `uvm_error("", "Randomize failed")
      uvm_config_db #(my_config)::set(this, "*.m_seqr", "config", cfg);
      
      seq = top_sequence::type_id::create("seq");
      if( !seq.randomize() ) 
        `uvm_error("", "Randomize failed")
      seq.starting_phase = phase;

      component = uvm_top.find("*.m_seqr");
      if ($cast(sequencer, component))
        seq.start(sequencer);
    endtask
     
  endclass: my_test
  
  
  class my_test2 extends my_test;

    `uvm_component_utils(my_test2)

    function new (string name, uvm_component parent);
      super.new(name, parent);
    endfunction : new

    function void start_of_simulation_phase(uvm_phase phase);
      super.start_of_simulation_phase(phase);

      child_sequence::type_id::set_type_override( alt_child_sequence::get_type() );
    endfunction : start_of_simulation_phase

  endclass: my_test2
  

endpackage: my_pkg


module top;

  import uvm_pkg::*;
  import my_pkg::*;
  
  dut_if dut_if1 ();
  
  dut    dut1 ( .dif(dut_if1) );

  // Clock generator
  initial
  begin
    dut_if1.clock = 0;
    forever #5 dut_if1.clock = ~dut_if1.clock;
  end

  initial
  begin
    uvm_config_db #(virtual dut_if)::set(null, "*", "dut_if", dut_if1);
    
    uvm_top.finish_on_completion = 1;
    
    //    run_test("my_test");  // Original test
    run_test("my_test2");       // Alternative test
  end

endmodule: top
