| /* | |
| 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.hpp" | |
| #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 "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; | |
| } |