| /* |
| 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: DesignElaboration.cpp |
| * Author: alain |
| * |
| * Created on July 12, 2017, 8:55 PM |
| */ |
| #include "Utils/StringUtils.h" |
| #include "SourceCompile/VObjectTypes.h" |
| #include "Design/VObject.h" |
| #include "Library/Library.h" |
| #include "Design/FileContent.h" |
| #include "SourceCompile/SymbolTable.h" |
| #include "ErrorReporting/Error.h" |
| #include "ErrorReporting/Location.h" |
| #include "ErrorReporting/Error.h" |
| #include "ErrorReporting/ErrorDefinition.h" |
| #include "ErrorReporting/ErrorContainer.h" |
| #include "Config/ConfigSet.h" |
| #include "CommandLine/CommandLineParser.h" |
| #include "SourceCompile/CompilationUnit.h" |
| #include "SourceCompile/PreprocessFile.h" |
| #include "SourceCompile/CompileSourceFile.h" |
| #include "SourceCompile/ParseFile.h" |
| #include "SourceCompile/Compiler.h" |
| #include "DesignCompile/CompileDesign.h" |
| #include "Testbench/Property.h" |
| #include "Design/Function.h" |
| #include "Testbench/ClassDefinition.h" |
| #include "DesignCompile/DesignElaboration.h" |
| #include <queue> |
| |
| using namespace SURELOG; |
| |
| DesignElaboration::DesignElaboration(CompileDesign* compileDesign) |
| : ElaborationStep(compileDesign) { |
| m_moduleDefFactory = NULL; |
| m_moduleInstFactory = NULL; |
| m_exprBuilder.seterrorReporting( |
| m_compileDesign->getCompiler()->getErrorContainer(), |
| m_compileDesign->getCompiler()->getSymbolTable()); |
| } |
| |
| DesignElaboration::~DesignElaboration() {} |
| |
| bool DesignElaboration::elaborate() { |
| createBuiltinPrimitives_(); |
| setupConfigurations_(); |
| identifyTopModules_(); |
| elaborateAllModules_(true); |
| elaborateAllModules_(false); |
| reduceUnnamedBlocks_(); |
| checkElaboration_(); |
| reportElaboration_(); |
| return true; |
| } |
| |
| bool DesignElaboration::setupConfigurations_() { |
| ConfigSet* configSet = |
| m_compileDesign->getCompiler()->getDesign()->getConfigSet(); |
| SymbolTable* st = |
| m_compileDesign->getCompiler()->getCommandLineParser()->getSymbolTable(); |
| std::vector<Config>& allConfigs = configSet->getAllConfigs(); |
| std::vector<SymbolId> selectedConfigIds = |
| m_compileDesign->getCompiler()->getCommandLineParser()->getUseConfigs(); |
| std::set<std::string> selectedConfigs; |
| for (auto confId : selectedConfigIds) { |
| std::string name = st->getSymbol(confId); |
| if (name.find(".") == std::string::npos) { |
| name = "work@" + name; |
| } else { |
| name = StringUtils::replaceAll(name, ".", "@"); |
| } |
| selectedConfigs.insert(name); |
| bool found = false; |
| for (auto& config : allConfigs) { |
| if (config.getName() == name) { |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| Location loc(st->registerSymbol(name)); |
| Error err(ErrorDefinition::CMD_UNDEFINED_CONFIG, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| } |
| |
| std::queue<std::string> configq; |
| for (auto& config : allConfigs) { |
| if (selectedConfigs.find(config.getName()) != selectedConfigs.end()) { |
| config.setIsUsed(); |
| config.setTopLevel(true); |
| configq.push(config.getName()); |
| } |
| } |
| std::set<Config*> configS; |
| while (configq.size()) { |
| std::string configName = configq.front(); |
| configq.pop(); |
| Config* conf = configSet->getConfig(configName); |
| if (conf) { |
| if (configS.find(conf) != configS.end()) { |
| continue; |
| } |
| configS.insert(conf); |
| |
| conf->setIsUsed(); |
| for (auto& usec : conf->getInstanceUseClauses()) { |
| if (usec.second.getType() == UseClause::UseConfig) { |
| std::string confName = usec.second.getName(); |
| configq.push(confName); |
| Config* conf = configSet->getConfig(confName); |
| if (!conf) { |
| FileContent* fC = usec.second.getFileContent(); |
| Location loc( |
| st->registerSymbol(fC->getFileName(usec.second.getNodeId())), |
| fC->Line(usec.second.getNodeId()), 0, |
| st->registerSymbol(confName)); |
| Error err(ErrorDefinition::ELAB_UNDEFINED_CONFIG, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| } |
| } |
| } |
| } |
| |
| std::vector<std::string> unused; |
| for (auto& config : allConfigs) { |
| std::string name = config.getName(); |
| FileContent* fC = config.getFileContent(); |
| SymbolId fid = st->registerSymbol(fC->getFileName(config.getNodeId())); |
| unsigned int line = fC->Line(config.getNodeId()); |
| Location loc(fid, line, 0, st->getId(config.getName())); |
| if (!config.isUsed()) { |
| Error err(ErrorDefinition::ELAB_CONFIGURATION_IGNORED, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| unused.push_back(name); |
| } else { |
| Error err(ErrorDefinition::ELAB_CONFIGURATION_USED, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| } |
| |
| // Remove unused configs from set |
| for (auto name : unused) { |
| std::vector<Config>::iterator itr; |
| for (itr = allConfigs.begin(); itr != allConfigs.end(); itr++) { |
| if ((*itr).getName() == name) { |
| allConfigs.erase(itr); |
| break; |
| } |
| } |
| } |
| |
| // Create top level module list and recurse configs |
| for (auto& config : allConfigs) { |
| if (config.isTopLevel()) { |
| std::string lib = config.getDesignLib(); |
| std::string top = config.getDesignTop(); |
| std::string name = lib + "@" + top; |
| m_toplevelConfigModules.insert(name); |
| m_instConfig.insert(std::make_pair(name, config)); |
| m_cellConfig.insert(std::make_pair(name, config)); |
| |
| for (auto& instClause : config.getInstanceUseClauses()) { |
| m_instUseClause.insert( |
| std::make_pair(lib + "@" + instClause.first, instClause.second)); |
| if (instClause.second.getType() == UseClause::UseConfig) { |
| Config* config = configSet->getConfig(instClause.second.getName()); |
| if (config) { |
| std::set<Config*> configStack; |
| recurseBuildInstanceClause_(lib + "@" + instClause.first, config, |
| configStack); |
| } |
| } |
| } |
| for (auto& cellClause : config.getCellUseClauses()) { |
| m_cellUseClause.insert( |
| std::make_pair(cellClause.first, cellClause.second)); |
| } |
| } |
| } |
| return true; |
| } |
| |
| void DesignElaboration::recurseBuildInstanceClause_( |
| std::string parentPath, Config* config, std::set<Config*>& configStack) { |
| if (configStack.find(config) != configStack.end()) { |
| return; |
| } |
| configStack.insert(config); |
| |
| ConfigSet* configSet = |
| m_compileDesign->getCompiler()->getDesign()->getConfigSet(); |
| for (auto& useClause : config->getInstanceUseClauses()) { |
| std::string inst = useClause.first; |
| std::string fullPath = parentPath + "." + inst; |
| m_instUseClause.insert(std::make_pair(fullPath, useClause.second)); |
| if (useClause.second.getType() == UseClause::UseConfig) { |
| Config* config = configSet->getConfig(useClause.second.getName()); |
| if (config) { |
| recurseBuildInstanceClause_(parentPath + "." + useClause.first, config, |
| configStack); |
| } |
| } |
| } |
| for (auto& useClause : config->getCellUseClauses()) { |
| std::string inst = useClause.first; |
| std::string fullPath = inst; |
| m_cellUseClause.insert(std::make_pair(fullPath, useClause.second)); |
| } |
| } |
| |
| bool DesignElaboration::identifyTopModules_() { |
| m_topLevelModules.clear(); |
| bool modulePresent = false; |
| bool toplevelModuleFound = false; |
| SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable(); |
| auto all_files = |
| m_compileDesign->getCompiler()->getDesign()->getAllFileContents(); |
| typedef std::multimap<std::string, std::pair<DesignElement*, FileContent*>> |
| ModuleMultiMap; |
| ModuleMultiMap all_modules; |
| for (auto file : all_files) { |
| if (m_compileDesign->getCompiler()->isLibraryFile(file.first)) continue; |
| for (DesignElement& element : file.second->getDesignElements()) { |
| std::string elemName = st->getSymbol(element.m_name); |
| if (element.m_type == DesignElement::Module) { |
| if (element.m_parent) { |
| // This is a nested element |
| continue; |
| } |
| std::string topname = file.second->getLibrary()->getName(); |
| topname += "@" + elemName; |
| |
| if (!file.second->getParent()) { |
| // Files that have parent are splited files (When a module is too |
| // large it is splited) |
| all_modules.insert( |
| std::make_pair(topname, std::make_pair(&element, file.second))); |
| } |
| |
| modulePresent = true; |
| bool used = false; |
| for (auto file1 : all_files) { |
| if (file1.second->getReferencedObjects().find(elemName) != |
| file1.second->getReferencedObjects().end()) { |
| used = true; |
| break; |
| } |
| } |
| |
| if (!used) { |
| bool isTop = true; |
| |
| if (m_toplevelConfigModules.size()) { |
| isTop = false; |
| if (m_toplevelConfigModules.find(topname) != |
| m_toplevelConfigModules.end()) { |
| isTop = true; |
| } |
| } |
| |
| if (isTop) { |
| SymbolId topid = st->registerSymbol(topname); |
| auto itr = m_uniqueTopLevelModules.find(topname); |
| Location loc( |
| st->registerSymbol(file.second->getFileName(element.m_node)), |
| element.m_line, 0, topid); |
| if (itr == m_uniqueTopLevelModules.end()) { |
| m_uniqueTopLevelModules.insert(topname); |
| m_topLevelModules.push_back(std::make_pair(topname, file.second)); |
| toplevelModuleFound = true; |
| Error err(ErrorDefinition::ELAB_TOP_LEVEL_MODULE, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError( |
| err); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // Check for multiple definition |
| std::string prevModuleName = ""; |
| DesignElement* prevModuleDefinition = NULL; |
| FileContent* prevFileContent = NULL; |
| for (ModuleMultiMap::iterator itr = all_modules.begin(); |
| itr != all_modules.end(); itr++) { |
| std::string moduleName = (*itr).first; |
| DesignElement* moduleDefinition = (*itr).second.first; |
| FileContent* fileContent = (*itr).second.second; |
| bool done = false; |
| if (moduleName == prevModuleName) { |
| FileContent* fC1 = (*itr).second.second; |
| NodeId nodeId1 = moduleDefinition->m_node; |
| std::string fileName1 = fC1->getFileName(nodeId1); |
| unsigned int line1 = fC1->Line(nodeId1); |
| Location loc1(st->registerSymbol(fileName1), line1, 0, |
| st->registerSymbol(moduleName)); |
| |
| std::vector<Location> locations; |
| |
| while (1) { |
| FileContent* fC2 = prevFileContent; |
| NodeId nodeId2 = prevModuleDefinition->m_node; |
| std::string fileName2 = fC2->getFileName(nodeId2); |
| unsigned int line2 = fC2->Line(nodeId2); |
| Location loc2(st->registerSymbol(fileName2), line2, 0, |
| st->registerSymbol(moduleName)); |
| |
| if ((fileName1 != fileName2) || (line1 != line2)) { |
| locations.push_back(loc2); |
| } |
| |
| itr++; |
| if (itr == all_modules.end()) { |
| done = true; |
| break; |
| } else { |
| std::string nextModuleName = (*itr).first; |
| DesignElement* nextModuleDefinition = (*itr).second.first; |
| FileContent* nextFileContent = (*itr).second.second; |
| prevModuleName = nextModuleName; |
| prevModuleDefinition = nextModuleDefinition; |
| prevFileContent = nextFileContent; |
| if (prevModuleName != moduleName) { |
| moduleName = prevModuleName; |
| moduleDefinition = prevModuleDefinition; |
| fileContent = prevFileContent; |
| break; |
| } |
| } |
| } |
| |
| if (locations.size()) { |
| Error err1(ErrorDefinition::ELAB_MULTIPLY_DEFINED_MODULE, loc1, |
| &locations); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err1); |
| } |
| } |
| prevModuleName = moduleName; |
| prevModuleDefinition = moduleDefinition; |
| prevFileContent = fileContent; |
| if (done) break; |
| } |
| |
| if (m_topLevelModules.size() > 1) { |
| Location loc(0); |
| Error err(ErrorDefinition::ELAB_MULTIPLE_TOP_LEVEL_MODULES, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| if (modulePresent && (!toplevelModuleFound)) { |
| Location loc(0); |
| Error err(ErrorDefinition::ELAB_NO_TOP_LEVEL_MODULE, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| |
| return true; |
| } |
| |
| bool DesignElaboration::createBuiltinPrimitives_() { |
| m_moduleDefFactory = new ModuleDefinitionFactory(); |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| |
| // Register built-in primitives |
| for (auto type : |
| {"cmos", "rcmos", "bufif0", "bufif1", "notif0", |
| "notif1", "nmos", "pmos", "rnmos", "rpmos", |
| "and", "or", "nand", "nor", "xor", |
| "xnor", "buf", "not", "tranif0", "tranif1", |
| "rtranif0", "rtranif1", "tran", "rtran", "UnsupportedPrimitive"}) { |
| std::string name = std::string("work@") + type; |
| design->addModuleDefinition(name, |
| m_moduleDefFactory->newModuleDefinition( |
| NULL, 0, std::string("work@") + type)); |
| } |
| |
| return true; |
| } |
| |
| bool DesignElaboration::elaborateAllModules_(bool onlyTopLevel) { |
| bool status = true; |
| for (auto topmodule : m_topLevelModules) { |
| if (!elaborateModule_(topmodule.first, topmodule.second, onlyTopLevel)) { |
| status = false; |
| } |
| } |
| return status; |
| } |
| |
| Config* DesignElaboration::getInstConfig(std::string name) { |
| Config* config = NULL; |
| auto itr = m_instConfig.find(name); |
| if (itr != m_instConfig.end()) { |
| config = &(*itr).second; |
| } |
| return config; |
| } |
| |
| Config* DesignElaboration::getCellConfig(std::string name) { |
| Config* config = NULL; |
| auto itr = m_cellConfig.find(name); |
| if (itr != m_cellConfig.end()) { |
| config = &(*itr).second; |
| } |
| return config; |
| } |
| |
| bool DesignElaboration::elaborateModule_(std::string moduleName, |
| FileContent* fC, bool onlyTopLevel) { |
| FileContent::NameIdMap& nameIds = fC->getObjectLookup(); |
| std::vector<VObjectType> types = {VObjectType::slUdp_instantiation, |
| VObjectType::slModule_instantiation, |
| VObjectType::slInterface_instantiation, |
| VObjectType::slProgram_instantiation}; |
| std::string libName = fC->getLibrary()->getName(); |
| Config* config = getInstConfig(moduleName); |
| if (config == NULL) config = getCellConfig(moduleName); |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| if (!m_moduleInstFactory) m_moduleInstFactory = new ModuleInstanceFactory(); |
| for (auto nameId : nameIds) { |
| if ((fC->Type(nameId.second) == VObjectType::slModule_declaration) && |
| (moduleName == (libName + "@" + nameId.first))) { |
| DesignComponent* def = design->getComponentDefinition(moduleName); |
| if (onlyTopLevel) { |
| ModuleInstance* instance = m_moduleInstFactory->newModuleInstance( |
| def, fC, nameId.second, NULL, moduleName, moduleName); |
| design->addTopLevelModuleInstance(instance); |
| } else { |
| ModuleInstance* instance = design->findInstance(moduleName); |
| for (unsigned int i = 0; i < def->getFileContents().size(); i++) |
| elaborateInstance_(def->getFileContents()[i], def->getNodeIds()[i], 0, |
| m_moduleInstFactory, instance, config); |
| } |
| break; |
| } |
| } |
| return true; |
| } |
| |
| void DesignElaboration::recurseInstanceLoop_( |
| std::vector<int>& from, std::vector<int>& to, std::vector<int>& indexes, |
| unsigned int pos, DesignComponent* def, FileContent* fC, |
| NodeId subInstanceId, NodeId paramOverride, ModuleInstanceFactory* factory, |
| ModuleInstance* parent, Config* config, std::string instanceName, |
| std::string modName, std::vector<ModuleInstance*>& allSubInstances) { |
| if (pos == indexes.size()) { |
| // This is where the real logic goes. |
| // indexes[i] contain the value of the i-th index. |
| for (unsigned int i = 0; i < indexes.size(); i++) { |
| instanceName += std::to_string(indexes[i]); |
| } |
| ModuleInstance* child = factory->newModuleInstance( |
| def, fC, subInstanceId, parent, instanceName, modName); |
| VObjectType type = fC->Type(subInstanceId); |
| if (def && (type != VObjectType::slGate_instantiation)) |
| for (unsigned int i = 0; i < def->getFileContents().size(); i++) |
| elaborateInstance_(def->getFileContents()[i], def->getNodeIds()[i], |
| paramOverride, factory, child, config); |
| allSubInstances.push_back(child); |
| |
| } else { |
| for (indexes[pos] = from[pos]; indexes[pos] <= to[pos]; indexes[pos]++) { |
| // Recurse for the next level |
| recurseInstanceLoop_(from, to, indexes, pos + 1, def, fC, subInstanceId, |
| paramOverride, factory, parent, config, instanceName, |
| modName, allSubInstances); |
| } |
| } |
| } |
| |
| void DesignElaboration::elaborateInstance_(FileContent* fC, NodeId nodeId, |
| NodeId parentParamOverride, |
| ModuleInstanceFactory* factory, |
| ModuleInstance* parent, |
| Config* config) { |
| if (!parent) return; |
| std::vector<ModuleInstance*> allSubInstances; |
| std::string genBlkBaseName = "genblk"; |
| unsigned int genBlkIndex = 1; |
| bool reuseInstance = false; |
| std::string mname; |
| std::vector<VObjectType> types; |
| std::vector<std::string> params; |
| |
| // Scan for parameters, including DefParams |
| collectParams_(params, fC, nodeId, parent, parentParamOverride); |
| |
| // Apply DefParams |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| for (auto name : params) { |
| DefParam* defparam = |
| design->getDefParam(parent->getFullPathName() + "." + name); |
| if (defparam) { |
| Value* value = defparam->getValue(); |
| if (value) { |
| parent->setValue(name, value, m_exprBuilder); |
| defparam->setUsed(); |
| } |
| } |
| } |
| |
| // Scan for regular instances and generate blocks |
| types = { |
| VObjectType::slUdp_instantiation, |
| VObjectType::slModule_instantiation, |
| VObjectType::slInterface_instantiation, |
| VObjectType::slProgram_instantiation, |
| VObjectType::slGate_instantiation, |
| VObjectType::slConditional_generate_construct, // Generate construct are |
| // a kind of instantiation |
| VObjectType::slGenerate_module_conditional_statement, |
| VObjectType::slLoop_generate_construct, |
| VObjectType::slGenerate_module_loop_statement, |
| VObjectType::slPar_block, |
| VObjectType::slSeq_block}; |
| |
| std::vector<VObjectType> stopPoints = { |
| VObjectType::slConditional_generate_construct, |
| VObjectType::slGenerate_module_conditional_statement, |
| VObjectType::slLoop_generate_construct, |
| VObjectType::slGenerate_module_loop_statement, |
| VObjectType::slPar_block, |
| VObjectType::slSeq_block, |
| VObjectType::slModule_declaration}; |
| |
| std::vector<NodeId> subInstances = |
| fC->sl_collect_all(nodeId, types, stopPoints); |
| |
| for (auto subInstanceId : subInstances) { |
| NodeId childId = 0; |
| std::string instName; |
| std::string modName; |
| DesignComponent* def = NULL; |
| NodeId paramOverride = 0; |
| Config* subConfig = config; |
| VObjectType type = fC->Type(subInstanceId); |
| |
| if (type == slSeq_block || type == slPar_block) { |
| NodeId identifierId = fC->Child(subInstanceId); |
| if (fC->Name(identifierId)) |
| instName = fC->SymName(identifierId); |
| else |
| instName = "UNNAMED"; |
| } else if (type == slConditional_generate_construct) { |
| NodeId constructId = fC->Child(subInstanceId); |
| NodeId condId = fC->Child(constructId); |
| NodeId blockId = fC->Sibling(condId); |
| NodeId nameId = fC->Child(blockId); |
| if (fC->Name(nameId)) |
| instName = fC->SymName(nameId); |
| else |
| instName = "UNNAMED"; |
| } else { |
| NodeId instId = fC->sl_collect(subInstanceId, slName_of_instance); |
| NodeId identifierId = 0; |
| if (instId != InvalidNodeId) { |
| identifierId = fC->Child(instId); |
| instName = fC->SymName(identifierId); |
| } |
| } |
| |
| // Special module binding for built-in primitives |
| if (type == VObjectType::slGate_instantiation) { |
| VObjectType gatetype = fC->Type(fC->Child(subInstanceId)); |
| switch (gatetype) { |
| case VObjectType::slNInpGate_And: |
| modName = "work@and"; |
| break; |
| case VObjectType::slNInpGate_Or: |
| modName = "work@or"; |
| break; |
| case VObjectType::slNInpGate_Nand: |
| modName = "work@nand"; |
| break; |
| case VObjectType::slNInpGate_Nor: |
| modName = "work@nor"; |
| break; |
| case VObjectType::slNInpGate_Xor: |
| modName = "work@xor"; |
| break; |
| case VObjectType::slNInpGate_Xnor: |
| modName = "work@xnor"; |
| break; |
| case VObjectType::slNOutGate_Buf: |
| modName = "work@buf"; |
| break; |
| case VObjectType::slNOutGate_Not: |
| modName = "work@not"; |
| break; |
| // TODO: Cater for the transistor level |
| default: |
| modName = "work@UnsupportedPrimitive"; |
| break; |
| } |
| |
| def = design->getComponentDefinition(modName); |
| childId = 0; // = def->getNodeId (); |
| ModuleInstance* child = factory->newModuleInstance( |
| def, fC, subInstanceId, parent, instName, modName); |
| allSubInstances.push_back(child); |
| |
| } |
| // Special module binding for generate statements |
| else if (type == VObjectType::slConditional_generate_construct || |
| type == VObjectType::slGenerate_module_conditional_statement || |
| type == VObjectType::slLoop_generate_construct || |
| type == VObjectType::slGenerate_module_loop_statement) { |
| modName = genBlkBaseName + std::to_string(genBlkIndex); |
| |
| std::vector<VObjectType> btypes = { |
| VObjectType::slGenerate_module_block, VObjectType::slGenerate_block, |
| VObjectType::slGenerate_module_named_block}; |
| |
| std::vector<NodeId> blockIds = |
| fC->sl_collect_all(subInstanceId, btypes, true); |
| bool namedBlock = false; |
| if (blockIds.size()) { |
| NodeId blockId = blockIds[0]; |
| NodeId blockNameId = fC->Child(blockId); |
| if (fC->Type(blockNameId) == VObjectType::slStringConst) { |
| namedBlock = true; |
| modName = fC->SymName(blockNameId); |
| } |
| } |
| if (!namedBlock) genBlkIndex++; |
| instName = modName; |
| std::string fullName; |
| std::string libName = fC->getLibrary()->getName(); |
| if (instName == parent->getInstanceName()) { |
| fullName += parent->getFullPathName(); |
| reuseInstance = true; |
| } else { |
| fullName += parent->getModuleName() + "." + instName; |
| } |
| def = design->getComponentDefinition(fullName); |
| if (def == NULL) { |
| def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId, |
| fullName); |
| design->addModuleDefinition(fullName, (ModuleDefinition*)def); |
| } |
| |
| NodeId conditionId = fC->Child(subInstanceId); |
| |
| if (fC->Type(conditionId) == VObjectType::slGenvar_initialization || |
| fC->Type(conditionId) == |
| VObjectType::slGenvar_decl_assignment) { // For loop stmt |
| |
| // Var init |
| NodeId varId = fC->Child(conditionId); |
| NodeId constExpr = fC->Sibling(varId); |
| Value* initValue = m_exprBuilder.evalExpr(fC, constExpr, parent); |
| std::string name = fC->SymName(varId); |
| parent->setValue(name, initValue, m_exprBuilder); |
| |
| // End-loop test |
| NodeId endLoopTest = fC->Sibling(conditionId); |
| |
| // Iteration |
| NodeId iteration = fC->Sibling(endLoopTest); |
| NodeId var = fC->Child(iteration); |
| NodeId assignOp = fC->Sibling(var); |
| NodeId expr = fC->Sibling(assignOp); |
| if (expr == 0) { // Unary operator like i++ |
| expr = var; |
| } |
| // Generate block |
| NodeId genBlock = fC->Sibling(iteration); |
| |
| bool cont = true; |
| Value* testCond = m_exprBuilder.evalExpr(fC, endLoopTest, parent); |
| cont = testCond->getValueUL(); |
| m_exprBuilder.deleteValue(testCond); |
| |
| while (cont) { |
| Value* currentIndexValue = parent->getValue(name); |
| long currVal = currentIndexValue->getValueUL(); |
| std::string indexedModName = |
| modName + "[" + std::to_string(currVal) + "]"; |
| instName = indexedModName; |
| ModuleInstance* child = factory->newModuleInstance( |
| def, fC, genBlock, parent, instName, indexedModName); |
| child->setValue(name, currentIndexValue, m_exprBuilder); |
| elaborateInstance_(def->getFileContents()[0], genBlock, 0, factory, |
| child, config); |
| allSubInstances.push_back(child); |
| |
| Value* newVal = m_exprBuilder.evalExpr(fC, expr, parent); |
| parent->setValue(name, newVal, m_exprBuilder); |
| Value* testCond = m_exprBuilder.evalExpr(fC, endLoopTest, parent); |
| cont = testCond->getValueUL(); |
| m_exprBuilder.deleteValue(testCond); |
| } |
| if (allSubInstances.size()) { |
| ModuleInstance** children = |
| new ModuleInstance*[allSubInstances.size()]; |
| for (unsigned int index = 0; index < allSubInstances.size(); |
| index++) { |
| children[index] = allSubInstances[index]; |
| } |
| parent->addSubInstances(children, allSubInstances.size()); |
| } |
| continue; |
| |
| } else { // If-Else or Case stmt |
| if (fC->Type(conditionId) != VObjectType::slConstant_expression) { |
| conditionId = fC->Child(conditionId); |
| } |
| Value* condValue = m_exprBuilder.evalExpr(fC, conditionId, parent); |
| long condVal = condValue->getValueUL(); |
| m_exprBuilder.deleteValue(condValue); |
| NodeId tmp = fC->Sibling(conditionId); |
| if (fC->Type(tmp) == VObjectType::slCase_generate_item) { // Case stmt |
| NodeId caseItem = tmp; |
| bool nomatch = true; |
| while (nomatch) { |
| NodeId exprItem = fC->Child(caseItem); |
| if (fC->Type(exprItem) == |
| VObjectType::slGenerate_block) // Default block |
| nomatch = false; |
| while (nomatch) { |
| // Find if one of the case expr matches the case expr |
| if (fC->Type(exprItem) == VObjectType::slConstant_expression) { |
| Value* caseValue = m_exprBuilder.evalExpr(fC, exprItem, parent); |
| long caseVal = caseValue->getValueUL(); |
| m_exprBuilder.deleteValue(caseValue); |
| if (condVal == caseVal) { |
| nomatch = false; |
| break; |
| } |
| } else |
| break; |
| exprItem = fC->Sibling(exprItem); |
| } |
| |
| if (nomatch) { |
| // Next case stmt |
| caseItem = fC->Sibling(caseItem); |
| if (!caseItem) break; |
| if (fC->Type(caseItem) != VObjectType::slCase_generate_item) |
| break; |
| } else { |
| // We found a match |
| while (fC->Type(exprItem) == VObjectType::slConstant_expression) |
| exprItem = fC->Sibling(exprItem); |
| childId = exprItem; |
| } |
| } |
| } else { // If-Else stmt |
| if (condVal) { // If branch |
| if (tmp) |
| childId = tmp; |
| else // There is no If stmt |
| continue; |
| } else { // Else branch |
| if (tmp) tmp = fC->Sibling(tmp); |
| if (tmp) |
| childId = tmp; |
| else // There is no Else stmt |
| continue; |
| } |
| } |
| } |
| |
| libName = fC->getLibrary()->getName(); |
| fullName = parent->getModuleName() + "." + instName; |
| def = design->getComponentDefinition(fullName); |
| if (def == NULL) { |
| def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId, |
| fullName); |
| design->addModuleDefinition(fullName, (ModuleDefinition*)def); |
| } |
| |
| ModuleInstance* child = factory->newModuleInstance( |
| def, fC, subInstanceId, parent, instName, modName); |
| elaborateInstance_(def->getFileContents()[0], childId, paramOverride, |
| factory, child, config); |
| allSubInstances.push_back(child); |
| |
| } |
| // Named blocks |
| else if (type == slSeq_block || type == slPar_block) { |
| std::string libName = fC->getLibrary()->getName(); |
| std::string fullName = parent->getModuleName() + "." + instName; |
| |
| def = design->getComponentDefinition(fullName); |
| if (def == NULL) { |
| def = m_moduleDefFactory->newModuleDefinition(fC, subInstanceId, |
| fullName); |
| design->addModuleDefinition(fullName, (ModuleDefinition*)def); |
| } |
| |
| ModuleInstance* child = factory->newModuleInstance( |
| def, fC, subInstanceId, parent, instName, modName); |
| elaborateInstance_(def->getFileContents()[0], subInstanceId, |
| paramOverride, factory, child, config); |
| allSubInstances.push_back(child); |
| |
| } |
| // Regular module binding |
| else { |
| NodeId moduleName = |
| fC->sl_collect(subInstanceId, VObjectType::slStringConst); |
| std::string libName = fC->getLibrary()->getName(); |
| mname = fC->SymName(moduleName); |
| |
| std::vector<std::string> libs; |
| if (config) { |
| for (auto lib : config->getDefaultLibs()) { |
| libs.push_back(lib); |
| } |
| libs.push_back(libName); |
| } else { |
| libs.push_back(libName); |
| } |
| |
| for (auto lib : libs) { |
| modName = lib + "@" + mname; |
| def = design->getComponentDefinition(modName); |
| if (def) { |
| break; |
| } else { |
| modName = parent->getDefinition()->getName() + "::" + mname; |
| def = design->getComponentDefinition(modName); |
| if (def) { |
| break; |
| } |
| } |
| } |
| |
| auto itr = m_cellUseClause.find(mname); |
| if (itr != m_cellUseClause.end()) { |
| UseClause& use = (*itr).second; |
| switch (use.getType()) { |
| case UseClause::UseModule: { |
| std::string name = use.getName(); |
| def = design->getComponentDefinition(name); |
| if (def) use.setUsed(); |
| break; |
| } |
| case UseClause::UseLib: { |
| for (auto lib : use.getLibs()) { |
| modName = lib + "@" + mname; |
| def = design->getComponentDefinition(modName); |
| if (def) { |
| use.setUsed(); |
| break; |
| } |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| |
| if (def) childId = def->getNodeIds()[0]; |
| |
| NodeId tmpId = fC->Sibling(moduleName); |
| if (fC->Type(tmpId) == VObjectType::slParameter_value_assignment) { |
| paramOverride = tmpId; |
| } |
| |
| bool loopDetected = false; |
| ModuleInstance* tmp = parent; |
| while (tmp) { |
| if (tmp->getDefinition() == def) { |
| loopDetected = true; |
| break; |
| } |
| tmp = tmp->getParent(); |
| } |
| if (loopDetected) { |
| SymbolTable* st = m_compileDesign->getCompiler() |
| ->getErrorContainer() |
| ->getSymbolTable(); |
| Location loc(st->registerSymbol(fC->getFileName(subInstanceId)), |
| fC->Line(subInstanceId), 0, st->registerSymbol(modName)); |
| Location loc2(st->registerSymbol( |
| tmp->getFileContent()->getFileName(tmp->getNodeId())), |
| tmp->getFileContent()->Line(tmp->getNodeId()), 0); |
| Error err(ErrorDefinition::ELAB_INSTANTIATION_LOOP, loc, loc2); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } else { |
| std::vector<int> from; |
| std::vector<int> to; |
| std::vector<int> index; |
| |
| std::vector<VObjectType> insttypes = { |
| VObjectType::slHierarchical_instance, |
| VObjectType::slN_input_gate_instance, |
| VObjectType::slN_output_gate_instance, VObjectType::slUdp_instance}; |
| |
| std::vector<NodeId> hierInstIds = |
| fC->sl_collect_all(subInstanceId, insttypes, true); |
| |
| NodeId hierInstId = InvalidNodeId; |
| if (hierInstIds.size()) hierInstId = hierInstIds[0]; |
| |
| if (hierInstId == InvalidNodeId) continue; |
| |
| while (hierInstId) { |
| NodeId instId = fC->sl_collect(hierInstId, slName_of_instance); |
| NodeId identifierId = 0; |
| if (instId != InvalidNodeId) { |
| identifierId = fC->Child(instId); |
| instName = fC->SymName(identifierId); |
| } |
| |
| auto itr = |
| m_instUseClause.find(parent->getFullPathName() + "." + instName); |
| if (itr != m_instUseClause.end()) { |
| UseClause& use = (*itr).second; |
| switch (use.getType()) { |
| case UseClause::UseModule: { |
| std::string name = use.getName(); |
| def = design->getComponentDefinition(name); |
| if (def) use.setUsed(); |
| break; |
| } |
| case UseClause::UseLib: { |
| for (auto lib : use.getLibs()) { |
| modName = lib + "@" + mname; |
| def = design->getComponentDefinition(modName); |
| if (def) { |
| use.setUsed(); |
| break; |
| } |
| } |
| break; |
| } |
| case UseClause::UseConfig: { |
| std::string useConfig = use.getName(); |
| Config* config = design->getConfigSet()->getConfig(useConfig); |
| if (config) { |
| subConfig = config; |
| std::string lib = config->getDesignLib(); |
| std::string top = config->getDesignTop(); |
| modName = lib + "@" + top; |
| def = design->getComponentDefinition(modName); |
| if (def) use.setUsed(); |
| } |
| } |
| default: |
| break; |
| } |
| } |
| |
| if (def) |
| childId = def->getNodeIds()[0]; |
| else { |
| SymbolTable* st = m_compileDesign->getCompiler() |
| ->getErrorContainer() |
| ->getSymbolTable(); |
| Location loc(st->registerSymbol(fC->getFileName(subInstanceId)), |
| fC->Line(subInstanceId), 0, |
| st->registerSymbol(modName)); |
| Error err(ErrorDefinition::ELAB_NO_MODULE_DEFINITION, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError( |
| err, false, false); |
| } |
| |
| NodeId unpackedDimId = 0; |
| |
| if (identifierId) unpackedDimId = fC->Sibling(identifierId); |
| |
| if (unpackedDimId) { |
| // Vector instances |
| while (unpackedDimId) { |
| if (fC->Type(unpackedDimId) == slUnpacked_dimension) { |
| NodeId constantRangeId = fC->Child(unpackedDimId); |
| NodeId leftNode = fC->Child(constantRangeId); |
| NodeId rightNode = fC->Sibling(leftNode); |
| Value* leftVal = m_exprBuilder.evalExpr(fC, leftNode, parent); |
| Value* rightVal = m_exprBuilder.evalExpr(fC, rightNode, parent); |
| unsigned long left = leftVal->getValueUL(); |
| unsigned long right = rightVal->getValueUL(); |
| m_exprBuilder.deleteValue(leftVal); |
| m_exprBuilder.deleteValue(rightVal); |
| if (left < right) { |
| from.push_back(left); |
| to.push_back(right); |
| index.push_back(left); |
| } else { |
| from.push_back(right); |
| to.push_back(left); |
| index.push_back(right); |
| } |
| } |
| unpackedDimId = fC->Sibling(unpackedDimId); |
| } |
| recurseInstanceLoop_(from, to, index, 0, def, fC, subInstanceId, |
| paramOverride, factory, parent, subConfig, |
| instName, modName, allSubInstances); |
| } else { |
| // Simple instance |
| ModuleInstance* child = NULL; |
| if (reuseInstance) { |
| child = parent; |
| child->setNodeId(subInstanceId); |
| } else { |
| child = factory->newModuleInstance(def, fC, subInstanceId, parent, |
| instName, modName); |
| } |
| if (def && (type != VObjectType::slGate_instantiation)) |
| elaborateInstance_(def->getFileContents()[0], childId, |
| paramOverride, factory, child, subConfig); |
| |
| if (!reuseInstance) allSubInstances.push_back(child); |
| } |
| |
| hierInstId = fC->Sibling(hierInstId); |
| } |
| |
| // std::cout << "INST: " << modName << " " << instName << " " << def << |
| // std::endl; |
| } |
| } |
| } |
| // Record sub-scopes and sub-instances |
| if (allSubInstances.size()) { |
| ModuleInstance** children = new ModuleInstance*[allSubInstances.size()]; |
| for (unsigned int index = 0; index < allSubInstances.size(); index++) { |
| children[index] = allSubInstances[index]; |
| } |
| parent->addSubInstances(children, allSubInstances.size()); |
| } |
| } |
| |
| void DesignElaboration::reportElaboration_() { |
| unsigned int nbTopLevelModules = 0; |
| unsigned int maxDepth = 0; |
| unsigned int numberOfInstances = 0; |
| unsigned int numberOfLeafInstances = 0; |
| unsigned int nbUndefinedModules = 0; |
| unsigned int nbUndefinedInstances = 0; |
| |
| m_compileDesign->getCompiler()->getDesign()->reportInstanceTreeStats( |
| nbTopLevelModules, maxDepth, numberOfInstances, numberOfLeafInstances, |
| nbUndefinedModules, nbUndefinedInstances); |
| |
| SymbolTable* symtable = m_compileDesign->getCompiler()->getSymbolTable(); |
| |
| Location loc1(symtable->registerSymbol(std::to_string(nbTopLevelModules))); |
| Error err1(ErrorDefinition::ELAB_NB_TOP_LEVEL_MODULES, loc1); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err1); |
| |
| Location loc2(symtable->registerSymbol(std::to_string(maxDepth))); |
| Error err2(ErrorDefinition::ELAB_MAX_INSTANCE_DEPTH, loc2); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err2); |
| |
| Location loc3(symtable->registerSymbol(std::to_string(numberOfInstances))); |
| Error err3(ErrorDefinition::ELAB_NB_INSTANCES, loc3); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err3); |
| |
| Location loc4( |
| symtable->registerSymbol(std::to_string(numberOfLeafInstances))); |
| Error err4(ErrorDefinition::ELAB_NB_LEAF_INSTANCES, loc4); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err4); |
| |
| if (nbUndefinedModules) { |
| Location loc5(symtable->registerSymbol(std::to_string(nbUndefinedModules))); |
| Error err5(ErrorDefinition::ELAB_NB_UNDEF_MODULES, loc5); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err5); |
| } |
| |
| if (nbUndefinedInstances) { |
| Location loc6( |
| symtable->registerSymbol(std::to_string(nbUndefinedInstances))); |
| Error err6(ErrorDefinition::ELAB_NB_UNDEF_INSTANCES, loc6); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err6); |
| } |
| CommandLineParser* cl = |
| m_compileDesign->getCompiler()->getCommandLineParser(); |
| if (cl->getDebugInstanceTree() && (!cl->muteStdout())) { |
| std::cout << "Instance tree:" << std::endl; |
| std::cout |
| << m_compileDesign->getCompiler()->getDesign()->reportInstanceTree(); |
| std::cout << std::endl; |
| } |
| } |
| |
| void DesignElaboration::collectParams_(std::vector<std::string>& params, |
| FileContent* fC, NodeId nodeId, |
| ModuleInstance* instance, |
| NodeId parentParamOverride) { |
| if (!nodeId) return; |
| if (!instance) return; |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable(); |
| ErrorContainer* errors = m_compileDesign->getCompiler()->getErrorContainer(); |
| DesignComponent* module = instance->getDefinition(); |
| |
| // Parameters imported by package imports |
| std::vector<FileCNodeId> pack_imports; |
| for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) { |
| pack_imports.push_back(import); |
| } |
| for (auto import : module->getObjects(VObjectType::slPackage_import_item)) { |
| pack_imports.push_back(import); |
| } |
| |
| for (auto pack_import : pack_imports) { |
| NodeId pack_id = pack_import.fC->Child(pack_import.nodeId); |
| std::string pack_name = pack_import.fC->SymName(pack_id); |
| Package* def = design->getPackage(pack_name); |
| if (def) { |
| auto& paramSet = def->getObjects(VObjectType::slParam_assignment); |
| for (unsigned int i = 0; i < paramSet.size(); i++) { |
| FileContent* packageFile = paramSet[i].fC; |
| NodeId param = paramSet[i].nodeId; |
| |
| NodeId ident = packageFile->Child(param); |
| std::string name = packageFile->SymName(ident); |
| Value* value = m_exprBuilder.clone(def->getValues()[i]); |
| instance->setValue(name, value, m_exprBuilder); |
| params.push_back(name); |
| } |
| } else { |
| Location loc(st->registerSymbol(pack_import.fC->getFileName(pack_id)), |
| pack_import.fC->Line(pack_id), 0, |
| st->registerSymbol(pack_name)); |
| Error err(ErrorDefinition::ELAB_UNDEFINED_PACKAGE, loc); |
| errors->addError(err); |
| } |
| } |
| |
| for (FileCNodeId param : |
| module->getObjects(VObjectType::slParam_assignment)) { |
| NodeId ident = param.fC->Child(param.nodeId); |
| std::string name = param.fC->SymName(ident); |
| Value* value = |
| m_exprBuilder.evalExpr(param.fC, param.fC->Sibling(ident), instance); |
| instance->setValue(name, value, m_exprBuilder); |
| params.push_back(name); |
| } |
| |
| std::vector<VObjectType> types; |
| // Param overrides |
| if (parentParamOverride) { |
| FileContent* parentFile = |
| instance->getParent()->getDefinition()->getFileContents()[0]; |
| types = {VObjectType::slOrdered_parameter_assignment, |
| VObjectType::slNamed_parameter_assignment}; |
| std::vector<NodeId> overrideParams = |
| parentFile->sl_collect_all(parentParamOverride, types); |
| |
| unsigned int index = 0; |
| for (auto paramAssign : overrideParams) { |
| NodeId child = parentFile->Child(paramAssign); |
| if (parentFile->Type(child) == VObjectType::slStringConst) { |
| // Named param |
| std::string name = parentFile->SymName(child); |
| NodeId expr = parentFile->Sibling(child); |
| Value* value = |
| m_exprBuilder.evalExpr(parentFile, expr, instance->getParent()); |
| instance->setValue(name, value, m_exprBuilder); |
| } else { |
| // Index param |
| NodeId expr = child; |
| Value* value = |
| m_exprBuilder.evalExpr(parentFile, expr, instance->getParent()); |
| std::string name = "OUT_OF_RANGE_PARAM_INDEX"; |
| if (index < params.size()) { |
| name = params[index]; |
| } else { |
| Location loc(st->registerSymbol(parentFile->getFileName(paramAssign)), |
| parentFile->Line(paramAssign), 0, |
| st->registerSymbol(std::to_string(index))); |
| Error err(ErrorDefinition::ELAB_OUT_OF_RANGE_PARAM_INDEX, loc); |
| errors->addError(err); |
| } |
| instance->setValue(name, value, m_exprBuilder); |
| index++; |
| } |
| } |
| } |
| |
| // Defparams |
| types = {VObjectType::slDefparam_assignment}; |
| std::vector<VObjectType> stopPoints = { |
| VObjectType::slConditional_generate_construct, |
| VObjectType::slGenerate_module_conditional_statement, |
| VObjectType::slLoop_generate_construct, |
| VObjectType::slGenerate_module_loop_statement, |
| VObjectType::slPar_block, |
| VObjectType::slSeq_block, |
| VObjectType::slModule_declaration}; |
| |
| std::vector<NodeId> defParams = fC->sl_collect_all(nodeId, types, stopPoints); |
| for (auto defParam : defParams) { |
| NodeId hIdent = fC->Child(defParam); |
| NodeId var = fC->Child(hIdent); |
| NodeId value = fC->Sibling(hIdent); |
| std::string fullPath = fC->SymName(var); |
| std::string path; |
| for (unsigned int i = 0; i < fullPath.size(); i++) { |
| if (fullPath[i] == '.') break; |
| path += fullPath[i]; |
| } |
| std::string pathRoot; |
| pathRoot = fC->getLibrary()->getName() + "@"; |
| pathRoot += path; |
| path = fullPath; |
| |
| // path refers to a sub instance |
| std::string prefix; |
| if (design->findInstance(pathRoot)) { |
| std::string p = design->findInstance(pathRoot)->getFullPathName(); |
| if (strstr(p.c_str(), ".")) { |
| prefix = instance->getFullPathName() + "."; |
| } else { |
| prefix = fC->getLibrary()->getName() + "@"; |
| } |
| } else { |
| prefix = instance->getFullPathName() + "."; |
| } |
| path = prefix + path; |
| Value* val = m_exprBuilder.evalExpr(fC, value, instance); |
| design->addDefParam(path, fC, hIdent, val); |
| } |
| } |
| |
| void DesignElaboration::checkElaboration_() { |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| design->checkDefParamUsage(); |
| checkConfigurations_(); |
| } |
| |
| void DesignElaboration::checkConfigurations_() { |
| SymbolTable* st = m_compileDesign->getCompiler()->getSymbolTable(); |
| for (auto& pathUseC : m_cellUseClause) { |
| UseClause& useC = pathUseC.second; |
| if (!useC.isUsed()) { |
| FileContent* fC = useC.getFileContent(); |
| Location loc(st->registerSymbol(fC->getFileName(useC.getNodeId())), |
| fC->Line(useC.getNodeId()), 0, |
| st->registerSymbol(pathUseC.first)); |
| Error err(ErrorDefinition::ELAB_USE_CLAUSE_IGNORED, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| } |
| for (auto& pathUseC : m_instUseClause) { |
| UseClause& useC = pathUseC.second; |
| if (!useC.isUsed()) { |
| FileContent* fC = useC.getFileContent(); |
| Location loc(st->registerSymbol(fC->getFileName(useC.getNodeId())), |
| fC->Line(useC.getNodeId()), 0, |
| st->registerSymbol(pathUseC.first)); |
| Error err(ErrorDefinition::ELAB_USE_CLAUSE_IGNORED, loc); |
| m_compileDesign->getCompiler()->getErrorContainer()->addError(err); |
| } |
| } |
| } |
| |
| void DesignElaboration::reduceUnnamedBlocks_() { |
| Design* design = m_compileDesign->getCompiler()->getDesign(); |
| std::queue<ModuleInstance*> queue; |
| for (auto instance : design->getTopLevelModuleInstances()) { |
| queue.push(instance); |
| } |
| |
| while (queue.size()) { |
| ModuleInstance* current = queue.front(); |
| queue.pop(); |
| for (unsigned int i = 0; i < current->getNbChildren(); i++) { |
| queue.push(current->getChildren(i)); |
| } |
| FileContent* fC = current->getFileContent(); |
| NodeId id = current->getNodeId(); |
| VObjectType type = fC->Type(id); |
| |
| ModuleInstance* parent = current->getParent(); |
| if (parent) { |
| FileContent* fCP = parent->getFileContent(); |
| NodeId idP = parent->getNodeId(); |
| VObjectType typeP = fCP->Type(idP); |
| |
| if ((type == VObjectType::slConditional_generate_construct || |
| type == VObjectType::slGenerate_module_conditional_statement || |
| type == VObjectType::slLoop_generate_construct || |
| type == VObjectType::slGenerate_module_loop_statement) && |
| (typeP == VObjectType::slConditional_generate_construct || |
| typeP == VObjectType::slGenerate_module_conditional_statement || |
| typeP == VObjectType::slLoop_generate_construct || |
| typeP == VObjectType::slGenerate_module_loop_statement)) { |
| std::string fullModName = current->getModuleName(); |
| fullModName = StringUtils::leaf(fullModName); |
| std::string fullModNameP = parent->getModuleName(); |
| fullModNameP = StringUtils::leaf(fullModNameP); |
| if (strstr(fullModName.c_str(), "genblk")) { |
| if (fullModName == fullModNameP) |
| parent->getParent()->overrideParentChild(parent->getParent(), |
| parent, current); |
| } else { |
| if (strstr(fullModNameP.c_str(), "genblk")) |
| parent->getParent()->overrideParentChild(parent->getParent(), |
| parent, current); |
| } |
| } |
| } |
| } |
| } |