| /* |
| 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.hpp" |
| #include "../SourceCompile/CompilationUnit.h" |
| #include "../SourceCompile/PreprocessFile.h" |
| #include "../SourceCompile/CompileSourceFile.h" |
| #include "../SourceCompile/Compiler.h" |
| #include "../SourceCompile/ParseFile.h" |
| #include "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 "SVLibShapeListener.h" |
| #include "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; |
| } |
| |