| /* | |
| 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: CompileModule.cpp | |
| * Author: alain | |
| * | |
| * Created on March 22, 2018, 9:43 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 "../Testbench/ClassDefinition.h" | |
| #include "CompileHelper.h" | |
| #include "CompileDesign.h" | |
| #include "CompileModule.h" | |
| using namespace SURELOG; | |
| CompileModule::~CompileModule() {} | |
| int FunctorCompileModule::operator()() const { | |
| CompileModule* instance = new CompileModule(m_compileDesign, m_module, | |
| m_design, m_symbols, m_errors); | |
| instance->compile(); | |
| delete instance; | |
| return true; | |
| } | |
| bool CompileModule::compile() { | |
| FileContent* fC = m_module->m_fileContents[0]; | |
| NodeId nodeId = m_module->m_nodeIds[0]; | |
| Location loc(m_symbols->registerSymbol(fC->getFileName(nodeId)), | |
| fC->Line(nodeId), 0, | |
| m_symbols->registerSymbol(m_module->getName())); | |
| VObjectType moduleType = fC->Type(nodeId); | |
| ErrorDefinition::ErrorType errType = ErrorDefinition::COMP_COMPILE_MODULE; | |
| switch (moduleType) { | |
| case VObjectType::slInterface_declaration: | |
| errType = ErrorDefinition::COMP_COMPILE_INTERFACE; | |
| break; | |
| case VObjectType::slUdp_declaration: | |
| errType = ErrorDefinition::COMP_COMPILE_UDP; | |
| break; | |
| case VObjectType::slChecker_declaration: | |
| errType = ErrorDefinition::COMP_COMPILE_CHECKER; | |
| break; | |
| default: | |
| break; | |
| } | |
| Error err(errType, loc); | |
| ErrorContainer* errors = new ErrorContainer(m_symbols); | |
| errors->regiterCmdLine( | |
| m_compileDesign->getCompiler()->getCommandLineParser()); | |
| errors->addError(err); | |
| errors->printMessage( | |
| err, | |
| m_compileDesign->getCompiler()->getCommandLineParser()->muteStdout()); | |
| delete errors; | |
| switch (moduleType) { | |
| case VObjectType::slModule_declaration: | |
| if (!collectModuleObjects_()) return false; | |
| if (!checkModule_()) return false; | |
| break; | |
| case VObjectType::slInterface_declaration: | |
| if (!collectInterfaceObjects_()) return false; | |
| if (!checkInterface_()) return false; | |
| break; | |
| case VObjectType::slUdp_declaration: | |
| break; | |
| case VObjectType::slChecker_declaration: | |
| break; | |
| case VObjectType::slProgram_declaration: | |
| break; | |
| default: | |
| break; | |
| } | |
| return true; | |
| } | |
| VObjectType getSignalType(FileContent* fC, NodeId net_port_type) { | |
| VObjectType signal_type = VObjectType::slData_type_or_implicit; | |
| if (net_port_type) { | |
| NodeId data_type_or_implicit = fC->Child(net_port_type); | |
| if (fC->Type(data_type_or_implicit) == VObjectType::slNetType_Wire) { | |
| signal_type = VObjectType::slNetType_Wire; | |
| } else { | |
| NodeId data_type = fC->Child(data_type_or_implicit); | |
| if (data_type) { | |
| VObjectType the_type = fC->Type(data_type); | |
| if (the_type == VObjectType::slData_type) { | |
| NodeId integer_vector_type = fC->Child(data_type); | |
| the_type = fC->Type(integer_vector_type); | |
| if (the_type == VObjectType::slIntVec_TypeBit || | |
| the_type == VObjectType::slIntVec_TypeLogic || | |
| the_type == VObjectType::slIntVec_TypeReg) { | |
| signal_type = the_type; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return signal_type; | |
| } | |
| void setDirectionAndType(ModuleDefinition* module, FileContent* fC, | |
| NodeId signal, VObjectType type, | |
| VObjectType signal_type) { | |
| while (signal) { | |
| for (auto& port : module->getPorts()) { | |
| if (port.getName() == fC->SymName(signal)) { | |
| VObjectType dir_type = slNoType; | |
| if (type == VObjectType::slInput_declaration) | |
| dir_type = slPortDir_Inp; | |
| else if (type == VObjectType::slOutput_declaration) | |
| dir_type = slPortDir_Out; | |
| else if (type == VObjectType::slInout_declaration) | |
| dir_type = slPortDir_Inout; | |
| port.setDirection(dir_type); | |
| if (signal_type != VObjectType::slData_type_or_implicit) | |
| port.setType(signal_type); | |
| break; | |
| } | |
| } | |
| signal = fC->Sibling(signal); | |
| } | |
| } | |
| bool CompileModule::collectModuleObjects_() { | |
| 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, | |
| VObjectType::slClass_declaration}; | |
| for (unsigned int i = 0; i < m_module->m_fileContents.size(); i++) { | |
| FileContent* fC = m_module->m_fileContents[i]; | |
| std::string libName = fC->getLibrary()->getName(); | |
| VObject current = fC->Object(m_module->m_nodeIds[i]); | |
| NodeId id = current.m_child; | |
| if (!id) id = current.m_sibling; | |
| if (!id) return false; | |
| // Package imports | |
| std::vector<FileCNodeId> pack_imports; | |
| // - Local file imports | |
| for (auto import : fC->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_module, m_design, pack_fC, pack_id); | |
| } | |
| std::stack<NodeId> stack; | |
| stack.push(id); | |
| VObjectType port_direction = VObjectType::slNoType; | |
| while (stack.size()) { | |
| 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_module, m_design, fC, id); | |
| break; | |
| } | |
| case VObjectType::slAnsi_port_declaration: { | |
| NodeId net_port_header = fC->Child(id); | |
| NodeId identifier = fC->Sibling(net_port_header); | |
| NodeId net_port_type = fC->Child(net_port_header); | |
| VObjectType dir_type = fC->Type(net_port_type); | |
| if (dir_type == VObjectType::slPortDir_Out || | |
| dir_type == VObjectType::slPortDir_Inp || | |
| dir_type == VObjectType::slPortDir_Inout || | |
| dir_type == VObjectType::slPortDir_Ref) { | |
| port_direction = dir_type; | |
| net_port_type = fC->Sibling(net_port_type); | |
| VObjectType signal_type = getSignalType(fC, net_port_type); | |
| Signal signal(fC, identifier, signal_type, port_direction); | |
| m_module->m_ports.push_back(signal); | |
| } else { | |
| NodeId data_type_or_implicit = fC->Child(net_port_type); | |
| NodeId data_type = fC->Child(data_type_or_implicit); | |
| if (data_type) { | |
| NodeId if_type_name_s = fC->Child(data_type); | |
| if (fC->Type(if_type_name_s) == VObjectType::slIntVec_TypeReg || | |
| fC->Type(if_type_name_s) == VObjectType::slIntVec_TypeLogic) { | |
| Signal signal(fC, identifier, fC->Type(if_type_name_s), | |
| VObjectType::slNoType); | |
| m_module->m_ports.push_back(signal); | |
| } else { | |
| std::string interfaceName = | |
| libName + "@" + fC->SymName(if_type_name_s); | |
| Signal signal(fC, if_type_name_s, identifier); | |
| ModuleDefinition* interface = | |
| m_design->getModuleDefinition(interfaceName); | |
| if (interface) { | |
| signal.setInterfaceDef(interface); | |
| } else { | |
| Location loc(m_symbols->registerSymbol( | |
| fC->getFileName(if_type_name_s)), | |
| fC->Line(if_type_name_s), 0, | |
| m_symbols->registerSymbol(interfaceName)); | |
| Error err(ErrorDefinition::COMP_UNDEFINED_INTERFACE, loc); | |
| m_errors->addError(err); | |
| } | |
| } | |
| } else { | |
| Signal signal(fC, identifier, | |
| VObjectType::slData_type_or_implicit, | |
| port_direction); | |
| m_module->m_ports.push_back(signal); | |
| } | |
| } | |
| break; | |
| } | |
| case VObjectType::slPort: | |
| /* | |
| n<mem_if> u<3> t<StringConst> p<6> s<5> l<1> | |
| n<> u<4> t<Constant_bit_select> p<5> l<1> | |
| n<> u<5> t<Constant_select> p<6> c<4> l<1> | |
| n<> u<6> t<Port_reference> p<11> c<3> s<10> l<1> | |
| n<mif> u<7> t<StringConst> p<10> s<9> l<1> | |
| n<> u<8> t<Constant_bit_select> p<9> l<1> | |
| n<> u<9> t<Constant_select> p<10> c<8> l<1> | |
| n<> u<10> t<Port_reference> p<11> c<7> l<1> | |
| n<> u<11> t<Port_expression> p<12> c<6> l<1> | |
| n<> u<12> t<Port> p<13> c<11> l<1> | |
| */ | |
| { | |
| NodeId Port_expression = fC->Child(id); | |
| if (Port_expression && | |
| (fC->Type(Port_expression) == VObjectType::slPort_expression)) { | |
| NodeId if_type = fC->Child(Port_expression); | |
| if (fC->Type(if_type) == VObjectType::slPort_reference) { | |
| NodeId if_type_name_s = fC->Child(if_type); | |
| NodeId if_name = fC->Sibling(if_type); | |
| if (if_name) { | |
| NodeId if_name_s = fC->Child(if_name); | |
| std::string interfaceName = | |
| libName + "@" + fC->SymName(if_type_name_s); | |
| Signal signal(fC, if_type_name_s, if_name_s); | |
| ModuleDefinition* interface = | |
| m_design->getModuleDefinition(interfaceName); | |
| if (interface) { | |
| signal.setInterfaceDef(interface); | |
| } else { | |
| Location loc(m_symbols->registerSymbol( | |
| fC->getFileName(if_type_name_s)), | |
| fC->Line(if_type_name_s), 0, | |
| m_symbols->registerSymbol(interfaceName)); | |
| Error err(ErrorDefinition::COMP_UNDEFINED_INTERFACE, loc); | |
| m_errors->addError(err); | |
| } | |
| m_module->m_ports.push_back(signal); | |
| } else { | |
| Signal signal(fC, if_type_name_s, | |
| VObjectType::slData_type_or_implicit, | |
| port_direction); | |
| m_module->m_ports.push_back(signal); | |
| } | |
| } | |
| } | |
| break; | |
| } | |
| case VObjectType::slInput_declaration: | |
| case VObjectType::slOutput_declaration: | |
| case VObjectType::slInout_declaration: { | |
| /* | |
| n<> u<24> t<Data_type_or_implicit> p<25> l<7> | |
| n<> u<25> t<Net_port_type> p<28> c<24> s<27> l<7> | |
| n<c0> u<26> t<StringConst> p<27> l<7> | |
| n<> u<27> t<List_of_port_identifiers> p<28> c<26> l<7> | |
| n<> u<28> t<Output_declaration> p<29> c<25> l<7> | |
| */ | |
| NodeId net_port_type = fC->Child(id); | |
| VObjectType signal_type = getSignalType(fC, net_port_type); | |
| NodeId list_of_port_identifiers = fC->Sibling(net_port_type); | |
| if (fC->Type(list_of_port_identifiers) == | |
| VObjectType::slPacked_dimension) { | |
| list_of_port_identifiers = fC->Sibling(list_of_port_identifiers); | |
| } | |
| NodeId signal = fC->Child(list_of_port_identifiers); | |
| setDirectionAndType(m_module, fC, signal, type, signal_type); | |
| break; | |
| } | |
| case VObjectType::slClocking_declaration: | |
| compileClockingBlock_(fC, id); | |
| break; | |
| case VObjectType::slNet_declaration: { | |
| /* | |
| n<> u<17> t<NetType_Wire> p<18> l<27> | |
| n<> u<18> t<NetTypeOrTrireg_Net> p<22> c<17> s<21> l<27> | |
| n<a> u<19> t<StringConst> p<20> l<27> | |
| n<> u<20> t<Net_decl_assignment> p<21> c<19> l<27> | |
| n<> u<21> t<List_of_net_decl_assignments> p<22> c<20> l<27> | |
| n<> u<22> t<Net_declaration> p<23> c<18> l<27> | |
| */ | |
| NodeId netTypeOrTrireg_Net = fC->Child(id); | |
| NodeId netType_Wire = fC->Child(netTypeOrTrireg_Net); | |
| NodeId list_of_net_decl_assignments = | |
| fC->Sibling(netTypeOrTrireg_Net); | |
| if (fC->Type(list_of_net_decl_assignments) == | |
| VObjectType::slPacked_dimension) { | |
| list_of_net_decl_assignments = | |
| fC->Sibling(list_of_net_decl_assignments); | |
| } | |
| NodeId net_decl_assignment = fC->Child(list_of_net_decl_assignments); | |
| while (net_decl_assignment) { | |
| NodeId signal = fC->Child(net_decl_assignment); | |
| for (auto& port : m_module->m_ports) { | |
| if (port.getName() == fC->SymName(signal)) { | |
| port.setType(fC->Type(netType_Wire)); | |
| break; | |
| } | |
| } | |
| net_decl_assignment = fC->Sibling(net_decl_assignment); | |
| } | |
| break; | |
| } | |
| case VObjectType::slData_declaration: { | |
| NodeId subNode = fC->Child(id); | |
| VObjectType subType = fC->Type(subNode); | |
| switch (subType) { | |
| case VObjectType::slType_declaration: { | |
| /* | |
| n<> u<15> t<Data_type> p<17> c<8> s<16> l<13> | |
| n<fsm_t> u<16> t<StringConst> p<17> l<13> | |
| n<> u<17> t<Type_declaration> p<18> c<15> l<13> | |
| n<> u<18> t<Data_declaration> p<19> c<17> l<13> | |
| */ | |
| m_helper.compileTypeDef(m_module, fC, id); | |
| break; | |
| } | |
| case VObjectType::slVariable_declaration: { | |
| /* | |
| n<> u<29> t<IntVec_TypeReg> p<30> l<29> | |
| n<> u<30> t<Data_type> p<34> c<29> s<33> l<29> | |
| n<b> u<31> t<StringConst> p<32> l<29> | |
| n<> u<32> t<Variable_decl_assignment> p<33> c<31> l<29> | |
| n<> u<33> t<List_of_variable_decl_assignments> p<34> c<32> l<29> | |
| n<> u<34> t<Variable_declaration> p<35> c<30> l<29> | |
| n<> u<35> t<Data_declaration> p<36> c<34> l<29> | |
| */ | |
| NodeId variable_declaration = fC->Child(id); | |
| NodeId data_type = fC->Child(variable_declaration); | |
| NodeId intVec_TypeReg = fC->Child(data_type); | |
| NodeId list_of_variable_decl_assignments = fC->Sibling(data_type); | |
| if (fC->Type(list_of_variable_decl_assignments) == | |
| VObjectType::slPacked_dimension) { | |
| list_of_variable_decl_assignments = | |
| fC->Sibling(list_of_variable_decl_assignments); | |
| } | |
| NodeId variable_decl_assignment = | |
| fC->Child(list_of_variable_decl_assignments); | |
| while (variable_decl_assignment) { | |
| NodeId signal = fC->Child(variable_decl_assignment); | |
| for (auto& port : m_module->m_ports) { | |
| if (port.getName() == fC->SymName(signal)) { | |
| port.setType(fC->Type(intVec_TypeReg)); | |
| break; | |
| } | |
| } | |
| variable_decl_assignment = | |
| fC->Sibling(variable_decl_assignment); | |
| } | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| case VObjectType::slPort_declaration: { | |
| /* | |
| n<Configuration> u<21> t<StringConst> p<22> l<7> | |
| n<> u<22> t<Interface_identifier> p<26> c<21> s<25> l<7> | |
| n<cfg> u<23> t<StringConst> p<24> l<7> | |
| n<> u<24> t<Interface_identifier> p<25> c<23> l<7> | |
| n<> u<25> t<List_of_interface_identifiers> p<26> c<24> l<7> | |
| n<> u<26> t<Interface_port_declaration> p<27> c<22> l<7> | |
| n<> u<27> t<Port_declaration> p<28> c<26> l<7> | |
| */ | |
| NodeId subNode = fC->Child(id); | |
| VObjectType subType = fC->Type(subNode); | |
| switch (subType) { | |
| case VObjectType::slInterface_port_declaration: { | |
| NodeId interface_identifier = fC->Child(subNode); | |
| NodeId interfIdName = fC->Child(interface_identifier); | |
| std::string interfName = fC->SymName(interfIdName); | |
| DesignComponent* def = NULL; | |
| DataType* type = NULL; | |
| std::pair<FileCNodeId, DesignComponent*>* datatype = | |
| m_module->getNamedObject(interfName); | |
| if (!datatype) { | |
| def = m_module->getClassDefinition(m_module->getName() + | |
| "::" + interfName); | |
| } | |
| if (datatype) { | |
| def = datatype->second; | |
| } | |
| if (def == NULL) { | |
| def = m_design->getComponentDefinition(libName + "@" + | |
| interfName); | |
| } | |
| if (def == NULL) { | |
| type = m_module->getDataType(interfName); | |
| } | |
| if (def == NULL && type == NULL && (interfName != "logic") && | |
| (interfName != "byte") && (interfName != "bit") && | |
| (interfName != "new") && (interfName != "expect") && | |
| (interfName != "var") && (interfName != "signed") && | |
| (interfName != "unsigned") && (interfName != "do") && | |
| (interfName != "final") && (interfName != "global") && | |
| (interfName != "soft")) { | |
| Location loc(m_symbols->registerSymbol(fC->getFileName(id)), | |
| fC->Line(id), 0, | |
| m_symbols->registerSymbol(interfName)); | |
| Error err(ErrorDefinition::COMP_UNDEFINED_TYPE, loc); | |
| m_errors->addError(err); | |
| } | |
| NodeId list_of_interface_identifiers = | |
| fC->Sibling(interface_identifier); | |
| NodeId identifier = fC->Child(list_of_interface_identifiers); | |
| while (identifier) { | |
| std::string name = fC->SymName(identifier); | |
| identifier = fC->Sibling(identifier); | |
| // TODO | |
| } | |
| break; | |
| } | |
| case VObjectType::slInput_declaration: | |
| case VObjectType::slOutput_declaration: | |
| case VObjectType::slInout_declaration: { | |
| /* | |
| n<> u<24> t<Data_type_or_implicit> p<25> l<7> | |
| n<> u<25> t<Net_port_type> p<28> c<24> s<27> l<7> | |
| n<c0> u<26> t<StringConst> p<27> l<7> | |
| n<> u<27> t<List_of_port_identifiers> p<28> c<26> l<7> | |
| n<> u<28> t<Output_declaration> p<29> c<25> l<7> | |
| */ | |
| NodeId net_port_type = fC->Child(subNode); | |
| VObjectType signal_type = getSignalType(fC, net_port_type); | |
| NodeId list_of_port_identifiers = fC->Sibling(net_port_type); | |
| if (fC->Type(list_of_port_identifiers) == | |
| VObjectType::slPacked_dimension) { | |
| list_of_port_identifiers = | |
| fC->Sibling(list_of_port_identifiers); | |
| } | |
| NodeId signal = fC->Child(list_of_port_identifiers); | |
| setDirectionAndType(m_module, fC, signal, subType, signal_type); | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| break; | |
| } | |
| case VObjectType::slParam_assignment: | |
| case VObjectType::slHierarchical_instance: | |
| case VObjectType::slN_input_gate_instance: | |
| case VObjectType::slN_output_gate_instance: | |
| case VObjectType::slUdp_instance: | |
| case VObjectType::slUdp_instantiation: | |
| case VObjectType::slModule_instantiation: | |
| case VObjectType::slInterface_instantiation: | |
| case VObjectType::slGate_instantiation: | |
| case VObjectType::slConditional_generate_construct: | |
| case VObjectType::slGenerate_module_conditional_statement: | |
| case VObjectType::slLoop_generate_construct: | |
| case VObjectType::slGenerate_module_loop_statement: | |
| case VObjectType::slPar_block: | |
| case VObjectType::slSeq_block: | |
| case VObjectType::slDefparam_assignment: { | |
| FileCNodeId fnid(fC, id); | |
| m_module->addObject(type, fnid); | |
| break; | |
| } | |
| default: | |
| break; | |
| } | |
| if (current.m_sibling) stack.push(current.m_sibling); | |
| if (current.m_child) { | |
| if (stopPoints.size()) { | |
| bool stop = false; | |
| for (auto t : stopPoints) { | |
| if (t == current.m_type) { | |
| stop = true; | |
| break; | |
| } | |
| } | |
| if (!stop) | |
| if (current.m_child) stack.push(current.m_child); | |
| } else { | |
| if (current.m_child) stack.push(current.m_child); | |
| } | |
| } | |
| } | |
| } | |
| return true; | |
| } | |
| bool CompileModule::collectInterfaceObjects_() { | |
| for (unsigned int i = 0; i < m_module->m_fileContents.size(); i++) { | |
| FileContent* fC = m_module->m_fileContents[i]; | |
| VObject current = fC->Object(m_module->m_nodeIds[i]); | |
| NodeId id = current.m_child; | |
| if (!id) id = current.m_sibling; | |
| if (!id) return false; | |
| // Package imports | |
| std::vector<FileCNodeId> pack_imports; | |
| // - Local file imports | |
| for (auto import : fC->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_module, m_design, pack_fC, pack_id); | |
| } | |
| std::stack<NodeId> stack; | |
| stack.push(id); | |
| while (stack.size()) { | |
| 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_module, m_design, fC, id); | |
| break; | |
| } | |
| case VObjectType::slAnsi_port_declaration: { | |
| NodeId Net_port_header = fC->Child(id); | |
| NodeId net = fC->Sibling(Net_port_header); | |
| NodeId Direction = fC->Child(Net_port_header); | |
| VObjectType direction = fC->Type(Direction); | |
| NodeId Net_port_type = fC->Sibling(Direction); | |
| NodeId NetType = fC->Child(Net_port_type); | |
| VObjectType nettype = fC->Type(NetType); | |
| Signal signal(fC, net, nettype, direction); | |
| m_module->m_ports.push_back(signal); | |
| break; | |
| } | |
| case VObjectType::slNet_declaration: { | |
| NodeId NetTypeOrTrireg_Net = fC->Child(id); | |
| NodeId NetType = fC->Child(NetTypeOrTrireg_Net); | |
| VObjectType nettype = fC->Type(NetType); | |
| NodeId net = fC->Sibling(NetTypeOrTrireg_Net); | |
| NodeId List_of_net_decl_assignments; | |
| if (fC->Type(net) == slPacked_dimension) { | |
| List_of_net_decl_assignments = fC->Sibling(net); | |
| } else { | |
| List_of_net_decl_assignments = net; | |
| } | |
| NodeId Net_decl_assignment = fC->Child(List_of_net_decl_assignments); | |
| net = fC->Child(Net_decl_assignment); | |
| bool existing = false; | |
| for (auto& port : m_module->m_ports) { | |
| if (port.getName() == fC->SymName(net)) { | |
| existing = true; | |
| port.setType(nettype); | |
| break; | |
| } | |
| } | |
| if (!existing) { | |
| Signal signal(fC, net, nettype, VObjectType::slNoType); | |
| m_module->m_ports.push_back(signal); | |
| } | |
| break; | |
| } | |
| case VObjectType::slData_declaration: { | |
| /* | |
| n<> u<29> t<IntVec_TypeReg> p<30> l<29> | |
| n<> u<30> t<Data_type> p<34> c<29> s<33> l<29> | |
| n<b> u<31> t<StringConst> p<32> l<29> | |
| n<> u<32> t<Variable_decl_assignment> p<33> c<31> l<29> | |
| n<> u<33> t<List_of_variable_decl_assignments> p<34> c<32> l<29> | |
| n<> u<34> t<Variable_declaration> p<35> c<30> l<29> | |
| n<> u<35> t<Data_declaration> p<36> c<34> l<29> | |
| */ | |
| NodeId variable_declaration = fC->Child(id); | |
| NodeId data_type = fC->Child(variable_declaration); | |
| NodeId intVec_TypeReg = fC->Child(data_type); | |
| NodeId list_of_variable_decl_assignments = fC->Sibling(data_type); | |
| if (fC->Type(list_of_variable_decl_assignments) == | |
| VObjectType::slPacked_dimension) { | |
| list_of_variable_decl_assignments = | |
| fC->Sibling(list_of_variable_decl_assignments); | |
| } | |
| NodeId variable_decl_assignment = | |
| fC->Child(list_of_variable_decl_assignments); | |
| while (variable_decl_assignment) { | |
| NodeId signal = fC->Child(variable_decl_assignment); | |
| bool port_exist = false; | |
| for (auto& port : m_module->m_ports) { | |
| if (port.getName() == fC->SymName(signal)) { | |
| port_exist = true; | |
| port.setType(fC->Type(intVec_TypeReg)); | |
| break; | |
| } | |
| } | |
| if (!port_exist) { | |
| Signal sig(fC, signal, fC->Type(intVec_TypeReg), | |
| VObjectType::slNoType); | |
| m_module->m_ports.push_back(sig); | |
| } | |
| variable_decl_assignment = fC->Sibling(variable_decl_assignment); | |
| } | |
| break; | |
| } | |
| case VObjectType::slClocking_declaration: | |
| compileClockingBlock_(fC, id); | |
| break; | |
| case VObjectType::slGenerate_interface_item: { | |
| // TODO: rewrite this rough implementation | |
| std::vector<VObjectType> types = {VObjectType::slModport_item}; | |
| std::vector<NodeId> items = fC->sl_collect_all(id, types); | |
| for (auto nodeId : items) { | |
| Location loc(m_symbols->registerSymbol(fC->getFileName(nodeId)), | |
| fC->Line(nodeId), 0, 0); | |
| Error err(ErrorDefinition::COMP_NO_MODPORT_IN_GENERATE, loc); | |
| m_errors->addError(err); | |
| } | |
| break; | |
| } | |
| case VObjectType::slModport_item: | |
| /* | |
| n<tb> u<45> t<StringConst> p<56> s<50> l<43> | |
| n<> u<46> t<PortDir_Inp> p<49> s<48> l<43> | |
| n<clk> u<47> t<StringConst> p<48> l<43> | |
| n<> u<48> t<Modport_simple_port> p<49> c<47> l<43> | |
| n<> u<49> t<Modport_simple_ports_declaration> p<50> c<46> l<43> | |
| n<> u<50> t<Modport_ports_declaration> p<56> c<49> s<55> l<43> | |
| n<> u<51> t<PortDir_Out> p<54> s<53> l<43> | |
| n<reset> u<52> t<StringConst> p<53> l<43> | |
| n<> u<53> t<Modport_simple_port> p<54> c<52> l<43> | |
| n<> u<54> t<Modport_simple_ports_declaration> p<55> c<51> l<43> | |
| n<> u<55> t<Modport_ports_declaration> p<56> c<54> l<43> | |
| n<> u<56> t<Modport_item> p<57> c<45> l<43> | |
| */ | |
| { | |
| NodeId modportname = fC->Child(id); | |
| SymbolId modportsymb = fC->Name(modportname); | |
| NodeId modport_ports_declaration = fC->Sibling(modportname); | |
| VObjectType port_direction_type = VObjectType::slNoType; | |
| while (modport_ports_declaration) { | |
| NodeId port_declaration = fC->Child(modport_ports_declaration); | |
| VObjectType port_declaration_type = fC->Type(port_declaration); | |
| if (port_declaration_type == | |
| VObjectType::slModport_simple_ports_declaration) { | |
| NodeId port_direction = fC->Child(port_declaration); | |
| port_direction_type = fC->Type(port_direction); | |
| NodeId modport_simple_port = fC->Sibling(port_direction); | |
| while (modport_simple_port) { | |
| NodeId simple_port_name = fC->Child(modport_simple_port); | |
| SymbolId port_symbol = fC->Name(simple_port_name); | |
| bool port_exists = false; | |
| for (auto& port : m_module->m_ports) { | |
| if (fC->Name(port.getNodeId()) == port_symbol) { | |
| port_exists = true; | |
| break; | |
| } | |
| } | |
| if (!port_exists) { | |
| Location loc(m_symbols->registerSymbol( | |
| fC->getFileName(simple_port_name)), | |
| fC->Line(simple_port_name), 0, | |
| m_symbols->registerSymbol( | |
| fC->SymName(simple_port_name))); | |
| Error err(ErrorDefinition::COMP_MODPORT_UNDEFINED_PORT, | |
| loc); | |
| m_errors->addError(err); | |
| } | |
| Signal signal(fC, simple_port_name, | |
| VObjectType::slData_type_or_implicit, | |
| port_direction_type); | |
| m_module->insertModPort(modportsymb, signal); | |
| modport_simple_port = fC->Sibling(modport_simple_port); | |
| } | |
| } else if (port_declaration_type == | |
| VObjectType:: | |
| slModport_hierarchical_ports_declaration) { | |
| } else if (port_declaration_type == | |
| VObjectType::slModport_tf_ports_declaration) { | |
| } else { | |
| // CLOCKING | |
| NodeId clocking_block_name = port_declaration; | |
| SymbolId clocking_block_symbol = | |
| m_symbols->registerSymbol(fC->SymName(clocking_block_name)); | |
| ClockingBlock* cb = | |
| m_module->getClockingBlock(clocking_block_symbol); | |
| if (cb == NULL) { | |
| Location loc(m_symbols->registerSymbol( | |
| fC->getFileName(clocking_block_name)), | |
| fC->Line(clocking_block_name), 0, | |
| clocking_block_symbol); | |
| Error err( | |
| ErrorDefinition::COMP_MODPORT_UNDEFINED_CLOCKING_BLOCK, | |
| loc); | |
| m_errors->addError(err); | |
| } else { | |
| m_module->insertModPort(modportsymb, *cb); | |
| } | |
| } | |
| modport_ports_declaration = | |
| fC->Sibling(modport_ports_declaration); | |
| } | |
| } | |
| default: | |
| break; | |
| } | |
| if (current.m_sibling) stack.push(current.m_sibling); | |
| if (current.m_child) stack.push(current.m_child); | |
| } | |
| } | |
| return true; | |
| } | |
| bool CompileModule::checkModule_() { | |
| int countMissingType = 0; | |
| int countMissingDirection = 0; | |
| Location* missingTypeLoc = NULL; | |
| Location* missingDirectionLoc = NULL; | |
| for (auto& port : m_module->m_ports) { | |
| if (port.isInterface()) continue; | |
| if (port.getType() == VObjectType::slData_type_or_implicit) { | |
| if (port.getDirection() == VObjectType::slPortDir_Out || | |
| port.getDirection() == VObjectType::slPortDir_Inout) { | |
| if (countMissingType == 0) | |
| missingTypeLoc = new Location( | |
| m_symbols->registerSymbol( | |
| port.getFileContent()->getFileName(port.getNodeId())), | |
| port.getFileContent()->Line(port.getNodeId()), 0, | |
| m_symbols->registerSymbol(port.getName())); | |
| countMissingType++; | |
| } | |
| } | |
| if (port.getDirection() == VObjectType::slNoType) { | |
| if (countMissingDirection == 0) | |
| missingDirectionLoc = new Location( | |
| m_symbols->registerSymbol( | |
| port.getFileContent()->getFileName(port.getNodeId())), | |
| port.getFileContent()->Line(port.getNodeId()), 0, | |
| m_symbols->registerSymbol(port.getName())); | |
| countMissingDirection++; | |
| } | |
| } | |
| if (countMissingType) { | |
| Location countLoc( | |
| 0, 0, 0, | |
| m_symbols->registerSymbol(std::to_string(countMissingType - 1))); | |
| if (countMissingType - 1 > 0) { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc, | |
| countLoc); | |
| m_errors->addError(err); | |
| } else { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc); | |
| m_errors->addError(err); | |
| } | |
| delete missingTypeLoc; | |
| } | |
| if (countMissingDirection) { | |
| Location countLoc( | |
| 0, 0, 0, | |
| m_symbols->registerSymbol(std::to_string(countMissingDirection - 1))); | |
| if (countMissingDirection - 1 > 0) { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_DIRECTION, | |
| *missingDirectionLoc, countLoc); | |
| m_errors->addError(err); | |
| } else { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_DIRECTION, | |
| *missingDirectionLoc); | |
| m_errors->addError(err); | |
| } | |
| delete missingDirectionLoc; | |
| } | |
| return true; | |
| } | |
| bool CompileModule::checkInterface_() { | |
| int countMissingType = 0; | |
| Location* missingTypeLoc = NULL; | |
| for (auto& port : m_module->m_ports) { | |
| if (port.getType() == VObjectType::slData_type_or_implicit) { | |
| if (port.getDirection() == VObjectType::slPortDir_Out || | |
| port.getDirection() == VObjectType::slPortDir_Inout) { | |
| if (countMissingType == 0) | |
| missingTypeLoc = new Location( | |
| m_symbols->registerSymbol( | |
| port.getFileContent()->getFileName(port.getNodeId())), | |
| port.getFileContent()->Line(port.getNodeId()), 0, | |
| m_symbols->registerSymbol(port.getName())); | |
| countMissingType++; | |
| } | |
| } | |
| } | |
| if (countMissingType) { | |
| Location countLoc( | |
| 0, 0, 0, | |
| m_symbols->registerSymbol(std::to_string(countMissingType - 1))); | |
| if (countMissingType - 1 > 0) { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc, | |
| countLoc); | |
| m_errors->addError(err); | |
| } else { | |
| Error err(ErrorDefinition::COMP_PORT_MISSING_TYPE, *missingTypeLoc); | |
| m_errors->addError(err); | |
| } | |
| delete missingTypeLoc; | |
| } | |
| return true; | |
| } | |
| void CompileModule::compileClockingBlock_(FileContent* fC, NodeId id) { | |
| /* | |
| n<cb> u<12> t<StringConst> p<21> s<20> l<39> | |
| n<> u<13> t<Edge_Posedge> p<19> s<18> l<39> | |
| n<clk> u<14> t<StringConst> p<17> s<16> l<39> | |
| n<> u<15> t<Bit_select> p<16> l<39> | |
| n<> u<16> t<Select> p<17> c<15> l<39> | |
| n<> u<17> t<Primary> p<18> c<14> l<39> | |
| n<> u<18> t<Expression> p<19> c<17> l<39> | |
| n<> u<19> t<Event_expression> p<20> c<13> l<39> | |
| n<> u<20> t<Clocking_event> p<21> c<19> l<39> | |
| n<> u<21> t<Clocking_declaration> p<22> c<12> l<39> | |
| */ | |
| NodeId clocking_block_name = fC->Child(id); | |
| SymbolId clocking_block_symbol = | |
| m_symbols->registerSymbol(fC->SymName(clocking_block_name)); | |
| NodeId clocking_event = fC->Sibling(clocking_block_name); | |
| ClockingBlock cb(fC, clocking_block_name, clocking_event); | |
| m_module->addClockingBlock(clocking_block_symbol, cb); | |
| } |