summaryrefslogtreecommitdiff
path: root/src/mem/slicc/symbols/SymbolTable.cc
diff options
context:
space:
mode:
authorNathan Binkert <nate@binkert.org>2009-05-11 10:38:43 -0700
committerNathan Binkert <nate@binkert.org>2009-05-11 10:38:43 -0700
commit2f30950143cc70bc42a3c8a4111d7cf8198ec881 (patch)
tree708f6c22edb3c6feb31dd82866c26623a5329580 /src/mem/slicc/symbols/SymbolTable.cc
parentc70241810d4e4f523f173c1646b008dc40faad8e (diff)
downloadgem5-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/SymbolTable.cc')
-rw-r--r--src/mem/slicc/symbols/SymbolTable.cc934
1 files changed, 934 insertions, 0 deletions
diff --git a/src/mem/slicc/symbols/SymbolTable.cc b/src/mem/slicc/symbols/SymbolTable.cc
new file mode 100644
index 000000000..37e233e88
--- /dev/null
+++ b/src/mem/slicc/symbols/SymbolTable.cc
@@ -0,0 +1,934 @@
+
+/*
+ * 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 "SymbolTable.hh"
+#include "fileio.hh"
+#include "html_gen.hh"
+#include "mif_gen.hh"
+#include "Action.hh"
+
+SymbolTable g_sym_table;
+
+SymbolTable::SymbolTable()
+{
+ m_sym_map_vec.setSize(1);
+ m_depth = 0;
+
+ {
+ Map<string, string> pairs;
+ pairs.add("enumeration", "yes");
+ newSym(new Type("MachineType", Location(), pairs));
+ }
+
+ {
+ Map<string, string> pairs;
+ pairs.add("primitive", "yes");
+ pairs.add("external", "yes");
+ newSym(new Type("void", Location(), pairs));
+ }
+}
+
+SymbolTable::~SymbolTable()
+{
+ int size = m_sym_vec.size();
+ for(int i=0; i<size; i++) {
+ delete m_sym_vec[i];
+ }
+}
+
+void SymbolTable::newSym(Symbol* sym_ptr)
+{
+ registerSym(sym_ptr->toString(), sym_ptr);
+ m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects.
+}
+
+void SymbolTable::newMachComponentSym(Symbol* sym_ptr)
+{
+ // used to cheat-- that is, access components in other machines
+ StateMachine* mach_ptr = getStateMachine("current_machine");
+ if (mach_ptr != NULL) {
+ m_machine_component_map_vec.lookup(mach_ptr->toString()).add(sym_ptr->toString(), sym_ptr);
+ }
+}
+
+Var* SymbolTable::getMachComponentVar(string mach, string ident)
+{
+ Symbol* s = m_machine_component_map_vec.lookup(mach).lookup(ident);
+ return dynamic_cast<Var*>(s);
+}
+
+
+void SymbolTable::registerSym(string id, Symbol* sym_ptr)
+{
+
+ // Check for redeclaration (in the current frame only)
+ if (m_sym_map_vec[m_depth].exist(id)) {
+ sym_ptr->error("Symbol '" + id + "' redeclared in same scope.");
+ }
+ // FIXME - warn on masking of a declaration in a previous frame
+ m_sym_map_vec[m_depth].add(id, sym_ptr);
+}
+
+void SymbolTable::registerGlobalSym(string id, Symbol* sym_ptr)
+{
+ // Check for redeclaration (global frame only)
+ if (m_sym_map_vec[0].exist(id)) {
+ sym_ptr->error("Global symbol '" + id + "' redeclared in global scope.");
+ }
+ m_sym_map_vec[0].add(id, sym_ptr);
+}
+
+Symbol* SymbolTable::getSym(string ident) const
+{
+ for (int i=m_depth; i>=0; i--) {
+ if (m_sym_map_vec[i].exist(ident)) {
+ return m_sym_map_vec[i].lookup(ident);
+ }
+ }
+ return NULL;
+}
+
+void SymbolTable::newCurrentMachine(StateMachine* sym_ptr)
+{
+ registerGlobalSym(sym_ptr->toString(), sym_ptr);
+ registerSym("current_machine", sym_ptr);
+ m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects.
+
+ Map<string, Symbol*> m;
+ m_machine_component_map_vec.add(sym_ptr->toString(),m);
+
+}
+
+Type* SymbolTable::getType(string ident) const
+{
+ return dynamic_cast<Type*>(getSym(ident));
+}
+
+Var* SymbolTable::getVar(string ident) const
+{
+ return dynamic_cast<Var*>(getSym(ident));
+}
+
+Func* SymbolTable::getFunc(string ident) const
+{
+ return dynamic_cast<Func*>(getSym(ident));
+}
+
+StateMachine* SymbolTable::getStateMachine(string ident) const
+{
+ return dynamic_cast<StateMachine*>(getSym(ident));
+}
+
+void SymbolTable::pushFrame()
+{
+ m_depth++;
+ m_sym_map_vec.expand(1);
+ m_sym_map_vec[m_depth].clear();
+}
+
+void SymbolTable::popFrame()
+{
+ m_depth--;
+ assert(m_depth >= 0);
+ m_sym_map_vec.expand(-1);
+}
+
+void SymbolTable::writeCFiles(string path) const
+{
+ int size = m_sym_vec.size();
+ {
+ // Write the Types.hh include file for the types
+ ostringstream sstr;
+ sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl;
+ sstr << endl;
+ sstr << "#include \"RubySlicc_includes.hh\"" << endl;
+ for(int i=0; i<size; i++) {
+ Type* type = dynamic_cast<Type*>(m_sym_vec[i]);
+ if (type != NULL && !type->isPrimitive()) {
+ sstr << "#include \"" << type->cIdent() << ".hh" << "\"" << endl;
+ }
+ }
+ conditionally_write_file(path + "/Types.hh", sstr);
+ }
+
+ // Write all the symbols
+ for(int i=0; i<size; i++) {
+ m_sym_vec[i]->writeCFiles(path + '/');
+ }
+
+ writeChipFiles(path);
+}
+
+void SymbolTable::writeChipFiles(string path) const
+{
+ // Create Chip.cc and Chip.hh
+
+ // FIXME - Note: this method is _really_ ugly. Most of this
+ // functionality should be pushed into each type of symbol and use
+ // virtual methods to get the right behavior for each type of
+ // symbol. This is also more flexible, and much cleaner.
+
+ int size = m_sym_vec.size();
+
+ // Create Chip.h
+ {
+ ostringstream sstr;
+ sstr << "/** \\file Chip.h " << endl;
+ sstr << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl;
+ sstr << " */ " <<endl<<endl;
+
+ sstr << "#ifndef CHIP_H" << endl;
+ sstr << "#define CHIP_H" << endl;
+ sstr << endl;
+
+ // Includes
+ sstr << "#include \"Global.hh\"" << endl;
+ sstr << "#include \"Types.hh\"" << endl;
+ sstr << "#include \"AbstractChip.hh\"" << endl;
+ sstr << "class Network;" << endl;
+ sstr << endl;
+
+ // Class declarations for all Machines/Controllers
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ sstr << "class " << machine->getIdent() << "_Controller;" << endl;
+ }
+ }
+
+ sstr << "class Chip : public AbstractChip {" << endl;
+ sstr << "public:" << endl;
+ sstr << endl;
+ sstr << " // Constructors" << endl;
+ sstr << " Chip(NodeID chip_number, Network* net_ptr);" << endl;
+ sstr << endl;
+ sstr << " // Destructor" << endl;
+ sstr << " ~Chip();" << endl;
+ sstr << endl;
+ sstr << " // Public Methods" << endl;
+ sstr << " void recordCacheContents(CacheRecorder& tr) const;" << endl;
+ sstr << " void dumpCaches(ostream& out) const;" << endl;
+ sstr << " void dumpCacheData(ostream& out) const;" << endl;
+ sstr << " static void printStats(ostream& out);" << endl;
+ sstr << " static void clearStats();" << endl;
+ sstr << " void printConfig(ostream& out);" << endl;
+ sstr << " void print(ostream& out) const;" << endl;
+
+ // Used by coherence checker
+ sstr << "#ifdef CHECK_COHERENCE" << endl;
+ sstr << " bool isBlockShared(const Address& addr) const;" << endl;
+ sstr << " bool isBlockExclusive(const Address& addr) const;" << endl;
+ sstr << "#endif /* CHECK_COHERENCE */" << endl;
+
+ sstr << endl;
+ sstr << "private:" << endl;
+ sstr << " // Private copy constructor and assignment operator" << endl;
+ sstr << " Chip(const Chip& obj);" << endl;
+ sstr << " Chip& operator=(const Chip& obj);" << endl;
+ sstr << endl;
+ sstr << "public: // FIXME - these should not be public" << endl;
+ sstr << " // Data Members (m_ prefix)" << endl;
+ sstr << endl;
+ sstr << " Chip* m_chip_ptr;" << endl;
+ sstr << endl;
+ sstr << " // SLICC object variables" << endl;
+ sstr << endl;
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->existPair("chip_object")) {
+ if (var->existPair("no_chip_object")) {
+ // Do nothing
+ } else {
+ string template_hack = "";
+ if (var->existPair("template_hack")) {
+ template_hack = var->lookupPair("template_hack");
+ }
+ if (// var->existPair("network") || var->getType()->existPair("cache") ||
+// var->getType()->existPair("tbe") || var->getType()->existPair("newtbe") ||
+// var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
+// var->getType()->existPair("filter") || var->getType()->existPair("timer") ||
+// var->existPair("trigger_queue")
+ var->existPair("no_vector")
+ ) {
+ sstr << " " << var->getType()->cIdent() << template_hack << "* m_"
+ << var->cIdent() << "_ptr;" << endl;
+ } else {
+ // create pointer except those created in AbstractChip
+ if (!(var->existPair("abstract_chip_ptr"))) {
+ sstr << " Vector < " << var->getType()->cIdent() << template_hack
+ << "* > m_" << var->cIdent() << "_vec;" << endl;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ sstr << endl;
+ sstr << " // SLICC machine/controller variables" << endl;
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " Vector < " << ident << "* > m_" << ident << "_vec;\n";
+ }
+ }
+
+ sstr << endl;
+
+ sstr << " // machine external SLICC function decls\n";
+
+ // Look at all 'Functions'
+ for(int i=0; i<size; i++) {
+ Func* func = dynamic_cast<Func*>(m_sym_vec[i]);
+ if (func != NULL) {
+ string proto;
+ func->funcPrototype(proto);
+ if (proto != "") {
+ sstr << " " << proto;
+ }
+ }
+ }
+
+ sstr << "};" << endl;
+ sstr << endl;
+ sstr << "#endif // CHIP_H" << endl;
+
+ conditionally_write_file(path + "/Chip.hh", sstr);
+ }
+ // Create Chip.cc
+ {
+ ostringstream sstr;
+ sstr << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl<<endl;
+ sstr << "#include \"Chip.hh\"" << endl;
+ sstr << "#include \"Network.hh\"" << endl;
+ sstr << "#include \"CacheRecorder.hh\"" << endl;
+ sstr << "" << endl;
+
+ sstr << "// Includes for controllers" << endl;
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ sstr << "#include \"" << machine->getIdent() << "_Controller.hh\"" << endl;
+ }
+ }
+
+ sstr << "" << endl;
+ sstr << "Chip::Chip(NodeID id, Network* net_ptr):AbstractChip(id, net_ptr)" << endl;
+ sstr << "{" << endl;
+ sstr << " m_chip_ptr = this;" << endl;
+
+ // FIXME - WHY IS THIS LOOP HERE?
+ // WE SEEM TO BE CREATING A SEQUENCER HERE THEN OVERWRITTING THAT INSTANITATION
+ // IN THE NEXT LOOP
+// // find sequencer's type
+// for(int i=0; i<size; i++) {
+// Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+// if(var && var->cIdent() == "sequencer")
+// sstr << " m_sequencer_ptr = new " << var->getType()->cIdent() << "(this);\n";
+// }
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL && var->existPair("chip_object") && !var->existPair("no_chip_object")) {
+
+ sstr << " // " << var->cIdent() << endl;
+ if (!var->existPair("network")) {
+ // Not a network port object
+ if (var->getType()->existPair("primitive")) {
+ // Normal non-object
+ // sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n";
+
+ sstr << " m_" << var->cIdent();
+ sstr << "_vec.setSize(RubyConfig::numberOf";
+ sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << ";\n";
+ if (var->existPair("default")) {
+ sstr << " *(m_" << var->cIdent() << "_vec[i]) = " << var->lookupPair("default") << ";\n";
+ }
+ sstr << " }\n";
+
+ } else {
+
+ // Normal Object
+ string template_hack = "";
+ if (var->existPair("template_hack")) {
+ template_hack = var->lookupPair("template_hack");
+ }
+ if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") ||
+// var->getType()->existPair("newtbe") || var->getType()->existPair("timer") ||
+// var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
+// var->getType()->existPair("filter") || var->existPair("trigger_queue")
+ var->existPair("no_vector")) {
+ sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack;
+ if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
+ if (var->existPair("constructor_hack")) {
+ string constructor_hack = var->lookupPair("constructor_hack");
+ sstr << "(this, " << constructor_hack << ")";
+ } else {
+ sstr << "(this)";
+ }
+ }
+ sstr << ";\n";
+ sstr << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl;
+
+ if (var->existPair("default")) {
+ sstr << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default")
+ << "; // Object default" << endl;
+ } else if (var->getType()->hasDefault()) {
+ sstr << " (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault()
+ << "; // Type " << var->getType()->getIdent() << " default" << endl;
+ }
+
+ // Set ordering
+ if (var->existPair("ordered") && !var->existPair("trigger_queue")) {
+ // A buffer
+ string ordered = var->lookupPair("ordered");
+ sstr << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
+ }
+
+ // Set randomization
+ if (var->existPair("random")) {
+ // A buffer
+ string value = var->lookupPair("random");
+ sstr << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
+ }
+
+ // Set Priority
+ if (var->getType()->isBuffer() && var->existPair("rank") && !var->existPair("trigger_queue")) {
+ string rank = var->lookupPair("rank");
+ sstr << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n";
+ }
+ } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) {
+ // FIXME - dnuca mover is a special case
+ sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl;
+ sstr << " if (RubyConfig::isL2CacheDNUCAMoverChip(m_id)) {" << endl;
+ sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack;
+ if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
+ if (var->existPair("constructor_hack")) {
+ string constructor_hack = var->lookupPair("constructor_hack");
+ sstr << "(this, " << constructor_hack << ")";
+ } else {
+ sstr << "(this)";
+ }
+ }
+ sstr << ";\n";
+ sstr << " }\n";
+ } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) {
+ sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl;
+ sstr << " \n";
+ } else {
+ sstr << " m_" << var->cIdent();
+ sstr << "_vec.setSize(RubyConfig::numberOf";
+ sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+
+
+ ostringstream tail;
+ tail << template_hack;
+ if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
+ if (var->existPair("constructor_hack")) {
+ string constructor_hack = var->lookupPair("constructor_hack");
+ tail << "(this, " << constructor_hack << ")";
+ } else {
+ tail << "(this)";
+ }
+ }
+ tail << ";\n";
+
+
+ if(var->existPair("child_selector")){
+ string child_selector = var->lookupPair("child_selector");
+ string child_types = var->lookupPair("child_types");
+ string::iterator it = child_types.begin();
+
+ uint num_types = 0;
+ for(uint t=0;t<child_types.size();t++){
+ if(child_types.at(t) == '<'){
+ num_types++;
+ }
+ }
+
+ string* types = new string[num_types];
+ string* ids = new string[num_types];
+ int type_idx = 0;
+ bool id_done = false;
+ for(uint t=0;t<child_types.size();t++){
+ if(child_types[t] == '<'){
+ id_done = false;
+ uint r;
+ for(r=t+1;child_types.at(r)!='>';r++){
+ if(r == child_types.size()){
+ cerr << "Parse error in child_types" << endl;
+ exit(EXIT_FAILURE);
+ }
+ if(child_types.at(r) == ' ') continue; //ignore whitespace
+ if(child_types.at(r) == ',') {id_done = true;continue;}
+ if(id_done == true)
+ types[type_idx].push_back(child_types.at(r));
+ else
+ ids[type_idx].push_back(child_types.at(r));
+ }
+ type_idx++;
+ t = r;
+ }
+ }
+
+ for(uint t=0;t<num_types;t++){
+ if(t==0)
+ sstr << " if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl;
+ else
+ sstr << " else if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i] = new " << types[t] << tail.str() << endl;
+ }
+ }
+ else {
+ sstr << " m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << tail.str() << endl;
+ }
+
+ sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
+ if (var->existPair("ordered")) {
+ string ordered = var->lookupPair("ordered");
+ sstr << " m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n";
+ }
+ if (var->existPair("rank")) {
+ string rank = var->lookupPair("rank");
+ sstr << " m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n";
+ }
+
+ // Set buffer size
+ if (var->getType()->isBuffer() && !var->existPair("infinite")) {
+ sstr << " if (FINITE_BUFFERING) {\n";
+ sstr << " m_" << var->cIdent() << "_vec[i]->setSize(PROCESSOR_BUFFER_SIZE);\n";
+ sstr << " }\n";
+ }
+
+ sstr << " }\n";
+ }
+ }
+
+ sstr << endl;
+
+ } else {
+ // Network port object
+ string network = var->lookupPair("network");
+ string ordered = var->lookupPair("ordered");
+ string vnet = var->lookupPair("virtual_network");
+
+ if (var->getMachine() != NULL) {
+ sstr << " m_" << var->cIdent() << "_vec.setSize(RubyConfig::numberOf"
+ << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i] = m_net_ptr->get"
+ << network << "NetQueue(i+m_id*RubyConfig::numberOf" <<var->getMachine()->getIdent()
+ << "PerChip()+MachineType_base_number(string_to_MachineType(\""
+ << var->getMachine()->getIdent() << "\")), "
+ << ordered << ", " << vnet << ");\n";
+ sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
+ } else { // old protocol
+ sstr << " m_" << var->cIdent() << "_vec.setSize(1);" << endl;
+ sstr << " for (int i = 0; i < 1; i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i] = m_net_ptr->get"
+ << network << "NetQueue(m_id, "
+ << ordered << ", " << vnet << ");\n";
+ sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
+ }
+
+ // Set ordering
+ if (var->existPair("ordered")) {
+ // A buffer
+ string ordered = var->lookupPair("ordered");
+ sstr << " m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n";
+ }
+
+ // Set randomization
+ if (var->existPair("random")) {
+ // A buffer
+ string value = var->lookupPair("random");
+ sstr << " m_" << var->cIdent() << "_vec[i]->setRandomization(" << value << ");\n";
+ }
+
+ // Set Priority
+ if (var->existPair("rank")) {
+ string rank = var->lookupPair("rank");
+ sstr << " m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n";
+ }
+
+ // Set buffer size
+ if (var->getType()->isBuffer()) {
+ sstr << " if (FINITE_BUFFERING) {\n";
+ sstr << " m_" << var->cIdent() << "_vec[i]->setSize(PROTOCOL_BUFFER_SIZE);\n";
+ sstr << " }\n";
+ }
+
+ sstr << " }\n";
+ }
+ }
+ }
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " m_" << ident << "_vec.setSize(RubyConfig::numberOf" << machine->getIdent()
+ << "PerChip(m_id));" << endl;
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << ident << "_vec[i] = new " << ident << "(this, i);\n";
+ sstr << " assert(m_" << ident << "_vec[i] != NULL);" << endl;
+ sstr << " }\n";
+ sstr << endl;
+ }
+ }
+
+ sstr << "}" << endl;
+ sstr << endl;
+ sstr << "Chip::~Chip()\n";
+ sstr << "{\n";
+
+// // FIXME: sequencer shouldn' be manually handled
+// sstr << " delete m_sequencer_ptr;" << endl;
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->existPair("chip_object")) {
+ if (var->existPair("no_chip_object")) {
+ // Do nothing
+ } else {
+ string template_hack = "";
+ if (var->existPair("template_hack")) {
+ template_hack = var->lookupPair("template_hack");
+ }
+ if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") ||
+// var->getType()->existPair("newtbe") || var->getType()->existPair("timer") ||
+// var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
+// var->getType()->existPair("filter") || var->existPair("trigger_queue")
+ var->existPair("no_vector")) {
+ sstr << " delete m_" << var->cIdent() << "_ptr;\n";
+ } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) {
+ sstr << " if (RubyConfig::isL2CacheDNUCAMoverChip(m_id)) {" << endl;
+ sstr << " delete m_" << var->cIdent() << "_ptr;\n";
+ sstr << " }\n";
+ } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) {
+ sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl;
+ } else if (!var->existPair("network")) {
+ // Normal Object
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " delete m_" << var->cIdent() << "_vec[i];\n";
+ sstr << " }\n";
+ }
+ }
+ }
+ }
+ }
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " delete m_" << ident << "_vec[i];\n";
+ sstr << " }\n";
+ }
+ }
+ sstr << "}\n";
+
+ sstr << "\n";
+ sstr << "void Chip::clearStats()\n";
+ sstr << "{\n";
+
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " " << ident << "::clearStats();\n";
+ }
+ }
+
+ sstr << "}\n";
+
+ sstr << "\n";
+ sstr << "void Chip::printStats(ostream& out)\n";
+ sstr << "{\n";
+ sstr << " out << endl;\n";
+ sstr << " out << \"Chip Stats\" << endl;\n";
+ sstr << " out << \"----------\" << endl << endl;\n";
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " " << ident << "::dumpStats(out);\n";
+ }
+ }
+
+ sstr << "}" << endl;
+ sstr << endl;
+ sstr << "void Chip::printConfig(ostream& out)\n";
+ sstr << "{\n";
+ sstr << " out << \"Chip Config\" << endl;\n";
+ sstr << " out << \"-----------\" << endl;\n";
+ sstr << " out << \"Total_Chips: \" << RubyConfig::numberOfChips() << endl;\n";
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->existPair("chip_object")) {
+ if (var->existPair("no_chip_object")) {
+ // Do nothing
+ } else {
+ string template_hack = "";
+ if (var->existPair("template_hack")) {
+ template_hack = var->lookupPair("template_hack");
+ }
+
+ if (!var->existPair("network") && (!var->getType()->existPair("primitive"))) {
+ // Normal Object
+ if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
+ if (var->existPair("no_vector")) {
+ sstr << " m_" << var->cIdent() << "_ptr->printConfig(out);\n";
+ } else {
+ sstr << " out << \"\\n" << var->cIdent() << " numberPerChip: \" << RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip() << endl;\n";
+ sstr << " m_" << var->cIdent() << "_vec[0]->printConfig(out);\n";
+// sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+// << "PerChip(m_id); i++) {" << endl;
+// sstr << " m_" << var->cIdent() << "_vec[i]->printConfig(out);\n";
+// sstr << " }\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ sstr << " out << endl;\n";
+ sstr << "}" << endl;
+
+ sstr << endl;
+ sstr << "void Chip::print(ostream& out) const\n";
+ sstr << "{\n";
+ sstr << " out << \"Ruby Chip\" << endl;\n";
+ sstr << "}" << endl;
+
+ sstr << "#ifdef CHECK_COHERENCE" << endl;
+ sstr << endl;
+ sstr << "bool Chip::isBlockShared(const Address& addr) const" << endl;
+ sstr << "{" << endl;
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockShared(addr)) {\n";
+ sstr << " return true; \n";
+ sstr << " }\n";
+ sstr << " }\n";
+ }
+ }
+ sstr << " return false;" << endl;
+ sstr << "}" << endl;
+ sstr << endl;
+
+ sstr << endl;
+ sstr << "bool Chip::isBlockExclusive(const Address& addr) const" << endl;
+ sstr << "{" << endl;
+
+ // Look at all 'Machines'
+ for(int i=0; i<size; i++) {
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ string ident = machine->getIdent() + "_Controller";
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockExclusive(addr)) {\n";
+ sstr << " return true; \n";
+ sstr << " }\n";
+ sstr << " }\n";
+ }
+ }
+
+ sstr << " return false;" << endl;
+ sstr << "}" << endl;
+ sstr << endl;
+
+ sstr << "#endif /* CHECK_COHERENCE */ " << endl;
+
+
+ sstr << endl;
+ sstr << "void Chip::dumpCaches(ostream& out) const" << endl;
+ sstr << "{" << endl;
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i]->print(out);\n";
+ sstr << " }\n";
+ }
+ }
+ }
+ sstr << "}" << endl;
+ sstr << endl;
+
+ // Function to dump cache tag and data information
+ sstr << "void Chip::dumpCacheData(ostream& out) const" << endl;
+ sstr << "{" << endl;
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i]->printData(out);\n";
+ sstr << " }\n";
+ }
+ }
+ }
+ sstr << "}" << endl;
+ sstr << endl;
+
+ sstr << "void Chip::recordCacheContents(CacheRecorder& tr) const" << endl;
+ sstr << "{" << endl;
+
+ // Look at all 'Vars'
+ for(int i=0; i<size; i++) {
+ Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
+ if (var != NULL) {
+ if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation
+ sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
+ << "PerChip(m_id); i++) {" << endl;
+ sstr << " m_" << var->cIdent() << "_vec[i]->recordCacheContents(tr);\n";
+ sstr << " }\n";
+ }
+ }
+ }
+ sstr << "}" << endl;
+
+ conditionally_write_file(path + "/Chip.cc", sstr);
+ }
+}
+
+Vector<StateMachine*> SymbolTable::getStateMachines() const
+{
+ Vector<StateMachine*> machine_vec;
+ int size = m_sym_vec.size();
+ for(int i=0; i<size; i++) {
+ StateMachine* type = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (type != NULL) {
+ machine_vec.insertAtBottom(type);
+ }
+ }
+ return machine_vec;
+}
+
+void SymbolTable::writeHTMLFiles(string path) const
+{
+ // Create index.html
+ {
+ ostringstream out;
+ createHTMLindex(path, out);
+ conditionally_write_file(path + "index.html", out);
+ }
+
+ // Create empty.html
+ {
+ ostringstream out;
+ out << "<HTML></HTML>";
+ conditionally_write_file(path + "empty.html", out);
+ }
+
+ // Write all the symbols
+ int size = m_sym_vec.size();
+ for(int i=0; i<size; i++) {
+ m_sym_vec[i]->writeHTMLFiles(path);
+ }
+}
+
+void write_file(string filename, ostringstream& sstr)
+{
+ ofstream out;
+
+ out.open(filename.c_str());
+ out << sstr.str();
+ out.close();
+}
+
+void SymbolTable::writeMIFFiles(string path) const
+{
+ int size = m_sym_vec.size();
+ for(int i=0; i<size; i++) {
+ ostringstream states, events, actions, transitions;
+ StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+ if (machine != NULL) {
+ printStateTableMIF(*machine, states);
+ write_file(path + machine->getIdent() + "_states.mif", states);
+ printEventTableMIF(*machine, events);
+ write_file(path + machine->getIdent() + "_events.mif", events);
+ printActionTableMIF(*machine, actions);
+ write_file(path + machine->getIdent() + "_actions.mif", actions);
+ printTransitionTableMIF(*machine, transitions);
+ write_file(path + machine->getIdent() + "_transitions.mif", transitions);
+ }
+ }
+}
+
+
+void SymbolTable::print(ostream& out) const
+{
+ out << "[SymbolTable]"; // FIXME
+}