ruby: Ruby support for LLSC

This commit is contained in:
Brad Beckmann
2010-03-21 21:22:21 -07:00
parent f53287f9ad
commit 6d22db4eaa
4 changed files with 102 additions and 20 deletions

View File

@@ -252,6 +252,7 @@ void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
m_cache[cacheSet][i] = entry; // Init entry m_cache[cacheSet][i] = entry; // Init entry
m_cache[cacheSet][i]->m_Address = address; m_cache[cacheSet][i]->m_Address = address;
m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid;
DPRINTF(RubyCache, "Allocate clearing lock for addr: %llx\n", address);
m_locked[cacheSet][i] = -1; m_locked[cacheSet][i] = -1;
m_tag_index[address] = i; m_tag_index[address] = i;
@@ -273,6 +274,7 @@ void CacheMemory::deallocate(const Address& address)
if (location != -1){ if (location != -1){
delete m_cache[cacheSet][location]; delete m_cache[cacheSet][location];
m_cache[cacheSet][location] = NULL; m_cache[cacheSet][location] = NULL;
DPRINTF(RubyCache, "Deallocate clearing lock for addr: %llx\n", address);
m_locked[cacheSet][location] = -1; m_locked[cacheSet][location] = -1;
m_tag_index.erase(address); m_tag_index.erase(address);
} }
@@ -320,7 +322,10 @@ void CacheMemory::changePermission(const Address& address, AccessPermission new_
lookup(address).m_Permission = new_perm; lookup(address).m_Permission = new_perm;
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
m_locked[cacheSet][loc] = -1; if (new_perm != AccessPermission_Read_Write) {
DPRINTF(RubyCache, "Permission clearing lock for addr: %llx\n", address);
m_locked[cacheSet][loc] = -1;
}
assert(getPermission(address) == new_perm); assert(getPermission(address) == new_perm);
} }
@@ -422,6 +427,10 @@ void CacheMemory::setMemoryValue(const Address& addr, char* value,
void void
CacheMemory::setLocked(const Address& address, int context) CacheMemory::setLocked(const Address& address, int context)
{ {
DPRINTF(RubyCache,
"Setting Lock for addr: %llx to %d\n",
address,
context);
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
@@ -432,6 +441,7 @@ CacheMemory::setLocked(const Address& address, int context)
void void
CacheMemory::clearLocked(const Address& address) CacheMemory::clearLocked(const Address& address)
{ {
DPRINTF(RubyCache, "Clear Lock for addr: %llx\n", address);
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
@@ -446,6 +456,11 @@ CacheMemory::isLocked(const Address& address, int context)
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
assert(loc != -1); assert(loc != -1);
DPRINTF(RubyCache,
"Testing Lock for addr: %llx cur %d con %d\n",
address,
m_locked[cacheSet][loc],
context);
return m_locked[cacheSet][loc] == context; return m_locked[cacheSet][loc] == context;
} }

View File

@@ -210,18 +210,33 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
pc = pkt->req->getPC(); pc = pkt->req->getPC();
} }
if (pkt->isRead()) { if (pkt->isLLSC()) {
if (pkt->req->isInstFetch()) { if (pkt->isWrite()) {
type = RubyRequestType_IFETCH; DPRINTF(MemoryAccess, "Issuing SC\n");
type = RubyRequestType_Locked_Write;
} else { } else {
type = RubyRequestType_LD; DPRINTF(MemoryAccess, "Issuing LL\n");
assert(pkt->isRead());
type = RubyRequestType_Locked_Read;
} }
} else if (pkt->isWrite()) {
type = RubyRequestType_ST;
} else if (pkt->isReadWrite()) {
type = RubyRequestType_RMW_Write;
} else { } else {
panic("Unsupported ruby packet type\n"); if (pkt->isRead()) {
if (pkt->req->isInstFetch()) {
type = RubyRequestType_IFETCH;
} else {
type = RubyRequestType_LD;
}
} else if (pkt->isWrite()) {
type = RubyRequestType_ST;
} else if (pkt->isReadWrite()) {
//
// Fix me. Just because the packet is a read/write request does not
// necessary mean it is a read-modify-write atomic operation.
//
type = RubyRequestType_RMW_Write;
} else {
panic("Unsupported ruby packet type\n");
}
} }
RubyRequest ruby_request(pkt->getAddr(), RubyRequest ruby_request(pkt->getAddr(),
@@ -234,10 +249,31 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
// Submit the ruby request // Submit the ruby request
RequestStatus requestStatus = ruby_port->makeRequest(ruby_request); RequestStatus requestStatus = ruby_port->makeRequest(ruby_request);
if (requestStatus == RequestStatus_Issued) {
//
// If the request successfully issued or the SC request completed because
// exclusive permission was lost, then we should return true.
// Otherwise, we need to delete the senderStatus we just created and return
// false.
//
if ((requestStatus == RequestStatus_Issued) ||
(requestStatus == RequestStatus_LlscFailed)) {
//
// The communicate to M5 whether the SC command succeeded by seting the
// packet's extra data.
//
if (pkt->isLLSC() && pkt->isWrite()) {
if (requestStatus == RequestStatus_LlscFailed) {
DPRINTF(MemoryAccess, "SC failed and request completed\n");
pkt->req->setExtraData(0);
} else {
pkt->req->setExtraData(1);
}
}
return true; return true;
} }
DPRINTF(MemoryAccess, DPRINTF(MemoryAccess,
"Request for address #x did not issue because %s\n", "Request for address #x did not issue because %s\n",
pkt->getAddr(), pkt->getAddr(),

View File

@@ -49,3 +49,5 @@ Source('RubyPort.cc')
Source('Sequencer.cc', Werror=False) Source('Sequencer.cc', Werror=False)
Source('System.cc') Source('System.cc')
Source('TimerTable.cc') Source('TimerTable.cc')
TraceFlag('RubyCache')

View File

@@ -334,11 +334,24 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
if (ruby_request.data != NULL) { if (ruby_request.data != NULL) {
if ((type == RubyRequestType_LD) || if ((type == RubyRequestType_LD) ||
(type == RubyRequestType_IFETCH) || (type == RubyRequestType_IFETCH) ||
(type == RubyRequestType_RMW_Read)) { (type == RubyRequestType_RMW_Read) ||
memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len); (type == RubyRequestType_Locked_Read)) {
memcpy(ruby_request.data,
data.getData(request_address.getOffset(), ruby_request.len),
ruby_request.len);
} else { } else {
data.setData(ruby_request.data, request_address.getOffset(), ruby_request.len);
data.setData(ruby_request.data,
request_address.getOffset(),
ruby_request.len);
} }
} else {
DPRINTF(MemoryAccess,
"WARNING. Data not transfered from Ruby to M5 for type %s\n",
RubyRequestType_to_string(type));
} }
// //
@@ -403,11 +416,27 @@ RequestStatus Sequencer::makeRequest(const RubyRequest & request)
bool found = insertRequest(srequest); bool found = insertRequest(srequest);
if (!found) { if (!found) {
if (request.type == RubyRequestType_Locked_Write) { if (request.type == RubyRequestType_Locked_Write) {
// NOTE: it is OK to check the locked flag here as the mandatory queue will be checked first //
// ensuring that nothing comes between checking the flag and servicing the store // NOTE: it is OK to check the locked flag here as the mandatory queue
if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) { // will be checked first ensuring that nothing comes between checking
return RequestStatus_LlscFailed; // the flag and servicing the store.
} //
if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)),
m_version)) {
removeRequest(srequest);
if (Debug::getProtocolTrace()) {
g_system_ptr->getProfiler()->profileTransition("Seq",
m_version,
Address(request.paddr),
"",
"SC Fail",
"",
RubyRequestType_to_string(request.type));
}
return RequestStatus_LlscFailed;
}
else { else {
m_dataCache_ptr->clearLocked(line_address(Address(request.paddr))); m_dataCache_ptr->clearLocked(line_address(Address(request.paddr)));
} }