diff options
author | Nathan Binkert <nate@binkert.org> | 2009-05-11 10:38:43 -0700 |
---|---|---|
committer | Nathan Binkert <nate@binkert.org> | 2009-05-11 10:38:43 -0700 |
commit | 2f30950143cc70bc42a3c8a4111d7cf8198ec881 (patch) | |
tree | 708f6c22edb3c6feb31dd82866c26623a5329580 /src/mem/slicc/symbols/Type.cc | |
parent | c70241810d4e4f523f173c1646b008dc40faad8e (diff) | |
download | gem5-2f30950143cc70bc42a3c8a4111d7cf8198ec881.tar.xz |
ruby: Import ruby and slicc from GEMS
We eventually plan to replace the m5 cache hierarchy with the GEMS
hierarchy, but for now we will make both live alongside eachother.
Diffstat (limited to 'src/mem/slicc/symbols/Type.cc')
-rw-r--r-- | src/mem/slicc/symbols/Type.cc | 746 |
1 files changed, 746 insertions, 0 deletions
diff --git a/src/mem/slicc/symbols/Type.cc b/src/mem/slicc/symbols/Type.cc new file mode 100644 index 000000000..a49e9d7ba --- /dev/null +++ b/src/mem/slicc/symbols/Type.cc @@ -0,0 +1,746 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Type.hh" +#include "fileio.hh" +#include "Map.hh" +#include "StateMachine.hh" + +Type::Type(string id, const Location& location, + const Map<string, string>& pairs, + StateMachine* machine_ptr) + : Symbol(id, location, pairs) +{ + if (machine_ptr == NULL) { + m_c_id = id; + } else if (isExternal() || isPrimitive()) { + if (existPair("external_name")) { + m_c_id = lookupPair("external_name"); + } else { + m_c_id = id; + } + } else { + m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name + } + + if(existPair("desc")){ + m_desc = lookupPair("desc"); + } else { + m_desc = "No description avaliable"; + } + + // check for interface that this Type implements + if(existPair("interface")) { + string interface = lookupPair("interface"); + if(interface == "Message" || interface == "NetworkMessage") { + addPair("message", "yes"); + } + if(interface == "NetworkMessage") { + addPair("networkmessage", "yes"); + } + } + + // FIXME - all of the following id comparisons are fragile hacks + if ((getIdent() == "CacheMemory") || (getIdent() == "NewCacheMemory") || + (getIdent() == "TLCCacheMemory") || (getIdent() == "DNUCACacheMemory") || + (getIdent() == "DNUCABankCacheMemory") || (getIdent() == "L2BankCacheMemory") || + (getIdent() == "CompressedCacheMemory") || (getIdent() == "PrefetchCacheMemory")) { + addPair("cache", "yes"); + } + + if ((getIdent() == "TBETable") || (getIdent() == "DNUCATBETable") || (getIdent() == "DNUCAStopTable")) { + addPair("tbe", "yes"); + } + + if ((getIdent() == "NewTBETable")) { + addPair("newtbe", "yes"); + } + + if ((getIdent() == "TimerTable")) { + addPair("timer", "yes"); + } + + if ((getIdent() == "DirectoryMemory")) { + addPair("dir", "yes"); + } + + if ((getIdent() == "PersistentTable")) { + addPair("persistent", "yes"); + } + + if ((getIdent() == "Prefetcher")) { + addPair("prefetcher", "yes"); + } + + if ((getIdent() == "DNUCA_Movement")) { + addPair("mover", "yes"); + } + + if (id == "MachineType") { + m_isMachineType = true; + } else { + m_isMachineType = false; + } +} + +// Return false on error +bool Type::dataMemberAdd(string id, Type* type_ptr, Map<string, string>& pairs, + string* init_code) +{ + if (dataMemberExist(id)) { + return false; // Error + } else { + m_data_member_map.add(id, type_ptr); + m_data_member_ident_vec.insertAtBottom(id); + m_data_member_type_vec.insertAtBottom(type_ptr); + m_data_member_pairs_vec.insertAtBottom(pairs); + m_data_member_init_code_vec.insertAtBottom(init_code); + } + + return true; +} + +string Type::methodId(string name, + const Vector<Type*>& param_type_vec) +{ + string paramStr = ""; + for (int i = 0; i < param_type_vec.size(); i++) { + paramStr += "_"+param_type_vec[i]->cIdent(); + } + return name+paramStr; +} + +bool Type::methodAdd(string name, + Type* return_type_ptr, + const Vector<Type*>& param_type_vec) +{ + string id = methodId(name, param_type_vec); + if (methodExist(id)) { + return false; // Error + } else { + m_method_return_type_map.add(id, return_type_ptr); + m_method_param_type_map.add(id, param_type_vec); + return true; + } +} + +bool Type::enumAdd(string id, Map<string, string> pairs_map) +{ + if (enumExist(id)) { + return false; + } else { + m_enum_map.add(id, true); + m_enum_vec.insertAtBottom(id); + m_enum_pairs.insertAtBottom(pairs_map); + + // Add default + if (!existPair("default")) { + addPair("default", cIdent()+"_NUM"); + } + + return true; + } +} + +void Type::writeCFiles(string path) const +{ + if (isExternal()) { + // Do nothing + } else if (isEnumeration()) { + printEnumH(path); + printEnumC(path); + } else { // User defined structs and messages + printTypeH(path); + printTypeC(path); + } +} + +void Type::printTypeH(string path) const +{ + ostringstream out; + int size = m_data_member_type_vec.size(); + string type_name = cIdent(); // Identifier for the type in C + + // Header + out << "/** \\file " << type_name << ".hh" << endl; + out << " * " << endl; + out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; + out << " */" << endl; + out << endl; + out << "#ifndef " << type_name << "_H" << endl; + out << "#define " << type_name << "_H" << endl; + out << endl; + + // Include all of the #includes needed + out << "#include \"Global.hh\"" << endl; + out << "#include \"Allocator.hh\"" << endl; + for (int i=0; i < size; i++) { + Type* type = m_data_member_type_vec[i]; + if (!type->isPrimitive()) { + out << "#include \"" << type->cIdent() << ".hh" << "\"" << endl; + } + } + string interface = ""; + if(existPair("interface")) { + interface = lookupPair("interface"); + out << "#include \"" << interface << ".hh\"" << endl; + } + + // Class definition + out << "class " << type_name; + + if(interface != "") { + out << " : public " << interface ; + } + + out << " {" << endl; + out << "public:" << endl; + + // ******** Default constructor ******** + + out << " " << type_name << "() " << endl; + + // Call superclass constructor + if (interface != "") { + out << " : " << interface << "()" << endl; + } + + out << " {" << endl; + + if(!isGlobal()) { + for (int i=0; i < size; i++) { + + Type* type_ptr = m_data_member_type_vec[i]; + string id = m_data_member_ident_vec[i]; + if (m_data_member_pairs_vec[i].exist("default")) { + // look for default value + string default_value = m_data_member_pairs_vec[i].lookup("default"); + out << " m_" << id << " = " << default_value << "; // default for this field " << endl; + } else if (type_ptr->hasDefault()) { + // Look for the type default + string default_value = type_ptr->getDefault(); + out << " m_" << id << " = " << default_value << "; // default value of " << type_ptr->cIdent() << endl; + } else { + out << " // m_" << id << " has no default" << endl; + } + } + } // end of if(!isGlobal()) + out << " }" << endl; + + // ******** Default destructor ******** + out << " "; + out << "~" << type_name << "() { };" << endl; + + // ******** Full init constructor ******** + if(! isGlobal()) { + out << " " << type_name << "("; + + for (int i=0; i < size; i++) { + if (i != 0) { + out << ", "; + } + Type* type = m_data_member_type_vec[i]; + string id = m_data_member_ident_vec[i]; + out << "const " << type->cIdent() << "& local_" << id; + } + out << ")" << endl; + + // Call superclass constructor + if (interface != "") { + out << " : " << interface << "()" << endl; + } + + out << " {" << endl; + for (int i=0; i < size; i++) { + Type* type_ptr = m_data_member_type_vec[i]; + string id = m_data_member_ident_vec[i]; + out << " m_" << id << " = local_" << id << ";" << endl; + if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { + string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); + out << " m_" << id << next_line_value << ";" << endl; + } + + } + out << " }" << endl; + } // end of if(!isGlobal()) + + // bobba - + //******** Partial init constructor ******** + //** Constructor needs only the first n-1 data members for init + //** HACK to create objects with partially specified data members + //** Need to get rid of this and use hierarchy instead +// if(! isGlobal()) { +// out << " " << type_name << "("; + +// for (int i=0; i < size-1; i++) { +// if (i != 0) { +// out << ", "; +// } +// Type* type = m_data_member_type_vec[i]; +// string id = m_data_member_ident_vec[i]; +// out << "const " << type->cIdent() << "& local_" << id; +// } +// out << ")" << endl; + +// // Call superclass constructor +// if (interface != "") { +// out << " : " << interface << "()" << endl; +// } + +// out << " {" << endl; +// for (int i=0; i < size-1; i++) { +// Type* type_ptr = m_data_member_type_vec[i]; +// string id = m_data_member_ident_vec[i]; +// out << " m_" << id << " = local_" << id << ";" << endl; +// if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { +// string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); +// out << " m_" << id << next_line_value << ";" << endl; +// } + +// } +// out << " }" << endl; +// } // end of if(!isGlobal()) + + // ******** Message member functions ******** + // FIXME: those should be moved into slicc file, slicc should support more of + // the c++ class inheritance + + if (isMessage()) { + out << " Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }" << endl; + out << " void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }" << endl; + out << " static Allocator<" << type_name << ">* s_allocator_ptr;" << endl; + out << " static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<" << type_name << ">; }}" << endl; + } + + if(!isGlobal()) { + // const Get methods for each field + out << " // Const accessors methods for each field" << endl; + for (int i=0; i < size; i++) { + Type* type_ptr = m_data_member_type_vec[i]; + string type = type_ptr->cIdent(); + string id = m_data_member_ident_vec[i]; + out << "/** \\brief Const accessor method for " << id << " field." << endl; + out << " * \\return " << id << " field" << endl; + out << " */" << endl; + out << " const " << type << "& get" << id + << "() const { return m_" << id << "; }" << endl; + } + + out << endl; + + // Non-const Get methods for each field + out << " // Non const Accessors methods for each field" << endl; + for (int i=0; i < size; i++) { + Type* type_ptr = m_data_member_type_vec[i]; + string type = type_ptr->cIdent(); + string id = m_data_member_ident_vec[i]; + out << "/** \\brief Non-const accessor method for " << id << " field." << endl; + out << " * \\return " << id << " field" << endl; + out << " */" << endl; + out << " " << type << "& get" << id + << "() { return m_" << id << "; }" << endl; + } + + out << endl; + + // Set methods for each field + out << " // Mutator methods for each field" << endl; + for (int i=0; i < size; i++) { + Type* type_ptr = m_data_member_type_vec[i]; + string type = type_ptr->cIdent(); + string id = m_data_member_ident_vec[i]; + out << "/** \\brief Mutator method for " << id << " field */" << endl; + out << " void set" << id << "(const " << type << "& local_" + << id << ") { m_" << id << " = local_" << id << "; }" << endl; + } + + out << endl; + } // end of if(!isGlobal()) + + out << " void print(ostream& out) const;" << endl; + out << "//private:" << endl; + + // Data members for each field + for (int i=0; i < size; i++) { + if (!m_data_member_pairs_vec[i].exist("abstract")) { + out << " "; + // global structure + if(isGlobal()) out << "static const "; + + Type* type = m_data_member_type_vec[i]; + string id = m_data_member_ident_vec[i]; + out << type->cIdent() << " m_" << id; + + // init value + string* init_code = m_data_member_init_code_vec[i]; + if(init_code) { + // only global structure can have init value here + assert(isGlobal()); + out << " = " << *init_code << " "; + } + out << ";"; + if (m_data_member_pairs_vec[i].exist("desc")) { + string desc = m_data_member_pairs_vec[i].lookup("desc"); + out << " /**< " << desc << "*/"; + } + out << endl; + } + } + + out << "};" << endl; // End class + + out << "// Output operator declaration" << endl; + out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; + out << endl; + out << "// Output operator definition" << endl; + out << "extern inline" << endl; + out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " obj.print(out);" << endl; + out << " out << flush;" << endl; + out << " return out;" << endl; + out << "}" << endl; + out << endl; + out << "#endif // " << type_name << "_H" << endl; + + // Write it out + conditionally_write_file(path + type_name + ".hh", out); +} + +void Type::printTypeC(string path) const +{ + ostringstream out; + int size = m_data_member_type_vec.size(); + string type_name = cIdent(); // Identifier for the type in C + + // Header + out << "/** \\file " << type_name << ".cc" << endl; + out << " * " << endl; + out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; + out << " */" << endl; + out << endl; + out << "#include \"" << type_name << ".hh\"" << endl; + out << endl; + if (isMessage()) { + out << "Allocator<" << type_name << ">* " << type_name << "::s_allocator_ptr = NULL;" << endl; + } + out << "/** \\brief Print the state of this object */" << endl; + out << "void " << type_name << "::print(ostream& out) const" << endl; + out << "{" << endl; + out << " out << \"[" << type_name << ": \";" << endl; + + // For each field + for (int i=0; i < size; i++) { + string id = m_data_member_ident_vec[i]; + out << " out << \"" << id << "=\" << m_" << id << " << \" \";" << endl; + } + + if (isMessage()) { + out << " out << \"" << "Time" << "=\" << getTime()" << " << \" \";" << endl; + } + + // Trailer + out << " out << \"]\";" << endl; + out << "}" << endl; + + // Write it out + conditionally_write_file(path + type_name + ".cc", out); +} + +void Type::printEnumH(string path) const +{ + ostringstream out; + int size = m_enum_vec.size(); + string type_name = cIdent(); // Identifier for the type in C + string type_desc = desc(); + + // Header + out << "/** \\file " << type_name << ".hh" << endl; + out << " * " << endl; + out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; + out << " */" << endl; + + out << "#ifndef " << type_name << "_H" << endl; + out << "#define " << type_name << "_H" << endl; + out << endl; + // Include all of the #includes needed + out << "#include \"Global.hh\"" << endl; + if (m_isMachineType) { + out << "#include \"RubyConfig.hh\"" << endl << endl; + } + out << endl; + + // Class definition + out << "/** \\enum " << type_name << endl; + out << " * \\brief " << type_desc << endl; + out << " */" << endl; + out << "enum " << type_name << " {" << endl; + + out << " " << type_name << "_FIRST," << endl; + + // For each field + for(int i = 0; i < size; i++ ) { + string id = m_enum_vec[i]; + string description; + if(m_enum_pairs[i].exist("desc")){ + description = m_enum_pairs[i].lookup("desc"); + } else { + description = "No description avaliable"; + } + if (i == 0) { + out << " " << type_name << "_" << id << " = " << type_name << "_FIRST, /**< " << description << " */" << endl; + } + else { + out << " " << type_name << "_" << id << ", /**< " << description << " */" << endl; + } + } + out << " " << type_name << "_NUM" << endl; + out << "};" << endl; + + // Code to convert from a string to the enumeration + out << type_name << " string_to_" << type_name << "(const string& str);" << endl; + + // Code to convert state to a string + out << "string " << type_name << "_to_string(const " << type_name << "& obj);" << endl; + + // Code to increment an enumeration type + out << type_name << " &operator++( " << type_name << " &e);" << endl; + + // MachineType hack used to set the base component id for each Machine + if (m_isMachineType) { + out << "int " << type_name << "_base_level(const " << type_name << "& obj);" << endl; + out << "int " << type_name << "_base_number(const " << type_name << "& obj);" << endl; + out << "int " << type_name << "_base_count(const " << type_name << "& obj);" << endl; + out << "int " << type_name << "_chip_count(const " << type_name << "& obj, NodeID chipID);" << endl; + + for(int i = 0; i < size; i++ ) { + string id = m_enum_vec[i]; + out << "#define MACHINETYPE_" << id << " 1" << endl; + } + cout << endl; + } + + // Trailer + out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; + out << endl; + out << "#endif // " << type_name << "_H" << endl; + + // Write the file + conditionally_write_file(path + type_name + ".hh", out); +} + +void Type::printEnumC(string path) const +{ + ostringstream out; + int size = m_enum_vec.size(); + string type_name = cIdent(); // Identifier for the type in C + + // Header + out << "/** \\file " << type_name << ".hh" << endl; + out << " * " << endl; + out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; + out << " */" << endl; + + out << endl; + out << "#include \"" << type_name << ".hh\"" << endl; + out << endl; + + // Code for output operator + out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " out << " << type_name << "_to_string(obj);" << endl; + out << " out << flush;" << endl; + out << " return out;" << endl; + out << "}" << endl; + + // Code to convert state to a string + out << endl; + out << "string " << type_name << "_to_string(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return \"" << m_enum_vec[i] << "\";" << endl; + } + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return \"\";" << endl; + out << " }" << endl; + out << "}" << endl; + + // Code to convert from a string to the enumeration + out << endl; + out << type_name << " string_to_" << type_name << "(const string& str)" << endl; + out << "{" << endl; + out << " if (false) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " } else if (str == \"" << m_enum_vec[i] << "\") {" << endl; + out << " return " << type_name << "_" << m_enum_vec[i] << ";" << endl; + } + + out << " } else {" << endl; + out << " WARN_EXPR(str);" << endl; + out << " ERROR_MSG(\"Invalid string conversion for type " << type_name << "\");" << endl; + out << " }" << endl; + out << "}" << endl; + + // Code to increment an enumeration type + out << endl; + out << type_name << "& operator++( " << type_name << "& e) {" << endl; + out << " assert(e < " << type_name << "_NUM);" << endl; + out << " return e = " << type_name << "(e+1);" << endl; + out << "}" << endl; + + // MachineType hack used to set the base level and number of components for each Machine + if (m_isMachineType) { + out << endl; + out << "/** \\brief returns the base vector index for each machine type to be used by NetDest " << endl; + out << " * " << endl; + out << " * \\return the base vector index for each machine type to be used by NetDest" << endl; + out << " * \\see NetDest.hh" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_level(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + Vector < string > MachineNames; + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return " << MachineNames.size() << ";" << endl; + MachineNames.insertAtBottom(m_enum_vec[i]); + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + out << " return " << MachineNames.size() << ";" << endl; + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + out << endl; + out << "/** \\brief The return value indicates the number of components created" << endl; + out << " * before a particular machine's components" << endl; + out << " * " << endl; + out << " * \\return the base number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_number(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + MachineNames.clear(); + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return 0"; + for ( int m = 0; m<MachineNames.size(); m++) { + out << "+RubyConfig::numberOf" << MachineNames[m] << "()"; + } + out << ";" << endl; + MachineNames.insertAtBottom(m_enum_vec[i]); + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + out << " return 0"; + for ( int m = 0; m<MachineNames.size(); m++) { + out << "+RubyConfig::numberOf" << MachineNames[m] << "()"; + } + out << ";" << endl; + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + + out << endl; + out << "/** \\brief returns the total number of components for each machine" << endl; + out << " * \\return the total number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_count(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return RubyConfig::numberOf" << m_enum_vec[i] << "();" << endl; + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + out << endl; + out << "/** \\brief returns the total number of components for each machine" << endl; + out << " * \\return the total number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_chip_count(const " << type_name << "& obj, NodeID chipID)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return RubyConfig::numberOf" << m_enum_vec[i] << "PerChip(chipID);" << endl; + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + + } + + // Write the file + conditionally_write_file(path + type_name + ".cc", out); +} |