| /* | |
| 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.hpp" | |
| #include "../SourceCompile/CompilationUnit.h" | |
| #include "../SourceCompile/PreprocessFile.h" | |
| #include "../SourceCompile/CompileSourceFile.h" | |
| #include "../SourceCompile/ParseFile.h" | |
| #include "../SourceCompile/Compiler.h" | |
| #include "CompileDesign.h" | |
| #include "../Testbench/Property.h" | |
| #include "../Design/Function.h" | |
| #include "../Testbench/ClassDefinition.h" | |
| #include "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); | |
| } | |
| } | |
| } | |
| } | |
| } |