blob: 878db4e02e5d76baa963293a1869443d4ed27c8f [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: 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);
}