| /* |
| 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(); |
| } |