What is a uvm environment?

UVM environment is a class based component that is part of the UVM methodology. It acts as a wrapper for the underlying components and objects. It extends from the uvm_component base class and inherits all the methonds and properties from it's parent class.

Why do we need a uvm environment component?

The primary purpose of a uvm_env component extended class is to provide a heirarchical parent for all the lower components. In simple words, we can list the whys of a uvm environment component in the follwing list

  1. This is the class where different agents are instantiated with different configurations.
  2. We can set and get different config class settings into this class. Using these config objects we can decide the configuration/layout of the lower testbench.
  3. Conventionally, one instance of a UVM component acts as a single instance of a testbench. This essentially means that we can have multiple instances of the same uvm environment, but with different configurations and architectures.
Code
// Filename : basic_env.sv

class basic_env extends uvm_env;
	`uvm_component_utils(basic_env)
	
	uvm_root             top;
	
	virtual basic_if     basic_vif;
	
	basic_config         cfg;
	basic_coverage       basic_cov;
	
	basic_sequencer basic_seqr;
	
	basic_scoreboard	 basic_sb;
	basic_agent			 basic_agt;
	
	extern         function      new(string name, uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void connect_phase(uvm_phase phase);
	extern virtual function void end_of_elaboration_phase(uvm_phase phase);
	extern virtual function void start_of_simulation_phase(uvm_phase phase);
	
	extern virtual task  main_phase(uvm_phase phase);
	
	extern virtual function void extract_phase(uvm_phase phase);
	extern virtual function void check_phase(uvm_phase phase);
	extern virtual function void report_phase(uvm_phase phase);
	extern virtual function void final_phase(uvm_phase phase);
	
	extern virtual function 	 basic_config get_cfg();
	
endclass: basic_env

//------------------------------------------------------------------//

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

endfunction: new

//------------------------------------------------------------------//

function void basic_env::build_phase(uvm_phase phase);
	super.build_phase(phase);
	
	top = uvm_root::get();
	
	cfg = basic_config::type_id::create("cfg", this);
	
	if(!uvm_config_db#(virtual basic_if)::get(null, get_full_name(), "basic_vif", basic_vif))
    begin
		`uvm_fatal(get_type_name(), "basic interface not set")
	end
	
	// Create the coverage object if coverage enabled:

	if (cfg.coverage_enable)
    begin
		basic_cov = basic_coverage::type_id::create("basic_cov", this);
    end
	
	if(cfg.scoreboard_enable)
    begin
		basic_sb = basic_scoreboard::type_id::create("basic_sb", this);
		basic_sb.cfg = cfg;
	end

    basic_agt = basic_agent::type_id::create("basic_agt", this);
    basic_agt.cfg = cfg;
	
endfunction: build_phase

//------------------------------------------------------------------//

function void basic_env::connect_phase(uvm_phase phase);
	super.connect_phase(phase);

endfunction: connect_phase

//------------------------------------------------------------------//

function void basic_env::end_of_elaboration_phase(uvm_phase phase);
	super.end_of_elaboration_phase(phase);
	
endfunction: end_of_elaboration_phase

//------------------------------------------------------------------//

function void basic_env::start_of_simulation_phase(uvm_phase phase);
	super.start_of_simulation_phase(phase);
	
endfunction: start_of_simulation_phase

//------------------------------------------------------------------//

task basic_env::main_phase(uvm_phase phase);
	super.main_phase(phase);
	phase.raise_objection(this);
	
	phase.drop_objection(this);
endtask: main_phase

//------------------------------------------------------------------//

function void basic_env::extract_phase(uvm_phase phase);
	super.extract_phase(phase);
	
endfunction: extract_phase

//------------------------------------------------------------------//

function void basic_env::check_phase(uvm_phase phase);
	super.check_phase(phase);
	
endfunction: check_phase

//------------------------------------------------------------------//

function void basic_env::report_phase(uvm_phase phase);
	super.report_phase(phase);
	
endfunction: report_phase

//------------------------------------------------------------------//

function void basic_env::final_phase(uvm_phase phase);
	super.final_phase(phase);
	
endfunction: final_phase

//------------------------------------------------------------------//

function basic_config basic_env::get_cfg();

	return this.cfg;
endfunction: get_cfg
Theory Questions
    Yes, a uvm_env can contain another uvm_env, and this is referred to as hierarchical environments.