| /* |
| 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: TestbenchElaboration.cpp |
| * Author: alain |
| * |
| * Created on February 6, 2019, 9:01 PM |
| */ |
| |
| #include <queue> |
| |
| #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 "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/TestbenchElaboration.h" |
| |
| using namespace SURELOG; |
| |
| TestbenchElaboration::~TestbenchElaboration() {} |
| |
| bool TestbenchElaboration::bindTypedefs_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Design* design = compiler->getDesign(); |
| |
| std::vector<std::pair<TypeDef*, DesignComponent*>> defs; |
| |
| for (auto file : design->getAllFileContents()) { |
| FileContent* fC = file.second; |
| for (auto typed : fC->getTypeDefMap()) { |
| TypeDef* typd = typed.second; |
| defs.push_back(std::make_pair(typd, fC)); |
| } |
| } |
| |
| for (auto package : design->getPackageDefinitions()) { |
| Package* pack = package.second; |
| for (auto typed : pack->getTypeDefMap()) { |
| TypeDef* typd = typed.second; |
| defs.push_back(std::make_pair(typd, pack)); |
| } |
| } |
| |
| for (auto program_def : design->getProgramDefinitions()) { |
| Program* program = program_def.second; |
| for (auto typed : program->getTypeDefMap()) { |
| TypeDef* typd = typed.second; |
| defs.push_back(std::make_pair(typd, program)); |
| } |
| } |
| |
| for (auto class_def : design->getClassDefinitions()) { |
| ClassDefinition* classp = class_def.second; |
| for (auto typed : classp->getTypeDefMap()) { |
| TypeDef* typd = typed.second; |
| defs.push_back(std::make_pair(typd, classp)); |
| } |
| } |
| |
| for (auto def : defs) { |
| TypeDef* typd = def.first; |
| DesignComponent* comp = def.second; |
| if (typd->getDefinition() == NULL) { |
| DataType* def = |
| bindTypeDef_(typd, comp, ErrorDefinition::NO_ERROR_MESSAGE); |
| if (def && (typd != def)) { |
| typd->setDefinition(def); |
| } else { |
| FileContent* fC = typd->getFileContent(); |
| NodeId id = typd->getNodeId(); |
| std::string fileName = fC->getFileName(id); |
| unsigned int line = fC->Line(id); |
| std::string definition_string; |
| NodeId defNode = typd->getDefinitionNode(); |
| VObjectType defType = fC->Type(defNode); |
| if (defType == VObjectType::slStringConst) { |
| definition_string = fC->SymName(defNode); |
| } |
| Location loc1(symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol(definition_string)); |
| Error err1(ErrorDefinition::COMP_UNDEFINED_TYPE, loc1); |
| errors->addError(err1); |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| bool checkValidFunction(DataType* dtype, std::string function, Statement* stmt, |
| Design* design, std::string& datatypeName) { |
| bool validFunction = true; |
| VObjectType type = dtype->getType(); |
| DataType* def = dtype->getDefinition(); |
| if (type == VObjectType::slClass_declaration) { |
| ClassDefinition* the_class = dynamic_cast<ClassDefinition*>(dtype); |
| if (the_class) { |
| Function* func = the_class->getFunction(function); |
| if (func) |
| stmt->setFunction(func); |
| else |
| validFunction = false; |
| } else { |
| the_class = dynamic_cast<ClassDefinition*>(def); |
| if (the_class) { |
| Function* func = the_class->getFunction(function); |
| if (func) |
| stmt->setFunction(func); |
| else |
| validFunction = false; |
| } |
| } |
| } else if (dtype->isString_type(type)) { |
| ClassDefinition* array = design->getClassDefinition("builtin::string"); |
| Function* func = array->getFunction(function); |
| if (func) |
| stmt->setFunction(func); |
| else { |
| datatypeName = "string"; |
| validFunction = false; |
| } |
| } else |
| validFunction = false; |
| return validFunction; |
| } |
| |
| bool checkValidBuiltinClass_(std::string classname, std::string function, |
| Statement* stmt, Design* design, |
| std::string& datatypeName) { |
| bool validFunction = true; |
| ClassDefinition* array = design->getClassDefinition("builtin::" + classname); |
| Function* func = array->getFunction(function); |
| if (func) |
| stmt->setFunction(func); |
| else { |
| datatypeName = classname; |
| validFunction = false; |
| } |
| return validFunction; |
| } |
| |
| void computeVarChain(FileContent* fC, NodeId nodeId, |
| std::vector<std::string>& var_chain) { |
| while (nodeId) { |
| VObjectType type = fC->Type(nodeId); |
| switch (type) { |
| case VObjectType::slStringConst: { |
| var_chain.push_back(fC->SymName(nodeId)); |
| break; |
| } |
| case VObjectType::slImplicit_class_handle: { |
| NodeId child = fC->Child(nodeId); |
| VObjectType childType = fC->Type(child); |
| if (childType == VObjectType::slThis_keyword) |
| var_chain.push_back("this"); |
| else if (childType == VObjectType::slSuper_keyword) |
| var_chain.push_back("super"); |
| else |
| var_chain.push_back("UNKNOWN_TYPE"); |
| break; |
| } |
| default: |
| var_chain.push_back("UNKNOWN_NAME"); |
| break; |
| } |
| nodeId = fC->Sibling(nodeId); |
| } |
| } |
| |
| bool TestbenchElaboration::bindClasses_() { |
| checkForMultipleDefinition_(); |
| bindBaseClasses_(); |
| bindDataTypes_(); |
| bindFunctions_(); |
| bindTasks_(); |
| return true; |
| } |
| |
| bool TestbenchElaboration::checkForMultipleDefinition_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Check for multiple definition |
| std::string prevClassName = ""; |
| ClassDefinition* prevClassDefinition = NULL; |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| bool done = false; |
| if (className == prevClassName) { |
| FileContent* fC1 = classDefinition->getFileContents()[0]; |
| NodeId nodeId1 = classDefinition->getNodeIds()[0]; |
| std::string fileName1 = fC1->getFileName(nodeId1); |
| unsigned int line1 = fC1->Line(nodeId1); |
| Location loc1(symbols->registerSymbol(fileName1), line1, 0, |
| symbols->registerSymbol(className)); |
| |
| std::vector<Location> locations; |
| |
| while (1) { |
| FileContent* fC2 = prevClassDefinition->getFileContents()[0]; |
| NodeId nodeId2 = prevClassDefinition->getNodeIds()[0]; |
| std::string fileName2 = fC2->getFileName(nodeId2); |
| unsigned int line2 = fC2->Line(nodeId2); |
| Location loc2(symbols->registerSymbol(fileName2), line2, 0, |
| symbols->registerSymbol(className)); |
| |
| if ((fileName1 != fileName2) || (line1 != line2)) { |
| std::string diff; |
| if (fC1->diffTree(diff, nodeId1, fC2, nodeId2)) { |
| locations.push_back(loc2); |
| } |
| } |
| |
| itr++; |
| if (itr == classes.end()) { |
| done = true; |
| break; |
| } else { |
| std::string nextClassName = (*itr).first; |
| ClassDefinition* nextClassDefinition = (*itr).second; |
| prevClassName = nextClassName; |
| prevClassDefinition = nextClassDefinition; |
| if (prevClassName != className) { |
| className = prevClassName; |
| classDefinition = prevClassDefinition; |
| break; |
| } |
| } |
| } |
| |
| if (locations.size()) { |
| Error err1(ErrorDefinition::COMP_MULTIPLY_DEFINED_CLASS, loc1, |
| &locations); |
| errors->addError(err1); |
| } |
| } |
| prevClassName = className; |
| prevClassDefinition = classDefinition; |
| if (done) break; |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindBaseClasses_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Bind base classes |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| for (auto& class_def : classDefinition->getBaseClassMap()) { |
| DataType* the_def = |
| bindDataType_(class_def.first, class_def.second->getFileContent(), |
| class_def.second->getNodeId(), classDefinition, |
| ErrorDefinition::COMP_UNDEFINED_BASE_CLASS); |
| class_def.second = dynamic_cast<ClassDefinition*>(the_def); |
| if (class_def.second) { |
| // Super |
| DataType* thisdt = new DataType( |
| class_def.second->getFileContent(), class_def.second->getNodeId(), |
| class_def.second->getName(), VObjectType::slClass_declaration); |
| thisdt->setDefinition(class_def.second); |
| Property* prop = new Property(thisdt, classDefinition->getFileContent(), |
| classDefinition->getNodeId(), 0, "super", |
| false, false, false, false, false); |
| classDefinition->insertProperty(prop); |
| } else { |
| class_def.second = dynamic_cast<Parameter*>(the_def); |
| if (class_def.second) { |
| // Super |
| DataType* thisdt = new DataType( |
| class_def.second->getFileContent(), class_def.second->getNodeId(), |
| class_def.second->getName(), VObjectType::slClass_declaration); |
| thisdt->setDefinition(class_def.second); |
| Property* prop = |
| new Property(thisdt, classDefinition->getFileContent(), |
| classDefinition->getNodeId(), 0, "super", false, |
| false, false, false, false); |
| classDefinition->insertProperty(prop); |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindDataTypes_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Bind data types |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| |
| for (auto& datatype : classDefinition->getUsedDataTypeMap()) { |
| std::string dataTypeName = datatype.first; |
| DataType* dtype = datatype.second; |
| if (dtype->getDefinition()) continue; |
| VObjectType type = dtype->getType(); |
| if (type == VObjectType::slStringConst || |
| type == VObjectType::slNull_rule || |
| type == VObjectType::slClass_scope) { |
| DataType* the_def = bindDataType_(dataTypeName, dtype->getFileContent(), |
| dtype->getNodeId(), classDefinition, |
| ErrorDefinition::COMP_UNDEFINED_TYPE); |
| if (the_def != dtype) dtype->setDefinition(the_def); |
| } |
| } |
| for (auto& func : classDefinition->getFunctionMap()) { |
| for (auto& datatype : func.second->getUsedDataTypeMap()) { |
| std::string dataTypeName = datatype.first; |
| DataType* dtype = datatype.second; |
| if (dtype->getDefinition()) continue; |
| VObjectType type = dtype->getType(); |
| if (type == VObjectType::slStringConst || |
| type == VObjectType::slNull_rule || |
| type == VObjectType::slClass_scope) { |
| DataType* the_def = bindDataType_( |
| dataTypeName, dtype->getFileContent(), dtype->getNodeId(), |
| classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE); |
| if (the_def != dtype) dtype->setDefinition(the_def); |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindFunctions_() { |
| bindFunctionReturnTypesAndParamaters_(); |
| bindFunctionBodies_(); |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindFunctionReturnTypesAndParamaters_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Bind Function return values, parameters and body |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| for (auto& func : classDefinition->getFunctionMap()) { |
| DataType* dtype = func.second->getReturnType(); |
| std::string dataTypeName = dtype->getName(); |
| if (dtype->getDefinition()) continue; |
| if (dtype->getFileContent() == NULL) continue; |
| if (dtype->getType() == VObjectType::slStringConst) { |
| DataType* the_def = bindDataType_( |
| dataTypeName, dtype->getFileContent(), func.second->getNodeId(), |
| classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE); |
| if (the_def != dtype) dtype->setDefinition(the_def); |
| } |
| for (auto& param : func.second->getParams()) { |
| DataType* dtype = param->getDataType(); |
| std::string dataTypeName = dtype->getName(); |
| if (dtype->getDefinition()) continue; |
| if (dtype->getFileContent() == NULL) continue; |
| if (dtype->getType() == VObjectType::slStringConst) { |
| DataType* the_def = bindDataType_( |
| dataTypeName, dtype->getFileContent(), param->getNodeId(), |
| classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE); |
| if (the_def != dtype) dtype->setDefinition(the_def); |
| if (the_def && the_def->isParameter()) continue; |
| Value* value = param->getDefault(); |
| if (value) { |
| if (!dtype->isCompatible(value)) { |
| std::string name = param->getName(); |
| std::string typeName = dtype->getName(); |
| NodeId p = param->getNodeId(); |
| FileContent* fC = dtype->getFileContent(); |
| std::string fileName = fC->getFileName(p); |
| unsigned int line = fC->Line(p); |
| Location loc1( |
| symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol(name + " of type " + typeName)); |
| std::string exp; |
| if (value->getType() == Value::Type::String) |
| exp = value->getValueS(); |
| else if (value->getType() == Value::Type::Double) |
| exp = std::to_string(value->getValueD(0)); |
| else |
| exp = std::to_string(value->getValueL(0)); |
| Location loc2(0, 0, 0, symbols->registerSymbol(exp)); |
| Error err1(ErrorDefinition::COMP_INCOMPATIBLE_TYPES, loc1, loc2); |
| errors->addError(err1); |
| } |
| } |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindSubRoutineCall_(ClassDefinition* classDefinition, |
| Statement* stmt, Design* design, |
| SymbolTable* symbols, |
| ErrorContainer* errors) { |
| std::string datatypeName; |
| SubRoutineCallStmt* st = dynamic_cast<SubRoutineCallStmt*>(stmt); |
| std::vector<std::string> var_chain = st->getVarChainNames(); |
| std::string function = st->getFunc(); |
| bool validFunction = true; |
| DataType* dtype = NULL; |
| Variable* the_obj = NULL; |
| if (st->isStatic()) |
| the_obj = locateStaticVariable_( |
| var_chain, st->getFileContent(), st->getNodeId(), stmt->getScope(), |
| classDefinition, ErrorDefinition::ELAB_UNDEF_VARIABLE); |
| else |
| the_obj = locateVariable_(var_chain, st->getFileContent(), st->getNodeId(), |
| stmt->getScope(), classDefinition, |
| ErrorDefinition::ELAB_UNDEF_VARIABLE); |
| |
| if (the_obj) { |
| dtype = the_obj->getDataType(); |
| if (dtype == NULL) return true; |
| VObjectType type = dtype->getType(); |
| DataType* def = dtype->getDefinition(); |
| |
| if (type == VObjectType::slClass_declaration) { |
| validFunction = |
| checkValidFunction(dtype, function, stmt, design, datatypeName); |
| } else if (dtype->isNumber(type) || dtype->isInteger_type(type) || |
| dtype->isNon_integer_type(type) || dtype->isString_type(type)) { |
| if (def) { |
| type = def->getType(); |
| dtype = def; |
| } |
| |
| NodeId range = the_obj->getRange(); |
| if (range) { |
| VObjectType rangeType = the_obj->getFileContent()->Type(range); |
| |
| if (rangeType == VObjectType::slUnsized_dimension) { |
| // Vector |
| validFunction = checkValidBuiltinClass_("array", function, stmt, |
| design, datatypeName); |
| } else if (rangeType == VObjectType::slVariable_dimension) { |
| FileContent* sfC = the_obj->getFileContent(); |
| NodeId subRange = sfC->Child(range); |
| VObjectType the_type = sfC->Type(subRange); |
| if (the_type == VObjectType::slQueue_dimension) { |
| // Queue |
| |
| // foreach (darray[id]) darray[id].func() |
| NodeId tmp = stmt->getNodeId(); |
| tmp = sfC->Child(tmp); |
| tmp = sfC->Sibling(tmp); |
| VObjectType t = sfC->Type(tmp); |
| if ((t == VObjectType::slConstant_bit_select) && sfC->Child(tmp)) { |
| // there is an actual array index |
| if (type == VObjectType::slClass_declaration) { |
| validFunction = checkValidFunction(dtype, function, stmt, |
| design, datatypeName); |
| } |
| } else { |
| validFunction = checkValidBuiltinClass_("queue", function, stmt, |
| design, datatypeName); |
| } |
| } else if (the_type == VObjectType::slUnpacked_dimension) { |
| // foreach (darray[id]) darray[id].func() |
| NodeId subroutine_call = stmt->getNodeId(); |
| NodeId var_id = sfC->Child(subroutine_call); |
| NodeId constant_bit_select = sfC->Sibling(var_id); |
| VObjectType t = sfC->Type(constant_bit_select); |
| NodeId select_id = sfC->Child(constant_bit_select); |
| if ((t == VObjectType::slConstant_bit_select) && select_id) { |
| validFunction = checkValidFunction(dtype, function, stmt, design, |
| datatypeName); |
| } else { |
| validFunction = checkValidBuiltinClass_("queue", function, stmt, |
| design, datatypeName); |
| } |
| } |
| } |
| } else { |
| validFunction = |
| checkValidFunction(dtype, function, stmt, design, datatypeName); |
| } |
| } |
| } |
| if (var_chain.size() == 0) { |
| if (st->isSystemCall()) { |
| validFunction = checkValidBuiltinClass_("system", function, stmt, design, |
| datatypeName); |
| if (!validFunction) { |
| FileContent* fC = st->getFileContent(); |
| NodeId p = st->getNodeId(); |
| std::string fileName = fC->getFileName(p); |
| unsigned int line = fC->Line(p); |
| Location loc1(symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol(function)); |
| Error err1(ErrorDefinition::COMP_UNDEFINED_SYSTEM_FUNCTION, loc1); |
| errors->addError(err1); |
| return true; |
| } |
| } else { |
| Function* func = classDefinition->getFunction(function); |
| if (func) |
| stmt->setFunction(func); |
| else { |
| validFunction = false; |
| dtype = classDefinition; |
| } |
| } |
| } |
| |
| if (validFunction == false) { |
| if (dtype->isParameter()) { |
| return true; |
| } |
| std::string name; |
| for (auto v : var_chain) name += v + "."; |
| if (name.size()) name = name.substr(0, name.size() - 1); |
| while (dtype && dtype->getDefinition()) { |
| dtype = dtype->getDefinition(); |
| } |
| if (name == "") { |
| name = "this"; |
| } |
| std::string typeName = dtype->getName(); |
| if (datatypeName != "") typeName = datatypeName; |
| NodeId p = st->getNodeId(); |
| FileContent* fC = st->getFileContent(); |
| std::string fileName = fC->getFileName(p); |
| unsigned int line = fC->Line(p); |
| Location loc1( |
| symbols->registerSymbol(fileName), line, 0, |
| symbols->registerSymbol("\"" + name + "\"" + " of type " + typeName)); |
| FileContent* fC2 = dtype->getFileContent(); |
| std::string fileName2 = fC2->getFileName(dtype->getNodeId()); |
| unsigned int line2 = fC2->Line(dtype->getNodeId()); |
| Location loc2(symbols->registerSymbol(fileName2), line2, 0, |
| symbols->registerSymbol(function)); |
| Error err1(ErrorDefinition::COMP_NO_METHOD_FOR_TYPE, loc1, loc2); |
| errors->addError(err1); |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindForLoop_(ClassDefinition* classDefinition, |
| Statement* stmt, ForLoopStmt* st) { |
| FileContent* sfC = st->getFileContent(); |
| NodeId fid = st->getNodeId(); |
| VObjectType itr_type = st->getIteratorType(); |
| DataType* itrDataType = new DataType(sfC, fid, "integer", itr_type); |
| for (auto itrId : st->getIteratorIds()) { |
| Variable* var = new Variable(itrDataType, sfC, itrId.first, 0, |
| sfC->SymName(itrId.first)); |
| st->getParentScope()->addVariable(var); |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindForeachLoop_(ClassDefinition* classDefinition, |
| Statement* stmt, |
| ForeachLoopStmt* st) { |
| NodeId arrayId = st->getArrayId(); |
| FileContent* sfC = st->getFileContent(); |
| std::vector<std::string> var_chain; |
| computeVarChain(sfC, arrayId, var_chain); |
| Variable* arrayVar = |
| locateVariable_(var_chain, sfC, arrayId, stmt->getScope(), |
| classDefinition, ErrorDefinition::ELAB_UNDEF_VARIABLE); |
| if (arrayVar) { |
| NodeId range = arrayVar->getRange(); |
| NodeId rangeTypeId = range; |
| DataType* itrDataType = NULL; |
| while (range) { |
| rangeTypeId = range; |
| range = sfC->Child(rangeTypeId); |
| } |
| VObjectType rangeType = sfC->Type(rangeTypeId); |
| if (rangeType == VObjectType::slStringConst) { |
| std::string dataTypeName = sfC->SymName(rangeTypeId); |
| itrDataType = |
| bindDataType_(dataTypeName, sfC, rangeTypeId, classDefinition, |
| ErrorDefinition::COMP_UNDEFINED_TYPE); |
| } else if (rangeType == VObjectType::slAssociative_dimension || |
| rangeType == VObjectType::slQueue_dimension) { |
| // Integer Type |
| itrDataType = new DataType(sfC, arrayId, "integer", |
| VObjectType::slIntegerAtomType_Int); |
| } |
| |
| for (auto itrId : st->getIteratorIds()) { |
| Variable* var = |
| new Variable(itrDataType, sfC, itrId, 0, sfC->SymName(itrId)); |
| st->getParentScope()->addVariable(var); |
| } |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindFunctionBodies_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| ErrorContainer* errors = compiler->getErrorContainer(); |
| SymbolTable* symbols = compiler->getSymbolTable(); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Bind Function return values, parameters and body |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| for (auto& func : classDefinition->getFunctionMap()) { |
| // Skip binding of parameterized classes |
| if (!classDefinition->hasCompleteBaseSpecification()) continue; |
| |
| std::queue<Statement*> stmts; |
| for (Statement* stmt : func.second->getStmts()) stmts.push(stmt); |
| |
| while (stmts.size()) { |
| Statement* stmt = stmts.front(); |
| stmts.pop(); |
| for (Statement* stmt1 : stmt->getStatements()) stmts.push(stmt1); |
| VObjectType stmt_type = stmt->getType(); |
| switch (stmt_type) { |
| case VObjectType::slPs_or_hierarchical_array_identifier: { |
| // Foreach loop |
| ForeachLoopStmt* st = dynamic_cast<ForeachLoopStmt*>(stmt); |
| if (st) { |
| bindForeachLoop_(classDefinition, stmt, st); |
| } |
| break; |
| } |
| case VObjectType::slFor_initialization: { |
| // For loop |
| ForLoopStmt* st = dynamic_cast<ForLoopStmt*>(stmt); |
| if (st) { |
| bindForLoop_(classDefinition, stmt, st); |
| } |
| break; |
| } |
| case VObjectType::slSubroutine_call_statement: |
| bindSubRoutineCall_(classDefinition, stmt, design, symbols, errors); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| bool TestbenchElaboration::bindTasks_() { |
| Compiler* compiler = m_compileDesign->getCompiler(); |
| // ErrorContainer* errors = compiler->getErrorContainer (); |
| // SymbolTable* symbols = compiler->getSymbolTable (); |
| Design* design = compiler->getDesign(); |
| ClassNameClassDefinitionMultiMap classes = design->getClassDefinitions(); |
| |
| // Bind Tasks parameters and body |
| for (ClassNameClassDefinitionMultiMap::iterator itr = classes.begin(); |
| itr != classes.end(); itr++) { |
| std::string className = (*itr).first; |
| ClassDefinition* classDefinition = (*itr).second; |
| |
| // Bind Tasks parameters |
| for (auto& func : classDefinition->getTaskMap()) { |
| for (auto param : func.second->getParams()) { |
| DataType* dtype = param->getDataType(); |
| std::string dataTypeName = dtype->getName(); |
| if (dtype->getDefinition()) continue; |
| if (dtype->getFileContent() == NULL) continue; |
| if (dtype->getType() == VObjectType::slStringConst) { |
| DataType* the_def = bindDataType_( |
| dataTypeName, dtype->getFileContent(), param->getNodeId(), |
| classDefinition, ErrorDefinition::COMP_UNDEFINED_TYPE); |
| if (the_def != dtype) dtype->setDefinition(the_def); |
| } |
| } |
| } |
| } |
| return true; |
| } |