Prettyprint all modules in the design hierarchy
From Verific Design Automation FAQ
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 (this step is optional).
- Traverse the design hierarchy and save all the modules 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 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()
{
const char *file_name = "test.v" ;
const char *top_name = "top" ;
const char *work_lib = "work" ;
if (!veri_file::Analyze(file_name, veri_file::VERILOG_2K /*Verilog 2000*/)) return 1 ;
if (veri_file::GetModule(top_name)) {
// Optional - statically elaborate all the top Verilog module. Return if any error shows up.
if (!veri_file::ElaborateStatic(top_name)) return 2 ; // 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) {
return 3 ; // 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);
}
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
SetItem *item = done.GetItem(module) ;
if (item) {
// Message::PrintLine("Been in module ", module->Name(), " before. Returning....") ;
return ; // We've already been here
}
// 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 module instance
VeriModule *mod = mod_inst ? mod_inst->GetInstantiatedModule() : 0 ; // The module instance is a module
if (mod) { // This is verilog module instantiation: need to go into that module
// Message::PrintLine("In module ", module->Name()) ;
// Message::PrintLine("Processing instance ", id->Name(), " of module ", mod->Name()); //, " in module ", module->Name()) ;
Accumulate(mod, done) ; // Traverse the instantiated module
}
}
// Insert the traversed module
// Message::PrintLine("Inserting module ", module->Name()) ;
done.Insert(module) ;
}
Input file test.v:
module top(a, b, c, d, e, f, out, m, n, o) ;
input a, b, c, d, e, f, m, n ;
output out, o ;
wire tmp1, tmp2 ;
mid1 i1(a, b, c, d, tmp1) ;
mid1 i2(a, d, e, f, tmp2) ;
mid1 i3(tmp1, tmp2, e, f, out) ;
bot bi(o, m, n);
endmodule
module mid1 (mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4, mid1_out,
mid1b_inp1, mid1b_inp2, mid1b_out) ;
input mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4 ;
output mid1_out ;
input mid1b_inp1, mid1b_inp2 ;
output mid1b_out ;
wire tmp1, tmp2 ;
mid2 m1(mid1_inp1, mid1_inp2, tmp1) ;
mid2 m2(mid1_inp3, mid1_inp4, tmp2) ;
mid2 m3(tmp1, tmp2, mid1_out) ;
bot b(mid1b_inp1, mid1b_inp2, mid1b_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, m, n, o) ;
input a, b, c, d, e, f, m, n ;
output out, o ;
wire tmp1, tmp2 ;
mid1 i1 (a, b, c, d, tmp1) ;
mid1 i2 (a, d, e, f, tmp2) ;
mid1 i3 (tmp1, tmp2, e, f, out) ;
bot bi (o, m, n) ;
endmodule
// Printing module mid1
module mid1 (mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4, mid1_out, mid1b_inp1, mid1b_inp2, mid1b_out) ;
input mid1_inp1, mid1_inp2, mid1_inp3, mid1_inp4 ;
output mid1_out ;
input mid1b_inp1, mid1b_inp2 ;
output mid1b_out ;
wire tmp1, tmp2 ;
mid2 m1 (mid1_inp1, mid1_inp2, tmp1) ;
mid2 m2 (mid1_inp3, mid1_inp4, tmp2) ;
mid2 m3 (tmp1, tmp2, mid1_out) ;
bot b (mid1b_inp1, mid1b_inp2, mid1b_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