blob: f24312a253c7ef507d090c11333a91f101b1ee2f [file] [log] [blame]
/*
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 <sys/param.h>
#include <unistd.h>
#include "CommandLine/CommandLineParser.h"
#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 = "1.00";
const std::vector<std::string> copyright = {
"Copyright (c) 2017-2019 Alain Dargelas,",
"http://www.apache.org/licenses/LICENSE-2.0"};
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>[+<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+<name>=<value>[+<name>=<value>...]",
" 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)",
" -Dvar=value Same as env var definition for -f files var substitution",
"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",
" -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",
" -mp <mb_max_process> 0 up to 512 max processes, 0 or 1 being single process",
" -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 ",
" -builtin <path> Alternative path to builtin.sv, python/ and pkg/ dirs",
"outputs under that path",
" --help This help",
" --version Surelog version",
"RETURN CODE:",
" Bit mask the return code, more than 1 bit can be on.",
" 0 - No issues",
" 0x1 - Fatal error(s)",
" 0x2 - Syntax error(s)",
" 0x4 - Error(s)"
};
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::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_parseOnly(false),
m_compile(false),
m_elaborate(false),
m_diff_comp_mode(diff_comp_mode),
m_help(false),
m_cacheAllowed(true),
m_nbMaxTreads(0),
m_nbMaxProcesses(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;
const size_t 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::string fileContent = ss.str();
fileContent = StringUtils::removeComments(fileContent);
fileContent = StringUtils::evaluateEnvVars (fileContent);
std::vector<std::string> argsInFile;
StringUtils::tokenize(fileContent, " \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];
m_exePath = exe_name;
std::string exe_path = FileUtils::getPathName(exe_name);
m_precompiledDirId = m_symbolTable->registerSymbol(exe_path + "pkg/");
if (!FileUtils::fileExists(exe_path + "pkg/")) {
if (FileUtils::fileExists("/usr/lib/surelog/pkg/")) {
m_precompiledDirId = m_symbolTable->registerSymbol("/usr/lib/surelog/pkg/");
}
if (FileUtils::fileExists("/usr/local/lib/surelog/pkg/")) {
m_precompiledDirId = m_symbolTable->registerSymbol("/usr/local/lib/surelog/pkg/");
}
}
std::string built_in_verilog = exe_path + "/sv/builtin.sv";
if (!FileUtils::fileExists(built_in_verilog)) {
built_in_verilog = "/usr/lib/surelog/sv/builtin.sv";
if (!FileUtils::fileExists("/usr/lib/surelog/sv/builtin.sv")) {
built_in_verilog = "/usr/local/lib/surelog/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], "-builtin")) {
if (i < argc - 1) {
m_builtinPath = argv[i + 1];
built_in_verilog = m_builtinPath + "/builtin.sv";
}
} else if (!strcmp (argv[i], "-l"))
{
if (i < argc - 1)
{
m_logFileId = m_symbolTable->registerSymbol (argv[i + 1]);
m_logFileSpecified = true;
}
}
else if (strstr (argv[i], "-D"))
{
std::string def;
std::string value;
std::string tmp = argv[i];
const size_t loc = tmp.find ("=");
if (loc == std::string::npos)
{
StringUtils::registerEnvVar (def, "");
}
else
{
def = tmp.substr (2, loc - 2);
value = tmp.substr (loc + 1);
StringUtils::registerEnvVar (def, value);
}
}
}
processArgs_(cmd_line, all_arguments);
for (unsigned int i = 0; i < all_arguments.size(); i++) {
if (all_arguments[i] == "-help" || all_arguments[i] == "-h" ||
all_arguments[i] == "--help") {
m_help = true;
std::string help = printStringArray(helpText);
m_errors->init();
logBanner(argc, argv);
std::cout << help;
return true;
}
if (all_arguments[i] == "--version") {
std::string version = "VERSION: " + m_versionNumber +"\n" +
"BUILT : " + std::string(__DATE__) + "\n";
std::cout << version << std::flush;
m_help = true;
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(), "-D")) {
} 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" || all_arguments[i] == "-mp") {
bool mt = (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) {
if (mt)
m_nbMaxTreads = maxMT;
else {
m_nbMaxTreads = maxMT;
m_nbMaxProcesses = maxMT;
}
} else {
if (mt) {
m_nbMaxTreads = maxMT;
if (m_nbMaxTreads < 2) m_nbMaxTreads = 2;
} else {
m_nbMaxTreads = maxMT;
if (m_nbMaxTreads < 2) m_nbMaxTreads = 2;
m_nbMaxProcesses = maxMT;
if (m_nbMaxProcesses < 2) m_nbMaxProcesses = 2;
}
Location loc(
getSymbolTable()->registerSymbol(std::to_string(maxMT)));
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] == "-parseonly") {
m_writePpOutput = true;
m_parse = true;
m_compile = false;
m_elaborate = false;
m_parseOnly = 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);
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;
}