Prettyprint all modules in the design hierarchy
From Verific Design Automation FAQ
Revision as of 22:22, 28 July 2019 by Hoa (Talk | contribs) (Created page with "There is an API to prettyprint a module, and there is an API to prettyprint all modules in a library. But there is no single API to prettyprint all modules in the design hier...")
There is an API to prettyprint a module, and there is an API to prettyprint all modules in a library.
But there is no single API to prettyprint all modules in the design hierarchy.
To do so, you need to:
- Statically elaborate the top module. - Traverse the design hierarchy and save all the modules in the design in a Set. - Iterate over all items (modules) of the Set, and prettyprint each of them.
C++:
#include <iostream> #include <fstream> using namespace std; // Verific utilities #include "Array.h" // Make class Array available #include "Set.h" // Make class Set available #include "Message.h" // Make message handlers available #include "Strings.h" // Definition of class to manipulate copy, concatenate, create etc... // Verific command line interface #include "Commands.h" // Make command line interface available #include "ComRead.h" // Using Verific command 'analyze' as template for command line parsing // Verific Verilog parser #include "veri_file.h" // Make verilog reader available #include "VeriModule.h" // Definition of a VeriModule and VeriPrimitive #include "VeriExpression.h" // Definition of VeriName #include "VeriId.h" // Definitions of all verilog identifier nodes #include "VeriScope.h" #ifdef VERIFIC_NAMESPACE using namespace Verific ; #endif void Accumulate(VeriModule *module, Set &done); int main(int argc, const char **argv) { // Set-up main line command line. // This makes all options on the TCL command "analyze" available on this main command line. Command *mainline = new ComAnalyze() ; // Add the following options used in this application : mainline->Add(new StringArg("top","name of top-level module",0/*not optional*/)) ; // Default command line if no arguments given : const char *default_argv[5] = {"parse_tree_hierarchy_traversal", "test.v", "-top", "top", 0} ; if (argc==1) { argc = 4 ; argv = default_argv ; } // Now parse the command line if (!mainline->ParseArgs(argc, argv)) { mainline->Usage() ; delete mainline ; return 1 ; /* Command line failed */ } // Same for SystemVerilog // veri_file::SetDefaultLibraryPath(lib_path) ; // Parse the 'analyze' command : if (!mainline->Process(0/*no tcl interpreter needed*/)) { mainline->Usage() ; delete mainline ; return 2 ; // failure in analysis } // Now get top design name : const char *top_name = mainline->StringVal("top") ; VERIFIC_ASSERT(top_name) ; // 'top' is not optional, so ParseArgs would already have failed. // First get the library (from the 'analyze' command) : const char *work_lib = mainline->StringVal("work") ; if (!work_lib) work_lib = "work" ; // default library name if (veri_file::GetModule(top_name)) { // Top level unit is a Verilog module // Statically elaborate all the Verilog modules. Return if any error shows up. if (!veri_file::ElaborateStatic(top_name)) return 3 ; // statically elaborates all verilog modules in the "work" libarary VeriModule *top_module = veri_file::GetModule(top_name) ; // Get the pointer to the top-level module if (!top_module) { delete mainline ; return 4 ; // Exit from application if there is no top module by the given name in the given Verilog designs } // Prettyprint only top module char *topfilename = Strings::save(top_module->Name(), "_pp.v"); veri_file::PrettyPrint(topfilename, top_module->Name(), work_lib); Strings::free(topfilename); top_module->Info("Start collecting modules in '%s' hierachy", top_module->Name()) ; Set modules(POINTER_HASH); Accumulate(top_module, modules); top_module->Info("Prettyprint all modules in '%s' hierachy", top_module->Name()) ; // Prettyprint all modules in the design hiearchy under top_module char *tophierfilename = Strings::save(top_module->Name(), "_hier_pp.v"); std::ofstream f(tophierfilename, std::ios::out) ; VeriModule *module ; SetIter si ; // FOREACH_SET_ITEM(&modules, si, &module) { // if you want to prettyprint top module last FOREACH_SET_ITEM_BACK(&modules, si, &module) { // if you want to prettyprint top module first if (module) { Message::PrintLine("Prettyprinting module : ", module->Name()) ; f << "// Printing module " << module->Name() << endl; module->PrettyPrint(f, 0); } } f.close(); Strings::free(tophierfilename); } delete mainline ; return 0 ; // all good } // This function is recursive in nature, and collects all other // modules that the incoming module depends on in a container. void Accumulate(VeriModule *module, Set &done) { if (!module) return ; // Ignore NULL netlists // Get the scope of the module: VeriScope *scope = module->GetScope() ; // Find all the declared ids in this scope: Map *ids = scope ? scope->DeclArea() : 0 ; MapIter mi ; VeriIdDef *id ; FOREACH_MAP_ITEM(ids, mi, 0, &id) { // Traverse declared ids if (!id || !id->IsInst()) continue ; // Consider only the instance ids VeriModuleInstantiation *mod_inst = id->GetModuleInstance() ; // Take the moduleinstance VeriModule *mod = mod_inst ? mod_inst->GetInstantiatedModule() : 0 ; // The module instance is a module if (mod) { // This is verilog module insatantiation: need to go into that module Message::PrintLine("Processing instance : ", id->Name(), ", module: ", mod->Name()) ; SetItem *item = done.GetItem(module) ; if (item) { return ; // We've already been here } Accumulate(mod, done) ; // Traverse the instantiated module } } // Insert the traversed module done.Insert(module) ; }
input test.sv:
module top(a, b, c, d, e, f, out) ; input a, b, c, d, e, f ; output out ; wire tmp1, tmp2 ; mid1 i1(a, b, c, d, tmp1) ; mid1 i2(a, d, e, f, tmp2) ; mid1 i3(tmp1, tmp2, e, f, out) ; endmodule module mid1 (mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4, mid1_out) ; input mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4 ; output mid1_out ; wire tmp1, tmp2 ; mid2 m1(mid1_inp1, mid1_inp2, tmp1) ; mid2 m2(mid1_inp3, mid1_inp4, tmp2) ; mid2 m3(tmp1, tmp2, mid1_out) ; endmodule module mid2 (mid2_inp1, mid2_inp2, mid2_out) ; input mid2_inp1, mid2_inp2 ; output mid2_out ; bot b(mid2_inp1, mid2_inp2, mid2_out) ; endmodule module bot (bot_inp1, bot_inp2, bot_out) ; input bot_inp1, bot_inp2 ; output bot_out ; assign bot_out = bot_inp1 & bot_inp2 ; endmodule
Output file top_hier_pp.v:
// Printing module top module top (a, b, c, d, e, f, out) ; input a, b, c, d, e, f ; output out ; wire tmp1, tmp2 ; mid1 i1 (a, b, c, d, tmp1) ; mid1 i2 (a, d, e, f, tmp2) ; mid1 i3 (tmp1, tmp2, e, f, out) ; endmodule // Printing module mid1 module mid1 (mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4, mid1_out) ; input mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4 ; output mid1_out ; wire tmp1, tmp2 ; mid2 m1 (mid1_inp1, mid1_inp2, tmp1) ; mid2 m2 (mid1_inp3, mid1_inp4, tmp2) ; mid2 m3 (tmp1, tmp2, mid1_out) ; endmodule // Printing module mid2 module mid2 (mid2_inp1, mid2_inp2, mid2_out) ; input mid2_inp1, mid2_inp2 ; output mid2_out ; bot b (mid2_inp1, mid2_inp2, mid2_out) ; endmodule // Printing module bot module bot (bot_inp1, bot_inp2, bot_out) ; input bot_inp1, bot_inp2 ; output bot_out ; assign bot_out = (bot_inp1 & bot_inp2) ; endmodule