/*----------------------------------------------------------------------------- * Copyright (c) 1997-2009 Mark Hummel DBA Raquette Software. * All rights reserved * * This file contains source code written by Raquette Software, * 68 Stewart Street, Franklin MA 02038. It may not be used without * express written permission. The expression of the information * contained herein is protected under federal copyright laws and * all copying without permission is prohibited and may be subject * to criminal penalties. The Author assumes no responsibility for * errors, omissions, or damages caused by the use of these programs * or from use of the information contained herein. * *----------------------------------------------------------------------------- */ /****************************************************************************** * * * example1.cc * - methods for example plugin * ****************************************************************************** */ #include "example1.h" /************************************************ CreateToolInstance - entry point for dll. Vrq will call this entry point (must be C code) to create and initialize the tool. If tool creation fails, return NULL and vrq will ignore DLL. ************************************************/ extern "C" { CBackend* CreateToolInstance() { /* * Only initialize the tool if it was built for * the running version of vrq. */ if( strcmp( VRQ_VERSION, VrqVersionString() ) ) { return NULL; } /* * Create tool and return it. */ return new CExample1(); } } /************************************************ Constructor - Initialize tool ************************************************/ CExample1::CExample1( ) { /* * Initialize local variables */ listNets = 0; listRegs = 0; /* * Register switches (plus args) for use in the vrq help system */ RegisterSwitch("+example1-list-nets", "print list of declared nets"); RegisterSwitch("+example1-list-regs", "print list of declared regs"); /* * Predeclare all the warning and error messages for later use. */ mVIDNR = Message::RegisterWarning( this, Message::eWARNING, "VIDNR", "variable '%s::%s' is declared but not referenced\n", "<module>", "<variable>" ); } /************************************************ AcceptAllPlusArgs - return TRUE if tool accepts arbitrary plusargs. ************************************************/ int CExample1::AcceptAllPlusArgs( void ) { /* * Tool does not support arbitary plusargs */ return FALSE; } /************************************************ HideTool - return TRUE if tool should be hidden from help system. This allows a tool to be functional and hidden. ***********************************************/ int CExample1::HideTool() { return FALSE; } /************************************************ IgnoreVrqComments - return TRUE if tool requires lexer to treat vrq translate_on/off pragmas as pure comments. ***********************************************/ int CExample1::IgnoreVrqComments() { return FALSE; } /************************************************ ResolveModules - return TRUE if tool requires all module references to be resolved. This is done by search specified library search paths. ***********************************************/ int CExample1::ResolveModules() { return FALSE; } /************************************************ ResolveInstance - return TRUE if tool requires the given module reference to be resolved. This is allows a tool to implement a fine grain filter on what must be resolved. Note this only called if ResolvedModules returns TRUE. ***********************************************/ int CExample1::ResolveInstance( CModule*, CInstance* ) { return FALSE; } /************************************************ Activate - This routine is called before a tool is invoked. It is only called once and will only be called if the tool will be used in a pipeline. ***********************************************/ void CExample1::Activate() { } /************************************************ GetToolName - return name of tool ************************************************/ char* CExample1::GetToolName( void ) { static char toolName[] = "example1"; return toolName; } /************************************************ GetToolDescription - return description of tool. This text is used in vrq help text, man pages, etc. ************************************************/ char* CExample1::GetToolDescription( void ) { static char toolDescription[] = "Example plugin that dumps a" " list of declare registers or nets"; return toolDescription; } /************************************************ FindDecls - callback routine used to gather a list of variable statistics. ***********************************************/ static CModule* currentModule = NULL; int FindDecls( CNode* n, void* arg ) { map<CDecl*,CExample1::DeclRecord>* d2r = (map<CDecl*,CExample1::DeclRecord>*)arg; CDecl* decl; switch( n->GetOp() ) { case eMODULE_DEF: currentModule = n->Arg<CModule*>(0); break; case ePORT_DECL: decl = n->Arg<CPortDir*>(0)->GetDecl(); if( decl ) { if( d2r->find(decl) == d2r->end() ) { (*d2r)[decl].decl = decl; (*d2r)[decl].module = NULL; (*d2r)[decl].declared = 0; (*d2r)[decl].refCount = 0; (*d2r)[decl].module = currentModule; } (*d2r)[decl].declared = 1; (*d2r)[decl].refCount++; (*d2r)[decl].module = currentModule; } break; case eREG_DECL: decl = n->Arg<CReg*>(0); if( d2r->find(decl) == d2r->end() ) { (*d2r)[decl].decl = decl; (*d2r)[decl].module = NULL; (*d2r)[decl].declared = 0; (*d2r)[decl].refCount = 0; (*d2r)[decl].module = currentModule; } (*d2r)[decl].declared = 1; break; case eNET_DECL: decl = n->Arg<CNet*>(0); if( d2r->find(decl) == d2r->end() ) { (*d2r)[decl].decl = decl; (*d2r)[decl].module = NULL; (*d2r)[decl].declared = 0; (*d2r)[decl].refCount = 0; (*d2r)[decl].module = currentModule; } (*d2r)[decl].declared = 1; break; case eREG_REF: decl = n->Arg<CReg*>(0); if( d2r->find(decl) == d2r->end() ) { (*d2r)[decl].decl = decl; (*d2r)[decl].module = NULL; (*d2r)[decl].declared = 0; (*d2r)[decl].refCount = 0; (*d2r)[decl].module = currentModule; } (*d2r)[decl].refCount++; break; case eNET_REF: decl = n->Arg<CNet*>(0); if( d2r->find(decl) == d2r->end() ) { (*d2r)[decl].decl = decl; (*d2r)[decl].module = NULL; (*d2r)[decl].declared = 0; (*d2r)[decl].refCount = 0; (*d2r)[decl].module = currentModule; } (*d2r)[decl].refCount++; break; } /* * Don't terminate search */ return 1; } /************************************************ Process - process a compilation unit ************************************************/ void CExample1::Process( list<CElement>& inputList, list<CElement>& outputList ) { /* * check whether switches have been specified. */ listNets = GetPlusArg( "example1-list-nets" ) != NULL; listRegs = GetPlusArg( "example1-list-regs" ) != NULL; /* * process each compilation unit */ list<CElement>::iterator ptr; for( ptr = inputList.begin(); ptr != inputList.end(); ++ptr ) { /* * Transverse the entire code tree for the given compilation * unit. For each node FindDecls will be called to * accumulate variable statistics. */ CNode* code = ptr->Code(); code->PreVisit1( FindDecls, &decl2Record ); } /* * iterate through the list of variables and flag * any that are declared but not referenced. */ map<CDecl*,DeclRecord>::iterator mptr; for( mptr = decl2Record.begin(); mptr != decl2Record.end(); ++mptr ) { int declared = mptr->second.declared; int refCount = mptr->second.refCount; CModule* module = mptr->second.module; CDecl* decl = mptr->second.decl; if( declared && refCount == 0 ) { message( decl->GetCoord(), mVIDNR, module->GetName(), decl->GetName() ); } } /* * iterate through the list of variables and dump the * statistics that have been collected. */ for( mptr = decl2Record.begin(); mptr != decl2Record.end(); ++mptr ) { int declared = mptr->second.declared; int refCount = mptr->second.refCount; CModule* module = mptr->second.module; CDecl* decl = mptr->second.decl; if( decl->GetClass() == eNET && !listNets ) { continue; } if( decl->GetClass() == eREG && !listRegs ) { continue; } logprintf( "decl %s::%s: declared=%d reference count=%d\n", module->GetName(), decl->GetName(), declared, refCount ); } }