diff --git a/src/mem/ruby/libruby.hh b/src/mem/ruby/libruby.hh index 3b6e19c41..a73ff5cf4 100644 --- a/src/mem/ruby/libruby.hh +++ b/src/mem/ruby/libruby.hh @@ -31,10 +31,11 @@ struct RubyRequest { uint64_t pc; RubyRequestType type; RubyAccessMode access_mode; + unsigned proc_id; RubyRequest() {} - RubyRequest(uint64_t _paddr, uint8_t* _data, int _len, uint64_t _pc, RubyRequestType _type, RubyAccessMode _access_mode) - : paddr(_paddr), data(_data), len(_len), pc(_pc), type(_type), access_mode(_access_mode) + RubyRequest(uint64_t _paddr, uint8_t* _data, int _len, uint64_t _pc, RubyRequestType _type, RubyAccessMode _access_mode, unsigned _proc_id = 0) + : paddr(_paddr), data(_data), len(_len), pc(_pc), type(_type), access_mode(_access_mode), proc_id(_proc_id) {} }; diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 3a93cc745..7da3d317a 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -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,9 @@ 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 started_writes() = 0; + virtual void clear_atomic() = 0; virtual void print(ostream & out) const = 0; virtual void printStats(ostream & out) const = 0; diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index a030fc7c2..780c1128e 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -61,6 +61,8 @@ void Sequencer::init(const vector & argv) m_instCache_ptr = NULL; m_dataCache_ptr = NULL; m_controller = NULL; + m_servicing_atomic = -1; + m_atomics_counter = 0; for (size_t i=0; iruby_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); } @@ -342,7 +350,7 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) { } // Returns true if the sequencer already has a load or store outstanding -bool Sequencer::isReady(const RubyRequest& request) const { +bool Sequencer::isReady(const RubyRequest& request) { // POLINA: check if we are currently flushing the write buffer, if so Ruby is returned as not ready // to simulate stalling of the front-end // Do we stall all the sequencers? If it is atomic instruction - yes! @@ -357,6 +365,31 @@ bool Sequencer::isReady(const RubyRequest& request) const { return false; } + if (m_servicing_atomic != -1 && m_servicing_atomic != (int)request.proc_id) { + assert(m_atomics_counter > 0); + return false; + } + else { + if (request.type == RubyRequestType_RMW_Read) { + if (m_servicing_atomic == -1) { + assert(m_atomics_counter == 0); + m_servicing_atomic = (int)request.proc_id; + } + else { + assert(m_servicing_atomic == (int)request.proc_id); + } + m_atomics_counter++; + } + else if (request.type == RubyRequestType_RMW_Write) { + assert(m_servicing_atomic == (int)request.proc_id); + assert(m_atomics_counter > 0); + m_atomics_counter--; + if (m_atomics_counter == 0) { + m_servicing_atomic = -1; + } + } + } + return true; } @@ -383,6 +416,9 @@ int64_t Sequencer::makeRequest(const RubyRequest & request) m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); } } + if (request.type == RubyRequestType_RMW_Write) { + m_controller->started_writes(); + } issueRequest(request); // TODO: issue hardware prefetches here @@ -438,7 +474,7 @@ void Sequencer::issueRequest(const RubyRequest& request) { } Address line_addr(request.paddr); line_addr.makeLineAddress(); - CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No); + CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id); if (Debug::getProtocolTrace()) { g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr), diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh index 9b55e9781..2b1f023c5 100644 --- a/src/mem/ruby/system/Sequencer.hh +++ b/src/mem/ruby/system/Sequencer.hh @@ -84,7 +84,7 @@ public: // called by Tester or Simics int64_t makeRequest(const RubyRequest & request); - bool isReady(const RubyRequest& request) const; + bool isReady(const RubyRequest& request); bool empty() const; void print(ostream& out) const; @@ -125,7 +125,8 @@ private: // Global outstanding request count, across all request tables int m_outstanding_count; bool m_deadlock_check_scheduled; - + int m_servicing_atomic; + int m_atomics_counter; }; // Output operator declaration diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc index 7bc84ffe0..0a3d4a85d 100644 --- a/src/mem/slicc/symbols/StateMachine.cc +++ b/src/mem/slicc/symbols/StateMachine.cc @@ -290,6 +290,9 @@ 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 started_writes();" << 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; @@ -299,8 +302,13 @@ void StateMachine::printControllerH(ostream& out, string component) out << " int m_" << m_config_parameters->ref(i)->getName() << ";" << endl; } if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " bool servicing_atomic;" << endl; - out << " Address locked_read_request;" << endl; + out << " int servicing_atomic;" << endl; + out << " bool started_receiving_writes;" << 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; @@ -409,8 +417,13 @@ void StateMachine::printControllerC(ostream& out, string component) out << " : m_name(name)" << endl; out << "{ " << endl; if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " servicing_atomic = false;" << endl; - out << " locked_read_request = Address(-1);" << endl; + out << " servicing_atomic = 0;" << endl; + out << " started_receiving_writes = 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 << " read_counter = 0;" << endl; } out << " m_num_controllers++; " << endl; for(int i=0; i < numObjects(); i++) { @@ -716,23 +729,6 @@ 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 (c_code_string.find("writeCallback") != string::npos) { - string::size_type pos = c_code_string.find("(((*m_L1Cache_sequencer_ptr)).writeCallback"); - assert(pos != string::npos); - string atomics_string = "\n if (servicing_atomic) { \n \ - servicing_atomic = false; \n \ - locked_read_request = Address(-1); \n \ - } \n \ - else if (!servicing_atomic) { \n \ - if (addr == locked_read_request) { \n \ - servicing_atomic = true; \n \ - } \n \ - } \n "; - c_code_string.insert(pos, atomics_string); - } - } out << c_code_string; out << "}" << endl; @@ -798,43 +794,84 @@ 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 (servicing_atomic == 0) { \n \ + if (locked_read_request1 == Address(-1)) { \n \ + assert(read_counter == 0); \n \ + locked_read_request1 = addr; \n \ + assert(read_counter == 0); \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 (!started_receiving_writes) { \n \ + if (servicing_atomic == 1) { \n \ + if (locked_read_request2 == Address(-1)) { \n \ + assert(locked_read_request1 != Address(-1)); \n \ + assert(read_counter == 1); \n \ + locked_read_request2 = addr; \n \ + assert(read_counter == 1); \n \ + read_counter++; \n \ + } \n \ + else if (addr == locked_read_request2) { \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 (servicing_atomic == 2) { \n \ + if (locked_read_request3 == Address(-1)) { \n \ + assert(locked_read_request1 != Address(-1)); \n \ + assert(locked_read_request2 != Address(-1)); \n \ + assert(read_counter == 1); \n \ + locked_read_request3 = addr; \n \ + assert(read_counter == 2); \n \ + read_counter++; \n \ + } \n \ + else if (addr == locked_read_request3) { \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 (servicing_atomic == 3) { \n \ + if (locked_read_request4 == Address(-1)) { \n \ + assert(locked_read_request1 != Address(-1)); \n \ + assert(locked_read_request2 != Address(-1)); \n \ + assert(locked_read_request3 != Address(-1)); \n \ + assert(read_counter == 1); \n \ + locked_read_request4 = addr; \n \ + assert(read_counter == 3); \n \ + read_counter++; \n \ + } \n \ + else if (addr == locked_read_request4) { \n \ + ; // do nothing \n\ + } \n \ + else { \n \ + assert(0); // should never be here if servicing one request at a time \n\ + } \n \ + } \n \ + else { \n \ + assert(0); \n \ } \n \ } \n \ - else { \n \ - if (locked_read_request != Address(-1)) { \n \ - locked_read_request = Address(-1); \n \ - servicing_atomic = false; \n \ - } \n \ - } \n \ - if (!postpone) { \n \ + } \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,9 +886,16 @@ 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(((*m_L1Cache_forwardToCache_ptr)).peek());" << endl; - out << " if ((servicing_atomic && locked_read_request == ((*in_msg_ptr)).m_Address)) {" << endl; + out << " if ((((servicing_atomic == 1) && (locked_read_request1 == ((*in_msg_ptr)).m_Address)) || " << endl; + out << " ((servicing_atomic == 2) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address)) || " << endl; + out << " ((servicing_atomic == 3) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address)) || " << endl; + out << " ((servicing_atomic == 4) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || 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; out << " if (!postpone) {" << endl; } @@ -876,6 +920,49 @@ 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 << " servicing_atomic++; " << endl; + out << "}" << endl; + out << "void " << component << "_Controller::started_writes()" << endl; + out << "{" << endl; + out << " started_receiving_writes = true; " << endl; + out << "}" << endl; + out << "void " << component << "_Controller::clear_atomic()" << endl; + out << "{" << endl; + out << " assert(servicing_atomic > 0); " << endl; + out << " read_counter--; " << endl; + out << " servicing_atomic--; " << endl; + out << " if (read_counter == 0) { " << endl; + out << " servicing_atomic = 0; " << endl; + out << " started_receiving_writes = 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::started_writes()" << endl; + out << "{" << endl; + out << " assert(0); " << endl; + out << "}" << endl; + 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) diff --git a/src/mem/slicc/symbols/Type.cc b/src/mem/slicc/symbols/Type.cc index eb53cc7b9..5afe53423 100644 --- a/src/mem/slicc/symbols/Type.cc +++ b/src/mem/slicc/symbols/Type.cc @@ -277,6 +277,11 @@ void Type::printTypeH(string path) const string id = m_data_member_ident_vec[i]; out << "const " << type->cIdent() << "& local_" << id; } + + if (isMessage()) { + out << ", const unsigned local_proc_id" << flush; + } + out << ")" << endl; // Call superclass constructor @@ -293,7 +298,9 @@ void Type::printTypeH(string path) const string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); out << " m_" << id << next_line_value << ";" << endl; } - + } + if (isMessage()) { + out << " proc_id = local_proc_id;" << endl << flush; } out << " }" << endl; } // end of if(!isGlobal()) @@ -428,6 +435,10 @@ void Type::printTypeH(string path) const } } + if (isMessage()) { + out << " unsigned proc_id;" << endl << flush; + } + out << "};" << endl; // End class out << "// Output operator declaration" << endl;