| /* | |
| 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: Compiler.cpp | |
| * Author: alain | |
| * | |
| * Created on March 4, 2017, 5:16 PM | |
| */ | |
| #include <stdint.h> | |
| #include "CommandLine/CommandLineParser.h" | |
| #include "ErrorReporting/ErrorContainer.h" | |
| #include "SourceCompile/SymbolTable.h" | |
| #include "SourceCompile/CompilationUnit.h" | |
| #include "SourceCompile/PreprocessFile.h" | |
| #include "SourceCompile/CompilationUnit.h" | |
| #include "SourceCompile/CompileSourceFile.h" | |
| #include "SourceCompile/Compiler.h" | |
| #include "SourceCompile/CheckCompile.h" | |
| #include "antlr4-runtime.h" | |
| #include "DesignCompile/CompileDesign.h" | |
| #include "SourceCompile/AnalyzeFile.h" | |
| #include "Library/ParseLibraryDef.h" | |
| #include "Utils/FileUtils.h" | |
| #include "Package/Precompiled.h" | |
| #include "Utils/StringUtils.h" | |
| #include "Utils/Timer.h" | |
| #include <math.h> | |
| using namespace antlr4; | |
| #include "API/PythonAPI.h" | |
| #include "SourceCompile/CheckCompile.h" | |
| #include <mutex> | |
| #include <thread> | |
| #include <vector> | |
| using namespace SURELOG; | |
| Compiler::Compiler(CommandLineParser* commandLineParser, ErrorContainer* errors, | |
| SymbolTable* symbolTable) | |
| : m_commandLineParser(commandLineParser), | |
| m_errors(errors), | |
| m_symbolTable(symbolTable), | |
| m_commonCompilationUnit(NULL) { | |
| m_design = NULL; | |
| #ifdef USETBB | |
| if (getCommandLineParser()->useTbb() && | |
| (getCommandLineParser()->getNbMaxTreads() > 0)) | |
| tbb::task_scheduler_init init(getCommandLineParser()->getNbMaxTreads()); | |
| #endif | |
| } | |
| Compiler::Compiler(const Compiler& orig) {} | |
| Compiler::~Compiler() { | |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr; | |
| for (itr = m_antlrPpMap.begin(); itr != m_antlrPpMap.end(); itr++) { | |
| delete (*itr).second; | |
| } | |
| if (m_commonCompilationUnit) { | |
| delete m_commonCompilationUnit; | |
| } | |
| cleanup_(); | |
| } | |
| struct FunctorCompileOneFile { | |
| FunctorCompileOneFile(CompileSourceFile* compileSource, | |
| CompileSourceFile::Action action) | |
| : m_compileSourceFile(compileSource), m_action(action) {} | |
| int operator()() const { | |
| if (m_compileSourceFile->getCommandLineParser()->pythonListener() || | |
| m_compileSourceFile->getCommandLineParser() | |
| ->pythonEvalScriptPerFile()) { | |
| PyThreadState* interpState = PythonAPI::initNewInterp(); | |
| m_compileSourceFile->setPythonInterp(interpState); | |
| } | |
| return m_compileSourceFile->compile(m_action); | |
| } | |
| private: | |
| CompileSourceFile* m_compileSourceFile; | |
| CompileSourceFile::Action m_action; | |
| }; | |
| bool Compiler::compileOneFile_(CompileSourceFile* compiler, | |
| CompileSourceFile::Action action) { | |
| bool status = compiler->compile(action); | |
| return status; | |
| } | |
| bool Compiler::isLibraryFile(SymbolId id) { | |
| if (m_libraryFiles.find(id) == m_libraryFiles.end()) { | |
| return false; | |
| } else { | |
| return true; | |
| } | |
| } | |
| bool Compiler::ppinit_() { | |
| if (!m_commandLineParser->fileunit()) { | |
| m_commonCompilationUnit = new CompilationUnit(false); | |
| } | |
| CompilationUnit* comp_unit = m_commonCompilationUnit; | |
| // Source files (.v, .sv on the command line) | |
| std::set<SymbolId> sourceFiles; | |
| unsigned int size = m_commandLineParser->getSourceFiles().size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| SymbolTable* symbols = m_symbolTable; | |
| if (m_commandLineParser->fileunit()) { | |
| comp_unit = new CompilationUnit(true); | |
| m_compilationUnits.push_back(comp_unit); | |
| symbols = new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| } | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| SymbolId id = m_commandLineParser->getSourceFiles()[i]; | |
| std::string fileName = m_commandLineParser->getSymbolTable()->getSymbol(id); | |
| std::string fullPath = FileUtils::getFullPath(fileName); | |
| SymbolId fullPathId = | |
| m_commandLineParser->getSymbolTable()->registerSymbol(fullPath); | |
| Library* library = m_librarySet->getLibrary(fullPathId); | |
| sourceFiles.insert(fullPathId); | |
| CompileSourceFile* compiler = new CompileSourceFile( | |
| m_commandLineParser->getSourceFiles()[i], m_commandLineParser, errors, | |
| this, symbols, comp_unit, library); | |
| m_compilers.push_back(compiler); | |
| } | |
| // Library files | |
| std::set<SymbolId> libFiles; | |
| // (-v <file>) | |
| size = m_commandLineParser->getLibraryFiles().size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| SymbolId id = m_commandLineParser->getLibraryFiles()[i]; | |
| libFiles.insert(id); | |
| } | |
| // (-y <path> +libext+<ext>) | |
| for (auto path : m_commandLineParser->getLibraryPaths()) { | |
| for (auto ext : m_commandLineParser->getLibraryExtensions()) { | |
| auto files = FileUtils::collectFiles( | |
| path, ext, m_commandLineParser->getSymbolTable()); | |
| for (auto file : files) { | |
| libFiles.insert(file); | |
| } | |
| } | |
| } | |
| for (auto id : libFiles) { | |
| SymbolTable* symbols = m_symbolTable; | |
| if (m_commandLineParser->fileunit()) { | |
| comp_unit = new CompilationUnit(true); | |
| m_compilationUnits.push_back(comp_unit); | |
| symbols = new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| } | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| std::string fullPath = FileUtils::getFullPath( | |
| m_commandLineParser->getSymbolTable()->getSymbol(id)); | |
| // This line registers the file in the "work" library: | |
| SymbolId fullPathId = | |
| m_commandLineParser->getSymbolTable()->registerSymbol(fullPath); | |
| /*Library* library = */ m_librarySet->getLibrary(fullPathId); | |
| m_libraryFiles.insert(id); | |
| m_libraryFiles.insert(fullPathId); | |
| // No need to register a compiler | |
| // CompileSourceFile* compiler = new CompileSourceFile | |
| // (m_commandLineParser->getLibraryFiles ()[i], | |
| // m_commandLineParser, | |
| // errors, this, | |
| // symbols, comp_unit, | |
| // library); | |
| // m_compilers.push_back (compiler); | |
| } | |
| // Libraries (.map) | |
| for (auto& lib : m_librarySet->getLibraries()) { | |
| for (auto id : lib.getFiles()) { | |
| std::string fileName = lib.getSymbols()->getSymbol(id); | |
| if (sourceFiles.find(id) != sourceFiles.end()) { | |
| // These files are already included in the command line | |
| continue; | |
| } | |
| if (strstr(fileName.c_str(), ".map")) { | |
| // .map files are not parsed with the regular parser | |
| continue; | |
| } | |
| SymbolTable* symbols = m_symbolTable; | |
| if (m_commandLineParser->fileunit()) { | |
| comp_unit = new CompilationUnit(true); | |
| m_compilationUnits.push_back(comp_unit); | |
| symbols = new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| } | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| CompileSourceFile* compiler = new CompileSourceFile( | |
| id, m_commandLineParser, errors, this, symbols, comp_unit, &lib); | |
| m_compilers.push_back(compiler); | |
| } | |
| } | |
| return true; | |
| } | |
| bool Compiler::parseinit_() { | |
| Precompiled* prec = Precompiled::getSingleton(); | |
| // Single out the large files. | |
| // Small files are going to be scheduled in multiple threads based on size. | |
| // Large files are going to be compiled in a different batch in multithread | |
| if (!m_commandLineParser->fileunit()) { | |
| unsigned int size = m_symbolTables.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_symbolTables[i]; | |
| } | |
| size = m_errorContainers.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_errorContainers[i]; | |
| } | |
| m_symbolTables.clear(); | |
| m_errorContainers.clear(); | |
| } | |
| std::vector<CompileSourceFile*> tmp_compilers; | |
| unsigned int size = m_compilers.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| std::string fileName = m_compilers[i]->getSymbolTable()->getSymbol( | |
| m_compilers[i]->getPpOutputFileId()); | |
| std::string origFile = m_compilers[i]->getSymbolTable()->getSymbol( | |
| m_compilers[i]->getFileId()); | |
| unsigned int nbThreads = m_commandLineParser->getNbMaxTreads(); | |
| std::string root = fileName; | |
| root = StringUtils::getRootFileName(root); | |
| if (prec->isFilePrecompiled(root)) { | |
| nbThreads = 0; | |
| } | |
| int effectiveNbThreads = 0; | |
| if (nbThreads > 4) | |
| effectiveNbThreads = (int)(log(((float)nbThreads + 1.0) / 4.0) * 10.0); | |
| else | |
| effectiveNbThreads = nbThreads; | |
| AnalyzeFile* fileAnalyzer = new AnalyzeFile( | |
| m_commandLineParser, m_design, fileName, origFile, effectiveNbThreads); | |
| fileAnalyzer->analyze(); | |
| m_compilers[i]->setFileAnalyzer(fileAnalyzer); | |
| if (fileAnalyzer->getSplitFiles().size() > 1) { | |
| // Schedule parent | |
| m_compilersParentFiles.push_back(m_compilers[i]); | |
| m_compilers[i]->initParser(); | |
| if (!m_commandLineParser->fileunit()) { | |
| SymbolTable* symbols = | |
| new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| m_compilers[i]->setSymbolTable(symbols); | |
| // fileContent->setSymbolTable(symbols); | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| m_compilers[i]->setErrorContainer(errors); | |
| } | |
| FileContent* fileContent = | |
| new FileContent(m_compilers[i]->getParser()->getFileId(0), | |
| m_compilers[i]->getParser()->getLibrary(), | |
| m_compilers[i]->getSymbolTable(), | |
| m_compilers[i]->getErrorContainer(), NULL, 0); | |
| m_compilers[i]->getParser()->setFileContent(fileContent); | |
| int j = 0; | |
| for (auto chunk : fileAnalyzer->getSplitFiles()) { | |
| SymbolTable* symbols = | |
| new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| SymbolId ppId = symbols->registerSymbol(chunk); | |
| symbols->registerSymbol( | |
| m_compilers[i]->getParser()->getFileName(LINE1)); | |
| CompileSourceFile* chunkCompiler = new CompileSourceFile( | |
| m_compilers[i], ppId, fileAnalyzer->getLineOffsets()[j]); | |
| // Schedule chunk | |
| tmp_compilers.push_back(chunkCompiler); | |
| chunkCompiler->setSymbolTable(symbols); | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| chunkCompiler->setErrorContainer(errors); | |
| // chunkCompiler->getParser ()->setFileContent (fileContent); | |
| FileContent* fileContent = | |
| new FileContent(m_compilers[i]->getParser()->getFileId(0), | |
| m_compilers[i]->getParser()->getLibrary(), symbols, | |
| errors, NULL, ppId); | |
| chunkCompiler->getParser()->setFileContent(fileContent); | |
| getDesign()->addFileContent(m_compilers[i]->getParser()->getFileId(0), | |
| fileContent); | |
| j++; | |
| } | |
| } else { | |
| if (!m_commandLineParser->fileunit()) { | |
| SymbolTable* symbols = | |
| new SymbolTable(*m_commandLineParser->getSymbolTable()); | |
| m_symbolTables.push_back(symbols); | |
| m_compilers[i]->setSymbolTable(symbols); | |
| ErrorContainer* errors = new ErrorContainer(symbols); | |
| m_errorContainers.push_back(errors); | |
| errors->regiterCmdLine(m_commandLineParser); | |
| m_compilers[i]->setErrorContainer(errors); | |
| } | |
| tmp_compilers.push_back(m_compilers[i]); | |
| } | |
| } | |
| m_compilers = tmp_compilers; | |
| return true; | |
| } | |
| bool Compiler::pythoninit_() { return parseinit_(); } | |
| ErrorContainer::Stats Compiler::getErrorStats() { | |
| ErrorContainer::Stats stats; | |
| unsigned int size = m_errorContainers.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| ErrorContainer::Stats tmp; | |
| tmp = m_errorContainers[i]->getErrorStats(); | |
| stats += tmp; | |
| } | |
| return stats; | |
| } | |
| bool Compiler::cleanup_() { | |
| unsigned int size = m_compilers.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_compilers[i]; | |
| } | |
| size = m_compilationUnits.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_compilationUnits[i]; | |
| } | |
| size = m_symbolTables.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_symbolTables[i]; | |
| } | |
| size = m_errorContainers.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| delete m_errorContainers[i]; | |
| } | |
| return true; | |
| } | |
| bool Compiler::compileFileSet_(CompileSourceFile::Action action, | |
| bool allowMultithread, | |
| std::vector<CompileSourceFile*>& container) { | |
| unsigned short maxThreadCount = m_commandLineParser->getNbMaxTreads(); | |
| if (allowMultithread == false) { | |
| maxThreadCount = 0; | |
| } | |
| if (maxThreadCount == 0) { | |
| // Single thread | |
| unsigned int size = container.size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| container[i]->setPythonInterp(PythonAPI::getMainInterp()); | |
| bool status = compileOneFile_(container[i], action); | |
| m_errors->appendErrors(*container[i]->getErrorContainer()); | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| if ((!status) || container[i]->getErrorContainer()->hasFatalErrors()) | |
| return false; | |
| } | |
| } else if (getCommandLineParser()->useTbb() && | |
| (action != CompileSourceFile::Action::Parse)) { | |
| #ifdef USETBB | |
| // TBB Thread management | |
| int maxThreadCount = m_commandLineParser->getNbMaxTreads(); | |
| if (allowMultithread == false) { | |
| maxThreadCount = 0; | |
| } | |
| unsigned int size = container.size(); | |
| if (maxThreadCount) { | |
| for (unsigned int i = 0; i < size; i++) { | |
| m_taskGroup.run(FunctorCompileOneFile(container[i], action)); | |
| } | |
| m_taskGroup.wait(); | |
| bool fatalErrors = false; | |
| for (unsigned int i = 0; i < size; i++) { | |
| // Promote report to master error container | |
| m_errors->appendErrors(*container[i]->getErrorContainer()); | |
| if (container[i]->getErrorContainer()->hasFatalErrors()) { | |
| fatalErrors = true; | |
| } | |
| if (getCommandLineParser()->pythonListener()) { | |
| container[i]->shutdownPythonInterp(); | |
| } | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| } | |
| if (fatalErrors) return false; | |
| } else { | |
| for (unsigned int i = 0; i < size; i++) { | |
| container[i]->setPythonInterp(PythonAPI::getMainInterp()); | |
| bool status = compileOneFile_(container[i], action); | |
| m_errors->appendErrors(*container[i]->getErrorContainer()); | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| if ((!status) || container[i]->getErrorContainer()->hasFatalErrors()) | |
| return false; | |
| } | |
| } | |
| #endif | |
| } else { | |
| // Custom Thread management | |
| // Optimize the load balance, try to even out the work in each thread by the | |
| // size of the files | |
| std::vector<std::vector<CompileSourceFile*>> jobArray(maxThreadCount); | |
| std::vector<unsigned long> jobSize(maxThreadCount); | |
| for (unsigned short i = 0; i < maxThreadCount; i++) jobSize[i] = 0; | |
| for (unsigned int i = 0; i < container.size(); i++) { | |
| unsigned int size = container[i]->getJobSize(action); | |
| unsigned int newJobIndex = 0; | |
| uint64_t minJobQueue = ULLONG_MAX; | |
| for (unsigned short ii = 0; ii < maxThreadCount; ii++) { | |
| if (jobSize[ii] < minJobQueue) { | |
| newJobIndex = ii; | |
| minJobQueue = jobSize[ii]; | |
| } | |
| } | |
| jobSize[newJobIndex] += size; | |
| jobArray[newJobIndex].push_back(container[i]); | |
| } | |
| if (getCommandLineParser()->profile()) { | |
| if (action == CompileSourceFile::Preprocess) | |
| std::cout << "Preprocessing task\n"; | |
| else if (action == CompileSourceFile::Parse) | |
| std::cout << "Parsing task\n"; | |
| else | |
| std::cout << "Misc Task\n"; | |
| for (unsigned short i = 0; i < maxThreadCount; i++) { | |
| std::cout << "Thread " << i << " : \n"; | |
| int sum = 0; | |
| for (unsigned int j = 0; j < jobArray[i].size(); j++) { | |
| std::string fileName; | |
| if (jobArray[i][j]->getPreprocessor()) | |
| fileName = jobArray[i][j]->getPreprocessor()->getFileName(0); | |
| if (jobArray[i][j]->getParser()) | |
| fileName = jobArray[i][j]->getParser()->getFileName(0); | |
| sum += jobArray[i][j]->getJobSize(action); | |
| std::cout << jobArray[i][j]->getJobSize(action) << " " << fileName | |
| << "\n"; | |
| } | |
| std::cout << ", Total: " << sum << std::endl << std::flush; | |
| } | |
| } | |
| // Create the threads with their respective workloads | |
| std::vector<std::thread*> threads; | |
| for (unsigned short i = 0; i < maxThreadCount; i++) { | |
| std::thread* th = new std::thread([=] { | |
| for (unsigned int j = 0; j < jobArray[i].size(); j++) { | |
| if (getCommandLineParser()->pythonListener() || | |
| getCommandLineParser()->pythonEvalScriptPerFile()) { | |
| PyThreadState* interpState = PythonAPI::initNewInterp(); | |
| jobArray[i][j]->setPythonInterp(interpState); | |
| } | |
| jobArray[i][j]->compile(action); | |
| if (getCommandLineParser()->pythonListener() || | |
| getCommandLineParser()->pythonEvalScriptPerFile()) { | |
| jobArray[i][j]->shutdownPythonInterp(); | |
| } | |
| } | |
| }); | |
| threads.push_back(th); | |
| } | |
| // Sync the threads | |
| for (unsigned int th = 0; th < threads.size(); th++) { | |
| threads[th]->join(); | |
| } | |
| // Delete the threads | |
| for (unsigned int th = 0; th < threads.size(); th++) { | |
| delete threads[th]; | |
| } | |
| // Promote report to master error container | |
| bool fatalErrors = false; | |
| for (unsigned int j = 0; j < container.size(); j++) { | |
| m_errors->appendErrors(*container[j]->getErrorContainer()); | |
| if (container[j]->getErrorContainer()->hasFatalErrors()) | |
| fatalErrors = true; | |
| } | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| if (fatalErrors) return false; | |
| } | |
| return true; | |
| } | |
| bool Compiler::compile() { | |
| std::string profile; | |
| Timer tmr; | |
| Timer tmrTotal; | |
| // Scan the libraries definition | |
| if (!parseLibrariesDef_()) return false; | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Scan libraries took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| // Preprocess | |
| ppinit_(); | |
| if (!compileFileSet_(CompileSourceFile::Preprocess, | |
| m_commandLineParser->fileunit(), m_compilers)) | |
| return false; | |
| // Single thread post Preprocess | |
| if (!compileFileSet_(CompileSourceFile::PostPreprocess, false, m_compilers)) | |
| return false; | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Preprocessing took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| // Parse | |
| bool parserInitialized = false; | |
| if (m_commandLineParser->parse() || m_commandLineParser->pythonListener() || | |
| m_commandLineParser->pythonEvalScriptPerFile() || | |
| m_commandLineParser->pythonEvalScript()) { | |
| parseinit_(); | |
| parserInitialized = true; | |
| if (!compileFileSet_(CompileSourceFile::Parse, true, m_compilers)) | |
| return false; // Small files and large file chunks | |
| if (!compileFileSet_(CompileSourceFile::Parse, true, | |
| m_compilersParentFiles)) | |
| return false; // Recombine chunks | |
| } | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = | |
| "Parsing took " + StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| for (unsigned int i = 0; i < m_compilersParentFiles.size(); i++) { | |
| msg += m_compilersParentFiles[i]->getParser()->getProfileInfo(); | |
| } | |
| for (unsigned int i = 0; i < m_compilers.size(); i++) { | |
| msg += m_compilers[i]->getParser()->getProfileInfo(); | |
| } | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| // Check Parsing | |
| CheckCompile* checkComp = new CheckCompile(this); | |
| checkComp->check(); | |
| delete checkComp; | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| // Python Listener | |
| if (m_commandLineParser->pythonListener() || | |
| m_commandLineParser->pythonEvalScriptPerFile()) { | |
| if (!parserInitialized) pythoninit_(); | |
| if (!compileFileSet_(CompileSourceFile::PythonAPI, true, m_compilers)) | |
| return false; | |
| if (!compileFileSet_(CompileSourceFile::PythonAPI, true, | |
| m_compilersParentFiles)) | |
| return false; | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Python file processing took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| } | |
| if (m_commandLineParser->compile()) { | |
| // Compile Design, has its own thread management | |
| CompileDesign* compileDesign = new CompileDesign(this); | |
| compileDesign->compile(); | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Compilation took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| if (m_commandLineParser->elaborate()) { | |
| compileDesign->elaborate(); | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Elaboration took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + "s\n"; | |
| std::cout << msg << std::endl; | |
| profile += msg; | |
| tmr.reset(); | |
| } | |
| if (m_commandLineParser->pythonEvalScript()) { | |
| PythonAPI::evalScript(m_commandLineParser->getSymbolTable()->getSymbol( | |
| m_commandLineParser->pythonEvalScriptId()), | |
| m_design); | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Python design processing took " + | |
| StringUtils::to_string(tmr.elapsed_rounded()) + | |
| "s\n"; | |
| profile += msg; | |
| std::cout << msg << std::endl; | |
| tmr.reset(); | |
| } | |
| } | |
| m_errors->printMessages(m_commandLineParser->muteStdout()); | |
| } | |
| delete compileDesign; | |
| } | |
| if (m_commandLineParser->profile()) { | |
| std::string msg = "Total time " + | |
| StringUtils::to_string(tmrTotal.elapsed_rounded()) + | |
| "s\n"; | |
| profile += msg; | |
| profile = std::string("==============\n") + "PROFILE\n" + | |
| std::string("==============\n") + profile + "==============\n"; | |
| std::cout << profile << std::endl; | |
| m_errors->printToLogFile(profile); | |
| } | |
| return true; | |
| } | |
| void Compiler::registerAntlrPpHandlerForId( | |
| SymbolId id, PreprocessFile::AntlrParserHandler* pp) { | |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr = | |
| m_antlrPpMap.find(id); | |
| if (itr != m_antlrPpMap.end()) { | |
| delete (*itr).second; | |
| m_antlrPpMap.erase(itr); | |
| m_antlrPpMap.insert(std::make_pair(id, pp)); | |
| return; | |
| } | |
| m_antlrPpMap.insert(std::make_pair(id, pp)); | |
| } | |
| PreprocessFile::AntlrParserHandler* Compiler::getAntlrPpHandlerForId( | |
| SymbolId id) { | |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr = | |
| m_antlrPpMap.find(id); | |
| if (itr != m_antlrPpMap.end()) { | |
| PreprocessFile::AntlrParserHandler* ptr = (*itr).second; | |
| return ptr; | |
| } | |
| return NULL; | |
| } | |
| bool Compiler::parseLibrariesDef_() { | |
| m_librarySet = new LibrarySet(); | |
| m_configSet = new ConfigSet(); | |
| m_design = new Design(this, m_librarySet, m_configSet); | |
| ParseLibraryDef* libParser = new ParseLibraryDef( | |
| m_commandLineParser, m_errors, m_symbolTable, m_librarySet, m_configSet); | |
| return libParser->parseLibrariesDefinition(); | |
| } |