Process -f file and explore the Netlist Database
From Verific Design Automation FAQ
C++:
#include "Map.h" // Make associated hash table class Map available
#include "Array.h" // Make associated hash table class Array available
#include "Set.h" // Make associated hash table class Set available
#include "Message.h" // Make message handlers available
#include "veri_file.h" // Make verilog reader available
#include "DataBase.h" // Make (hierarchical netlist) database API available
#include "RuntimeFlags.h"
#include <string.h>
#include <stdio.h>
#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif
void Accumulate(Netlist *netlist, Set &done) ;
void PrintInstances(Netlist *netlist) ;
void PrintInterface(Netlist *netlist) ;
int main(int argc, char **argv)
{
if (argc < 2) Message::PrintLine("Default input -f file: files.f. Specify command line argument to override") ;
///////////////////
// F-file processing
///////////////////
const char *f_file_name = 0 ;
if (argc>1) {
f_file_name = argv[1] ; // Set the file name as specified by the user
} else {
f_file_name = "files.f" ; // Set default file name
}
// NO_MODE: mode keyed off the file dialect - MFCU Verilog 2000 and SFCU for SystemVerilog
unsigned cu_mode = veri_file::NO_MODE ;
// UNDEFINED: dialect keyed off the file extension - .v for Verilog 2000 and .sv for SystemVerilog
unsigned f_analysis_mode = veri_file::UNDEFINED ;
Array *file_names = veri_file::ProcessFFile(f_file_name, veri_file::F_FILE_NONE /* or veri_file::F_FILE_CAPITAL */, f_analysis_mode) ;
if (!file_names) return 1 ; // Failed to process the F file
Array veri_files ;
unsigned i ;
char *file_name ;
FOREACH_ARRAY_ITEM(file_names, i, file_name) {
if (strstr(file_name, ".v") || strstr(file_name, ".sv")) {
veri_files.InsertLast(file_name) ;
} else {
printf("File %s has an invalid extension - ignored.\n", file_name) ;
}
}
// Next, check whether the analysis mode is set from -f file:
if (f_analysis_mode == veri_file::UNDEFINED) {
// Default to Verilog 2001:
f_analysis_mode = veri_file::VERILOG_2K ;
// But treat .sv files as SystemVerilog:
veri_file::AddFileExtMode(".sv", veri_file::SYSTEM_VERILOG) ;
}
///////////////////
// Analysis
///////////////////
// Analyze all the Verilog files at-once
if (!veri_file::AnalyzeMultipleFiles(&veri_files, f_analysis_mode, "work", cu_mode)) return 1 ;
// Everything is done, clean up the file names and the allocated array:
while (file_names->Size()) Strings::free((char *)file_names->RemoveLast()) ;
delete file_names ;
///////////////////
// Elaboration
///////////////////
// Optional:
// This will do a "lightweighed" RTL elaboration, skipping all "always" constructs.
// It's faster than full elaboration and will ignore many errors.
RuntimeFlags::SetVar ("veri_ignore_always_constructs", 1) ;
if (!veri_file::ElaborateAll("work")) {
// Here, design analysis and elaboration failed
return 1 ;
}
///////////////////
// Exploring the netlist database
///////////////////
// Get a handle to the top-level netlist
Netlist *top = Netlist::PresentDesign() ;
if (!top) {
Message::PrintLine("Cannot find any handle to the top-level netlist") ;
return 4 ;
}
// Print out module that we have handle to
Message::Msg(VERIFIC_INFO, 0, top->Linefile(), "top level design is %s(%s)",
top->Owner()->Name(), top->Name()) ;
// Lets accumulate all netlist
Set netlists(POINTER_HASH) ;
Accumulate(top, netlists) ;
// Names of netlists along with the instantiation reference count.
Netlist *netlist ;
SetIter si ;
Message::PrintLine("") ;
FOREACH_SET_ITEM(&netlists, si, &netlist) {
if (netlist->IsUserDeclared()) { // only report user-declared modules
Message::PrintLine("") ;
Message::Msg(VERIFIC_INFO, 0, netlist->Linefile(), "module %s was instantiated %d times",
netlist->Owner()->Name(), netlist->NumOfRefs()) ;
PrintInterface(netlist) ;
PrintInstances(netlist) ;
}
}
return 0 ;
}
// This function is recursive in nature, and collects all other
// netlists that the incoming netlist depends on in a container.
void Accumulate(Netlist *netlist, Set &done)
{
if (!netlist) return ; // Ignore NULL netlists
SetItem *item = done.GetItem(netlist) ;
if (item) {
return ; // We've already been here
}
Instance *inst ;
MapIter mi ;
FOREACH_INSTANCE_OF_NETLIST(netlist, mi, inst) {
// Now go into the netlist associated with the instance
Accumulate(inst->View(), done) ;
}
// Insert the traversed Netlist
done.Insert(netlist) ;
}
// Print all instances of the netlist
void PrintInstances (Netlist *netlist)
{
if (!netlist) return ; // Ignore NULL netlists
if (!netlist->IsUserDeclared()) return ; // Ignore Verific operators and primitives
Instance *inst ;
MapIter mi ;
FOREACH_INSTANCE_OF_NETLIST(netlist, mi, inst) {
if (inst->IsUserDeclared()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Instance %s of module %s", inst->Name(), inst->View()->Owner()->Name()) ;
}
}
}
// Print all ports of the netlist
void PrintInterface (Netlist *netlist)
{
if (!netlist) return ; // Ignore NULL netlists
if (!netlist->IsUserDeclared()) return ; // Ignore Verific operators and primitives
Port *port ;
MapIter mi ;
FOREACH_PORT_OF_NETLIST(netlist, mi, port) {
if (!port) continue ;
if (port->Bus()) continue ;
if (port->IsInout()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Inout port %s", port->Name()) ;
}
if (port->IsOutput()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Output port %s", port->Name()) ;
}
if (port->IsInput()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Input port %s", port->Name()) ;
}
}
PortBus *port_bus ;
FOREACH_PORTBUS_OF_NETLIST(netlist, mi, port_bus) {
if (!port_bus) continue ;
if (port_bus->IsInout()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Inout port_bus %s[%d:%d]", port_bus->Name(), port_bus->LeftIndex(), port_bus->RightIndex()) ;
}
if (port_bus->IsOutput()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Output port_bus %s[%d:%d]", port_bus->Name(), port_bus->LeftIndex(), port_bus->RightIndex()) ;
}
if (port_bus->IsInput()) {
Message::Msg(VERIFIC_NONE, 0, 0, "Input port_bus %s[%d:%d]", port_bus->Name(), port_bus->LeftIndex(), port_bus->RightIndex()) ;
}
}
}