Verification environment is developed by extending vmm_env class. The TestBench simulation needs some systematic flow like reset, initialize etc. vmm_env base class has methods formalize the simulation steps. All methods are declared as virtual methods. All the Verification components and instantiated, connected and component activities starting is done in this class. As it contains all verification components instances, the environment class affects the entire test environment.
The vmm_env class divides a simulation into the following steps, with corresponding methods:
gen_cfg() :
Randomize test configuration parameters.
build() :
Creates the instances of channels and transactors. Transactors are connected using channels. DUT is also connected to TestBench using the interfaces.
reset_dut() :
Reset the DUT using the interface signals.
cfg_dut() :
Configures the DUT configuration parameters.
start() :
Starts all the components of the verification environment to start component activity. All the transactors (atomic_gen, senario_gen, vmm_xactor....) have start method, which starts their activities. All the components start() methods are called in this method.
wait_for_end() :
This method waits till the test is done.
stop() :
Stops all the components of the verification environment to terminate the simulation cleanly. Stop data generators.
cleanup() :
Performs clean-up operations to let the simulation terminate gracefully. It waits for DUT to drain all the data it has.
report() :
The report method in vmm_env collects error and warning metrics from all the log objects and reports a summary of the results.
To create a user environment, define a new class extended from vmm_env and extend the above methods. To retain the core functionality of the base class methods, each extended method must call super. as the first line of code.
In The following example, we are defining a new class Custom_env from vmm_env and extending all the vmm_env class methods. All the methods are extended and `vmm_note() message is included to understand the simulation flow.
class Custom_env extends vmm_env;
function new();
super.new("Custom_env");
endfunction
virtualfunctionvoid gen_cfg();
super.gen_cfg();
`vmm_note(this.log,"Start of gen_cfg() method ");
`vmm_note(this.log,"End of gen_cfg() method ");
endfunction
virtualfunctionvoid build();
super.build();
`vmm_note(this.log,"Start of build() method ");
`vmm_note(this.log,"End of build() method ");
endfunction
virtualtask reset_dut();
super.reset_dut();
`vmm_note(this.log,"Start of reset_dut() method ");
`vmm_note(this.log,"End of reset_dut() method ");
endtask
virtualtask cfg_dut();
super.cfg_dut();
`vmm_note(this.log,"Start of cfg_dut() method ");
`vmm_note(this.log,"End of cfg_dut() method ");
endtask
virtualtask start();
super.start();
`vmm_note(this.log,"Start of start() method ");
`vmm_note(this.log,"End of start() method ");
endtask
virtualtask wait_for_end();
super.wait_for_end();
`vmm_note(this.log,"Start of wait_for_end() method ");
`vmm_note(this.log,"End of wait_for_end() method ");
endtask
virtualtask stop();
super.stop();
`vmm_note(this.log,"Start of stop() method ");
`vmm_note(this.log,"End of stop() method ");
endtask
virtualtask cleanup();
super.cleanup();
`vmm_note(this.log,"Start of cleanup() method ");
`vmm_note(this.log,"End of cleanup() method ");
endtask
virtualtask report();
super.report();
`vmm_note(this.log,"Start of report() method \n\n\n");
`vmm_note(this.log,"End of report() method");
endtask
endclass
In addition to the methods that have already been discussed earlier, vmm_env also contains a run() method which does not require any user extension. This method is called from the testcase. When this method is called, individual steps in vmm_env are called in a sequence in the following order:
Now we will see the testcase implementation. VMM recommends the TestBench to be implemented in program block. In a program block, create an object of the Custom_env class and call the run() method.
Normal[NOTE] on Custom_env() at 0: Start of gen_cfg() method Normal[NOTE] on Custom_env() at 0: End of gen_cfg() method Normal[NOTE] on Custom_env() at 0: Start of build() method Normal[NOTE] on Custom_env() at 0: End of build() method Normal[NOTE] on Custom_env() at 0: Start of reset_dut() method Normal[NOTE] on Custom_env() at 0: End of reset_dut() method Normal[NOTE] on Custom_env() at 0: Start of cfg_dut() method Normal[NOTE] on Custom_env() at 0: End of cfg_dut() method Normal[NOTE] on Custom_env() at 0: Start of start() method Normal[NOTE] on Custom_env() at 0: End of start() method Normal[NOTE] on Custom_env() at 0: Start of wait_for_end() method Normal[NOTE] on Custom_env() at 0: End of wait_for_end() method Normal[NOTE] on Custom_env() at 0: Start of stop() method Normal[NOTE] on Custom_env() at 0: End of stop() method Normal[NOTE] on Custom_env() at 0: Start of cleanup() method Normal[NOTE] on Custom_env() at 0: End of cleanup() method Simulation PASSED on /./ (/./) at 0 (0 warnings, 0 demoted errors & 0 demoted warnings) Normal[NOTE] on Custom_env() at 0: Start of report() method Normal[NOTE] on Custom_env() at 0: End of report() method $finish at simulation time 0
Log file report shows that individual methods in vmm_env are called in a ordered sequence upon calling run() method.
When you call build() and if gen_cfg() is not called before that, gen_cfg() will be called first then build will execute.
Same way, if you call gen_cfg() followed by cfg_dut() followed by run(), then cfg_dut() will make sure to call build() followed by reset_dut() first before executing its user defined logic, run() will make sure to call start(), wait_for_end(), stop(), clean(), report()in the order given.
program test();
vmm_env env = new();
initial begin $display("*************** Before Calling env.gen_cfg() ***************");
env.gen_cfg();
$display("*************** Before Calling env.cfg_dut() ***************");
env.cfg_dut();
$display("*************** Before Calling env.run() ***************");
env.run();
end
*************** Before Calling env.gen_cfg() *************** Trace[INTERNAL] on Verif Env() at 0: Generating test configuration... *************** Before Calling env.cfg_dut() *************** Trace[INTERNAL] on Verif Env() at 0: Building verification environment... Trace[INTERNAL] on Verif Env() at 0: Reseting DUT... Trace[INTERNAL] on Verif Env() at 0: Configuring... *************** Before Calling env.run() *************** Trace[INTERNAL] on Verif Env() at 0: Starting verification environment... Trace[INTERNAL] on Verif Env() at 0: Saving RNG state information... Trace[INTERNAL] on Verif Env() at 0: Waiting for end of test... Trace[INTERNAL] on Verif Env() at 0: Stopping verification environment... Trace[INTERNAL] on Verif Env() at 0: Cleaning up... Simulation PASSED on /./ (/./) at 0 (0 warnings, 0 demoted errors & 0 demoted warnings)