Process -f file and explore the Netlist Database (C++)
From Verific Design Automation FAQ
#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()) ; } } }