blob: 22cb4d7cb0de09fb65ff6e5fa375890981015ae3 [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_sequence.svh
* PROJECT: svaunit
* Description: SVAUnit sequencer class definition and SVAUnit base sequence calss definition
*******************************************************************************/
`ifndef SVAUNIT_SEQUENCE_SVH
`define SVAUNIT_SEQUENCE_SVH
// SVAUnit sequencer class
class svaunit_sequencer extends uvm_virtual_sequencer;
`uvm_component_utils(svaunit_sequencer)
// Pointer to VPI wrapper component
svaunit_vpi_wrapper vpiw;
/* Constructor for an svaunit_sequencer
* @param name : instance name for svaunit_sequencer object
* @param parent : hierarchical parent for svaunit_sequencer
*/
function new(string name = "svaunit_sequencer", uvm_component parent);
super.new(name, parent);
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);
// Get the VPI wrapper from UVM config db
if (!uvm_config_db#(svaunit_vpi_wrapper)::get(uvm_root::get(), "*", "VPIW", vpiw)) begin
`uvm_fatal("SVAUNIT_NO_VPIW_SEQUENCER_ERR",
"SVAUnit VPI wrapper for the %s SVAUnit sequencer is not set! Please enable SVAUnit package!")
end
endfunction
endclass
// SVAUnit base virtual sequence
class svaunit_base_sequence extends uvm_sequence;
`uvm_object_utils(svaunit_base_sequence)
`uvm_declare_p_sequencer(svaunit_sequencer)
// Pointer to VPI wrapper
svaunit_vpi_wrapper vpiw;
// When this bit is 1, the sequence should stop
bit stop_test;
// Stores the name of the test where this sequence is added
local string test_name;
// Stores all tests names which started from this sequence
local string child_name[$];
// List of immediate assertions tested during a specific test
local svaunit_immediate_assertion_info lof_checks[$];
// Stores the fact that the list with checks was updated or not
local bit update_lof_checks;
/* Constructor for svaunit_base_sequence
* @param name : instance name for svaunit_base_sequence object
*/
function new(string name = "svaunit_base_sequence");
super.new(name);
// Get the VPI wrapper from UVM config db
if (!uvm_config_db#(svaunit_vpi_wrapper)::get(uvm_root::get(), "*", "VPIW", vpiw)) begin
`uvm_fatal("SVAUNIT_NO_VPIW_SEQUENCER_ERR",
"SVAUnit VPI wrapper for the %s SVAUnit sequencer is not set! Please enable SVAUnit package!")
end
update_lof_checks = 0;
stop_test = 0;
endfunction
/* Get stop bit for test
* @return the stop bit for test
*/
virtual function bit get_stop();
return stop_test;
endfunction
/* Get a list with all immediate assertions tested into tests
* @param a_checks : a list with all immediate assertions tested
*/
local function void get_checks(ref svaunit_immediate_assertion_info a_checks[$]);
if(update_lof_checks == 0) begin
vpiw.get_checks_for_test(get_test_name(), a_checks);
// Get the checks used in each test
foreach(child_name[child_index]) begin
vpiw.get_checks_for_test(child_name[child_index], a_checks);
end
update_lof_checks = 1;
end
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 report = "";
for(int level_idx = 0; level_idx < (a_level - 1); level_idx++) begin
extra = {"\t", extra};
end
if(a_level == 0) begin
extra = {"\t", extra};
end
report = {extra, get_test_name()};
foreach(child_name[index]) begin
extra = "";
for(int level_idx = 0; level_idx < (a_level + index + 2) ; level_idx++) begin
extra = {"\t", extra};
end
report = {report, "\n", extra, child_name[index]};
end
return report;
endfunction
// This task is called before the optional execution of pre_body and it is used to set the test name
virtual task pre_start();
uvm_sequence_base parent;
svaunit_base_sequence seq_parent;
string current_test_name;
super.pre_start();
parent = get_parent_sequence();
if(parent != null) begin
if(parent.get_name() == "") begin
current_test_name = $sformatf("%s", get_name());
end else begin
if(parent.get_name() == "uvm_test_top") begin
current_test_name = $sformatf("%s.%s", parent.get_type_name(), get_name());
end else begin
if(get_name() == "uvm_test_top") begin
current_test_name = $sformatf("%s", get_name());
end else begin
if($cast(seq_parent, parent)) begin
current_test_name = $sformatf("%s.%s", seq_parent.get_test_name(), get_name());
child_name.push_back($sformatf("%s", current_test_name));
set_child_name(child_name[child_name.size() - 1]);
end
end
end
end
end else begin
current_test_name = get_name();
end
set_test_name(current_test_name);
vpiw.set_test_name_vpi(current_test_name);
begin
uvm_component seqr_parent = p_sequencer.get_parent();
svaunit_base test;
if($cast(test, seqr_parent)) begin
test.sequence_name.push_back(current_test_name);
end
end
endtask
// Print a report for all checks tested for the current unit test
virtual function void print_checks();
get_checks(lof_checks);
vpiw.print_checks_from_specific_list(get_test_name(), lof_checks);
endfunction
// Print a report for all checks tested for the SVAs
virtual function void print_sva_and_checks();
string a_test_name = get_test_name();
get_checks(lof_checks);
vpiw.print_sva_and_checks_for_specific_list(a_test_name, lof_checks);
endfunction
// Print a report for all SVA which have failed
virtual function void print_failed_sva();
string crt_test_name = get_test_name();
get_checks(lof_checks);
vpiw.print_failed_sva_for_specific_list(crt_test_name, lof_checks);
endfunction
// Print the SVAUnit topology
virtual function void print_tree();
string report = "";
get_checks(lof_checks);
report = $sformatf("\n%s", form_tree(0));
`uvm_info(get_test_name(), report, UVM_LOW)
endfunction
// Print information about SVAUNIT checks
virtual function void print_tests();
get_checks(lof_checks);
endfunction
// Print status of test
virtual function void print_status();
get_checks(lof_checks);
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
*/
local function void get_sva_tested_names(ref string a_tested_sva_names[$]);
svaunit_concurrent_assertion_info tested_sva[$];
foreach(child_name[child_index]) begin
vpiw.get_sva_tested(child_name[child_index], tested_sva);
vpiw.get_sva_tested_names(tested_sva, a_tested_sva_names);
end
endfunction
/* Get the names of the SVAs which were not tested during test
* @param a_not_tested_sva : the names of the SVAs which were not tested during test
*/
local function void get_sva_not_tested_names(ref string a_not_tested_sva[$]);
// 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 lof_not_tested_sva[$];
int not_tested_index[$];
int n_tested_index[$];
svaunit_concurrent_assertion_info not_tested_sva[$];
foreach(child_name[child_index]) begin
vpiw.get_sva_not_tested(child_name[child_index], not_tested_sva);
vpiw.get_sva_not_tested_names(not_tested_sva, lof_not_tested_sva);
end
// Get tested SVAs
get_sva_tested_names(tested_sva_names);
foreach(lof_not_tested_sva[sva_index]) begin
n_tested_index = tested_sva_names.find_index() with (item == lof_not_tested_sva[sva_index]);
if(n_tested_index.size() == 0) begin
not_tested_index = a_not_tested_sva.find_index() with
(item == lof_not_tested_sva[sva_index]);
if(not_tested_index.size() == 0) begin
a_not_tested_sva.push_back(lof_not_tested_sva[sva_index]);
end
end
end
endfunction
// Print a list with all SVAs
virtual function void print_sva();
// Variable used to store the report string
string report = "";
// Variable used to store the SVA names which were tested
string tested_sva_names[$];
// Variable used to store the SVA names which were not tested
string not_tested_sva[$];
// Variable used to store the number of tested SVA
int unsigned nof_tested_sva;
// Variable used to store the number of not tested SVA
int unsigned nof_not_tested_sva;
get_sva_tested_names(tested_sva_names);
get_sva_not_tested_names(not_tested_sva);
nof_tested_sva = tested_sva_names.size();
nof_not_tested_sva = not_tested_sva.size();
// Form report string
report = $sformatf("\n\n-------------------- %s : SVAs statistics --------------------\n", get_test_name());
report = $sformatf("%s\n\t%0d/%0d SVA were exercised",
report, nof_tested_sva, nof_not_tested_sva + nof_tested_sva);
foreach(tested_sva_names[index]) begin
report = $sformatf("%s\n\t\t%s", report, tested_sva_names[index]);
end
// Verify if there were SVAs which have not been tested. In this case, in the report will appear also the SVAs
// which were not tested
if(nof_not_tested_sva > 0) begin
report = $sformatf("%s\n\n\t%0d SVA were not exercised", report, nof_not_tested_sva);
foreach(not_tested_sva[index]) begin
report = $sformatf("%s\n\t\t%s", report, not_tested_sva[index]);
end
end
report = $sformatf("%s\n", report);
`uvm_info(get_test_name(), report, UVM_LOW)
endfunction
// Print report for current test suite
virtual function void print_report();
get_checks(lof_checks);
print_tree();
print_status();
print_tests();
print_sva();
print_checks();
print_sva_and_checks();
print_failed_sva();
endfunction
/* Add child name into parent list
* @param a_child_name : the child name to be added inside list
*/
local function void set_child_name(string a_child_name);
uvm_sequence_base parent;
svaunit_base_sequence seq_parent;
parent = get_parent_sequence();
if(parent != null) begin
if($cast(seq_parent, parent)) begin
seq_parent.child_name.push_back($sformatf("%s",a_child_name));
seq_parent.set_child_name(a_child_name);
end
end
endfunction
/* Set the name of the test where the sequence is registered
* @param a_test_name : the test name to de added
*/
local function void set_test_name(string a_test_name);
test_name = a_test_name;
endfunction
/* Get the name of the test where the sequence is registered
* @return the test name
*/
virtual function string get_test_name();
return test_name;
endfunction
// Will start a scenario
virtual task body();
`uvm_info(get_test_name(), "Start a new sequence", UVM_LOW)
endtask
endclass
`endif