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