blob: db2699694c154bf73ed3986fd1af63d929d7c14d [file] [log] [blame] [edit]
/******************************************************************************
* (C) Copyright 2015 AMIQ Consulting
*
* 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.
*
* NAME: svaunit_test_suite.svh
* PROJECT: svaunit
* Description: svaunit test suite class definition
*******************************************************************************/
`ifndef SVAUNIT_TEST_SUITE_SVH
`define SVAUNIT_TEST_SUITE_SVH
// svaunit test suite class definition
class svaunit_test_suite extends svaunit_test;
`uvm_component_utils(svaunit_test_suite)
// List of tests of the current test suite
local svaunit_test lof_tests[$];
// If 1 the test suite will continue to run if the previous test was failed, if 0 it will be stopped
bit continue_driving;
/* Constructor for svaunit_test_suite
* @param name : instance name for svaunit_test_suite object
* @param parent : hierarchical parent for svaunit_test_suite
*/
function new (string name = "svaunit_test_suite", uvm_component parent);
super.new(name, parent);
continue_driving = 1;
endfunction
/* Build phase method used to instantiate components
* @param phase : the phase scheduled for build_phase method
*/
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_name_for_test();
endfunction
/* Set continue driving switch
* @param a_continue_driving : value of continue driving
*/
virtual function void set_continue_driving(bit a_continue_driving);
continue_driving = a_continue_driving;
endfunction
/* Get continue driving switch value
* @return the value of continue driving
*/
virtual function bit get_continue_driving();
return continue_driving;
endfunction
/* Create a test or a sequence instance name
* @param a_test_or_seq_type : the test or the sequence type used to create the object
* @return the name of the object to be created
*/
virtual function string create_test_name(string a_test_or_seq_type);
int index[$];
index = lof_tests.find_index() with (vpiw.find(item.get_test_name(), a_test_or_seq_type) != -1);
if(index.size() > 0) begin
return $sformatf("%s@%0d", a_test_or_seq_type, index.size());
end else begin
return a_test_or_seq_type;
end
endfunction
/* Add a given unit test into test list
* @param a_obj : a test or a sequence which needs to be added into the list
*/
virtual function void add_test (uvm_object a_obj);
svaunit_base_sequence a_seq;
svaunit_test a_test;
uvm_component parent;
string new_name = "";
if ($cast(a_seq, a_obj)) begin
automatic svaunit_sequence_test#(svaunit_base_sequence) the_test = svaunit_sequence_test#(svaunit_base_sequence
)::type_id::create(create_test_name(a_seq.get_type_name()), this);
if(!($cast(the_test.seq, a_seq))) begin
`uvm_fatal("SVAUNIT_CAST_ERR", $sformatf("Could not cast the %s sequence to svaunit_sequence_base",
the_test.get_test_name()))
end
parent = the_test.get_parent();
new_name = {new_name, parent.get_type_name(), ".", a_seq.get_type_name()};
the_test.update_test_name(create_test_name(new_name));
the_test.stop_test = a_seq.get_stop();
lof_tests.push_back(the_test);
end
if ($cast(a_test, a_obj)) begin
a_test.set_name_for_test();
lof_tests.push_back(a_test);
end
endfunction
// Update status for a test-suite
virtual function void update_status();
int unsigned nof_tests_not_run = 0;
foreach(lof_tests[test_index]) begin
lof_tests[test_index].update_status();
end
set_nof_tests(get_nof_tests());
set_nof_failures(get_nof_tests_failed());
nof_tests_not_run = get_nof_tests_did_not_run();
set_status(compute_status(get_nof_tests(), get_nof_tests_failed()));
endfunction
// {{{ Functions to get test info
/* Get the tests which ran from current test suite
* @param a_tests_ran : list of test which has ran from current test suite
*/
virtual function void get_ran_tests(ref svaunit_test a_tests_ran[$]);
foreach(lof_tests[test_index]) begin
if(lof_tests[test_index].started()) begin
a_tests_ran.push_back(lof_tests[test_index]);
end
end
endfunction
/* Get the tests which didn't run from current test suite
* @param a_tests_ran : list of test which didn't run from current test suite
*/
virtual function void get_did_not_run_tests(ref svaunit_test a_tests_ran[$]);
foreach(lof_tests[test_index]) begin
if(!(lof_tests[test_index].started())) begin
a_tests_ran.push_back(lof_tests[test_index]);
end
end
endfunction
/* Compute the number of tests from current test suite
* @return the number of tests from current test suite
*/
virtual function int unsigned get_nof_tests();
return lof_tests.size();
endfunction
/* Compute the number of tests from current test suite which have failed
* @return the number of tests from current test suite which have failed
*/
virtual function int unsigned get_nof_tests_failed();
int unsigned nof_tests_failed = 0;
foreach(lof_tests[test_index]) begin
if(lof_tests[test_index].get_status() == SVAUNIT_FAIL) begin
nof_tests_failed = nof_tests_failed + 1;
end
end
return nof_tests_failed;
endfunction
/* Compute the number of tests from current test suite which did not run
* @return the number of tests from current test suite which did not run
*/
virtual function int unsigned get_nof_tests_did_not_run();
int unsigned nof_tests_did_not_run = 0;
foreach(lof_tests[test_index]) begin
if(lof_tests[test_index].get_status() == SVAUNIT_DID_NOT_RUN) begin
nof_tests_did_not_run = nof_tests_did_not_run + 1;
end
end
return nof_tests_did_not_run;
endfunction
/* Compute the number of active tests during simulation for current test suite
* @return the number of active tests during simulation for current test suite
*/
virtual function int unsigned get_nof_active_tests();
// Variable used to store all tests which ran during simulation
svaunit_test tests_ran[$];
// Variable used to store the number of active tests during simulation for current test suite
int unsigned nof_active_tests;
// Get all tests which ran during simulation
get_ran_tests(tests_ran);
nof_active_tests = tests_ran.size();
tests_ran.delete();
return nof_active_tests;
endfunction
/* Get the tests names as a string
* @return a string with all tests names from this test suite
*/
virtual function string get_tests_names();
// Variable used to store the test_names from this test suite
string test_names = "";
// Compute the string with all test names
foreach(lof_tests[test_index]) begin
test_names = $sformatf("%s\n\t%s", test_names, lof_tests[test_index].get_test_name());
end
return test_names;
endfunction
/* Get the tests names which ran as a string
* @return a string with the tests names which ran from this test suite
*/
virtual function string get_tests_names_ran();
// Variable used to store the test_names from this test suite
string test_names = "";
// Get all tests which ran during simulation
svaunit_test tests_ran[$];
get_ran_tests(tests_ran);
// Compute the string with all test names
foreach(tests_ran[test_index]) begin
test_names = $sformatf("%s\n\t\t%s", test_names, tests_ran[test_index].get_test_name());
end
tests_ran.delete();
return test_names;
endfunction
/* Get the tests names which didn't run as a string
* @return a string with the tests names which didn't run from this test suite
*/
virtual function string get_tests_names_did_not_run();
// Variable used to store the test_names from this test suite
string test_names = "";
// Get all tests which ran during simulation
svaunit_test tests_ran[$];
get_did_not_run_tests(tests_ran);
// Compute the string with all test names
foreach(tests_ran[test_index]) begin
test_names = $sformatf("%s\n\t\t%s", test_names, tests_ran[test_index].get_test_name());
end
tests_ran.delete();
return test_names;
endfunction
// }}}
// {{{ Functions to get SVA info
/* Get the total number of SVAs tested from all tests
* @return the total number of SVAs tested from all tests
*/
virtual function int unsigned get_total_nof_tested_sva();
// Variable used to store the number of times an SVA was tested
int unsigned nof_tested_sva = 0;
foreach(lof_tests[test_index]) begin
// Get the number of times an SVA was tested
nof_tested_sva = nof_tested_sva + lof_tests[test_index].get_nof_tested_sva();
end
return nof_tested_sva;
endfunction
/* Get the names of the SVAs which were tested during test
* @param a_tested_sva_names : the names of the SVAs which were tested during test
*/
virtual function void get_sva_tested_names(ref string a_tested_sva_names[$]);
foreach(lof_tests[test_index]) begin
lof_tests[test_index].get_sva_tested_names(a_tested_sva_names);
end
endfunction
/* Get the names of the SVAs which were not tested during test
* @param a_sva_not_tested : the names of the SVAs which were not tested during test
*/
virtual function void get_sva_not_tested_names(ref string a_sva_not_tested[$]);
// Variable used to store the names of the SVA which were tested
string tested_sva_names[$];
// Variable used to store the names of the SVA which were tested/per test
string not_tested_sva_names[$];
int not_tested_index[$];
int n_tested_index[$];
foreach(lof_tests[test_index]) begin
lof_tests[test_index].get_sva_not_tested_names(not_tested_sva_names);
end
// Get tested SVAs
get_sva_tested_names(tested_sva_names);
foreach(not_tested_sva_names[sva_index]) begin
n_tested_index = tested_sva_names.find_index() with (item == not_tested_sva_names[sva_index]);
if(n_tested_index.size() == 0) begin
not_tested_index = a_sva_not_tested.find_index() with
(item == not_tested_sva_names[sva_index]);
if(not_tested_index.size() == 0) begin
a_sva_not_tested.push_back(not_tested_sva_names[sva_index]);
end
end
end
endfunction
// }}}
// {{{ Function to get checks info
/* Get a list with all immediate assertions tested into tests
* @param a_checks : a list with all immediate assertions tested
*/
virtual function void get_checks(ref svaunit_immediate_assertion_info a_checks[$]);
// Get the checks used in each test
foreach(lof_tests[test_index]) begin
lof_tests[test_index].get_checks(a_checks);
end
endfunction
// }}}
// {{{ Tasks to start testing
// Task used to start testing - The user should create here scenarios to verify SVAs
virtual task test();
endtask
// Pre-run behavior
virtual task pre_run();
`uvm_info(get_test_name(), "Start test suite", UVM_DEBUG)
// Raise objection mechanism for this test
uvm_test_done.raise_objection(this, "", 1);
// Set start bit
start_test();
endtask
// Post-run behavior
virtual task post_run();
`uvm_info(get_test_name(), "End test suite", UVM_DEBUG)
// Raise objection mechanism for this test
uvm_test_done.drop_objection(this, "", 1);
endtask
// Will start the test suite
virtual task start_ut();
if(enable == 1) begin
fork
begin
// Variable used to store the process id for test task
process simulate_ts;
fork
begin
simulate_ts = process::self();
fork
begin
// Run tests
foreach(lof_tests[test_index]) begin
if(((stop_test == 0) && (continue_driving == 0)) || (continue_driving == 1)) begin
lof_tests[test_index].start_test();
lof_tests[test_index].start_ut();
stop_test = lof_tests[test_index].get_stop();
end
end
end
begin
while(((stop_test == 0) && (continue_driving == 0)) || (continue_driving == 1)) begin
#1ns;
end
end
join_any
end
join
disable fork;
simulate_ts.kill();
end
join
// Update status
update_status();
// Compact immediate assertions
get_checks(lof_checks);
// Print report
print_report();
end
endtask
/* Run phase method used to run test
* @param phase : the phase scheduled for run_phase method
*/
virtual task run_phase(uvm_phase phase);
// Get parent of this test
uvm_component parent = get_parent();
// If the test haven't started and its parent is null, it should start from here
if((!started()) && (parent.get_name() == "")) begin
if(enable == 1) begin
pre_run();
// Run test body of this test suite
fork
begin
// Variable used to store the process id for start_up task
process start_ut_p;
fork
begin
start_ut_p = process::self();
start_ut();
disable fork;
end
join
start_ut_p.kill();
end
join
create_html_report();
post_run();
end
end
endtask
// }}}
// {{{ Reports
/* Get status as a string
* @return represents the status to be printed
*/
virtual function string get_status_as_string();
string nice_string = "";
string star = " ";
svaunit_status_type computed_test_status = get_status();
if(get_status() == SVAUNIT_FAIL) begin
star = "*";
end
nice_string = $sformatf("\n\t%s %s %s (%0d/%0d test cases PASSED)", star, get_test_name(),
computed_test_status.name(), get_nof_tests() - get_nof_tests_failed() - get_nof_tests_did_not_run(),
get_nof_tests());
return nice_string;
endfunction
/* Form the status of the test as a string
* @return a string which contains the status of test
*/
virtual function string get_status_tests();
string nice_string = "";
string extra = "";
// Get parent of this test
uvm_component parent = get_parent();
// If the test haven't started and it's parent is null, it should start from here
if(parent.get_name() != "") begin
extra = $sformatf("%s::", get_type_name());
end
nice_string = $sformatf("\n\n-------------------- %s test suite status --------------------\n", get_test_name());
nice_string = $sformatf("%s\t%s::%s\n", nice_string, get_type_name(), get_test_name());
foreach(lof_tests[test_index]) begin
nice_string = {nice_string, "\t\t ", lof_tests[test_index].get_status_tests()};
end
return nice_string;
endfunction
// Print status of test
virtual function void print_status();
string nice_string = "";
string star = " ";
svaunit_status_type computed_test_status = get_status();
if(get_status() == SVAUNIT_FAIL) begin
star = "*";
end
lof_tests.rsort(item) with (item.get_status() == SVAUNIT_FAIL);
nice_string = $sformatf("\n\n-------------------- %s test suite: Tests status statistics --------------------\n\n",
get_test_name());
nice_string = $sformatf("%s %s %s %s (%0d/%0d test cases PASSED)\n", nice_string, star, get_test_name(),
computed_test_status.name(), get_nof_tests() - get_nof_failures() - get_nof_tests_did_not_run(),
get_nof_tests());
foreach(lof_tests[test_index]) begin
nice_string = $sformatf("%s\t%s", nice_string, lof_tests[test_index].get_status_as_string());
end
nice_string = $sformatf("%s\n\n", nice_string);
`uvm_info(get_test_name(), nice_string, UVM_LOW)
endfunction
// Print the tests names which ran and the tests names which didn't run during simulation
virtual function void print_tests();
// Variable used to store the report string
string nice_string = "";
// Variable used to store the number of tests
int unsigned total_nof_tests = get_nof_tests();
// Variable used to store the number of active tests
int unsigned nof_active_tests = get_nof_active_tests();
string not_run_tests = get_tests_names_did_not_run();
nice_string = $sformatf("\n\n-------------------- %s test suite: Ran tests statistics --------------------\n\n", get_test_name());
// Form report string
nice_string = $sformatf("%s\t%0d/%0d Ran tests",
nice_string, nof_active_tests, total_nof_tests);
nice_string = $sformatf("%s\n\t%s\n\n", nice_string, get_tests_names_ran());
if(not_run_tests != "") begin
nice_string = $sformatf("\n%s\n\t%0d/%0d Tests did not run during simulation",
nice_string, total_nof_tests - nof_active_tests, total_nof_tests);
nice_string = $sformatf("%s\n\t%s\n\n", nice_string, not_run_tests);
end
`uvm_info(get_test_name(), nice_string, UVM_LOW)
endfunction
/* Form the test topology as a tree
* @param a_level : the level where the test is created
* @return a string representing the tree
*/
virtual function string form_tree(int a_level);
string extra = "";
string nice_string;
for(int level_idx = 0; level_idx < a_level; level_idx++) begin
extra = {"\t", extra};
end
if(a_level == 0) begin
extra = {"\t", extra};
end
nice_string = {extra, get_test_name()};
foreach(lof_tests[test_index]) begin
nice_string = {nice_string, "\n", extra, lof_tests[test_index].form_tree(a_level + 1)};
end
return nice_string;
endfunction
// }}}
endclass
`endif