blob: c4b7c25de7f4d9a0faf622b96dd3e238300fe39f [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: Design.cpp
* Author: alain
*
* Created on July 1, 2017, 1:23 PM
*/
#include <queue>
#include <set>
#include "Utils/StringUtils.h"
#include "SourceCompile/VObjectTypes.h"
#include "Design/VObject.h"
#include "Design/FileContent.h"
#include "SourceCompile/SymbolTable.h"
#include "ErrorReporting/Error.h"
#include "ErrorReporting/ErrorContainer.h"
#include "ErrorReporting/ErrorDefinition.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 "Utils/FileUtils.h"
#include "Design/Design.h"
#include "Testbench/ClassDefinition.h"
using namespace SURELOG;
Design::Design(const Design& orig) {}
Design::~Design() {}
static std::mutex m;
void Design::addFileContent(SymbolId fileId, FileContent* content) {
m.lock();
m_fileContents.push_back(std::make_pair(fileId, content));
m.unlock();
}
DesignComponent* Design::getComponentDefinition(
const std::string& componentName) {
DesignComponent* comp = (DesignComponent*)getModuleDefinition(componentName);
if (comp) return comp;
comp = (DesignComponent*)getProgram(componentName);
if (comp) return comp;
comp = (DesignComponent*)getClassDefinition(componentName);
if (comp) return comp;
return NULL;
}
ModuleDefinition* Design::getModuleDefinition(const std::string& moduleName) {
ModuleNameModuleDefinitionMap::iterator itr =
m_moduleDefinitions.find(moduleName);
if (itr != m_moduleDefinitions.end()) {
return (*itr).second;
}
return NULL;
}
std::string Design::reportInstanceTree() {
std::string tree;
ModuleInstance* tmp;
std::queue<ModuleInstance*> queue;
SymbolTable* symbols = m_errors->getSymbolTable();
for (auto instance : m_topLevelModuleInstances) {
queue.push(instance);
}
while (!queue.empty()) {
tmp = queue.front();
queue.pop();
if (tmp->getNbChildren()) {
for (unsigned int i = 0; i < tmp->getNbChildren(); i++) {
queue.push(tmp->getChildren(i));
}
}
std::string def;
def = tmp->getModuleName();
std::string undef;
VObjectType type = tmp->getType();
if (tmp->getDefinition() == NULL) {
undef = " [U]";
}
std::string type_s;
Location loc(symbols->registerSymbol(tmp->getFileName()), tmp->getLineNb(),
0, tmp->getFullPathId(symbols));
if (type == slUdp_instantiation) {
type_s = "[UDP]";
Error err(ErrorDefinition::ELAB_INSTANCE_PATH, loc);
m_errors->addError(err);
} else if (type == VObjectType::slModule_instantiation) {
type_s = "[MOD]";
Error err(ErrorDefinition::ELAB_INSTANCE_PATH, loc);
m_errors->addError(err);
} else if (type == VObjectType::slGate_instantiation) {
type_s = "[GAT]";
Error err(ErrorDefinition::ELAB_INSTANCE_PATH, loc);
m_errors->addError(err);
} else if (type == slInterface_instantiation) {
type_s = "[I/F]";
Error err(ErrorDefinition::ELAB_INTERFACE_INSTANCE_PATH, loc);
m_errors->addError(err);
} else if (type == slProgram_instantiation) {
type_s = "[PRG]";
Error err(ErrorDefinition::ELAB_PROGRAM_INSTANCE_PATH, loc);
m_errors->addError(err);
} else if (type == slModule_declaration) {
type_s = "[TOP]";
Error err(ErrorDefinition::ELAB_INSTANCE_PATH, loc);
m_errors->addError(err);
} else {
type_s = "[SCO]";
Error err(ErrorDefinition::ELAB_SCOPE_PATH, loc);
m_errors->addError(err);
}
tree += type_s + " " + def + undef + " " + tmp->getFullPathName() + "\n";
}
return tree;
}
void Design::reportInstanceTreeStats(unsigned int& nbTopLevelModules,
unsigned int& maxDepth,
unsigned int& numberOfInstances,
unsigned int& numberOfLeafInstances,
unsigned int& nbUndefinedModules,
unsigned int& nbUndefinedInstances) {
nbTopLevelModules = 0;
maxDepth = 0;
numberOfInstances = 0;
numberOfLeafInstances = 0;
nbUndefinedModules = 0;
nbUndefinedInstances = 0;
std::set<std::string> undefModules;
ModuleInstance* tmp;
std::queue<ModuleInstance*> queue;
for (auto instance : m_topLevelModuleInstances) {
queue.push(instance);
nbTopLevelModules++;
}
while (!queue.empty()) {
tmp = queue.front();
queue.pop();
bool isInstance = false;
if (!tmp->getDefinition())
isInstance = true;
else {
isInstance = tmp->getDefinition()->isInstance();
}
if (isInstance) {
numberOfInstances++;
unsigned int depth = tmp->getDepth();
if (depth > maxDepth) {
maxDepth = depth;
}
}
if (tmp->getNbChildren()) {
for (unsigned int i = 0; i < tmp->getNbChildren(); i++) {
queue.push(tmp->getChildren(i));
}
} else {
if (isInstance) numberOfLeafInstances++;
}
std::string def;
if (tmp->getDefinition()) {
} else {
nbUndefinedInstances++;
undefModules.insert(tmp->getModuleName());
}
}
nbUndefinedModules = undefModules.size();
}
ModuleInstance* Design::findInstance(std::string path, ModuleInstance* scope) {
std::vector<std::string> vpath;
StringUtils::tokenize(path, ".", vpath);
return findInstance(vpath, scope);
}
ModuleInstance* Design::findInstance(std::vector<std::string>& path,
ModuleInstance* scope) {
if (!path.size()) return NULL;
if (scope) {
ModuleInstance* res = findInstance_(path, scope);
if (res) return res;
} else {
for (auto top : m_topLevelModuleInstances) {
if (path.size() == 1) {
if (top->getInstanceName() == path[0]) {
return top;
}
} else {
if (top->getInstanceName() == path[0]) {
std::vector<std::string> subpath = path;
subpath.erase(subpath.begin());
ModuleInstance* res = findInstance_(subpath, top);
if (res) return res;
}
}
}
}
return NULL;
}
ModuleInstance* Design::findInstance_(std::vector<std::string>& path,
ModuleInstance* scope) {
if (!path.size()) return NULL;
if (scope == NULL) return NULL;
if (path.size() == 1) {
if (scope->getInstanceName() == path[0]) {
return scope;
}
}
for (unsigned int i = 0; i < scope->getNbChildren(); i++) {
ModuleInstance* child = scope->getChildren(i);
if (path.size()) {
if (child->getInstanceName() == path[0]) {
if (path.size() == 1) {
return child;
} else {
std::vector<std::string> subpath = path;
subpath.erase(subpath.begin());
ModuleInstance* res = findInstance(subpath, child);
if (res) return res;
}
}
}
}
return NULL;
}
DefParam* Design::getDefParam(std::string name) {
std::vector<std::string> vpath;
StringUtils::tokenize(name, ".", vpath);
std::map<std::string, DefParam*>::iterator itr = m_defParams.find(vpath[0]);
if (itr != m_defParams.end()) {
vpath.erase(vpath.begin());
return getDefParam_(vpath, (*itr).second);
}
return NULL;
}
Value* Design::getDefParamValue(std::string name) {
DefParam* def = getDefParam(name);
if (def) return def->getValue();
return NULL;
}
DefParam* Design::getDefParam_(std::vector<std::string>& path,
DefParam* parent) {
if (path.size() == 0) {
return parent;
}
std::map<std::string, DefParam*>::iterator itr =
parent->getChildren().find(path[0]);
if (itr != parent->getChildren().end()) {
path.erase(path.begin());
return getDefParam_(path, (*itr).second);
}
return NULL;
}
void Design::addDefParam(std::string name, FileContent* fC, NodeId nodeId,
Value* value) {
std::vector<std::string> vpath;
StringUtils::tokenize(name, ".", vpath);
std::map<std::string, DefParam*>::iterator itr = m_defParams.find(vpath[0]);
if (itr != m_defParams.end()) {
vpath.erase(vpath.begin());
addDefParam_(vpath, fC, nodeId, value, (*itr).second);
} else {
DefParam* def = new DefParam(vpath[0]);
m_defParams.insert(std::make_pair(vpath[0], def));
vpath.erase(vpath.begin());
addDefParam_(vpath, fC, nodeId, value, def);
}
}
void Design::addDefParam_(std::vector<std::string>& path, FileContent* fC,
NodeId nodeId, Value* value, DefParam* parent) {
if (path.size() == 0) {
parent->setValue(value);
parent->setLocation(fC, nodeId);
return;
}
std::map<std::string, DefParam*>::iterator itr =
parent->getChildren().find(path[0]);
if (itr != parent->getChildren().end()) {
path.erase(path.begin());
if (path.size() == 0) {
DefParam* previous = (*itr).second;
if ((fC->getFileId(nodeId) !=
previous->getLocation()->getFileId(previous->getNodeId())) ||
(fC->Line(nodeId) !=
previous->getLocation()->Line(previous->getNodeId()))) {
Location loc1(
fC->getFileId(nodeId), fC->Line(nodeId), 0,
m_errors->getSymbolTable()->registerSymbol(
previous->getFullName()));
Location loc2(previous->getLocation()->getFileId(previous->getNodeId()),
previous->getLocation()->Line(previous->getNodeId()), 0,
0);
Error err(ErrorDefinition::ELAB_MULTI_DEFPARAM_ON_OBJECT, loc1, loc2);
m_errors->addError(err);
}
}
addDefParam_(path, fC, nodeId, value, (*itr).second);
} else {
DefParam* def = new DefParam(path[0], parent);
parent->setChild(path[0], def);
path.erase(path.begin());
addDefParam_(path, fC, nodeId, value, def);
}
}
void Design::checkDefParamUsage(DefParam* parent) {
if (parent == NULL) {
// Start by all the top defs of the trie
for (auto top : m_defParams) {
checkDefParamUsage(top.second);
}
} else {
// Check the leaf
if (parent->getValue() && (!parent->isUsed())) {
if (parent->getParent()) {
ModuleInstance* inst = findInstance(parent->getParent()->getFullName());
if (inst && (!inst->getDefinition())) {
return;
} else {
}
} else {
return;
}
Location loc(
parent->getLocation()->getFileId(parent->getNodeId()),
parent->getLocation()->Line(parent->getNodeId()), 0,
m_errors->getSymbolTable()->registerSymbol(
parent->getFullName()));
Error err(ErrorDefinition::ELAB_UNMATCHED_DEFPARAM, loc);
m_errors->addError(err);
}
for (auto param : parent->getChildren()) {
checkDefParamUsage(param.second);
}
}
}
Package* Design::getPackage(std::string name) {
PackageNamePackageDefinitionMultiMap::iterator itr =
m_packageDefinitions.find(name);
if (itr == m_packageDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
Program* Design::getProgram(std::string name) {
ProgramNameProgramDefinitionMap::iterator itr =
m_programDefinitions.find(name);
if (itr == m_programDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
ClassDefinition* Design::getClassDefinition(std::string name) {
ClassNameClassDefinitionMap::iterator itr =
m_uniqueClassDefinitions.find(name);
if (itr == m_uniqueClassDefinitions.end()) {
return NULL;
} else {
return (*itr).second;
}
}
void Design::orderPackages() {
if (m_orderedPackageNames.size() == 0) return;
m_orderedPackageDefinitions.resize(m_orderedPackageNames.size());
unsigned int index = 0;
typedef std::map<std::string, int> MultiDefCount;
MultiDefCount multiDefCount;
for (auto packageName : m_orderedPackageNames) {
for (unsigned int i = 0; i < m_packageDefinitions.size(); i++) {
PackageNamePackageDefinitionMultiMap::iterator pos =
m_packageDefinitions.begin();
for (unsigned ii = 0; ii < i; ii++) pos++;
std::pair<const std::string, Package*>* name_pack;
name_pack = &(*pos);
if (packageName == name_pack->first) {
MultiDefCount::iterator itr = multiDefCount.find(packageName);
if (itr == multiDefCount.end()) {
multiDefCount.insert(std::make_pair(packageName, 1));
} else {
int level = (*itr).second;
(*itr).second++;
pos = m_packageDefinitions.begin();
for (unsigned ii = 0; ii < i + level; ii++) pos++;
name_pack = &(*pos);
}
m_orderedPackageDefinitions[index] = name_pack->second;
index++;
break;
}
}
}
}
Package* Design::addPackageDefinition(std::string packageName,
Package* package) {
PackageNamePackageDefinitionMultiMap::iterator itr =
m_packageDefinitions.find(packageName);
if (itr == m_packageDefinitions.end()) {
m_packageDefinitions.insert(std::make_pair(packageName, package));
return package;
} else {
Package* old = (*itr).second;
if (old->getFileContents()[0]->getParent() &&
(old->getFileContents()[0]->getParent() ==
package->getFileContents()[0]->getParent())) {
old->append(package);
return old;
} else {
m_packageDefinitions.insert(std::make_pair(packageName, package));
return package;
}
}
}
void Design::addClassDefinition(std::string className,
ClassDefinition* classDef) {
m_classDefinitions.insert(std::make_pair(className, classDef));
m_uniqueClassDefinitions.insert(std::make_pair(className, classDef));
}
void Design::clearContainers() {
m_moduleDefinitions.clear();
m_topLevelModuleInstances.clear();
m_defParams.clear();
m_packageDefinitions.clear();
m_orderedPackageDefinitions.clear();
m_programDefinitions.clear();
m_classDefinitions.clear();
m_uniqueClassDefinitions.clear();
m_orderedPackageNames.clear();
}