This example plugin searches the parsed code and finds register and net declarations and references.
A report of whether the variables are declared and how many times they are referenced is printed. It also issues warnings for any variables that are declared but not referenced.
The makefile for building the plugin (for linux based systems) follows (Makefile-example1):
#/*----------------------------------------------------------------------------- # * 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. # * # *----------------------------------------------------------------------------- # */ # # Extract installation flags and paths for vrq # VRQ_VERSION = $(shell vrq --version|head -n 1|cut -c 5-|cut -d , -f1) PLUGIN_DIR = $(shell vrq --pkglibdir) INCLUDE_DIR = $(shell vrq --includedir) CXXFLAGS = $(shell vrq --cflags) LDFLAGS = $(shell vrq --ldflags) # # name of plugin # PLUGIN=example1 # # Build object file # all: $(PLUGIN).so $(PLUGIN).o: $(PLUGIN).cc $(PLUGIN).h $(CXX) -I . -I $(INCLUDE_DIR) $(CXXFLAGS) \ -DVRQ_VERSION=\"$(VRQ_VERSION)\" -c $< -fPIC -DPIC -o $@ # # Build DLL # $(PLUGIN).so: $(PLUGIN).o $(CXX) $(LDFLAGS) -shared $< -Wl,-soname -Wl,$@ -o $@ # # Install plugin # install: $(PLUGIN).so install -c '$<' $(PLUGIN_DIR) # # Print installation flags and paths # env: echo "VRQ_VERSION: $(VRQ_VERSION)" echo "PLUGIN_DIR: $(PLUGIN_DIR)" echo "INCLUDE_DIR: $(INCLUDE_DIR)" echo "CXXFLAGS: $(CXXFLAGS)" echo "LDFLAGS: $(LDFLAGS)" # # remove built files # clean: -rm $(PLUGIN).o $(PLUGIN).so
The header file for the plugin is below (example1.h):
/*----------------------------------------------------------------------------- * 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.h * - example plugin * - * ****************************************************************************** */ #ifndef EXAMPLE1_H #define EXAMPLE1_H /* * include vrq headers */ #include "plugin.h" #include <map> /* * Plugin tools implement a subclass of CBackend. */ class CExample1 : public CBackend { private: Message* mVIDNR; // error message object int listNets; // non-zero if +example-list-nets has // been specified int listRegs; // non-zero if +example-list-regs has // been specified public: /* * data structure used to record variable info */ struct DeclRecord { CDecl* decl; // declaration object CModule* module; // containing module int refCount; // number of references to declaration int declared; // variable has been explicitly declared }; private: map<CDecl*,DeclRecord> decl2Record; // map of variable to // info data structure. public: /* * Methods */ CExample1( void ); virtual char* GetToolName( void ); virtual char* GetToolDescription( void ); virtual int AcceptAllPlusArgs( void ); virtual int HideTool(); virtual int IgnoreVrqComments(); virtual int ResolveModules(); virtual int ResolveInstance( CModule*, CInstance* ); virtual void Activate(); virtual void Process( list<CElement>& inputList, list<CElement>& outputList ); }; #endif // EXAMPLE1_H
The source for the plugin follows (example1.cc):
/*----------------------------------------------------------------------------- * 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 ); } }