| /* |
| 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; |
| } |