summaryrefslogtreecommitdiff
path: root/src/mem/slicc/symbols/SymbolTable.cc
diff options
context:
space:
mode:
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..70391f838
--- /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 "mem/slicc/symbols/SymbolTable.hh"
+#include "mem/slicc/generator/fileio.hh"
+#include "mem/slicc/generator/html_gen.hh"
+#include "mem/slicc/generator/mif_gen.hh"
+#include "mem/slicc/symbols/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 mem/protocol/Types.hh include file for the types
+ ostringstream sstr;
+ sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl;
+ sstr << endl;
+ sstr << "#include \"mem/ruby/slicc_interface/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 \"mem/protocol/" << 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 mem/protocol/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 \"mem/ruby/common/Global.hh\"" << endl;
+ sstr << "#include \"mem/protocol/Types.hh\"" << endl;
+ sstr << "#include \"mem/ruby/slicc_interface/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 \"mem/protocol/Chip.hh\"" << endl;
+ sstr << "#include \"mem/ruby/network/Network.hh\"" << endl;
+ sstr << "#include \"mem/ruby/recorder/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 \"mem/protocol/" << 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
+}