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