diff options
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); +} |