blob: a4791e0b124d95c9308658b92a00123c33e2e621 [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: 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;
}