| /* |
| Copyright 2019 Alain Dargelas |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /* |
| * File: CommandLineParser.cpp |
| * Author: alain |
| * |
| * Created on January 26, 2017, 9:47 PM |
| */ |
| #include <string> |
| #include <iostream> |
| #include <fstream> |
| #include <string> |
| #include <sstream> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include "CommandLineParser.hpp" |
| #include "../Utils/StringUtils.h" |
| #include "../Utils/FileUtils.h" |
| |
| #include "antlr4-runtime.h" |
| using namespace antlr4; |
| |
| #include "../API/PythonAPI.h" |
| |
| #include <ctime> |
| #include <thread> |
| |
| using namespace SURELOG; |
| |
| std::string defaultLogFileName = "surelog.log"; |
| std::string CommandLineParser::m_versionNumber = "0.05"; |
| |
| const std::vector<std::string> copyright = { |
| "Copyright (c) 2017-2019 ACE Cloud,", |
| "Authorized used only." |
| }; |
| |
| const std::vector<std::string> banner = { |
| "********************************************", |
| "* SURELOG System Verilog Compiler/Linter *", |
| "********************************************", |
| }; |
| |
| const std::vector<std::string> footer = { |
| "********************************************", |
| "* End SURELOG SVerilog Compiler/Linter *", |
| "********************************************", |
| }; |
| |
| const std::vector<std::string> helpText = { |
| " ------------ SURELOG HELP --------------", |
| "", |
| "STANDARD VERILOG COMMAND LINE:", |
| " -f <file> Accepts a file containing command line arguments", |
| " -v <file> Library file", |
| " -y <path> Library directory", |
| " +incdir+<dir>+... Specifies include paths", |
| " -Idir Specifies include paths", |
| " +libext+<extname>+... Specifies the library extensions", |
| " <file>.v Verilog File", |
| " <file>.sv System Verilog File", |
| " +liborder Lib Order option (ignored)", |
| " +librescan Lib Rescan option (ignored)", |
| " +libverbose Lib Verbose option (ignored)", |
| " +nolibcell No Lib Cell option (ignored)", |
| " +define+macro_name=definition+...", |
| " Defines a macro and optionally its value", |
| " -L <libName> Defines library compilation order", |
| " -map <mapFile> Specifies a library mapping file (multiple -map options supported)", |
| " -cfgfile <confiFile> Specifies a configuration file (multiple -cfgFile options supported)", |
| " -cfg <configName> Specifies a configuration to use (multiple -cfg options supported)", |
| "FLOWS OPTIONS:", |
| " -fileunit Compiles each Verilog file as an independent", |
| " compilation unit (under slpp_unit/ if -writepp used)", |
| " -diffcompunit Compiles both all files as a whole unit and", |
| " separate compilation units to perform diffs", |
| " -parse Parse/Compile/Elaborate the files after pre-processing step", |
| " -nocomp Turns off Compilation & Elaboration", |
| " -noelab Turns off Elaboration", |
| " -pythonlistener Enables the Parser Python Listener", |
| " -pythonlistenerfile <script.py> Specifies the AST python listener file", |
| " -pythonevalscriptperfile <script.py> Eval the Python script on each source file (Multithreaded)", |
| " -pythonevalscript <script.py> Eval the Python script at the design level", |
| " -nopython Turns off all Python features, including waivers", |
| " -strictpythoncheck Turns on strict Python checks", |
| // " -tbb Enables the Intel TBB Multithread library", |
| " -mt <nb_max_treads> 0 up to 512 max threads, 0 or 1 being single threaded,", |
| " if \"max\" is given, the program will use one thread", |
| " per core on the host", |
| " -split <line number> Split files or modules larger than specified line number for multi thread compilation", |
| " -timescale=<timescale> Specifies the overall timescale", |
| " -nobuiltin Do not parse SV builtin classes (array...)", |
| "", |
| "TRACES OPTIONS:", |
| " -d <int> Debug <level> 1-4, lib, ast, inst, incl", |
| " -nostdout Mutes Standard output", |
| " -verbose Gives verbose processing information", |
| " -profile Gives Profiling information", |
| " -l <file> Specifies log file, default is surelog.log under output dir", |
| "", |
| "OUTPUT OPTIONS:", |
| " -odir <dir> Specifies the output directory, default is ./", |
| " -writeppfile <file> Writes out Preprocessor output in file", |
| " (all compilation units will override this file)", |
| " -writepp Writes out Preprocessor output (all compilation", |
| " units will generate files under slpp_all/ or slpp_unit/)", |
| " -lineoffsetascomments Writes the preprocessor line offsets as comments as opposed as parser directives", |
| " -nocache Default allows to create a cache for include files, this option prevents it", |
| " -cache <dir> Specifies the cache directory, default is slpp_all/cache or slpp_unit/cache", |
| " -createcache Create cache for precompiled packages", |
| " -filterdirectives Filters out simple directives like", |
| " `default_nettype in pre-processor's output", |
| " -filterprotected Filters out protected regions in pre-processor's output", |
| " -filtercomments Filters out comments in pre-processor's output", |
| " -outputlineinfo Outputs SLline directives in pre-processor's output", |
| " -pploc Output message location in terms of post preprocessor location", |
| " -noinfo Filters out INFO messages", |
| " -nonote Filters out NOTE messages", |
| " -nowarning Filters out WARNING messages", |
| " -o <path> Turns on all compilation stages, produces all outputs under that path" |
| }; |
| |
| std::string |
| printStringArray (const std::vector<std::string>& array) |
| { |
| std::string report; |
| for (unsigned int i = 0; i < array.size (); i++) |
| { |
| report += array[i] + "\n"; |
| } |
| report += "\n"; |
| return report; |
| } |
| |
| const std::string CommandLineParser::currentDateTime() { |
| time_t now = time(0); |
| struct tm tstruct; |
| char buf[80]; |
| tstruct = *localtime(&now); |
| // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime |
| // for more information about date/time format |
| strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct); |
| |
| return buf; |
| } |
| |
| void |
| CommandLineParser::logBanner (int argc, const char ** argv) |
| { |
| std::string banners = printStringArray (banner); |
| std::string copyrights = printStringArray (copyright); |
| m_errors->printToLogFile (banners); |
| m_errors->printToLogFile (copyrights); |
| std::string version = "VERSION: " + m_versionNumber + + "\n" + |
| "BUILT : " + std::string(__DATE__) + "\n"; |
| std::string date = "DATE : " + currentDateTime() + "\n"; |
| std::string cmd = "COMMAND:"; |
| for (int i = 1; i < argc; i++) |
| { |
| cmd += std::string(" ") + argv[i]; |
| } |
| cmd += "\n\n"; |
| m_errors->printToLogFile (version); |
| m_errors->printToLogFile (date); |
| m_errors->printToLogFile (cmd); |
| } |
| |
| void CommandLineParser::printBanner() { |
| std::string banners = printStringArray (banner); |
| std::cout << banners; |
| } |
| |
| void CommandLineParser::printFooter() { |
| std::string footers = "\n"; |
| footers += printStringArray (footer); |
| std::cout << footers; |
| } |
| |
| void |
| CommandLineParser::logFooter () |
| { |
| std::string footers = "\n"; |
| footers += printStringArray (footer); |
| m_errors->printToLogFile (footers); |
| |
| } |
| |
| CommandLineParser::CommandLineParser (ErrorContainer* errors, SymbolTable* symbolTable, bool diff_comp_mode, bool fileUnit) : |
| m_writePpOutputFileId(0), m_writePpOutput(false), m_filterFileLine(true), m_debugLevel(0), m_errors(errors), m_symbolTable(symbolTable), m_lineOffsetsAsComments(false), |
| m_liborder(false), m_librescan(false), m_libverbose(false), m_nolibcell(false), m_muteStdout(false), m_verbose(false), m_fileunit(fileUnit), |
| m_filterSimpleDirectives(false), m_filterProtectedRegions(false), m_filterComments(false), m_parse(false), m_compile(false), m_elaborate(false), m_diff_comp_mode(diff_comp_mode), |
| m_help(false), m_cacheAllowed(true), m_nbMaxTreads(0), m_fullCompileDir(0), m_cacheDirId(0), m_note(true), m_info(true), m_warning(true), |
| m_pythonListener(false), m_debugAstModel(false), m_debugInstanceTree(false), m_debugLibraryDef(false), m_useTbb(false), m_pythonAllowed(true), m_nbLinesForFileSplitting(500), |
| m_pythonEvalScriptPerFile (false), m_pythonEvalScript (false), m_pythonEvalScriptPerFileId (0), m_pythonEvalScriptId (0), m_pythonListenerFileId(0), m_debugIncludeFileInfo(false), |
| m_createCache(false), m_profile(false), m_parseBuiltIn(true), m_ppOutputFileLocation(false), m_logFileSpecified(false) |
| { |
| m_errors->regiterCmdLine(this); |
| m_logFileId = m_symbolTable->registerSymbol(defaultLogFileName); |
| m_compileUnitDirectory = m_symbolTable->registerSymbol("slpp_unit/"); |
| m_compileAllDirectory = m_symbolTable->registerSymbol("slpp_all/"); |
| m_outputDir = m_symbolTable->registerSymbol("./"); |
| m_defaultLogFileId = m_symbolTable->registerSymbol(defaultLogFileName); |
| m_defaultCacheDirId = m_symbolTable->registerSymbol("cache/"); |
| m_precompiledDirId = m_symbolTable->registerSymbol("pkg"); |
| if (m_diff_comp_mode) |
| { |
| m_muteStdout = true; |
| m_verbose = false; |
| } |
| } |
| |
| CommandLineParser::CommandLineParser (const CommandLineParser& orig) { } |
| |
| CommandLineParser::~CommandLineParser () { } |
| |
| void CommandLineParser::splitPlusArg_(std::string s, std::string prefix, std::vector<SymbolId>& container) |
| { |
| std::istringstream f (s); |
| std::string tmp; |
| while (getline (f, tmp, '+')) |
| { |
| if (tmp.size () && (tmp != prefix)) |
| { |
| SymbolId id = m_symbolTable->registerSymbol (tmp); |
| container.push_back (id); |
| } |
| } |
| } |
| |
| void CommandLineParser::splitPlusArg_(std::string s, std::string prefix, std::map<SymbolId,std::string>& container) |
| { |
| std::istringstream f (s); |
| std::string tmp; |
| while (getline (f, tmp, '+')) |
| { |
| if (tmp.size () && (tmp != prefix)) |
| { |
| std::string def; |
| std::string value; |
| unsigned int loc = tmp.find("="); |
| if(loc == std::string::npos) |
| { |
| SymbolId id = m_symbolTable->registerSymbol (tmp); |
| container.insert(std::make_pair(id, std::string ())); |
| } |
| else |
| { |
| def = tmp.substr(0,loc); |
| value = tmp.substr(loc+1); |
| SymbolId id = m_symbolTable->registerSymbol (def); |
| container.insert(std::make_pair (id, value)); |
| } |
| } |
| } |
| } |
| |
| /* Custom parser for +arguments */ |
| bool CommandLineParser::plus_arguments_ (const std::string& s) |
| { |
| std::string incdir("+incdir+"); |
| std::string libext("+libext+"); |
| std::string define("+define+"); |
| if (s.size() == 0) |
| return false; |
| if (s.at (0) != '+') |
| return false; |
| if (s.compare (0, incdir.size(), incdir) == 0) |
| { |
| splitPlusArg_(s,"incdir", m_includePaths); |
| return true; |
| } |
| if (s.compare (0, libext.size(), libext) == 0) |
| { |
| splitPlusArg_(s,"libext", m_libraryExtensions); |
| return true; |
| } |
| if (s.compare (0, define.size(), define) == 0) |
| { |
| splitPlusArg_(s,"define", m_defineList); |
| return true; |
| } |
| return false; |
| } |
| |
| void |
| CommandLineParser::processArgs_ (std::vector<std::string>& args, std::vector<std::string>& container) |
| { |
| for (unsigned int i = 0; i < args.size (); i++) |
| { |
| if (args[i] == "-f") |
| { |
| std::string f = args[i + 1]; |
| SymbolId fId = m_symbolTable->registerSymbol (f); |
| std::ifstream ifs (f); |
| if (!ifs) |
| { |
| Location loc (fId); |
| Error err (ErrorDefinition::CMD_DASH_F_FILE_DOES_NOT_EXIST, loc); |
| m_errors->addError(err); |
| } |
| else |
| { |
| std::stringstream ss; |
| ss << ifs.rdbuf (); |
| ifs.close(); |
| std::vector<std::string> argsInFile; |
| StringUtils::tokenize (ss.str ()," \n\t\r",argsInFile); |
| processArgs_ (argsInFile, container); |
| } |
| i++; |
| } |
| else |
| { |
| container.push_back(args[i]); |
| } |
| } |
| } |
| |
| int |
| CommandLineParser::parseCommandLine (int argc, const char ** argv) |
| { |
| |
| std::string exe_name = argv[0]; |
| std::string exe_path = FileUtils::getPathName (exe_name); |
| m_precompiledDirId = m_symbolTable->registerSymbol(exe_path + "pkg/"); |
| std::string built_in_verilog = exe_path + "../sv/builtin.sv"; |
| std::vector<std::string> all_arguments; |
| std::vector<std::string> cmd_line; |
| for (int i = 1; i < argc; i++) |
| { |
| cmd_line.push_back (argv[i]); |
| |
| if (!strcmp(argv[i],"-l")) |
| { |
| if (i < argc - 1) |
| { |
| m_logFileId = m_symbolTable->registerSymbol (argv[i + 1]); |
| m_logFileSpecified = true; |
| } |
| } |
| |
| } |
| processArgs_ (cmd_line, all_arguments); |
| for (unsigned int i = 0; i < all_arguments.size (); i++) |
| { |
| if (all_arguments[i] == "-help" || all_arguments[i] == "-h") |
| { |
| m_help = true; |
| std::string help = printStringArray(helpText); |
| m_errors->init(); |
| logBanner (argc, argv); |
| printBanner(); |
| std::cout << help; |
| m_errors->printToLogFile (help); |
| return true; |
| } |
| if (all_arguments[i] == "-nobuiltin") |
| { |
| m_parseBuiltIn = false; |
| } |
| } |
| if (m_parseBuiltIn) |
| { |
| m_sourceFiles.push_back (m_symbolTable->registerSymbol (built_in_verilog)); |
| } |
| for (unsigned int i = 0; i < all_arguments.size (); i++) |
| { |
| if (all_arguments[i] == "-fileunit") |
| { |
| if (m_diff_comp_mode == false) // Controlled by constructor |
| m_fileunit = true; |
| } |
| else if (all_arguments[i] == "-mutestdout") |
| { |
| m_muteStdout = true; |
| } |
| else if (all_arguments[i] == "-nopython") |
| { |
| m_pythonAllowed = false; |
| } |
| } |
| |
| for (unsigned int i = 0; i < all_arguments.size (); i++) |
| { |
| if (all_arguments[i] == "-odir" || all_arguments[i] == "-o") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_ODIR, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_outputDir = m_symbolTable->registerSymbol (all_arguments[i]); |
| } |
| } |
| bool status = prepareCompilation_ (argc, argv); |
| if (!status) |
| return status; |
| |
| for (unsigned int i = 0; i < all_arguments.size (); i++) |
| { |
| if (plus_arguments_ (all_arguments[i])) |
| { |
| } |
| else if (all_arguments[i] == "-d") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_DEBUG_MISSING_LEVEL, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| if (all_arguments[i] == "ast") |
| { |
| m_debugAstModel = true; |
| } |
| else if (all_arguments[i] == "inst") |
| { |
| m_debugInstanceTree = true; |
| } |
| else if (all_arguments[i] == "lib") |
| { |
| m_debugLibraryDef = true; |
| } |
| else if (all_arguments[i] == "incl") |
| { |
| m_debugIncludeFileInfo = true; |
| } |
| else |
| { |
| int debugLevel = atoi (all_arguments[i].c_str ()); |
| if (debugLevel < 0 || debugLevel > 4) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_DEBUG_INCORRECT_LEVEL, loc); |
| m_errors->addError (err); |
| } |
| else |
| { |
| m_debugLevel = debugLevel; |
| } |
| } |
| } |
| else if (strstr(all_arguments[i].c_str(),"-timescale=")) |
| { |
| std::string timescale; |
| timescale = all_arguments[i].substr(11, std::string::npos); |
| if (timescale == "") |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_TIMESCALE_MISSING_SETTING, loc); |
| m_errors->addError (err); |
| break; |
| } |
| m_timescale = timescale; |
| } |
| else if (strstr(all_arguments[i].c_str(),"-I")) |
| { |
| std::string include; |
| include = all_arguments[i].substr(2, std::string::npos); |
| if (include == "") |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_INCLUDE_PATH_DOES_NOT_EXIST, loc); |
| m_errors->addError (err); |
| break; |
| } |
| m_includePaths.push_back(getSymbolTable ()->registerSymbol (include)); |
| } |
| else if (all_arguments[i] == "-split") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_SPLIT_FILE_MISSING_SIZE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_nbLinesForFileSplitting = atoi (all_arguments[i].c_str ()); |
| } |
| else if (all_arguments[i] == "-mt") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_MT_MISSING_LEVEL, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| unsigned int maxMT = 0; |
| if (all_arguments[i] == "max") |
| { |
| unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); |
| maxMT = concurentThreadsSupported; |
| |
| } |
| else |
| { |
| maxMT = atoi (all_arguments[i].c_str ()); |
| } |
| if (maxMT < 0 || maxMT > 512) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_MT_INCORRECT_LEVEL, loc); |
| m_errors->addError (err); |
| } |
| else |
| { |
| if (m_diff_comp_mode) |
| { |
| unsigned int concurentThreadsSupported = std::thread::hardware_concurrency(); |
| if (maxMT > (concurentThreadsSupported / 2)) |
| maxMT = (concurentThreadsSupported / 2); |
| } |
| |
| if (maxMT == 0) |
| m_nbMaxTreads = maxMT; |
| else |
| { |
| m_nbMaxTreads = maxMT; |
| if (m_nbMaxTreads < 2) |
| m_nbMaxTreads = 2; |
| Location loc (getSymbolTable ()->registerSymbol (std::to_string(m_nbMaxTreads))); |
| Error err (ErrorDefinition::CMD_NUMBER_THREADS, loc); |
| m_errors->addError (err); |
| } |
| } |
| } |
| else if (all_arguments[i] == "-strictpythoncheck") |
| { |
| PythonAPI::setStrictMode (true); |
| |
| } |
| else if (all_arguments[i] == "-tbb") |
| { |
| m_useTbb = true; |
| |
| } |
| else if (all_arguments[i] == "-createcache") |
| { |
| m_createCache = true; |
| } |
| else if (all_arguments[i] == "-lineoffsetascomments") |
| { |
| m_lineOffsetsAsComments = true; |
| } |
| else if (all_arguments[i] == "-v") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_LIBRARY_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_libraryFiles.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-y") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_LIBRARY_PATH_MISSING_PATH, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_libraryPaths.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-l") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_LOG_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_logFileId = m_symbolTable->registerSymbol (all_arguments[i]); |
| m_logFileSpecified = true; |
| } |
| else if (all_arguments[i] == "-L") |
| { |
| i++; |
| m_orderedLibraries.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-map") |
| { |
| i++; |
| m_libraryMapFiles.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-cfgfile") |
| { |
| i++; |
| m_configFiles.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-cfg") |
| { |
| i++; |
| m_useConfigs.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| else if (all_arguments[i] == "-writeppfile") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_writePpOutputFileId = m_symbolTable->registerSymbol (all_arguments[i]); |
| } |
| else if (all_arguments[i] == "-cache") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_cacheDirId = m_symbolTable->registerSymbol (all_arguments[i]); |
| } |
| else if (all_arguments[i] == "-writepp") |
| { |
| m_writePpOutput = true; |
| } |
| else if (all_arguments[i] == "-noinfo") |
| { |
| m_info = false; |
| } |
| else if (all_arguments[i] == "-nonote") |
| { |
| m_note = false; |
| } |
| else if (all_arguments[i] == "-nowarning") |
| { |
| m_warning = false; |
| } |
| else if (all_arguments[i] == "-profile") |
| { |
| m_profile = true; |
| } |
| else if (all_arguments[i] == "-nobuiltin") |
| { |
| m_parseBuiltIn = false; |
| } |
| else if (all_arguments[i] == "-outputlineinfo") |
| { |
| m_filterFileLine = false; |
| } |
| else if (all_arguments[i] == "+liborder") |
| { |
| m_liborder = true; |
| } |
| else if (all_arguments[i] == "+librescan") |
| { |
| m_librescan = true; |
| } |
| else if (all_arguments[i] == "+libverbose") |
| { |
| m_libverbose = true; |
| } |
| else if (all_arguments[i] == "+nolibcell") |
| { |
| m_nolibcell = true; |
| } |
| else if (all_arguments[i] == "-fileunit") |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_SEPARATE_COMPILATION_UNIT_ON, loc); |
| m_errors->addError (err); |
| } |
| else if (all_arguments[i] == "-diffcompunit") |
| { |
| if (m_fileunit) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_SEPARATE_COMPILATION_UNIT_ON, loc); |
| m_errors->addError (err); |
| } |
| } |
| else if (all_arguments[i] == "-odir") |
| { |
| i++; |
| } |
| else if (all_arguments[i] == "-o") |
| { |
| i++; |
| m_writePpOutput = true; |
| m_parse = true; |
| } |
| else if (all_arguments[i] == "-nostdout") |
| { |
| m_muteStdout = true; |
| } |
| else if (all_arguments[i] == "-verbose") |
| { |
| m_verbose = true; |
| } |
| else if (all_arguments[i] == "-filterdirectives") |
| { |
| m_filterSimpleDirectives = true; |
| } |
| else if (all_arguments[i] == "-filterprotected") |
| { |
| m_filterProtectedRegions = true; |
| } |
| else if (all_arguments[i] == "-filtercomments") |
| { |
| m_filterComments = true; |
| } |
| else if (all_arguments[i] == "-parse") |
| { |
| m_writePpOutput = true; |
| m_parse = true; |
| m_compile = true; |
| m_elaborate = true; |
| } |
| else if (all_arguments[i] == "-nocomp") |
| { |
| m_compile = false; |
| m_elaborate = false; |
| } |
| else if (all_arguments[i] == "-noelab") |
| { |
| m_elaborate = false; |
| } |
| else if (all_arguments[i] == "-pploc") |
| { |
| m_ppOutputFileLocation = true; |
| } |
| else if (all_arguments[i] == "-pythonlistener") |
| { |
| m_writePpOutput = true; |
| m_parse = true; |
| m_compile = true; |
| m_elaborate = true; |
| m_pythonListener = true; |
| if (!PythonAPI::isListenerLoaded()) { |
| Location loc(0); |
| Error err (ErrorDefinition::PY_NO_PYTHON_LISTENER_FOUND, loc); |
| m_errors->addError (err); |
| } |
| if(!m_pythonAllowed) |
| std::cout << "ERROR: No Python allowed, check your arguments!\n"; |
| } |
| else if (all_arguments[i] == "-nopython") |
| { |
| m_pythonAllowed = false; |
| } |
| else if (all_arguments[i] == "-pythonevalscriptperfile") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_writePpOutput = true; |
| m_parse = true; |
| m_compile = true; |
| m_elaborate = true; |
| m_pythonEvalScriptPerFile = true; |
| m_pythonEvalScriptPerFileId = m_symbolTable->registerSymbol (all_arguments[i]); |
| if(m_pythonAllowed) |
| PythonAPI::loadScript (all_arguments[i], true); |
| else |
| std::cout << "ERROR: No Python allowed, check your arguments!\n"; |
| } |
| else if (all_arguments[i] == "-pythonlistenerfile") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_writePpOutput = true; |
| m_parse = true; |
| m_compile = true; |
| m_elaborate = true; |
| m_pythonListener = true; |
| m_pythonListenerFileId = m_symbolTable->registerSymbol (all_arguments[i]); |
| PythonAPI::setListenerScript (all_arguments[i]); |
| } |
| else if (all_arguments[i] == "-pythonevalscript") |
| { |
| if (i == all_arguments.size () - 1) |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PP_FILE_MISSING_FILE, loc); |
| m_errors->addError (err); |
| break; |
| } |
| i++; |
| m_writePpOutput = true; |
| m_parse = true; |
| m_compile = true; |
| m_elaborate = true; |
| m_pythonEvalScript = true; |
| m_pythonEvalScriptId = m_symbolTable->registerSymbol (all_arguments[i]); |
| if(m_pythonAllowed) |
| PythonAPI::loadScript (all_arguments[i], true); |
| else |
| std::cout << "ERROR: No Python allowed, check your arguments!\n"; |
| } |
| else if (all_arguments[i] == "-nocache") |
| { |
| m_cacheAllowed = false; |
| } |
| else if (all_arguments[i].size () && all_arguments[i].at (0) == '+') |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_PLUS_ARG_IGNORED, loc); |
| m_errors->addError (err); |
| } |
| else if (all_arguments[i].size () && all_arguments[i].at (0) == '-') |
| { |
| Location loc (getSymbolTable ()->registerSymbol (all_arguments[i])); |
| Error err (ErrorDefinition::CMD_MINUS_ARG_IGNORED, loc); |
| m_errors->addError (err); |
| } |
| else |
| { |
| if (all_arguments[i] != "") |
| m_sourceFiles.push_back (m_symbolTable->registerSymbol (all_arguments[i])); |
| } |
| } |
| |
| status = checkCommandLine_ (); |
| return status; |
| } |
| |
| bool |
| CommandLineParser::checkCommandLine_ () |
| { |
| bool noError = true; |
| for (auto fid : m_sourceFiles) |
| { |
| if (!FileUtils::fileExists (m_symbolTable->getSymbol (fid))) |
| { |
| Location loc (fid); |
| Error err (ErrorDefinition::CMD_VERILOG_FILE_DOES_NOT_EXIST, loc); |
| m_errors->addError (err); |
| noError = false; |
| } |
| } |
| for (auto fid : m_libraryPaths) |
| { |
| if (!FileUtils::fileExists (m_symbolTable->getSymbol (fid))) |
| { |
| Location loc (fid); |
| Error err (ErrorDefinition::CMD_LIBRARY_PATH_DOES_NOT_EXIST, loc); |
| m_errors->addError (err); |
| } |
| } |
| for (auto fid : m_libraryFiles) |
| { |
| if (!FileUtils::fileExists (m_symbolTable->getSymbol (fid))) |
| { |
| Location loc (fid); |
| Error err (ErrorDefinition::CMD_LIBRARY_FILE_DOES_NOT_EXIST, loc); |
| m_errors->addError (err); |
| noError = false; |
| } |
| } |
| for (auto fid : m_includePaths) |
| { |
| if (!FileUtils::fileExists (m_symbolTable->getSymbol (fid))) |
| { |
| Location loc (fid); |
| Error err (ErrorDefinition::CMD_INCLUDE_PATH_DOES_NOT_EXIST, loc); |
| m_errors->addError (err); |
| } |
| } |
| if (!m_errors->printMessages (m_muteStdout)) |
| { |
| noError = false; |
| } |
| |
| return noError; |
| } |
| |
| bool |
| CommandLineParser::prepareCompilation_ (int argc, const char ** argv) |
| { |
| bool noError = true; |
| std::string odir = m_symbolTable->getSymbol (m_outputDir); |
| if (odir.size ()) |
| { |
| if (odir[odir.size () - 1] != '/') |
| { |
| odir += '/'; |
| } |
| } |
| |
| odir += m_symbolTable->getSymbol ((fileunit () ? m_compileUnitDirectory : m_compileAllDirectory)); |
| m_fullCompileDir = m_symbolTable->registerSymbol (odir); |
| |
| if (!m_logFileSpecified) |
| m_logFileId = m_symbolTable->registerSymbol (odir + defaultLogFileName); |
| |
| std::string cachedir; |
| if (m_cacheAllowed) |
| { |
| if (m_cacheDirId == 0) |
| { |
| cachedir = odir + m_symbolTable->getSymbol (m_defaultCacheDirId); |
| m_cacheDirId = m_symbolTable->registerSymbol (cachedir); |
| } |
| else |
| { |
| cachedir = m_symbolTable->getSymbol (m_cacheDirId); |
| } |
| } |
| |
| int status = FileUtils::mkDir (odir.c_str ()); |
| if (status != 0) |
| { |
| Location loc (m_fullCompileDir); |
| Error err (ErrorDefinition::CMD_PP_CANNOT_CREATE_OUTPUT_DIR, loc); |
| m_errors->addError (err); |
| noError = false; |
| } |
| |
| m_errors->init(); |
| logBanner (argc, argv); |
| if (!m_muteStdout) |
| { |
| printBanner(); |
| } |
| Location loc (m_logFileId); |
| Error err (ErrorDefinition::CMD_CREATING_LOG_FILE, loc); |
| m_errors->addError (err); |
| |
| if (m_cacheAllowed) |
| { |
| status = FileUtils::mkDir (cachedir.c_str ()); |
| if (status != 0) |
| { |
| Location loc (m_cacheDirId); |
| Error err (ErrorDefinition::CMD_PP_CANNOT_CREATE_CACHE_DIR, loc); |
| m_errors->addError (err); |
| noError = false; |
| } |
| } |
| |
| |
| if (m_errors->hasFatalErrors()) |
| { |
| noError = false; |
| } |
| |
| return noError; |
| } |
| |