In Verilog parsetree adding names to unnamed instances
From Verific Design Automation FAQ
In Verilog, each module instantiation should have a name. But name is optional for UDP instantiation and Verilog primitive instantiation.
Verific issues a warning for unnamed module instantiation:
test.v(16): WARNING: instantiating unknown module 'foo' (VERI-1063)
The warning is issued during elaboration because in analysis, it is not known whether the instantiated construct is a module, a UDP, or a primitive.
This application adds a name to each unnamed module instantiation. Note that this application has facilities to keep track of the scope of the instantiation statement.
#include <iostream>
#include "veri_file.h"
#include "VeriModule.h"
#include "VeriId.h"
#include "VeriExpression.h"
#include "VeriScope.h"
#include "Map.h"
using namespace std ;
#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif
class MyVisitor : public VeriVisitor
{
public:
MyVisitor() : VeriVisitor(), _scope_stack(0) { }
virtual ~MyVisitor() { }
virtual void VERI_VISIT(VeriModuleInstantiation, node)
{
VeriScope *current_scope = GetCurrentScope() ;
Array *inst_ids ;
inst_ids = node.GetIds() ;
unsigned i ;
VeriInstId *inst_id ;
FOREACH_ARRAY_ITEM(inst_ids, i, inst_id) {
if (!inst_id) continue ;
const char *inst_name = inst_id->InstName() ;
char *allocated_inst_name = 0 ;
if (!inst_name && current_scope) {
VeriIdDef *scope_id = current_scope->GetOwner();
unsigned uniq_no = 0 ;
char *suffix = Strings::itoa((int)(uniq_no)) ;
char *prefix = (scope_id && scope_id->Name()) ? Strings::save("unnamed_inst_", scope_id->Name(), "_") : Strings::save("unnamed_inst_") ;
allocated_inst_name = Strings::save(prefix, suffix) ;
while (current_scope->FindLocal(allocated_inst_name) && (uniq_no < 1000)) {
Strings::free(allocated_inst_name) ;
Strings::free(suffix) ;
suffix = Strings::itoa((int)(uniq_no)) ;
allocated_inst_name = Strings::save(prefix, suffix) ;
uniq_no++ ;
}
current_scope->Undeclare(inst_id) ;
inst_id->SetName(allocated_inst_name) ;
current_scope->Declare(inst_id, 0, 0) ;
Strings::free(allocated_inst_name) ;
Strings::free(suffix) ;
Strings::free(prefix) ;
}
}
}
virtual void PreAction(VeriTreeNode &node)
{
// Push the scope of the current node into the stack:
const VeriModuleItem *item = dynamic_cast<VeriModuleItem *>(&node) ;
VeriScope *scope = (item) ? item->GetScope() : 0 ;
if (scope) _scope_stack.InsertLast(scope) ;
}
virtual void PostAction(VeriTreeNode &node)
{
// Pop the scope of the current node from the stack:
const VeriModuleItem *item = dynamic_cast<VeriModuleItem *>(&node) ;
VeriScope *scope = (item) ? item->GetScope() : 0 ;
if (scope) (void) _scope_stack.RemoveLast() ;
}
// Get the current/active scope for the parse tree we are visiting:
VeriScope *GetCurrentScope() const { return (_scope_stack.Size()) ? (VeriScope *)_scope_stack.GetLast() : 0 ; }
private:
Array _scope_stack ;
} ;
int main() {
if (!veri_file::Analyze("test.v", veri_file::SYSTEM_VERILOG)) return 1 ;
veri_file::PrettyPrint ("pp_out_before.v.golden.new", 0) ;
MyVisitor mv ;
MapIter mi ;
VeriModule *mod ;
FOREACH_VERILOG_MODULE(mi, mod) {
if (!mod) continue ;
mod->Accept(mv) ;
}
veri_file::PrettyPrint ("pp_out_after.v.golden.new", 0) ;
return 0 ;
}