In Verilog parsetree adding names to unnamed instances

From Verific Design Automation FAQ
Revision as of 12:58, 24 April 2023 by Hoa (Talk | contribs) (Created page with "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...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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++ ;
                }
                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 ;
}