Merge with head.
This commit is contained in:
commit
a1ea10d7ba
|
@ -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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -61,6 +61,8 @@ void Sequencer::init(const vector<string> & 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; i<argv.size(); i+=2) {
|
||||
if ( argv[i] == "controller") {
|
||||
m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache"
|
||||
|
@ -272,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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<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 == 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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue