| /* |
| 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: CompileClass.cpp |
| * Author: alain |
| * |
| * Created on June 7, 2018, 10:26 PM |
| */ |
| #include "SourceCompile/VObjectTypes.h" |
| #include "Design/VObject.h" |
| #include "Library/Library.h" |
| #include "Design/Signal.h" |
| #include "Design/FileContent.h" |
| #include "Design/ClockingBlock.h" |
| #include "SourceCompile/SymbolTable.h" |
| #include "ErrorReporting/Error.h" |
| #include "ErrorReporting/Location.h" |
| #include "ErrorReporting/Error.h" |
| #include "CommandLine/CommandLineParser.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/ClassDefinition.h" |
| #include "DesignCompile/CompileClass.h" |
| |
| using namespace SURELOG; |
| |
| CompileClass::~CompileClass() {} |
| |
| int FunctorCompileClass::operator()() const { |
| CompileClass* instance = |
| new CompileClass(m_compileDesign, m_class, m_design, m_symbols, m_errors); |
| instance->compile(); |
| delete instance; |
| return true; |
| } |
| |
| bool CompileClass::compile() { |
| FileContent* fC = m_class->m_fileContents[0]; |
| NodeId nodeId = m_class->m_nodeIds[0]; |
| |
| std::string fileName = fC->getFileName(nodeId); |
| if (strstr(fileName.c_str(), "builtin.sv")) { |
| fileName = "builtin.sv"; |
| } |
| Location loc(m_symbols->registerSymbol(fileName), |
| fC->Line(nodeId), 0, |
| m_symbols->registerSymbol(m_class->getName())); |
| |
| Error err1(ErrorDefinition::COMP_COMPILE_CLASS, loc); |
| ErrorContainer* errors = new ErrorContainer(m_symbols); |
| errors->regiterCmdLine( |
| m_compileDesign->getCompiler()->getCommandLineParser()); |
| errors->addError(err1); |
| errors->printMessage( |
| err1, |
| m_compileDesign->getCompiler()->getCommandLineParser()->muteStdout()); |
| delete errors; |
| if (fC->getSize() == 0) return true; |
| |
| // Package imports |
| std::vector<FileCNodeId> pack_imports; |
| // - Local file imports |
| for (auto import : fC->getObjects(VObjectType::slPackage_import_item)) { |
| pack_imports.push_back(import); |
| } |
| // - Parent container imports |
| DesignComponent* container = m_class->getContainer(); |
| if (container) { |
| // FileCNodeId itself(container->getFileContents ()[0], |
| // container->getNodeIds ()[0]); pack_imports.push_back(itself); |
| for (auto import : |
| container->getObjects(VObjectType::slPackage_import_item)) { |
| pack_imports.push_back(import); |
| } |
| } |
| |
| for (auto pack_import : pack_imports) { |
| FileContent* pack_fC = pack_import.fC; |
| NodeId pack_id = pack_import.nodeId; |
| m_helper.importPackage(m_class, m_design, pack_fC, pack_id); |
| } |
| |
| compile_class_parameters_(fC, nodeId); |
| |
| // This |
| DataType* thisdt = |
| new DataType(fC, nodeId, "this", VObjectType::slClass_declaration); |
| thisdt->setDefinition(m_class); |
| Property* prop = new Property(thisdt, fC, nodeId, 0, "this", false, false, |
| false, false, false); |
| m_class->insertProperty(prop); |
| |
| VObject current = fC->Object(fC->getSize() - 2); |
| NodeId id = nodeId; |
| if (!id) return false; |
| std::stack<NodeId> stack; |
| stack.push(id); |
| bool inFunction_body_declaration = false; |
| bool inTask_body_declaration = false; |
| while (stack.size()) { |
| bool skipGuts = false; |
| id = stack.top(); |
| stack.pop(); |
| current = fC->Object(id); |
| VObjectType type = fC->Type(id); |
| switch (type) { |
| case VObjectType::slPackage_import_item: { |
| m_helper.importPackage(m_class, m_design, fC, id); |
| break; |
| } |
| case VObjectType::slClass_constructor_declaration: { |
| inFunction_body_declaration = true; |
| break; |
| } |
| case VObjectType::slFunction_body_declaration: { |
| inFunction_body_declaration = true; |
| break; |
| } |
| case VObjectType::slEndfunction: { |
| inFunction_body_declaration = false; |
| break; |
| } |
| case VObjectType::slTask_body_declaration: { |
| inTask_body_declaration = true; |
| break; |
| } |
| case VObjectType::slEndtask: { |
| inTask_body_declaration = false; |
| break; |
| } |
| case VObjectType::slClass_property: |
| if (inFunction_body_declaration || inTask_body_declaration) break; |
| compile_class_property_(fC, id); |
| break; |
| case VObjectType::slClass_constraint: |
| compile_class_constraint_(fC, id); |
| break; |
| case VObjectType::slClass_declaration: |
| if (id != nodeId) { |
| compile_class_declaration_(fC, id); |
| if (current.m_sibling) stack.push(current.m_sibling); |
| continue; |
| } |
| break; |
| case VObjectType::slCovergroup_declaration: |
| compile_covergroup_declaration_(fC, id); |
| break; |
| case VObjectType::slLocal_parameter_declaration: |
| compile_local_parameter_declaration_(fC, id); |
| break; |
| case VObjectType::slParameter_declaration: |
| compile_parameter_declaration_(fC, id); |
| break; |
| case VObjectType::slClass_method: |
| compile_class_method_(fC, id); |
| skipGuts = true; |
| break; |
| case VObjectType::slClass_type: |
| compile_class_type_(fC, id); |
| default: |
| break; |
| } |
| |
| if (current.m_sibling) stack.push(current.m_sibling); |
| if (!skipGuts) |
| if (current.m_child) stack.push(current.m_child); |
| } |
| |
| // Default constructor |
| DataType* returnType = new DataType(); |
| FunctionMethod* method = |
| new FunctionMethod(m_class, fC, nodeId, "new", returnType, false, false, |
| false, false, false, false); |
| method->compile(m_helper); |
| Function* prevDef = m_class->getFunction("new"); |
| if (!prevDef) { |
| m_class->insertFunction(method); |
| } |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_class_property_(FileContent* fC, NodeId id) { |
| NodeId data_declaration = fC->Child(id); |
| NodeId var_decl = fC->Child(data_declaration); |
| VObjectType type = fC->Type(data_declaration); |
| bool is_local = false; |
| bool is_static = false; |
| bool is_protected = false; |
| bool is_rand = false; |
| bool is_randc = false; |
| while ((type == VObjectType::slPropQualifier_ClassItem) || |
| (type == VObjectType::slPropQualifier_Rand) || |
| (type == VObjectType::slPropQualifier_Randc)) { |
| NodeId qualifier = fC->Child(data_declaration); |
| VObjectType qualType = fC->Type(qualifier); |
| if (qualType == VObjectType::slClassItemQualifier_Protected) |
| is_protected = true; |
| if (qualType == VObjectType::slClassItemQualifier_Static) is_static = true; |
| if (qualType == VObjectType::slClassItemQualifier_Local) is_local = true; |
| if (type == VObjectType::slPropQualifier_Rand) is_rand = true; |
| if (type == VObjectType::slPropQualifier_Randc) is_randc = true; |
| data_declaration = fC->Sibling(data_declaration); |
| type = fC->Type(data_declaration); |
| var_decl = fC->Child(data_declaration); |
| } |
| |
| if (type == VObjectType::slData_declaration) { |
| /* |
| n<A> u<3> t<StringConst> p<37> s<12> l<5> |
| n<> u<4> t<IntegerAtomType_Int> p<5> l<6> |
| n<> u<5> t<Data_type> p<9> c<4> s<8> l<6> |
| n<size> u<6> t<StringConst> p<7> l<6> |
| n<> u<7> t<Variable_decl_assignment> p<8> c<6> l<6> |
| n<> u<8> t<List_of_variable_decl_assignments> p<9> c<7> l<6> |
| n<> u<9> t<Variable_declaration> p<10> c<5> l<6> |
| n<> u<10> t<Data_declaration> p<11> c<9> l<6> |
| n<> u<11> t<Class_property> p<12> c<10> l<6> |
| n<> u<12> t<Class_item> p<37> c<11> s<35> l<6> |
| */ |
| VObjectType var_type = fC->Type(var_decl); |
| if (var_type == VObjectType::slVariable_declaration) { |
| NodeId data_type = fC->Child(var_decl); |
| NodeId node_type = fC->Child(data_type); |
| |
| VObjectType the_type = fC->Type(node_type); |
| std::string typeName; |
| if (the_type == VObjectType::slStringConst) { |
| typeName = fC->SymName(node_type); |
| } else if (the_type == VObjectType::slClass_scope) { |
| NodeId class_type = fC->Child(node_type); |
| NodeId class_name = fC->Child(class_type); |
| typeName = fC->SymName(class_name); |
| typeName += "::"; |
| NodeId symb_id = fC->Sibling(node_type); |
| typeName += fC->SymName(symb_id); |
| } else { |
| typeName = VObject::getTypeName(the_type); |
| } |
| DataType* datatype = m_class->getUsedDataType(typeName); |
| if (!datatype) { |
| DataType* type = |
| new DataType(fC, node_type, typeName, fC->Type(node_type)); |
| m_class->insertUsedDataType(typeName, type); |
| datatype = m_class->getUsedDataType(typeName); |
| } |
| |
| NodeId list_of_variable_decl_assignments = fC->Sibling(data_type); |
| NodeId variable_decl_assignment = |
| fC->Child(list_of_variable_decl_assignments); |
| while (variable_decl_assignment) { |
| NodeId var = fC->Child(variable_decl_assignment); |
| NodeId range = fC->Sibling(var); |
| std::string varName = fC->SymName(var); |
| |
| Property* previous = m_class->getProperty(varName); |
| if (previous) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(var)), |
| fC->Line(var), 0, m_symbols->registerSymbol(varName)); |
| FileContent* prevFile = previous->getFileContent(); |
| NodeId prevNode = previous->getNodeId(); |
| Location loc2( |
| m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, m_symbols->registerSymbol(varName)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PROPERTY, loc1, |
| loc2); |
| m_errors->addError(err); |
| } |
| |
| Property* prop = |
| new Property(datatype, fC, var, range, varName, is_local, is_static, |
| is_protected, is_rand, is_randc); |
| m_class->insertProperty(prop); |
| |
| variable_decl_assignment = fC->Sibling(variable_decl_assignment); |
| } |
| } else if (var_type == VObjectType::slType_declaration) { |
| compile_type_declaration_(fC, data_declaration); |
| } |
| } |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_class_method_(FileContent* fC, NodeId id) { |
| /* |
| n<> u<8> t<MethodQualifier_Virtual> p<21> s<20> l<12> |
| n<> u<9> t<Function_data_type> p<10> l<12> |
| n<> u<10> t<Function_data_type_or_implicit> p<19> c<9> s<11> l<12> |
| n<print_tree1> u<11> t<StringConst> p<19> s<17> l<12> |
| n<> u<12> t<IntegerAtomType_Int> p<13> l<12> |
| n<> u<13> t<Data_type> p<14> c<12> l<12> |
| n<> u<14> t<Data_type_or_implicit> p<16> c<13> s<15> l<12> |
| n<a> u<15> t<StringConst> p<16> l<12> |
| n<> u<16> t<Tf_port_item> p<17> c<14> l<12> |
| n<> u<17> t<Tf_port_list> p<19> c<16> s<18> l<12> |
| n<> u<18> t<Endfunction> p<19> l<14> |
| n<> u<19> t<Function_body_declaration> p<20> c<10> l<12> |
| n<> u<20> t<Function_declaration> p<21> c<19> l<12> |
| n<> u<21> t<Class_method> p<22> c<8> l<12> |
| */ |
| NodeId func_decl = fC->Child(id); |
| VObjectType func_type = fC->Type(func_decl); |
| std::string funcName; |
| std::string taskName; |
| bool is_virtual = false; |
| bool is_extern = false; |
| bool is_static = false; |
| bool is_local = false; |
| bool is_protected = false; |
| bool is_pure = false; |
| DataType* returnType = new DataType(); |
| while ((func_type == VObjectType::slMethodQualifier_Virtual) || |
| (func_type == VObjectType::slMethodQualifier_ClassItem) || |
| (func_type == VObjectType::slPure_virtual_qualifier) || |
| (func_type == VObjectType::slExtern_qualifier) || |
| (func_type == VObjectType::slClassItemQualifier_Protected)) { |
| if (func_type == VObjectType::slMethodQualifier_Virtual) { |
| is_virtual = true; |
| func_decl = fC->Sibling(func_decl); |
| func_type = fC->Type(func_decl); |
| } |
| if (func_type == VObjectType::slClassItemQualifier_Protected) { |
| is_protected = true; |
| func_decl = fC->Sibling(func_decl); |
| func_type = fC->Type(func_decl); |
| } |
| if (func_type == VObjectType::slPure_virtual_qualifier) { |
| is_virtual = true; |
| is_pure = true; |
| func_decl = fC->Sibling(func_decl); |
| func_type = fC->Type(func_decl); |
| } |
| if (func_type == VObjectType::slExtern_qualifier) { |
| is_extern = true; |
| func_decl = fC->Sibling(func_decl); |
| func_type = fC->Type(func_decl); |
| } |
| if (func_type == VObjectType::slMethodQualifier_ClassItem) { |
| NodeId qualifier = fC->Child(func_decl); |
| VObjectType type = fC->Type(qualifier); |
| if (type == VObjectType::slClassItemQualifier_Static) is_static = true; |
| if (type == VObjectType::slClassItemQualifier_Local) is_local = true; |
| if (type == VObjectType::slClassItemQualifier_Protected) |
| is_protected = true; |
| func_decl = fC->Sibling(func_decl); |
| func_type = fC->Type(func_decl); |
| } |
| } |
| if (func_type == VObjectType::slFunction_declaration) { |
| NodeId func_body_decl = fC->Child(func_decl); |
| NodeId function_data_type_or_implicit = fC->Child(func_body_decl); |
| NodeId function_data_type = fC->Child(function_data_type_or_implicit); |
| NodeId data_type = fC->Child(function_data_type); |
| NodeId type = fC->Child(data_type); |
| VObjectType the_type = fC->Type(type); |
| std::string typeName; |
| if (the_type == VObjectType::slStringConst) { |
| typeName = fC->SymName(type); |
| } else { |
| typeName = VObject::getTypeName(the_type); |
| } |
| returnType->init(fC, type, typeName, fC->Type(type)); |
| NodeId function_name = fC->Sibling(function_data_type_or_implicit); |
| funcName = fC->SymName(function_name); |
| |
| } else if (func_type == VObjectType::slTask_declaration) { |
| /* |
| n<cfg_dut> u<143> t<StringConst> p<146> s<144> l<37> |
| n<> u<144> t<Endtask> p<146> s<145> l<39> |
| n<cfg_dut> u<145> t<StringConst> p<146> l<39> |
| n<> u<146> t<Task_body_declaration> p<147> c<143> l<37> |
| n<> u<147> t<Task_declaration> p<148> c<146> l<37> |
| n<> u<148> t<Class_method> p<149> c<147> l<37> |
| */ |
| NodeId task_body_decl = fC->Child(func_decl); |
| NodeId task_name = fC->Child(task_body_decl); |
| taskName = fC->SymName(task_name); |
| } else if (func_type == VObjectType::slMethod_prototype) { |
| /* |
| n<> u<65> t<IntVec_TypeBit> p<66> l<37> |
| n<> u<66> t<Data_type> p<67> c<65> l<37> |
| n<> u<67> t<Function_data_type> p<69> c<66> s<68> l<37> |
| n<is_active> u<68> t<StringConst> p<69> l<37> |
| n<> u<69> t<Function_prototype> p<70> c<67> l<37> |
| n<> u<70> t<Method_prototype> p<71> c<69> l<37> |
| n<> u<71> t<Class_method> p<72> c<70> l<37> |
| */ |
| NodeId func_prototype = fC->Child(func_decl); |
| if (fC->Type(func_prototype) == VObjectType::slTask_prototype) { |
| NodeId task_name = fC->Child(func_prototype); |
| taskName = fC->SymName(task_name); |
| } else { |
| NodeId function_data_type = fC->Child(func_prototype); |
| NodeId data_type = fC->Child(function_data_type); |
| NodeId type = fC->Child(data_type); |
| VObjectType the_type = fC->Type(type); |
| std::string typeName; |
| if (the_type == VObjectType::slStringConst) { |
| typeName = fC->SymName(type); |
| } else { |
| typeName = VObject::getTypeName(the_type); |
| } |
| returnType->init(fC, type, typeName, fC->Type(type)); |
| NodeId function_name = fC->Sibling(function_data_type); |
| funcName = fC->SymName(function_name); |
| } |
| is_extern = true; |
| } else if (func_type == VObjectType::slClass_constructor_declaration) { |
| funcName = "new"; |
| returnType->init(fC, 0, "void", VObjectType::slNoType); |
| } else if (func_type == VObjectType::slClass_constructor_prototype) { |
| funcName = "new"; |
| } else { |
| funcName = "UNRECOGNIZED_METHOD_TYPE"; |
| } |
| if (taskName != "") { |
| TaskMethod* method = new TaskMethod(m_class, fC, id, taskName, is_extern); |
| method->compile(m_helper); |
| TaskMethod* prevDef = m_class->getTask(taskName); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(id)), |
| fC->Line(id), 0, m_symbols->registerSymbol(taskName)); |
| FileContent* prevFile = prevDef->getFileContent(); |
| NodeId prevNode = prevDef->getNodeId(); |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(taskName)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_TASK, loc1, loc2); |
| m_errors->addError(err); |
| } |
| m_class->insertTask(method); |
| } else { |
| FunctionMethod* method = new FunctionMethod( |
| m_class, fC, id, funcName, returnType, is_virtual, is_extern, is_static, |
| is_local, is_protected, is_pure); |
| Variable* variable = new Variable(returnType, fC, id, 0, funcName); |
| method->addVariable(variable); |
| method->compile(m_helper); |
| Function* prevDef = m_class->getFunction(funcName); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(id)), |
| fC->Line(id), 0, m_symbols->registerSymbol(funcName)); |
| FileContent* prevFile = prevDef->getFileContent(); |
| NodeId prevNode = prevDef->getNodeId(); |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(funcName)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_FUNCTION, loc1, loc2); |
| m_errors->addError(err); |
| } |
| m_class->insertFunction(method); |
| } |
| return true; |
| } |
| |
| bool CompileClass::compile_class_constraint_(FileContent* fC, |
| NodeId class_constraint) { |
| NodeId constraint_prototype = fC->Child(class_constraint); |
| NodeId constraint_name = fC->Child(constraint_prototype); |
| std::string constName = fC->SymName(constraint_name); |
| Constraint* prevDef = m_class->getConstraint(constName); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(class_constraint)), |
| fC->Line(class_constraint), 0, |
| m_symbols->registerSymbol(constName)); |
| FileContent* prevFile = prevDef->getFileContent(); |
| NodeId prevNode = prevDef->getNodeId(); |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(constName)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_CONSTRAINT, loc1, loc2); |
| m_errors->addError(err); |
| } |
| Constraint* constraint = new Constraint(fC, class_constraint, constName); |
| m_class->insertConstraint(constraint); |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_type_declaration_(FileContent* fC, NodeId id) { |
| /* |
| n<> u<8> t<IntegerAtomType_Int> p<9> l<3> |
| n<> u<9> t<Data_type> p<11> c<8> s<10> l<3> |
| n<my_int> u<10> t<StringConst> p<11> l<3> |
| n<> u<11> t<Type_declaration> p<12> c<9> l<3> |
| n<> u<12> t<Data_declaration> p<13> c<11> l<3> |
| n<> u<13> t<Class_property> p<14> c<12> l<3> |
| */ |
| m_helper.compileTypeDef(m_class, fC, id); |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_class_declaration_(FileContent* fC, NodeId id) { |
| NodeId class_name_id = fC->Child(id); |
| std::string class_name = |
| m_class->getName() + "::" + fC->SymName(class_name_id); |
| ClassDefinition* prevDef = m_class->getClass(class_name); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(class_name_id)), |
| fC->Line(class_name_id), 0, |
| m_symbols->registerSymbol(class_name)); |
| FileContent* prevFile = prevDef->getFileContent(); |
| NodeId prevNode = prevDef->getNodeId(); |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(class_name)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_INNER_CLASS, loc1, loc2); |
| m_errors->addError(err); |
| } |
| |
| ClassDefinition* the_class = |
| new ClassDefinition(class_name, m_class->getLibrary(), |
| m_class->getContainer(), fC, class_name_id, m_class); |
| m_class->insertClass(the_class); |
| |
| CompileClass* instance = new CompileClass(m_compileDesign, the_class, |
| m_design, m_symbols, m_errors); |
| instance->compile(); |
| delete instance; |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_covergroup_declaration_(FileContent* fC, NodeId id) { |
| NodeId covergroup_name = fC->Child(id); |
| std::string covergroupName = fC->SymName(covergroup_name); |
| CoverGroupDefinition* prevDef = m_class->getCoverGroup(covergroupName); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(covergroup_name)), |
| fC->Line(covergroup_name), 0, |
| m_symbols->registerSymbol(covergroupName)); |
| FileContent* prevFile = prevDef->getFileContent(); |
| NodeId prevNode = prevDef->getNodeId(); |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(covergroupName)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_COVERGROUP, loc1, loc2); |
| m_errors->addError(err); |
| } |
| CoverGroupDefinition* covergroup = |
| new CoverGroupDefinition(fC, id, covergroupName); |
| m_class->insertCoverGroup(covergroup); |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_local_parameter_declaration_(FileContent* fC, |
| NodeId id) { |
| /* |
| n<> u<8> t<IntegerAtomType_Int> p<9> l<3> |
| n<> u<9> t<Data_type> p<10> c<8> l<3> |
| n<> u<10> t<Data_type_or_implicit> p<20> c<9> s<19> l<3> |
| n<FOO> u<11> t<StringConst> p<18> s<17> l<3> |
| n<3> u<12> t<IntConst> p<13> l<3> |
| n<> u<13> t<Primary_literal> p<14> c<12> l<3> |
| n<> u<14> t<Constant_primary> p<15> c<13> l<3> |
| n<> u<15> t<Constant_expression> p<16> c<14> l<3> |
| n<> u<16> t<Constant_mintypmax_expression> p<17> c<15> l<3> |
| n<> u<17> t<Constant_param_expression> p<18> c<16> l<3> |
| n<> u<18> t<Param_assignment> p<19> c<11> l<3> |
| n<> u<19> t<List_of_param_assignments> p<20> c<18> l<3> |
| n<> u<20> t<Local_parameter_declaration> p<21> c<10> l<3> |
| */ |
| |
| NodeId data_type_or_implicit = fC->Child(id); |
| NodeId list_of_param_assignments = fC->Sibling(data_type_or_implicit); |
| NodeId param_assignment = fC->Child(list_of_param_assignments); |
| while (param_assignment) { |
| NodeId var = fC->Child(param_assignment); |
| std::string name = fC->SymName(var); |
| std::pair<FileCNodeId, DesignComponent*>* prevDef = |
| m_class->getNamedObject(name); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(var)), |
| fC->Line(var), 0, m_symbols->registerSymbol(name)); |
| FileContent* prevFile = prevDef->first.fC; |
| NodeId prevNode = prevDef->first.nodeId; |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(name)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PARAMETER, loc1, loc2); |
| m_errors->addError(err); |
| } |
| |
| FileCNodeId fnid(fC, id); |
| m_class->addObject(VObjectType::slLocal_parameter_declaration, fnid); |
| m_class->addNamedObject(name, fnid, NULL); |
| |
| param_assignment = fC->Sibling(param_assignment); |
| } |
| return true; |
| } |
| |
| bool CompileClass::compile_parameter_declaration_(FileContent* fC, NodeId id) { |
| NodeId data_type_or_implicit = fC->Child(id); |
| NodeId list_of_param_assignments = fC->Sibling(data_type_or_implicit); |
| NodeId param_assignment = fC->Child(list_of_param_assignments); |
| while (param_assignment) { |
| NodeId var = fC->Child(param_assignment); |
| std::string name = fC->SymName(var); |
| std::pair<FileCNodeId, DesignComponent*>* prevDef = |
| m_class->getNamedObject(name); |
| if (prevDef) { |
| Location loc1(m_symbols->registerSymbol(fC->getFileName(var)), |
| fC->Line(var), 0, m_symbols->registerSymbol(name)); |
| FileContent* prevFile = prevDef->first.fC; |
| NodeId prevNode = prevDef->first.nodeId; |
| Location loc2(m_symbols->registerSymbol(prevFile->getFileName(prevNode)), |
| prevFile->Line(prevNode), 0, |
| m_symbols->registerSymbol(name)); |
| Error err(ErrorDefinition::COMP_MULTIPLY_DEFINED_PARAMETER, loc1, loc2); |
| m_errors->addError(err); |
| } |
| |
| FileCNodeId fnid(fC, id); |
| m_class->addObject(VObjectType::slLocal_parameter_declaration, fnid); |
| m_class->addNamedObject(name, fnid, NULL); |
| |
| param_assignment = fC->Sibling(param_assignment); |
| } |
| return true; |
| } |
| |
| bool CompileClass::compile_class_type_(FileContent* fC, NodeId id) { |
| NodeId parent = fC->Parent(id); |
| VObjectType ptype = fC->Type(parent); |
| if (ptype != VObjectType::slClass_declaration) return true; |
| NodeId base_class_id = fC->Child(id); |
| std::string base_class_name = fC->SymName(base_class_id); |
| while (fC->Sibling(base_class_id) && |
| (fC->Type(fC->Sibling(base_class_id)) == VObjectType::slStringConst)) { |
| base_class_id = fC->Sibling(base_class_id); |
| base_class_name += "::" + fC->SymName(base_class_id); |
| } |
| // Insert base class placeholder |
| // Will be bound in UVMElaboration step |
| ClassDefinition* base_class = |
| new ClassDefinition(base_class_name, m_class->getLibrary(), |
| m_class->getContainer(), fC, base_class_id, NULL); |
| m_class->insertBaseClass(base_class); |
| |
| return true; |
| } |
| |
| bool CompileClass::compile_class_parameters_(FileContent* fC, NodeId id) { |
| /* |
| n<all_c> u<1> t<StringConst> p<16> s<14> l<3> |
| n<uvm_port_base> u<2> t<StringConst> p<12> s<8> l<7> |
| n<IF> u<3> t<StringConst> p<6> s<5> l<7> |
| n<uvm_void> u<4> t<StringConst> p<5> l<7> |
| n<> u<5> t<Data_type> p<6> c<4> l<7> |
| n<> u<6> t<List_of_type_assignments> p<7> c<3> l<7> |
| n<> u<7> t<Parameter_port_declaration> p<8> c<6> l<7> |
| n<> u<8> t<Parameter_port_list> p<12> c<7> s<10> l<7> |
| n<IF> u<9> t<StringConst> p<10> l<7> |
| n<> u<10> t<Class_type> p<12> c<9> s<11> l<7> |
| n<> u<11> t<Endclass> p<12> l<8> |
| n<> u<12> t<Class_declaration> p<13> c<2> l<7> |
| |
| or |
| |
| n<T1> u<3> t<StringConst> p<9> s<5> l<18> |
| n<> u<4> t<IntegerAtomType_Int> p<5> l<18> |
| n<> u<5> t<Data_type> p<9> c<4> s<6> l<18> |
| n<T2> u<6> t<StringConst> p<9> s<8> l<18> |
| n<T1> u<7> t<StringConst> p<8> l<18> |
| n<> u<8> t<Data_type> p<9> c<7> l<18> |
| n<> u<9> t<List_of_type_assignments> p<10> c<3> l<18> |
| n<> u<10> t<Parameter_port_declaration> p<11> c<9> l<18> |
| n<> u<11> t<Parameter_port_list> p<31> c<10> s<20> l<18> |
| |
| */ |
| |
| NodeId className = fC->Child(id); |
| NodeId paramList = fC->Sibling(className); |
| if (fC->Type(paramList) == VObjectType::slParameter_port_list) { |
| NodeId parameter_port_declaration = fC->Child(paramList); |
| while (parameter_port_declaration) { |
| NodeId list_of_type_assignments = fC->Child(parameter_port_declaration); |
| NodeId typeNameId = fC->Child(list_of_type_assignments); |
| while (typeNameId) { |
| NodeId ntype = fC->Sibling(typeNameId); |
| bool skip = false; |
| if (ntype && fC->Type(ntype) == VObjectType::slData_type) { |
| ntype = fC->Child(ntype); |
| skip = true; |
| } else { |
| ntype = 0; |
| } |
| Parameter* param = |
| new Parameter(fC, typeNameId, fC->SymName(typeNameId), ntype); |
| m_class->insertParameter(param); |
| typeNameId = fC->Sibling(typeNameId); |
| if (skip) typeNameId = fC->Sibling(typeNameId); |
| } |
| parameter_port_declaration = fC->Sibling(parameter_port_declaration); |
| } |
| } |
| return true; |
| } |