| /* |
| 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: SV3_1aTreeShapeHelper.cpp |
| * Author: alain |
| * |
| * Created on June 25, 2017, 2:51 PM |
| */ |
| |
| #include "SourceCompile/SymbolTable.h" |
| #include "CommandLine/CommandLineParser.h" |
| #include "ErrorReporting/ErrorContainer.h" |
| #include "SourceCompile/CompilationUnit.h" |
| #include "SourceCompile/PreprocessFile.h" |
| #include "SourceCompile/CompileSourceFile.h" |
| #include "SourceCompile/Compiler.h" |
| #include "SourceCompile/ParseFile.h" |
| |
| #include <cstdlib> |
| #include <iostream> |
| #include "antlr4-runtime.h" |
| using namespace std; |
| using namespace antlr4; |
| using namespace SURELOG; |
| |
| #include "parser/SV3_1aLexer.h" |
| #include "parser/SV3_1aParser.h" |
| #include "parser/SV3_1aParserBaseListener.h" |
| #include "SourceCompile/SV3_1aTreeShapeHelper.h" |
| using namespace antlr4; |
| #include "Utils/ParseUtils.h" |
| #include "SourceCompile/SV3_1aTreeShapeHelper.h" |
| |
| SV3_1aTreeShapeHelper::SV3_1aTreeShapeHelper(ParseFile* pf, |
| antlr4::CommonTokenStream* tokens, |
| unsigned int lineOffset) |
| : m_pf(pf), |
| m_fileContent(NULL), |
| m_currentElement(NULL), |
| m_tokens(tokens), |
| m_lineOffset(lineOffset), |
| m_version(SystemVerilog) { |
| if (pf->getCompileSourceFile()) |
| m_ppOutputFileLocation = pf->getCompileSourceFile() |
| ->getCommandLineParser() |
| ->usePPOutoutFileLocation(); |
| } |
| |
| SV3_1aTreeShapeHelper::SV3_1aTreeShapeHelper(ParseLibraryDef* pf, |
| antlr4::CommonTokenStream* tokens) |
| : m_pf(NULL), |
| m_fileContent(NULL), |
| m_currentElement(NULL), |
| m_tokens(tokens), |
| m_lineOffset(0), |
| m_ppOutputFileLocation(false), |
| m_version(SystemVerilog) {} |
| |
| SV3_1aTreeShapeHelper::~SV3_1aTreeShapeHelper() {} |
| |
| void SV3_1aTreeShapeHelper::logError(ErrorDefinition::ErrorType error, |
| ParserRuleContext* ctx, std::string object, |
| bool printColumn) { |
| std::pair<int, int> lineCol = ParseUtils::getLineColumn(m_tokens, ctx); |
| |
| Location loc( |
| m_pf->getFileId(lineCol.first /*+ m_lineOffset*/), |
| m_pf->getLineNb(lineCol.first /*+ m_lineOffset*/), |
| printColumn ? lineCol.second : 0, |
| m_pf->getCompileSourceFile()->getSymbolTable()->registerSymbol(object)); |
| Error err(error, loc); |
| m_pf->addError(err); |
| } |
| |
| void SV3_1aTreeShapeHelper::logError(ErrorDefinition::ErrorType error, |
| Location& loc, bool showDuplicates) { |
| Error err(error, loc); |
| m_pf->getCompileSourceFile()->getErrorContainer()->addError(err, |
| showDuplicates); |
| } |
| |
| void SV3_1aTreeShapeHelper::logError(ErrorDefinition::ErrorType error, |
| Location& loc, Location& extraLoc, |
| bool showDuplicates) { |
| std::vector<Location> extras; |
| extras.push_back(extraLoc); |
| Error err(error, loc, &extras); |
| m_pf->getCompileSourceFile()->getErrorContainer()->addError(err, |
| showDuplicates); |
| } |
| |
| NodeId SV3_1aTreeShapeHelper::generateDesignElemId() { |
| return m_pf->getCompilationUnit()->generateUniqueDesignElemId(); |
| } |
| |
| NodeId SV3_1aTreeShapeHelper::generateNodeId() { |
| return m_pf->getCompilationUnit()->generateUniqueNodeId(); |
| } |
| |
| SymbolId SV3_1aTreeShapeHelper::registerSymbol(std::string symbol) { |
| return m_pf->getSymbolTable()->registerSymbol(symbol); |
| } |
| |
| int SV3_1aTreeShapeHelper::registerObject(VObject& object) { |
| m_fileContent->getVObjects().push_back(object); |
| return LastObjIndex(); |
| } |
| |
| int SV3_1aTreeShapeHelper::LastObjIndex() { |
| return m_fileContent->getVObjects().size() - 1; |
| } |
| |
| int SV3_1aTreeShapeHelper::ObjectIndexFromContext(tree::ParseTree* ctx) { |
| ContextToObjectMap::iterator itr = m_contextToObjectMap.find(ctx); |
| if (itr == m_contextToObjectMap.end()) { |
| return -1; |
| } else { |
| return (*itr).second; |
| } |
| } |
| |
| VObject& SV3_1aTreeShapeHelper::Object(NodeId index) { |
| return m_fileContent->getVObjects()[index]; |
| } |
| |
| NodeId SV3_1aTreeShapeHelper::UniqueId(NodeId index) { |
| // return m_fileContent->m_objects[index].m_uniqueId; |
| return index; |
| } |
| |
| SymbolId& SV3_1aTreeShapeHelper::Name(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_name; |
| } |
| |
| NodeId& SV3_1aTreeShapeHelper::Child(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_child; |
| } |
| |
| NodeId& SV3_1aTreeShapeHelper::Sibling(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_sibling; |
| } |
| |
| NodeId& SV3_1aTreeShapeHelper::Definition(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_definition; |
| } |
| |
| NodeId& SV3_1aTreeShapeHelper::Parent(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_parent; |
| } |
| |
| unsigned short& SV3_1aTreeShapeHelper::Type(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_type; |
| } |
| |
| unsigned int& SV3_1aTreeShapeHelper::Line(NodeId index) { |
| return m_fileContent->getVObjects()[index].m_line; |
| } |
| |
| void SV3_1aTreeShapeHelper::addNestedDesignElement( |
| ParserRuleContext* ctx, std::string name, DesignElement::ElemType elemtype, |
| VObjectType objtype) { |
| SymbolId fileId; |
| unsigned int line = getFileLine(ctx, fileId); |
| |
| DesignElement elem(registerSymbol(name), fileId, elemtype, |
| generateDesignElemId(), line, 0); |
| elem.m_context = ctx; |
| elem.m_timeInfo = |
| m_pf->getCompilationUnit()->getTimeInfo(m_pf->getFileId(line), line); |
| if (m_nestedElements.size()) { |
| elem.m_timeInfo = m_nestedElements.top()->m_timeInfo; |
| elem.m_parent = m_nestedElements.top()->m_uniqueId; |
| } |
| m_fileContent->getDesignElements().push_back(elem); |
| m_currentElement = &m_fileContent->getDesignElements().back(); |
| m_nestedElements.push(m_currentElement); |
| } |
| |
| void SV3_1aTreeShapeHelper::addDesignElement(ParserRuleContext* ctx, |
| std::string name, |
| DesignElement::ElemType elemtype, |
| VObjectType objtype) { |
| SymbolId fileId; |
| unsigned int line = getFileLine(ctx, fileId); |
| DesignElement elem(registerSymbol(name), fileId, elemtype, |
| generateDesignElemId(), line, 0); |
| elem.m_context = ctx; |
| elem.m_timeInfo = |
| m_pf->getCompilationUnit()->getTimeInfo(m_pf->getFileId(line), line); |
| m_fileContent->getDesignElements().push_back(elem); |
| m_currentElement = &m_fileContent->getDesignElements().back(); |
| } |
| |
| unsigned int SV3_1aTreeShapeHelper::getFileLine(ParserRuleContext* ctx, |
| SymbolId& fileId) { |
| std::pair<int, int> lineCol = ParseUtils::getLineColumn(m_tokens, ctx); |
| unsigned int line = 0; |
| if (m_ppOutputFileLocation) { |
| fileId = m_pf->getFileId(0); |
| line = lineCol.first; |
| } else { |
| fileId = m_pf->getFileId(lineCol.first + m_lineOffset); |
| line = m_pf->getLineNb(lineCol.first + m_lineOffset); |
| } |
| return line; |
| } |
| |
| int SV3_1aTreeShapeHelper::addVObject(ParserRuleContext* ctx, std::string name, |
| VObjectType objtype) { |
| SymbolId fileId; |
| unsigned int line = getFileLine(ctx, fileId); |
| |
| VObject object(registerSymbol(name), fileId, objtype, line, 0); |
| m_fileContent->getVObjects().push_back(object); |
| int objectIndex = m_fileContent->getVObjects().size() - 1; |
| m_contextToObjectMap.insert(std::make_pair(ctx, objectIndex)); |
| addParentChildRelations(objectIndex, ctx); |
| if (m_fileContent->getDesignElements().size()) { |
| for (unsigned int i = 0; i <= m_fileContent->getDesignElements().size() - 1; |
| i++) { |
| DesignElement& elem = |
| m_fileContent |
| ->getDesignElements()[m_fileContent->getDesignElements().size() - |
| 1 - i]; |
| if (elem.m_context == ctx) { |
| // Use the file and line number of the design object (package, module), |
| // true file/line when splitting |
| m_fileContent->getVObjects().back().m_fileId = elem.m_fileId; |
| m_fileContent->getVObjects().back().m_line = elem.m_line; |
| elem.m_node = objectIndex; |
| break; |
| } |
| } |
| } |
| return objectIndex; |
| } |
| |
| int SV3_1aTreeShapeHelper::addVObject(ParserRuleContext* ctx, |
| VObjectType objtype) { |
| SymbolId fileId; |
| unsigned int line = getFileLine(ctx, fileId); |
| |
| VObject object(0, fileId, objtype, line, 0); |
| m_fileContent->getVObjects().push_back(object); |
| int objectIndex = m_fileContent->getVObjects().size() - 1; |
| m_contextToObjectMap.insert(std::make_pair(ctx, objectIndex)); |
| addParentChildRelations(objectIndex, ctx); |
| if (m_fileContent->getDesignElements().size()) { |
| for (unsigned int i = 0; i <= m_fileContent->getDesignElements().size() - 1; |
| i++) { |
| DesignElement& elem = |
| m_fileContent |
| ->getDesignElements()[m_fileContent->getDesignElements().size() - |
| 1 - i]; |
| if (elem.m_context == ctx) { |
| // Use the file and line number of the design object (package, module), |
| // true file/line when splitting |
| m_fileContent->getVObjects().back().m_fileId = elem.m_fileId; |
| m_fileContent->getVObjects().back().m_line = elem.m_line; |
| elem.m_node = objectIndex; |
| break; |
| } |
| } |
| } |
| return objectIndex; |
| } |
| |
| void SV3_1aTreeShapeHelper::addParentChildRelations(int indexParent, |
| ParserRuleContext* ctx) { |
| int currentIndex = indexParent; |
| for (tree::ParseTree* child : ctx->children) { |
| int childIndex = ObjectIndexFromContext(child); |
| if (childIndex != -1) { |
| Parent(childIndex) = UniqueId(indexParent); |
| if (currentIndex == indexParent) { |
| Child(indexParent) = UniqueId(childIndex); |
| } else { |
| Sibling(currentIndex) = UniqueId(childIndex); |
| } |
| currentIndex = childIndex; |
| } |
| } |
| } |
| |
| NodeId SV3_1aTreeShapeHelper::getObjectId(ParserRuleContext* ctx) { |
| ContextToObjectMap::iterator itr = m_contextToObjectMap.find(ctx); |
| if (itr == m_contextToObjectMap.end()) { |
| return 0; |
| } else { |
| return (*itr).second; |
| } |
| } |
| |
| std::pair<double, TimeInfo::Unit> SV3_1aTreeShapeHelper::getTimeValue( |
| SV3_1aParser::Time_literalContext* ctx) { |
| double actual_value = 0; |
| TimeInfo::Unit unit = TimeInfo::Second; |
| if (ctx->Integral_number()) |
| actual_value = atoi(ctx->Integral_number()->getText().c_str()); |
| if (ctx->Real_number()) |
| actual_value = atoi(ctx->Real_number()->getText().c_str()); |
| unit = TimeInfo::unitFromString(ctx->time_unit()->getText()); |
| |
| return std::make_pair(actual_value, unit); |
| } |