| /* | |
| 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: ParseLibraryDef.cpp | |
| * Author: alain | |
| * | |
| * Created on January 27, 2018, 5:05 PM | |
| */ | |
| #include "Utils/StringUtils.h" | |
| #include "CommandLine/CommandLineParser.h" | |
| #include "SourceCompile/CompilationUnit.h" | |
| #include "SourceCompile/PreprocessFile.h" | |
| #include "SourceCompile/CompileSourceFile.h" | |
| #include "SourceCompile/Compiler.h" | |
| #include "SourceCompile/ParseFile.h" | |
| #include "Library/ParseLibraryDef.h" | |
| #include "Utils/FileUtils.h" | |
| #include "antlr4-runtime.h" | |
| #include "atn/ParserATNSimulator.h" | |
| using namespace antlr4; | |
| using namespace SURELOG; | |
| #include "parser/SV3_1aLexer.h" | |
| #include "parser/SV3_1aParser.h" | |
| #include "Library/SVLibShapeListener.h" | |
| #include "Library/AntlrLibParserErrorListener.h" | |
| ParseLibraryDef::ParseLibraryDef(CommandLineParser* commandLineParser, | |
| ErrorContainer* errors, | |
| SymbolTable* symbolTable, | |
| LibrarySet* librarySet, ConfigSet* configSet) | |
| : m_fileId(0), | |
| m_commandLineParser(commandLineParser), | |
| m_errors(errors), | |
| m_symbolTable(symbolTable), | |
| m_librarySet(librarySet), | |
| m_configSet(configSet), | |
| m_fileContent(NULL) {} | |
| ParseLibraryDef::ParseLibraryDef(const ParseLibraryDef& orig) {} | |
| ParseLibraryDef::~ParseLibraryDef() {} | |
| bool ParseLibraryDef::parseLibrariesDefinition() { | |
| // Get .map files from command line | |
| std::vector<SymbolId> libraryMapFiles = | |
| m_commandLineParser->getLibraryMapFiles(); | |
| if (libraryMapFiles.empty()) { | |
| // or scan local dir | |
| libraryMapFiles = FileUtils::collectFiles("./", ".map", m_symbolTable); | |
| } | |
| // If "work" library is not yet declared from command line, create it | |
| std::string workN = "work"; | |
| if (m_librarySet->getLibrary(workN) == NULL) { | |
| Library work(workN, m_symbolTable); | |
| m_librarySet->addLibrary(work); | |
| } | |
| // Config files are parsed using the library top rule | |
| std::vector<SymbolId> cfgFiles = m_commandLineParser->getConfigFiles(); | |
| for (auto file : cfgFiles) { | |
| libraryMapFiles.push_back(file); | |
| } | |
| for (auto fileId : libraryMapFiles) { | |
| parseLibraryDefinition(fileId); | |
| } | |
| for (auto file : cfgFiles) { | |
| std::string fullPath = | |
| FileUtils::getFullPath(m_symbolTable->getSymbol(file)); | |
| m_librarySet->getLibrary(m_symbolTable->registerSymbol( | |
| fullPath)); // Register configuration files in "work" library | |
| } | |
| unsigned int size = m_commandLineParser->getSourceFiles().size(); | |
| for (unsigned int i = 0; i < size; i++) { | |
| SymbolId id = m_commandLineParser->getSourceFiles()[i]; | |
| std::string fullPath = FileUtils::getFullPath(m_symbolTable->getSymbol(id)); | |
| m_librarySet->getLibrary(m_symbolTable->registerSymbol( | |
| fullPath)); // Register files in "work" library | |
| } | |
| m_librarySet->checkErrors(m_symbolTable, m_errors); | |
| if (m_commandLineParser->getDebugLibraryDef()) { | |
| std::cout << m_librarySet->report(m_symbolTable) << std::endl; | |
| } | |
| return true; | |
| } | |
| bool ParseLibraryDef::parseLibraryDefinition(SymbolId fileId, Library* lib) { | |
| m_fileId = fileId; | |
| std::string fileName = m_symbolTable->getSymbol(fileId); | |
| std::string relativePath = FileUtils::getPathName(fileName); | |
| std::ifstream stream; | |
| stream.open(fileName); | |
| if (!stream.good()) { | |
| Location ppfile(fileId); | |
| Error err(ErrorDefinition::PA_CANNOT_OPEN_FILE, ppfile); | |
| m_errors->addError(err); | |
| return false; | |
| } | |
| Location ppfile(fileId); | |
| Error err(ErrorDefinition::PP_PROCESSING_SOURCE_FILE, ppfile); | |
| m_errors->addError(err); | |
| m_errors->printMessage(err, m_commandLineParser->muteStdout()); | |
| AntlrLibParserErrorListener* errorListener = | |
| new AntlrLibParserErrorListener(this); | |
| antlr4::ANTLRInputStream* m_inputStream = new ANTLRInputStream(stream); | |
| SV3_1aLexer* m_lexer = new SV3_1aLexer(m_inputStream); | |
| m_lexer->removeErrorListeners(); | |
| m_lexer->addErrorListener(errorListener); | |
| antlr4::CommonTokenStream* m_tokens = new CommonTokenStream(m_lexer); | |
| m_tokens->fill(); | |
| SV3_1aParser* m_parser = new SV3_1aParser(m_tokens); | |
| m_parser->removeErrorListeners(); | |
| m_parser->addErrorListener(errorListener); | |
| antlr4::tree::ParseTree* m_tree = m_parser->top_level_library_rule(); | |
| SVLibShapeListener* m_listener = | |
| new SVLibShapeListener(this, m_tokens, relativePath); | |
| tree::ParseTreeWalker::DEFAULT.walk(m_listener, m_tree); | |
| m_fileContent = m_listener->getFileContent(); | |
| if (m_fileContent->getLibrary() == NULL) { | |
| if (lib) { | |
| m_fileContent->setLibrary(lib); | |
| } else { | |
| std::string fullPath = | |
| FileUtils::getFullPath(m_symbolTable->getSymbol(m_fileId)); | |
| m_fileContent->setLibrary( | |
| m_librarySet->getLibrary(m_symbolTable->registerSymbol(fullPath))); | |
| } | |
| } | |
| if (m_commandLineParser->getDebugAstModel()) { | |
| std::cout << m_fileContent->printObjects(); | |
| } | |
| // delete m_tree; | |
| delete m_parser; | |
| delete m_tokens; | |
| delete m_lexer; | |
| delete m_inputStream; | |
| delete m_listener; | |
| return parseConfigDefinition(); | |
| } | |
| bool ParseLibraryDef::parseConfigDefinition() { | |
| FileContent* fC = m_fileContent; | |
| if (!fC) return false; | |
| std::vector<VObjectType> types = {VObjectType::slConfig_declaration}; | |
| std::vector<NodeId> configs = fC->sl_collect_all(0, types); | |
| for (auto config : configs) { | |
| NodeId ident = fC->Child(config); | |
| std::string name = fC->getLibrary()->getName() + "@" + fC->SymName(ident); | |
| m_symbolTable->registerSymbol(name); | |
| Config conf(name, fC, config); | |
| // Design clause | |
| std::vector<VObjectType> designStmt = {VObjectType::slDesign_statement}; | |
| std::vector<NodeId> designs = fC->sl_collect_all(config, designStmt); | |
| if (designs.size() == 0) { | |
| // TODO: Error | |
| } else if (designs.size() > 1) { | |
| // TODO: Error | |
| } else { | |
| NodeId design = designs[0]; | |
| NodeId libName = fC->Child(design); | |
| NodeId topName = fC->Sibling(libName); | |
| if (topName == 0) { | |
| conf.setDesignLib(fC->getLibrary()->getName()); | |
| conf.setDesignTop(fC->SymName(libName)); | |
| } else { | |
| conf.setDesignLib(fC->SymName(libName)); | |
| conf.setDesignTop(fC->SymName(topName)); | |
| } | |
| } | |
| // Default clause | |
| std::vector<VObjectType> defaultStmt = {VObjectType::slDefault_clause}; | |
| std::vector<NodeId> defaults = fC->sl_collect_all(config, defaultStmt); | |
| if (defaults.size() > 0) { | |
| NodeId defaultClause = defaults[0]; | |
| NodeId libList = fC->Sibling(defaultClause); | |
| if (fC->Type(libList) == VObjectType::slLiblist_clause) { | |
| NodeId lib = fC->Child(libList); | |
| while (lib) { | |
| conf.addDefaultLib(fC->SymName(lib)); | |
| lib = fC->Sibling(lib); | |
| } | |
| } | |
| } | |
| // Instance and Cell clauses | |
| std::vector<VObjectType> instanceStmt = {VObjectType::slInst_clause, | |
| VObjectType::slCell_clause}; | |
| std::vector<NodeId> instances = fC->sl_collect_all(config, instanceStmt); | |
| for (auto inst : instances) { | |
| VObjectType type = fC->Type(inst); | |
| NodeId instName = fC->Child(inst); | |
| if (type == slInst_clause) instName = fC->Child(instName); | |
| std::string instNameS; | |
| while (instName) { | |
| if (instNameS == "") | |
| instNameS = fC->SymName(instName); | |
| else | |
| instNameS += "." + fC->SymName(instName); | |
| instName = fC->Sibling(instName); | |
| } | |
| NodeId instClause = fC->Sibling(inst); | |
| if (fC->Type(instClause) == VObjectType::slLiblist_clause) { | |
| NodeId libList = fC->Child(instClause); | |
| std::vector<std::string> libs; | |
| while (libList) { | |
| libs.push_back(fC->SymName(libList)); | |
| libList = fC->Sibling(libList); | |
| } | |
| UseClause usec(UseClause::UseLib, libs, fC, instClause); | |
| if (type == slInst_clause) | |
| conf.addInstanceUseClause(instNameS, usec); | |
| else | |
| conf.addCellUseClause(instNameS, usec); | |
| } else if (fC->Type(instClause) == VObjectType::slUse_clause) { | |
| NodeId use = fC->Child(instClause); | |
| std::string useName; | |
| VObjectType useType = fC->Type(use); | |
| if (useType == slParameter_value_assignment) { | |
| UseClause usec(UseClause::UseParam, fC, use); | |
| conf.addInstanceUseClause(instNameS, usec); | |
| } else { | |
| NodeId mem = use; | |
| while (use) { | |
| if (useName == "") | |
| useName = fC->SymName(use); | |
| else | |
| useName += "." + fC->SymName(use); | |
| use = fC->Sibling(use); | |
| } | |
| useName = StringUtils::replaceAll(useName, ".", "@"); | |
| UseClause usec(UseClause::UseModule, useName, fC, mem); | |
| if (type == slInst_clause) | |
| conf.addInstanceUseClause(instNameS, usec); | |
| else | |
| conf.addCellUseClause(instNameS, usec); | |
| } | |
| } else if (fC->Type(instClause) == VObjectType::slUse_clause_config) { | |
| NodeId use = fC->Child(instClause); | |
| std::string useName; | |
| NodeId mem = use; | |
| while (use) { | |
| if (useName == "") | |
| useName = fC->SymName(use); | |
| else | |
| useName += "@" + fC->SymName(use); | |
| use = fC->Sibling(use); | |
| } | |
| UseClause usec(UseClause::UseConfig, useName, fC, mem); | |
| if (type == slInst_clause) | |
| conf.addInstanceUseClause(instNameS, usec); | |
| else | |
| conf.addCellUseClause(instNameS, usec); | |
| } | |
| } | |
| m_configSet->addConfig(conf); | |
| } | |
| return true; | |
| } |