Multi-line RMW handling
authorPolina Dudnik <pdudnik@gmail.com>
Fri, 14 Aug 2009 19:24:15 +0000 (14:24 -0500)
committerPolina Dudnik <pdudnik@gmail.com>
Fri, 14 Aug 2009 19:24:15 +0000 (14:24 -0500)
src/mem/ruby/slicc_interface/AbstractController.hh
src/mem/ruby/system/Sequencer.cc
src/mem/slicc/symbols/StateMachine.cc

index 3a93cc745350b6649ce24f2f082ca293df9b63de..329730ffd6766bae0f35bc403cd9ebbbe80b478e 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/protocol/MachineType.hh"
+#include "mem/ruby/common/Address.hh"
 
 class MessageBuffer;
 class Network;
@@ -20,6 +21,8 @@ public:
   virtual const string toString() const = 0;  // returns text version of controller type
   virtual const string getName() const = 0;   // return instance name
   virtual const MachineType getMachineType() const = 0;
+  virtual void set_atomic(Address addr) = 0;
+  virtual void clear_atomic() = 0;
 
   virtual void print(ostream & out) const = 0;
   virtual void printStats(ostream & out) const = 0;
index cd079cdc30a5a268a098fe04eacc94ec9bf4ffb5..eb3430b7f44ba343be672eab87dd5f0130e92a9b 100644 (file)
@@ -274,6 +274,12 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) {
   if (request->ruby_request.type == RubyRequestType_Locked_Read) {
     m_dataCache_ptr->setLocked(address, m_version);
   }
+  else if (request->ruby_request.type == RubyRequestType_RMW_Read) {
+    m_controller->set_atomic(address);
+  }
+  else if (request->ruby_request.type == RubyRequestType_RMW_Write) {
+    m_controller->clear_atomic();
+  }
 
   hitCallback(request, data);
 }
index 7bc84ffe0e44e32104da0358758983fe49037819..99c1953a1ce00ddd2758d3102869ee9a5e7d535e 100644 (file)
@@ -290,6 +290,8 @@ void StateMachine::printControllerH(ostream& out, string component)
   out << "  void print(ostream& out) const;" << endl;
   out << "  void printConfig(ostream& out) const;" << endl;
   out << "  void wakeup();" << endl;
+  out << "  void set_atomic(Address addr);" << endl;
+  out << "  void clear_atomic();" << endl;
   out << "  void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl;
   out << "  void clearStats() { s_profiler.clearStats(); }" << endl;
   out << "private:" << endl;
@@ -300,7 +302,11 @@ void StateMachine::printControllerH(ostream& out, string component)
   }
   if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
     out << "  bool servicing_atomic;" << endl;
-    out << "  Address locked_read_request;" << endl;
+    out << "  Address locked_read_request1;" << endl;
+    out << "  Address locked_read_request2;" << endl;
+    out << "  Address locked_read_request3;" << endl;
+    out << "  Address locked_read_request4;" << endl;
+    out << "  int read_counter;" << endl;
   }
   out << "  int m_number_of_TBEs;" << endl;
 
@@ -410,7 +416,11 @@ void StateMachine::printControllerC(ostream& out, string component)
   out << "{ " << endl;
   if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
     out << "  servicing_atomic = false;" << endl;
