PageRenderTime 62ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/vrq-1.0.88/src/main.cc

#
C++ | 1464 lines | 1037 code | 87 blank | 340 comment | 268 complexity | 44fe90e53ee1fc19d5c8c0b6b44be4e6 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. /*****************************************************************************
  2. * Copyright (C) 1997-2007, Mark Hummel
  3. * This file is part of Vrq.
  4. *
  5. * Vrq is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * Vrq is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor,
  18. * Boston, MA 02110-1301 USA
  19. *****************************************************************************
  20. */
  21. /******************************************************************************
  22. *
  23. *
  24. * main.cpp
  25. * - simulator startup code
  26. *
  27. *
  28. ******************************************************************************
  29. */
  30. /**
  31. * \mainpage
  32. * VRQ is modular verilog parser that supports plugin tools to process
  33. * verilog. Plugin tools are created as independent DLLs. The tools to
  34. * be invoked are specified on the command line. Multiple tools may be
  35. * invoke in a pipeline fashion within a single execution of vrq. A few
  36. * plugin tools are natively compiled into vrq, others are supplied as
  37. * separate executables. Vrq is pretty close to fully compliant with
  38. * the verilog 2005 specification, however not all tools support all
  39. * constructs.
  40. *
  41. * \section history History
  42. * VRQ was written over 10 years ago as part of my design and verification
  43. * consulting business. Over the years its been generalized to be a generic
  44. * front end parser with plugin backend customizable tools. I've choosen to
  45. * release it as Open Source Software to others may benefit from it as well.
  46. * It has been used in multiple startups and Fortune 500 companies to develop
  47. * ASICs and full custom components. In particular the \ref xprop_plugin is
  48. * one of it's most unique features as when it is used properly it can greatly
  49. * reduce the need for gate level simulation.
  50. *
  51. * \section further_info Further Info
  52. * - \ref quick_start
  53. * - \ref plugin_list
  54. * - \ref faq
  55. * - \ref manpage
  56. * - \ref plugin_info
  57. *
  58. * \page manpage Man Page
  59. * \htmlinclude vrq.1.html
  60. *
  61. * \page faq Frequently Asked Questions
  62. * \htmlinclude faq.html
  63. *
  64. * \page plugin_list Plugin List
  65. * - \ref dump_plugin
  66. * - \ref xprop_plugin
  67. * - sim
  68. * - builder
  69. * - coverage
  70. * - stats
  71. * - flatten
  72. * - \ref filter_plugin
  73. *
  74. * \page quick_start Quick Start
  75. * \section switches Switches
  76. * The parser has a number of switches that control the parsing of files.
  77. * Below is detail on a subset of the switches. For a complete list see the
  78. * \ref manpage .
  79. * - -y <directory> This switch may be used to specify a verilog library
  80. * search path for tools that require modules to be resolved.
  81. * - -v <lib_filename> This switch may be used to specify a verilog library
  82. * file for tools that require modules to be resolved.
  83. * - +libext+<extension> This switch may be used to specify the library
  84. * file suffix (used with the -y switch). Multiple extensions may be
  85. * specified by appending more extensions: +libext+<ext1>+<ext2>+...
  86. * - -infervectors This switch will allow the parser to infer register
  87. * definitions and vector wire definitions.
  88. * - -macrocheck This switch will cause the use of undefined macros to
  89. * be flagged as errors.
  90. * - -keeptickdefines This switch makes a best effort attempt to keep
  91. * tick defines and `include statements in the code (EXPERIMENTAL). `include
  92. * statements are keep if the include file is composed solely of pragmas,
  93. * comments and `define statements. `variables are evaluated if their
  94. * definition is in the same preprocessor zone as their instantiation.
  95. * Command line switches are in zone by themselves. Each compilation unit
  96. * (e.g. verilog inpug file) starts a new zone. Included files are part of the
  97. * zone of the including file. -passthru regions start a new zone. `ifdef
  98. * and `ifndef regions start a new zone if they are dependent upon undefined
  99. * preprocessor variables or are dependent upon preprocessor variable
  100. * defined in another zone. One of the side effects of enabling this
  101. * switch is that `define and `include statements can only occur on statement
  102. * boundries in the source code, otherwise a parsing error will result.
  103. * - +incdir+<directory> This switch will cause 'directory' to be searched
  104. * to resolve `include preprocessor directives. Multiple paths may be
  105. * specified by either using +incdir+ switches or by specifing multiple i
  106. * directories: +incdir+<dir1>+<dir2>+....
  107. * - -allowmissingincludes This switch will ignore `include preprocessor
  108. * directives that cannot be resolved.
  109. * - +define+<name>=<val> This switch specifies `define variables on
  110. * the command line.
  111. * - +<name>+<val> This switch is used to specify plusargs for tools
  112. * that use them.
  113. * - -pragma <regexp> This switch is used to identify classes of comments
  114. * as pragmas. Vrq will ensure that pragmas are not move relative to the
  115. * code they are embedded in. Note a side effect of using pragmas is that
  116. * vrq only allows pragmas in very specific locations in the code. Vrq
  117. * uses regcomp to process the match. Please see the 'regcomp' man page
  118. * for the format of 'regexp'. Multiple -pragma switch may appear on the
  119. * command line. If no -pragma switch is specified, vrq will make all i
  120. * // synopsys ..... and comments as pragmas.
  121. * - -passthru <name> This switch can be used to create a label to identify
  122. * regions of the source code that vrq should ignore and pass though
  123. * verbatim. These regions of code will be treated as comments and
  124. * `define substitution will be performed. To use the label use
  125. * `ifdef/`endif and `ifndef/`endif pairs to flags the regions as
  126. * shown below:
  127. * \code
  128. * `ifdef label
  129. * put code here that you want to pass through
  130. * `endif
  131. *
  132. * or
  133. *
  134. * `ifndef
  135. * put code here that you want to pass through
  136. * `endif
  137. * \endcode
  138. *
  139. * \section tool_pipelines Tool Pipelines
  140. * Vrq parses each file creating an Abstract Syntax Tree (AST) for each file.
  141. * This vector of AST's is passed on through a filter pipeline. Each filter
  142. * in the pipeline is specified using the -tool <toolname> switch. A filter
  143. * always takes a vector of AST's as input and optionally outputs a vector
  144. * of AST's. If a pipeline is specified where the final filter produces
  145. * AST's, vrq will automatically append the 'dump' tool to the end of the
  146. * pipeline.
  147. *
  148. * For instance if the following switches are used; -tool filter1 -tool filter2
  149. * is specified, vrq will create the following pipeline:
  150. * Parser -> filter1 -> filter2 -> dump
  151. *
  152. * Some tools are compiled in, others come with the vrq distribution and
  153. * are compiled as DLLs placed in the plugin dir specified at vrq install
  154. * time. The search path for plugins may be augmented by using the PLUGIN_DIR
  155. * environment variable. ie PLUGIN_DIR=path1:path2:path3. Third parties can
  156. * create their own filters using the vrq API. If these plugins are placed
  157. * in the plugin search path, vrq will automatically recognize them.
  158. *
  159. * Each AST is tagged by the parser with the input file name it was
  160. * derived from. Tools may modify these names and trees. Tools may also
  161. * expand or contract the number of AST in the vector.
  162. */
  163. #include <config.h>
  164. #include <stdio.h>
  165. #include <string.h>
  166. #include <unistd.h>
  167. #include <set>
  168. #include <vector>
  169. #include <list>
  170. #include <map>
  171. //#include <dlfcn.h>
  172. #include <sys/types.h>
  173. #include <dirent.h>
  174. #include "glue.h"
  175. #include "ltdl.h"
  176. #include "cobstack.h"
  177. #include "csymbol.h"
  178. #include "cvector.h"
  179. #include "cnode.h"
  180. #include "lex.h"
  181. #include "main.h"
  182. #include "csymtab.h"
  183. #include "cmacro.h"
  184. #include "cmodule.h"
  185. #include "cinstance.h"
  186. #include "systask.h"
  187. #include "build.h"
  188. #ifdef BUILTIN_SIM_PLUGIN
  189. #include "../plugin/sim/csim.h"
  190. #endif
  191. /*
  192. * add tool includes here
  193. */
  194. #include "cxprop.h"
  195. #include "cdumpverilog.h"
  196. map<string,CBackend*> tools;
  197. Message* mCRMOD;
  198. CObstack thePermStack( "permStack" );
  199. CObstack* permStack = &thePermStack;
  200. CObstack theUnitStack( "unitStack" );
  201. CObstack* unitStack = &theUnitStack;
  202. CObstack thePluginStack( "pluginStack" );
  203. CObstack* pluginStack = &thePluginStack;
  204. CObstack theTokenStack( "tokenStack" );
  205. CObstack* tokenStack = &theTokenStack;
  206. /*
  207. * set default logfile to stdout
  208. */
  209. FILE* logfile = stdout;
  210. /*
  211. * this must be instantiated here so it will
  212. * have a valid memmgr (permMgr).
  213. */
  214. list<CObstack*> CNode::stackList;
  215. /*
  216. * contains current definitions for macros
  217. * this namespace is global
  218. */
  219. CSymtab<CMacro> macroSymtab;
  220. /*
  221. * contains the definitions for
  222. * instances, functions, named blocks, nets
  223. * and registers for the current compilation unit.
  224. */
  225. CSymtab<CDecl> cuSymtab;
  226. /*
  227. * top level definitions for resolving all
  228. * non-nested module, macromodule, primitive,
  229. * program and interface identifiers.
  230. */
  231. CSymtab<CDecl> definitionSymtab = cuSymtab;
  232. /*
  233. * List of specified tools to run
  234. */
  235. list<CBackend*> enabledTools;
  236. /*
  237. * list of pragma templates
  238. */
  239. list<string> pragmas;
  240. set<string> pragmaTickDefines;
  241. /*
  242. * list of plugin directorys
  243. */
  244. list<string> pluginPaths;
  245. int totalMem = 0;
  246. const CSymbol** fileList = NULL; // list of files to compile
  247. const CSymbol** libSearchList = NULL; // list of paths to search for libraries
  248. const CSymbol** libFileSearchList = NULL; // list of library files to search
  249. const CSymbol** incSearchList = NULL; // list of paths to search for includes
  250. const CSymbol** libExtList = NULL; // list of library extentions
  251. static char whiteSpace[] = " \t\f\n\r";
  252. INT32 argNestLevel; // all argument parsing to nest
  253. vector<const CSymbol*> aFileList;
  254. vector<const CSymbol*> aLibSearchList;
  255. vector<const CSymbol*> aLibFileSearchList;
  256. vector<const CSymbol*> aIncSearchList;
  257. vector<const CSymbol*> aLibExtList;
  258. CNode* codeList = NULL;
  259. CSymtab<CDecl> portSymtab;
  260. CSymtab<CDecl> frefSymtab;
  261. int errorCount = 0;
  262. int warningCount = 0;
  263. int dumpFlag = FALSE;
  264. int debugFlag = FALSE;
  265. int quietFlag = FALSE;
  266. int inferVectors = FALSE;
  267. int macrocheck = FALSE;
  268. DelayMode_t delayMode = eTYP_DELAY;
  269. const char* outputPath = NULL;
  270. const char* outputDirectory = NULL;
  271. vector<char*> plusArgs;
  272. extern int modulesDirectlyDefined;
  273. extern int modulesIncluded;
  274. int ignoreVrqComments = 0;
  275. int verboseFlag = FALSE;
  276. int svEnable = FALSE;
  277. extern int keepMacros;
  278. extern int keepMacroDefinitions;
  279. /*
  280. * error messages
  281. */
  282. static Message* mILLPA = Message::RegisterWarning( NULL,
  283. Message::eERROR, "ILLPA",
  284. "%s is an illegal command line plusarg",
  285. "<plusarg>", 0 );
  286. static Message* mILLWS = Message::RegisterWarning( NULL,
  287. Message::eERROR, "ILLWS",
  288. "%s is an illegal warning specification",
  289. "<warning switch>", 0 );
  290. static Message* mILLSW = Message::RegisterWarning( NULL,
  291. Message::eERROR, "ILLSW",
  292. "%s is an illegal command line switch",
  293. "<switch>", 0 );
  294. static Message* mINAST = Message::RegisterWarning( NULL,
  295. Message::eERROR, "INAST",
  296. "%s is not a supported tool",
  297. "<tool>", 0 );
  298. CDumpVerilog* dumpVerilog;
  299. #ifdef BUILTIN_SIM_PLUGIN
  300. CSim* sim;
  301. #endif
  302. void ParseArguments( int argc, const char** argv );
  303. #define VRQ "Vrq"
  304. char copyright[] = "Copyright (C) 1997-2009 Mark Hummel\n\n"
  305. "Vrq comes with ABSOLUTELY NO WARRANTY; This is free\n"
  306. "software, and you are welcome to redistribute it under the\n"
  307. "terms of the GNU General Public License as published by\n"
  308. "the Free Software Foundation; either version 2 of the License,\n"
  309. "or (at your option) any later version. "
  310. "\n\n";
  311. /*************************************************
  312. library interface routines
  313. *************************************************/
  314. void shell_assert( const char* filename, int linenumber ) {
  315. fatal( NULL, "Assertion Failure -> %s[%d]\n", filename, linenumber );
  316. }
  317. void shell_xfree( void* p, int s ){
  318. free( p );
  319. totalMem -= s;
  320. }
  321. void* shell_xmalloc( int s ) {
  322. totalMem += s;
  323. return malloc(s);
  324. }
  325. /*************************************************
  326. PrintUsage
  327. - print command line help
  328. *************************************************/
  329. void PrintUsage( void )
  330. {
  331. INT32 i;
  332. printf( "\n" );
  333. printf( "'Vrq' is a framework for creating verilog based tools.\n\n" );
  334. printf( "Usage: vrq [options] <file1> [<file2>...]\n\n" );
  335. printf( "Options:\n" );
  336. printf( " --version Print version\n" );
  337. printf( " --help This message\n" );
  338. printf( " --bindir Binary install path\n");
  339. printf( " --libdir Library install path\n");
  340. printf( " --pkglibdir Plugin install path\n");
  341. printf( " --includedir Include install path\n");
  342. printf( " --cflags Compiler flags used\n");
  343. printf( " --ldflags Linker flags used\n");
  344. printf( " --libs Libraries used\n");
  345. printf( " -V Verbose\n" );
  346. printf( " -y <directory> Search directory for module definitions\n" );
  347. printf( " -f <filename> Read options from <filename>\n" );
  348. printf( " -v <lib_filename> Search file for module definitions\n" );
  349. printf( " -l <filename> Set log file to <filename>\n" );
  350. printf( " -w <message>=<policy> Set policy for warning <message> to <policy>; ignore, warning, error, info\n" );
  351. printf( " -w all=<policy> Set policy for all warnings to <policy>; ignore, warning, error, info\n" );
  352. printf( " -wl List all warning messages\n" );
  353. printf( " +libext+<extension> Specify library suffix to <extension>\n" );
  354. printf( " -sv Enable System Verilog support\n" );
  355. printf( " -dump Dump internal tree\n" );
  356. printf( " -debug Print debug/statistics info\n" );
  357. printf( " -quiet Print minimal runtime info\n" );
  358. printf( " -infervectors Infer reg and wire vectors\n" );
  359. printf( " -keeptickdefines Best effort attempt to keep tick defines and `include statements in code (EXPERIMENTAL)\n" );
  360. printf( " -macrocheck Do not allow undefined macros\n" );
  361. printf( " -o <filename> Specify output file\n" );
  362. printf( " -dir <directory> Specify output directory\n" );
  363. printf( " -pragma <regexp> Extended regular expression template for pragma comments\n" );
  364. printf( " -passthru <name> Pass through ifdef blocks with label\n" );
  365. printf( " +incdir+<directory> Specify include search path\n" );
  366. printf( " +define+<name>=<value> Define `define\n" );
  367. printf( " +<name>+<value> Define plusargs\n" );
  368. map<string,CBackend*>::iterator ptr;
  369. for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
  370. if( ptr->second->HideTool() ) {
  371. continue;
  372. }
  373. printf( " -tool %-20s %s\n",
  374. (*ptr).second->GetToolName(),
  375. (*ptr).second->GetToolDescription() );
  376. }
  377. for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
  378. if( ptr->second->HideTool() ) {
  379. continue;
  380. }
  381. list<string>& switches = ptr->second->GetSwitches();
  382. if( switches.size() == 0 ) {
  383. continue;
  384. }
  385. printf( "\n* '%s' Options\n", (*ptr).second->GetToolName() );
  386. list<string>::iterator swPtr;
  387. for( swPtr = switches.begin(); swPtr != switches.end(); ++swPtr ) {
  388. printf( " %-26s %s\n",
  389. swPtr->c_str(),
  390. (*ptr).second->GetSwitchDescription(swPtr->c_str()) );
  391. }
  392. }
  393. printf( "\n" );
  394. printf( "Report bugs at <http://sourceforge.net/projects/vrq>\n" );
  395. }
  396. /*************************************************
  397. VrqVersionString
  398. ************************************************/
  399. static const char* vrqVersion = VERSION;
  400. const char* VrqVersionString()
  401. {
  402. return vrqVersion;
  403. }
  404. /*************************************************
  405. GetPluginPaths
  406. - retrieve list of plugin location paths
  407. *************************************************/
  408. void GetPluginPaths( list<string>& paths )
  409. {
  410. paths = pluginPaths;
  411. }
  412. /*************************************************
  413. GetPlusArgs
  414. - retrieve plus arg list from command line
  415. args matching prefix
  416. *************************************************/
  417. void GetPlusArgs( const char* prefix, list<string>& args )
  418. {
  419. args.erase( args.begin(), args.end() );
  420. vector<char*>::iterator ptr;
  421. for( ptr = plusArgs.begin(); ptr != plusArgs.end(); ++ptr ) {
  422. int len = strlen( prefix );
  423. if( !strncmp( *ptr, prefix, len ) ) {
  424. args.push_back(*ptr+len);
  425. }
  426. }
  427. }
  428. /*************************************************
  429. GetPlusArg
  430. - retrieve plus arg from command line matching
  431. prefix
  432. *************************************************/
  433. char* GetPlusArg( const char* prefix )
  434. {
  435. vector<char*>::iterator ptr;
  436. for( ptr = plusArgs.begin(); ptr != plusArgs.end(); ++ptr ) {
  437. int len = strlen( prefix );
  438. if( !strncmp( *ptr, prefix, len ) ) {
  439. return (*ptr+len);
  440. }
  441. }
  442. return NULL;
  443. }
  444. /*************************************************
  445. AddPlusArg
  446. - add plus arg to list
  447. *************************************************/
  448. void AddPlusArg( const char* s )
  449. {
  450. plusArgs.push_back(strdup(s+1));
  451. }
  452. /*************************************************
  453. PlusArgMatch
  454. - return TRUE if plus arg matches string
  455. *************************************************/
  456. int PlusArgMatch( const char* s1, const char* s2 )
  457. {
  458. int l1 = strlen( s1 );
  459. int l2 = strlen( s2 );
  460. const char* p1 = strpbrk( s1, "+=" );
  461. if( p1 ) {
  462. l1 = p1 - s1;
  463. }
  464. const char* p2 = strpbrk( s2, "+=" );
  465. if( p2 ) {
  466. l2 = p2 - s2;
  467. }
  468. if( l1 == l2 && !strncmp(s1,s2,l1) ) {
  469. return TRUE;
  470. }
  471. return FALSE;
  472. }
  473. /*************************************************
  474. ValidatePlusArgs
  475. - validate all plus args
  476. *************************************************/
  477. void ValidatePlusArgs()
  478. {
  479. vector<char*>::iterator paPtr;
  480. for( paPtr = plusArgs.begin(); paPtr != plusArgs.end(); ++paPtr ) {
  481. list<CBackend*>::iterator ptr;
  482. if( PlusArgMatch( *paPtr, "define" ) ) {
  483. goto FOUND;
  484. }
  485. if( PlusArgMatch( *paPtr, "incdir" ) ) {
  486. goto FOUND;
  487. }
  488. if( PlusArgMatch( *paPtr, "libext" ) ) {
  489. goto FOUND;
  490. }
  491. if( PlusArgMatch( *paPtr, "xprop-allow-casex" ) ) {
  492. goto FOUND;
  493. }
  494. for( list<string>::iterator sPtr = dumpVerilog->GetSwitches().begin();
  495. sPtr != dumpVerilog->GetSwitches().end(); ++sPtr ) {
  496. if( PlusArgMatch( *paPtr, &sPtr->c_str()[1] ) ) {
  497. goto FOUND;
  498. }
  499. }
  500. for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
  501. if( (*ptr)->AcceptAllPlusArgs() ) {
  502. goto FOUND;
  503. }
  504. list<string>::iterator sPtr;
  505. for( sPtr = (*ptr)->GetSwitches().begin();
  506. sPtr != (*ptr)->GetSwitches().end(); ++sPtr ) {
  507. if( PlusArgMatch( *paPtr, &sPtr->c_str()[1] ) ) {
  508. goto FOUND;
  509. }
  510. }
  511. }
  512. message( NULL, mILLPA, *paPtr );
  513. if( errorCount ) {
  514. PrintUsage();
  515. exit(1);
  516. }
  517. FOUND:
  518. continue;
  519. }
  520. }
  521. /*************************************************
  522. DumpWarningList
  523. - output a list of all possible warnings
  524. *************************************************/
  525. void DumpWarningList()
  526. {
  527. list<Message*>& warnings = Message::MessageList();
  528. list<Message*>::iterator ptr;
  529. printf( "List of warning messages:\n" );
  530. for( ptr = warnings.begin(); ptr != warnings.end(); ++ptr ) {
  531. Message* message = *ptr;
  532. const char* policy;
  533. switch( message->Action() ) {
  534. case Message::eINFO:
  535. policy = "info";
  536. break;
  537. case Message::eIGNORE:
  538. policy = "ignore";
  539. break;
  540. case Message::eERROR:
  541. policy = "error";
  542. break;
  543. case Message::eWARNING:
  544. policy = "warning";
  545. break;
  546. default:
  547. MASSERT( FALSE );
  548. }
  549. printf( "%s[%s]: %s\n", message->Abbreviation(),
  550. policy, message->HelpText() );
  551. }
  552. exit(0);
  553. }
  554. /*************************************************
  555. ParseWarningSwitch
  556. - handle switch to modify warning policy
  557. *************************************************/
  558. void ParseWarningSwitch( const char* s )
  559. {
  560. string abbrev = s;
  561. string policy;
  562. const char* ptr;
  563. ptr = strchr( s, '=' );
  564. if( ptr ) {
  565. policy = ptr+1;
  566. abbrev = abbrev.substr(0, ptr-s);
  567. Message::Action_t action;
  568. if( !policy.compare( "ignore" ) ) {
  569. action = Message::eIGNORE;
  570. } else if( !policy.compare( "info" ) ) {
  571. action = Message::eINFO;
  572. } else if( !policy.compare( "error" ) ) {
  573. action = Message::eERROR;
  574. } else if( !policy.compare( "warning" ) ) {
  575. action = Message::eWARNING;
  576. } else {
  577. error( (Coord_t*)NULL, "illegal warning policy '%s'", policy.c_str() );
  578. goto ERROR;
  579. }
  580. if( !abbrev.compare( "all" ) ) {
  581. list<Message*>::iterator ptr;
  582. for( ptr = Message::MessageList().begin();
  583. ptr != Message::MessageList().end(); ++ ptr ) {
  584. if( (*ptr)->Locked() ) {
  585. continue;
  586. }
  587. (*ptr)->Action( action );
  588. }
  589. return;
  590. }
  591. Message* message = Message::Find( abbrev.c_str() );
  592. if( !message ) {
  593. error( (Coord_t*)NULL, "unknown warning message '%s'",
  594. abbrev.c_str() );
  595. goto ERROR;
  596. }
  597. if( message->Locked() ) {
  598. error( (Coord_t*)NULL, "message policy for '%s' cannot be changed",
  599. abbrev.c_str() );
  600. goto ERROR;
  601. }
  602. message->Action( action );
  603. return;
  604. }
  605. message( NULL, mILLWS, s );
  606. if( !errorCount ) {
  607. return;
  608. }
  609. PrintUsage();
  610. ERROR:
  611. exit(1);
  612. }
  613. /*************************************************
  614. ReadArgumentFile
  615. - read command line argument file
  616. *************************************************/
  617. void ReadArgumentFile( const char* filename )
  618. {
  619. int newArgc;
  620. const char** newArgv;
  621. const CSymbol** newArgvSymbol;
  622. vector<const CSymbol*> argList;
  623. FILE* fin = fopen( filename, "r" );
  624. if( fin == NULL ) {
  625. error( (Coord_t*)NULL, "Couldn't open file '%s'", filename );
  626. exit( 2 );
  627. }
  628. int strip = TRUE;
  629. newArgc = 1;
  630. argList.push_back( CSymbol::Lookup( "dummy" ) );
  631. while( TRUE ) {
  632. int c = fgetc( fin );
  633. int marker = (strchr( whiteSpace, c ) || c == EOF);
  634. if( c == '/' ) {
  635. int c1 = fgetc( fin );
  636. if( c1 == '/' ) {
  637. do {
  638. c1 = fgetc( fin );
  639. } while( c1 != EOF && c1 != '\n' && c1 != '\r' );
  640. marker = TRUE;
  641. } else if( c1 == '*' ) {
  642. while( 1 ) {
  643. c1 = fgetc( fin );
  644. if( c1 == EOF ) {
  645. break;
  646. }
  647. if( c1 != '*' ) {
  648. continue;
  649. }
  650. c1 = fgetc( fin );
  651. if( c1 == EOF ) {
  652. break;
  653. }
  654. if( c1 != '/' ) {
  655. continue;
  656. }
  657. break;
  658. }
  659. marker = TRUE;
  660. } else {
  661. ungetc( c1, fin );
  662. }
  663. }
  664. int done = (c == EOF);
  665. if( marker || done ) {
  666. if( strip ) {
  667. if( done ) {
  668. break;
  669. } else {
  670. continue;
  671. }
  672. }
  673. c = 0;
  674. strip = TRUE;
  675. permStack->Grow( &c, 1 );
  676. const CSymbol* sym = CSymbol::Lookup( (char*) permStack->Finish() );
  677. argList.push_back( sym );
  678. newArgc++;
  679. } else {
  680. strip = FALSE;
  681. permStack->Grow( &c, 1 );
  682. }
  683. if( done ) {
  684. break;
  685. }
  686. }
  687. newArgvSymbol = Finalize( permStack, argList );
  688. newArgv = (const char**)newArgvSymbol;
  689. fclose( fin );
  690. for( int j = 0; newArgvSymbol[j]; j++ ) {
  691. newArgv[j] = newArgvSymbol[j]->GetName();
  692. }
  693. ParseArguments( newArgc, newArgv );
  694. }
  695. /*************************************************
  696. ParseArguments
  697. - parse command line arguments
  698. *************************************************/
  699. void ParseArguments( int argc, const char** argv )
  700. {
  701. INT32 i;
  702. INT32 j;
  703. int c;
  704. FILE* fin;
  705. argNestLevel++;
  706. for( i = 1; i < argc; i++ ) {
  707. switch( argv[i][0] ) {
  708. case '-':
  709. if( !strcmp( &argv[i][1], "dump" ) ) {
  710. dumpFlag = TRUE;
  711. } else if( !strcmp( &argv[i][1], "sv" ) ) {
  712. svEnable = TRUE;
  713. } else if( !strcmp( &argv[i][1], "-version" ) ) {
  714. printf("%s %s, \n\n", VRQ, VERSION );
  715. printf( copyright );
  716. printf( "\nWritten by Mark Hummel\n" );
  717. exit(0);
  718. } else if( !strcmp( &argv[i][1], "-help" ) ) {
  719. PrintUsage();
  720. exit(0);
  721. } else if (!strcmp( &argv[i][1], "-bindir" ) ) {
  722. printf( "%s\n", BINDIR );
  723. exit(0);
  724. } else if (!strcmp( &argv[i][1], "-libdir" ) ) {
  725. printf( "%s\n", LIBDIR );
  726. exit(0);
  727. } else if (!strcmp( &argv[i][1], "-includedir" ) ) {
  728. printf( "%s\n", INCLUDEDIR );
  729. exit(0);
  730. } else if (!strcmp( &argv[i][1], "-pkglibdir" ) ) {
  731. printf( "%s\n", PKGLIBDIR );
  732. exit(0);
  733. } else if (!strcmp( &argv[i][1], "-cflags" ) ) {
  734. printf( "%s\n", CFLAGS );
  735. exit(0);
  736. } else if (!strcmp( &argv[i][1], "-ldflags" ) ) {
  737. printf( "%s\n", LDFLAGS );
  738. exit(0);
  739. } else if (!strcmp( &argv[i][1], "-libs" ) ) {
  740. printf( "%s\n", LIBS );
  741. exit(0);
  742. } else if( !strcmp( &argv[i][1], "macrocheck" ) ) {
  743. macrocheck = TRUE;
  744. } else if( !strcmp( &argv[i][1], "infervectors" ) ) {
  745. inferVectors = TRUE;
  746. } else if( !strcmp( &argv[i][1], "keeptickdefines" ) ) {
  747. keepMacros = TRUE;
  748. keepMacroDefinitions = TRUE;
  749. } else if( !strcmp( &argv[i][1], "debug" ) ) {
  750. debugFlag = TRUE;
  751. } else if( !strcmp( &argv[i][1], "quiet" ) ) {
  752. quietFlag = TRUE;
  753. } else if( !strcmp( &argv[i][1], "V" ) ) {
  754. verboseFlag = TRUE;
  755. } else if( !strcmp( &argv[i][1], "y" ) ) {
  756. aLibSearchList.push_back( CSymbol::Lookup( argv[i+1] ) );
  757. i++;
  758. } else if( !strcmp( &argv[i][1], "f" ) ) {
  759. ReadArgumentFile( argv[i+1] );
  760. i++;
  761. } else if( !strcmp( &argv[i][1], "w" ) ) {
  762. ParseWarningSwitch( argv[i+1] );
  763. i++;
  764. } else if( !strcmp( &argv[i][1], "wl" ) ) {
  765. DumpWarningList();
  766. } else if( !strcmp( &argv[i][1], "v" ) ) {
  767. aLibFileSearchList.push_back( CSymbol::Lookup( argv[i+1] ) );
  768. i++;
  769. } else if( !strcmp( &argv[i][1], "o" ) ) {
  770. outputPath = argv[i+1];
  771. i++;
  772. } else if( !strcmp( &argv[i][1], "dir" ) ) {
  773. outputDirectory = argv[i+1];
  774. i++;
  775. } else if( !strcmp( &argv[i][1], "pragma" ) ) {
  776. pragmas.push_back( argv[i+1] );
  777. i++;
  778. } else if( !strcmp( &argv[i][1], "passthru" ) ) {
  779. pragmaTickDefines.insert( argv[i+1] );
  780. i++;
  781. } else if( !strcmp( &argv[i][1],
  782. "allowmissingincludes" ) ) {
  783. ParseWarningSwitch( "vrq-COIDF=ignore" );
  784. warning( (Coord_t*)NULL, "switch '%s' is depreciated and will be removed in a future release", argv[i] );
  785. } else if( !strcmp( &argv[i][1], "l" ) ) {
  786. logfile = fopen( argv[i+1], "w" );
  787. if( logfile == NULL ) {
  788. logfile = stdout;
  789. error( (Coord_t*)NULL, "Couldn't open logfile '%s'", argv[i+1] );
  790. }
  791. i++;
  792. } else if( !strcmp( &argv[i][1], "tool" ) ) {
  793. INT32 j;
  794. map<string,CBackend*>::iterator ptr;
  795. for( ptr = tools.begin(); ptr != tools.end(); ++ptr ) {
  796. if( !strcmp( (*ptr).second->GetToolName(), argv[i+1] ) ) {
  797. enabledTools.push_back( (*ptr).second );
  798. i++;
  799. break;
  800. }
  801. }
  802. if( ptr == tools.end() ) {
  803. message( NULL, mINAST, argv[i+1] );
  804. if( errorCount ) {
  805. PrintUsage();
  806. exit(1);
  807. }
  808. }
  809. } else {
  810. message( NULL, mILLSW, argv[i] );
  811. if( errorCount ) {
  812. PrintUsage();
  813. exit(1);
  814. }
  815. }
  816. break;
  817. case '+':
  818. AddPlusArg( argv[i] );
  819. if( !strncmp( argv[i], "+incdir", 7 ) ) {
  820. const char* ptr = &argv[i][7];
  821. const char* ptr1;
  822. char c;
  823. while( ptr && *ptr == '+' ) {
  824. ptr++;
  825. ptr1 = strchr( ptr, '+' );
  826. if( ptr1 == NULL ) {
  827. ptr1 = ptr + strlen(ptr);
  828. if( ptr1 == ptr ) {
  829. break;
  830. }
  831. }
  832. permStack->Grow( ptr, ptr1-ptr );
  833. c = 0;
  834. permStack->Grow( &c, 1 );
  835. const CSymbol* sym = CSymbol::Lookup( (char*)permStack->Finish() );
  836. aIncSearchList.push_back( sym );
  837. ptr = ptr1;
  838. }
  839. }
  840. if( !strncmp( argv[i], "+define", 7 ) ) {
  841. const char* ptr = &argv[i][7];
  842. const char* ptr1;
  843. const char* ptr2;
  844. const char* ptr3;
  845. char* key;
  846. char* value;
  847. while( ptr && *ptr == '+' ) {
  848. ptr++;
  849. ptr3 = strchr( ptr, '+' );
  850. if( ptr3 == NULL ) {
  851. ptr3 = ptr + strlen(ptr);
  852. if( ptr3 == ptr ) {
  853. break;
  854. }
  855. }
  856. ptr1 = strchr( ptr, '=' );
  857. if( !ptr1 ) {
  858. ptr1 = ptr3;
  859. ptr2 = ptr3;
  860. } else if( ptr1 > ptr3 ) {
  861. ptr1 = ptr3;
  862. ptr2 = ptr3;
  863. } else {
  864. ptr2 = ptr1+1;
  865. }
  866. permStack->Grow( ptr, ptr1-ptr );
  867. c = 0;
  868. permStack->Grow( &c, 1 );
  869. key = (char*)permStack->Finish();
  870. permStack->Grow( ptr2, ptr3-ptr2 );
  871. c = 0;
  872. permStack->Grow( &c, 1 );
  873. value = (char*)permStack->Finish();
  874. CMacro* macro;
  875. CSymbol* symbol;
  876. macro = CMacro::LookupMacro( key );
  877. if( macro == NULL ) {
  878. symbol = CSymbol::Lookup( key );
  879. Coord_t loc = { 0, "" };
  880. macro = new(permStack) CMacro( symbol, &loc );
  881. } else {
  882. Coord_t loc = { 0, "" };
  883. macro->SetCoord( &loc );
  884. }
  885. macro->SetComplex(FALSE);
  886. macro->SetDefined(TRUE);
  887. macro->SetBody( value );
  888. macro->SetZone( 0 );
  889. ptr = ptr3;
  890. }
  891. }
  892. if( !strncmp( argv[i], "+libext", 7 ) ) {
  893. const char* ptr = &argv[i][7];
  894. const char* ptr1;
  895. char c;
  896. while( ptr && *ptr == '+' ) {
  897. ptr++;
  898. ptr1 = strchr( ptr, '+' );
  899. if( ptr1 == NULL ) {
  900. ptr1 = ptr + strlen(ptr);
  901. if( ptr1 == ptr ) {
  902. break;
  903. }
  904. }
  905. permStack->Grow( ptr, ptr1-ptr );
  906. c = 0;
  907. permStack->Grow( &c, 1 );
  908. const CSymbol* sym = CSymbol::Lookup( (char*) permStack->Finish() );
  909. aLibExtList.push_back( sym );
  910. ptr = ptr1;
  911. }
  912. }
  913. if( !strncmp( argv[i], "+xprop-allow-casex", 18 ) ) {
  914. ParseWarningSwitch( "xprop-CCBMS=ignore" );
  915. }
  916. break;
  917. default:
  918. aFileList.push_back( CSymbol::Lookup( argv[i] ) );
  919. break;
  920. }
  921. }
  922. argNestLevel--;
  923. if( argNestLevel == 0 ) {
  924. libSearchList = Finalize( permStack, aLibSearchList );
  925. libFileSearchList = Finalize( permStack, aLibFileSearchList );
  926. fileList = Finalize( permStack, aFileList );
  927. incSearchList = Finalize( permStack, aIncSearchList );
  928. libExtList = Finalize( permStack, aLibExtList );
  929. }
  930. ValidatePlusArgs();
  931. }
  932. /************************************************
  933. Load
  934. - load and compile a file,
  935. return a parse tree
  936. *************************************************/
  937. set<string> loadedFiles;
  938. CNode* Load( const char* filename, int direct, int included )
  939. {
  940. if( loadedFiles.find(filename) != loadedFiles.end() ) {
  941. return NULL;
  942. }
  943. loadedFiles.insert(filename);
  944. MASSERT( codeList == NULL );
  945. CNode* code;
  946. modulesDirectlyDefined = direct;
  947. modulesIncluded = included;
  948. int success = lex_openFile( strdup(filename) );
  949. if( success ) {
  950. prog_parse();
  951. }
  952. code = codeList;
  953. codeList = NULL;
  954. tokenStack->Free(NULL);
  955. return code;
  956. }
  957. /*************************************************
  958. _Resolve
  959. - attempt of search of module in a library
  960. returns code for loaded module, NULL if
  961. not found
  962. *************************************************/
  963. static CNode* _Resolve( CModule* module, int reportError )
  964. {
  965. INT32 i;
  966. INT32 j;
  967. MASSERT( !module->IsDefined() || !module->ModuleIncluded() );
  968. if( module->IsDefined() ) {
  969. module->ModuleIncluded(TRUE);
  970. return cMODULE_DEF(module);
  971. }
  972. for( i = 0; libSearchList[i]; i++ ) {
  973. for( j = 0; libExtList[j] || j == 0; j++ ) {
  974. string path = libSearchList[i]->GetName();
  975. path += PATH_SEPARATOR;
  976. path += module->GetName();
  977. if( libExtList[j] ) {
  978. path += libExtList[j]->GetName();
  979. }
  980. if( access( path.c_str(), R_OK ) != 0 ) {
  981. continue;
  982. }
  983. CNode* code = Load( path.c_str(), FALSE, FALSE );
  984. if( module->IsDefined() &&
  985. !module->ModuleIncluded() ) {
  986. if( !quietFlag ) {
  987. logprintf( "Loaded '%s' from library '%s'\n",
  988. module->GetName(), path.c_str() );
  989. }
  990. module->ModuleIncluded( TRUE );
  991. return cMODULE_DEF(module);
  992. }
  993. }
  994. }
  995. for( i = 0; libFileSearchList[i]; i++ ) {
  996. const char* path = libFileSearchList[i]->GetName();
  997. if( access( path, R_OK ) != 0 ) {
  998. continue;
  999. }
  1000. CNode* code = Load( path, FALSE, FALSE );
  1001. if( module->IsDefined() && !module->ModuleIncluded() ) {
  1002. if( !quietFlag ) {
  1003. logprintf( "Loaded '%s' from library '%s'\n",
  1004. module->GetName(), path );
  1005. }
  1006. module->ModuleIncluded( TRUE );
  1007. return cMODULE_DEF(module);
  1008. }
  1009. }
  1010. if( reportError ) {
  1011. message( module->GetCoord(), mCRMOD, module->GetName() );
  1012. }
  1013. return NULL;
  1014. }
  1015. /************************************************
  1016. ResolveModuleList
  1017. - attempt to resolve all referenced modules
  1018. return code for resolved modules
  1019. ************************************************/
  1020. static CNode* ResolveModuleList( CBackend* tool, CNode* n, int reportError )
  1021. {
  1022. CNode* result = NULL;
  1023. if( n == NULL ) {
  1024. return result;
  1025. }
  1026. switch( n->GetOp() ) {
  1027. case eLIST:
  1028. result = ResolveModuleList( tool,
  1029. n->Arg<CNode*>(0), reportError );
  1030. result = cLINK( ResolveModuleList( tool,
  1031. n->Arg<CNode*>(1), reportError ),
  1032. result );
  1033. break;
  1034. case eMODULE_DEF:
  1035. {
  1036. CModule* m = n->Arg<CModule*>(0);
  1037. vector<CInstance*>& inst = *m->GetInstanceList();
  1038. vector<CInstance*>::iterator p;
  1039. for( p = inst.begin(); p != inst.end(); ++p ) {
  1040. if( !tool->ResolveInstance( m, *p ) ) {
  1041. continue;
  1042. }
  1043. CModule* def = (*p)->GetDefinition();
  1044. if( !def->IsDefined() ||
  1045. !def->ModuleIncluded() ) {
  1046. result = cLINK( result,
  1047. _Resolve( def, reportError ) );
  1048. }
  1049. }
  1050. }
  1051. break;
  1052. case ePRAGMA:
  1053. case eCOMMENT:
  1054. case eVRQ:
  1055. break;
  1056. default:
  1057. MASSERT( FALSE );
  1058. }
  1059. return result;
  1060. }
  1061. /************************************************
  1062. ModulesResolved
  1063. - returns TRUE if all modules are resolved
  1064. ************************************************/
  1065. static int ModulesResolved( CBackend* tool, CNode* n )
  1066. {
  1067. int result = TRUE;
  1068. if( n == NULL ) {
  1069. return result;
  1070. }
  1071. switch( n->GetOp() ) {
  1072. case eLIST:
  1073. result &= ModulesResolved( tool, n->Arg<CNode*>(0) );
  1074. result &= ModulesResolved( tool, n->Arg<CNode*>(1) );
  1075. break;
  1076. case eMODULE_DEF:
  1077. {
  1078. CModule* m = n->Arg<CModule*>(0);
  1079. vector<CInstance*>& inst = *m->GetInstanceList();
  1080. vector<CInstance*>::iterator p;
  1081. for( p = inst.begin(); p != inst.end(); ++p ) {
  1082. if( !tool->ResolveInstance( m, *p ) ) {
  1083. continue;
  1084. }
  1085. CModule* def = (*p)->GetDefinition();
  1086. if( !def->IsDefined() ||
  1087. !def->ModuleIncluded() ) {
  1088. return FALSE;
  1089. }
  1090. }
  1091. }
  1092. break;
  1093. case ePRAGMA:
  1094. case eCOMMENT:
  1095. case eVRQ:
  1096. case eATTRIBUTE:
  1097. break;
  1098. default:
  1099. MASSERT( FALSE );
  1100. }
  1101. return result;
  1102. }
  1103. /*************************************************
  1104. LoadTools
  1105. - load available tools
  1106. *************************************************/
  1107. static set<lt_dlhandle> toolHandles;
  1108. void LoadTools()
  1109. {
  1110. CBackend* tool;
  1111. /*
  1112. * add vrq specific lib directory to search list
  1113. */
  1114. char* pld = getenv("PLUGIN_DIR");
  1115. if( pld ) {
  1116. char* ptr;
  1117. ptr = strtok( strdup(pld), ":" );
  1118. while( ptr != NULL ) {
  1119. pluginPaths.push_back( ptr );
  1120. ptr = strtok( NULL, ":" );
  1121. }
  1122. } else {
  1123. pluginPaths.push_back( PKGLIBDIR );
  1124. }
  1125. /*
  1126. * create built-in plugins
  1127. */
  1128. dumpVerilog = new CDumpVerilog();
  1129. tools[dumpVerilog->GetToolName()] = dumpVerilog;
  1130. tool = new CXProp();
  1131. tools[tool->GetToolName()] = tool;
  1132. #ifdef BUILTIN_SIM_PLUGIN
  1133. sim = new CSim();
  1134. tools[sim->GetToolName()] = sim;
  1135. #endif
  1136. int errors = lt_dlinit();
  1137. if( errors ) {
  1138. fprintf( stderr, "%s\n", lt_dlerror() );
  1139. return;
  1140. }
  1141. list<string>::iterator pluginPath;
  1142. for( pluginPath = pluginPaths.begin(); pluginPath != pluginPaths.end();
  1143. ++pluginPath ) {
  1144. DIR* dir;
  1145. dir = opendir(pluginPath->c_str());
  1146. if( dir ) {
  1147. while(1) {
  1148. struct dirent* entry = readdir( dir );
  1149. if( !entry ) {
  1150. break;
  1151. }
  1152. string path;
  1153. path = *pluginPath;
  1154. path += "/";
  1155. path += entry->d_name;
  1156. lt_dlhandle handle = lt_dlopen( path.c_str() );
  1157. if( !handle ) {
  1158. continue;
  1159. }
  1160. CBackend* (*sym)() = (CBackend*(*)())lt_dlsym( handle,
  1161. "CreateToolInstance" );
  1162. if( !sym ) {
  1163. lt_dlclose( handle );
  1164. continue;
  1165. }
  1166. /*
  1167. * don't reinitialize tool twice. This can happen
  1168. * because both *.la and *.so files are installed
  1169. * in the plugin dir
  1170. */
  1171. if( toolHandles.count( handle ) ) {
  1172. continue;
  1173. }
  1174. CBackend* t = (*sym)();
  1175. if( !t ) {
  1176. continue;
  1177. }
  1178. tools[t->GetToolName()] = t;
  1179. toolHandles.insert( handle );
  1180. }
  1181. closedir( dir );
  1182. }
  1183. }
  1184. }
  1185. /*************************************************
  1186. initial entry point
  1187. *************************************************/
  1188. static void DumpCode( FILE* f, CNode* n )
  1189. {
  1190. switch( n->GetOp() ) {
  1191. case eLIST:
  1192. if( n->Arg<CNode*>(0) ) DumpCode( f, n->Arg<CNode*>(0) );
  1193. if( n->Arg<CNode*>(1) ) DumpCode( f, n->Arg<CNode*>(1) );
  1194. break;
  1195. case eMODULE_DEF:
  1196. n->Arg<CModule*>(0)->Dump( f );
  1197. break;
  1198. case eCOMMENT:
  1199. case eVRQ:
  1200. break;
  1201. default:
  1202. fprintf( f, "unknown object or type %d\n", n->GetOp() );
  1203. }
  1204. }
  1205. // #define DEFINE_TEST_HARNESS
  1206. // #include "cnode_def.h"
  1207. // #undef DEFINE_TEST_HARNESS
  1208. int main( int argc, char** argv )
  1209. {
  1210. INT32 i;
  1211. INT32 j;
  1212. INT32 pass;
  1213. CBackend* tool;
  1214. // CNodeTestHarness();
  1215. /*
  1216. * error messages
  1217. */
  1218. mCRMOD = Message::RegisterWarning( NULL, Message::eERROR,
  1219. "CRMOD", "cannot resolve module %s" );
  1220. /*
  1221. * load tools
  1222. */
  1223. LoadTools();
  1224. /*
  1225. * initialize global structures
  1226. */
  1227. CSymbol::SetObstack( permStack );
  1228. Systask::Initialize();
  1229. /*
  1230. * parse command line arguments
  1231. */
  1232. argNestLevel = 0;
  1233. ParseArguments( argc, const_cast<const char**>(argv) );
  1234. if( debugFlag ) {
  1235. CObstack::OnExitDumpStats();
  1236. }
  1237. /*
  1238. * activate selected tools
  1239. */
  1240. list<CBackend*>::iterator ptr;
  1241. for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
  1242. (*ptr)->Activate();
  1243. ignoreVrqComments |= (*ptr)->IgnoreVrqComments();
  1244. }
  1245. /*
  1246. * print copyright banner
  1247. */
  1248. if( !quietFlag ) {
  1249. logprintf( "\n%s version %s, \n", VRQ, VERSION );
  1250. logprintf( copyright );
  1251. }
  1252. /*
  1253. * intialize subsystems
  1254. */
  1255. lex_init();
  1256. parse_init();
  1257. /*
  1258. * parse each file and hand off to tools
  1259. */
  1260. list<CElement> input;
  1261. list<CElement> output;
  1262. int consumed = 0;
  1263. if( !quietFlag ) {
  1264. logprintf( "Parsing...\n" );
  1265. }
  1266. for( i = 0; fileList[i] != NULL; i++ ) {
  1267. CNode* code = Load( fileList[i]->GetName(), TRUE, TRUE );
  1268. const char* name = rindex( fileList[i]->GetName(), '/' );
  1269. if( !name ) {
  1270. name = fileList[i]->GetName();
  1271. }
  1272. output.push_back( CElement( name, 1, code ) );
  1273. if( dumpFlag ) {
  1274. fprintf( stdout, "MACRO definitions:\n" );
  1275. fprintf( stdout, "------------------\n" );
  1276. macroSymtab.Dump( stdout, 1 );
  1277. fprintf( stdout, "global definitions:\n" );
  1278. fprintf( stdout, "------------------\n" );
  1279. definitionSymtab.Dump( stdout, 1 );
  1280. fprintf( stdout, "MODULE definitions:\n" );
  1281. fprintf( stdout, "------------------\n" );
  1282. DumpCode( stdout, code );
  1283. }
  1284. }
  1285. // CSymbol::DumpStats();
  1286. /*
  1287. * bail out if errors occurred
  1288. */
  1289. if( errorCount ) {
  1290. goto DONE;
  1291. }
  1292. /*
  1293. * run each tool in chain
  1294. */
  1295. for( ptr = enabledTools.begin(); ptr != enabledTools.end(); ++ptr ) {
  1296. input.erase( input.begin(), input.end() );
  1297. list<CElement>::iterator eptr;
  1298. for( eptr = output.begin(); eptr != output.end(); ++eptr ) {
  1299. /*
  1300. * if tools requires it resolve all module references
  1301. * Make 2 pass to see if search found other modules
  1302. */
  1303. int pass = 1;
  1304. CNode* code = eptr->Code();
  1305. while( (*ptr)->ResolveModules() &&
  1306. !ModulesResolved( *ptr, code ) ) {
  1307. CNode* rcode = ResolveModuleList( *ptr, code,
  1308. (*ptr)->RequireModuleResolution() && pass>1 );
  1309. if( pass > 1 && !rcode ) {
  1310. break;
  1311. }
  1312. pass++;
  1313. code = cLINK( rcode, code );
  1314. }
  1315. eptr->Code( code );
  1316. input.push_back( *eptr );
  1317. }
  1318. output.erase( output.begin(), output.end() );
  1319. if( errorCount ) {
  1320. goto DONE;
  1321. }
  1322. CBackend* tool = (*ptr);
  1323. if( !quietFlag ) {
  1324. logprintf( "Executing tool %s...\n", tool->GetToolName() );
  1325. }
  1326. /*
  1327. * use plugin storage manager by default
  1328. */
  1329. CNode::SetBuildStack( pluginStack );
  1330. try {
  1331. tool->Process( input, output );
  1332. } catch( CBackendAbort ) {
  1333. abort();
  1334. } catch( CBackendFail ) {
  1335. goto DONE;
  1336. } catch( CBackendExit ) {
  1337. // success!
  1338. } catch( ... ) {
  1339. abort();
  1340. }
  1341. /*
  1342. * restore environment
  1343. */
  1344. CNode::ResetBuildStack();
  1345. if( output.size() == 0 ) {
  1346. output = input;
  1347. consumed = 1;
  1348. }
  1349. }
  1350. /*
  1351. * If output hasn't be consumed run dump tool
  1352. */
  1353. if( !consumed && output.size() && errorCount == 0 ) {
  1354. if( !quietFlag ) {
  1355. logprintf( "Executing tool %s...\n",
  1356. dumpVerilog->GetToolName() );
  1357. }
  1358. list<CElement> dummy;
  1359. try {
  1360. dumpVerilog->Process( output, dummy );
  1361. } catch( CBackendAbort ) {
  1362. abort();
  1363. } catch( CBackendFail ) {
  1364. goto DONE;
  1365. } catch( CBackendExit ) {
  1366. // success!
  1367. } catch( ... ) {
  1368. abort();
  1369. }
  1370. }
  1371. DONE:
  1372. // logprintf( "Total Memory Allocated = %d\n", totalMem );
  1373. if( !quietFlag ) {
  1374. logprintf( "%d Errors, %d Warnings\n", errorCount, warningCount );
  1375. }
  1376. return (errorCount != 0);
  1377. }