-    out << "  locked_read_request = Address(-1);" << endl;
+    out << "  locked_read_request1 = Address(-1);" << endl;
+    out << "  locked_read_request2 = Address(-1);" << endl;
+    out << "  locked_read_request3 = Address(-1);" << endl;
+    out << "  locked_read_request4 = Address(-1);" << endl;
+    out << "  read_counter = 0;" << endl;
   }
   out << "  m_num_controllers++; " << endl;
   for(int i=0; i < numObjects(); i++) {
@@ -717,7 +727,7 @@ void StateMachine::printControllerC(ostream& out, string component)
       string c_code_string = action.lookupPair("c_code");
 
       // add here:
-      if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
+      if (0/*strncmp(component.c_str(), "L1Cache", 7) == 0*/) {
         if (c_code_string.find("writeCallback") != string::npos) {
           string::size_type pos = c_code_string.find("(((*m_L1Cache_sequencer_ptr)).writeCallback");
           assert(pos != string::npos);
@@ -798,43 +808,67 @@ void StateMachine::printCWakeup(ostream& out, string component)
     string::size_type pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);");
     assert(pos != string::npos);
     string atomics_string = "\n \
-             bool postpone = false; \n \
              if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \
                if (!servicing_atomic) { \n \
-                  if (locked_read_request == Address(-1)) { \n \
-                    locked_read_request = addr;  \n \
+                  if (locked_read_request1 == Address(-1)) { \n \
+                    assert(read_counter == 0); \n \ 
+                    locked_read_request1 = addr;  \n \
+                    read_counter++; \n \
                   } \n \
-                  else if (addr == locked_read_request) { \n \
+                  else if (addr == locked_read_request1) { \n \
                     ; // do nothing \n\ 
                   } \n \
                   else { \n \
                     assert(0); // should never be here if servicing one request at a time \n\ 
                   } \n \
                } \n \
-               else if (addr != locked_read_request) { \n \
-                 // this is probably caused by shift optimizations \n \
-                 locked_read_request = addr; \n\
+               else if (addr != locked_read_request1) { \n \
+                  if (locked_read_request2 == Address(-1)) { \n \
+                    assert(read_counter == 1); \n \
+                    locked_read_request2 = addr; \n \
+                    read_counter++; \n \
+                  } \n \
+                  else if (locked_read_request3 == Address(-1)) { \n \
+                    assert(read_counter == 2); \n \
+                    locked_read_request3 = addr; \n \
+                    read_counter++; \n \
+                  } \n \
+                  else if (locked_read_request4 == Address(-1)) { \n \
+                    assert(read_counter == 3); \n \
+                    locked_read_request4 = addr; \n \
+                    read_counter++; \n \
+                  } \n \
+                  else { \n \
+                    // reached limit of addresses that could be locked \n \
+                    // this can happen if there are multiple optimized consequtive shifts \n \
+                    assert(0); \n \
+                  } \n \
                } \n \
              } \n \
              else { \n \
-               if (locked_read_request != Address(-1)) { \n \
-                 locked_read_request = Address(-1); \n \
+               // if an atomic is followed by non-atomic, reset -> shift optimization \n \
+               // remove this and assert(0) once shifts are resolved \n \
+               if (locked_read_request1 != Address(-1)) { \n \
+                 locked_read_request1 = Address(-1); \n \
+                 locked_read_request2 = Address(-1); \n \
+                 locked_read_request3 = Address(-1); \n \
+                 locked_read_request4 = Address(-1); \n \
                  servicing_atomic = false; \n \
+                 read_counter = 0; \n \
                } \n \
              } \n \
-           if (!postpone) { \n \
                ";
 
 
 
     output.insert(pos, atomics_string);
-    string foo = "// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n";
+    /*string foo = "// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n";
     string::size_type next_pos = output.find(foo, pos);
     next_pos = next_pos + foo.length();
 
     assert(next_pos != string::npos);
     string complete = "              }\n";
-    output.insert(next_pos, complete);
+    output.insert(next_pos, complete);*/
     //out << port->lookupPair("c_code_in_port");
     out << output;
     out << endl;
@@ -849,7 +883,10 @@ void StateMachine::printCWakeup(ostream& out, string component)
           out << "    if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) {" << endl;
           out << "      const RequestMsg* in_msg_ptr;" << endl;
           out << "      in_msg_ptr = dynamic_cast<const RequestMsg*>(((*m_L1Cache_forwardToCache_ptr)).peek());" << endl;
-          out << "      if ((servicing_atomic && locked_read_request == ((*in_msg_ptr)).m_Address)) {" << endl;
+          out << "      if ((servicing_atomic && (locked_read_request1 == ((*in_msg_ptr)).m_Address) || " << endl;
+          out << "      (locked_read_request2 == ((*in_msg_ptr)).m_Address) || (locked_read_request3 == ((*in_msg_ptr)).m_Address) || " << endl;
+          out << "      (locked_read_request4 == ((*in_msg_ptr)).m_Address))) { " << endl;
+
           out << "        postpone = true;" << endl;
           out << "      }" << endl;
           out << "    }" << endl;
@@ -876,6 +913,42 @@ void StateMachine::printCWakeup(ostream& out, string component)
   //  out << "  DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl;
   out << "}" << endl;
   out << endl;
+
+
+  // tack on two more functions
+  if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
+    out << "void " << component << "_Controller::set_atomic(Address addr)" << endl;
+    out << "{" << endl;
+    out << "  if (!servicing_atomic) { " << endl;
+    out << "    assert(addr == locked_read_request1); " << endl; 
+    out << "    servicing_atomic = true; " << endl;
+    out << "  }" << endl;
+    out << "}" << endl;
+    out << "void " << component << "_Controller::clear_atomic()" << endl;
+    out << "{" << endl;
+    out << "  assert(servicing_atomic); " << endl;
+    out << "  read_counter--; " << endl;
+    out << "  if (read_counter == 0) { " << endl;
+    out << "    servicing_atomic = false; " << endl;
+    out << "    locked_read_request1 = Address(-1); " << endl;
+    out << "    locked_read_request2 = Address(-1); " << endl;
+    out << "    locked_read_request3 = Address(-1); " << endl;
+    out << "    locked_read_request4 = Address(-1); " << endl;
+    out << "  } " << endl;
+    out << "}" << endl;
+  }
+  else {
+    out << "void " << component << "_Controller::set_atomic(Address addr)" << endl;
+    out << "{" << endl;
+    out << "  assert(0); " << endl;
+    out << "}" << endl;
+
+    out << "void " << component << "_Controller::clear_atomic()" << endl;
+    out << "{" << endl;
+    out << "  assert(0); " << endl;
+    out << "}" << endl;
+  }
+
 }
 
 void StateMachine::printCSwitch(ostream& out, string component)