summaryrefslogtreecommitdiff
path: root/src/mem/ruby
diff options
context:
space:
mode:
authorBrad Beckmann <Brad.Beckmann@amd.com>2010-03-21 21:22:21 -0700
committerBrad Beckmann <Brad.Beckmann@amd.com>2010-03-21 21:22:21 -0700
commit6d22db4eaa6cfb73b4a393c9f180867cebe2328f (patch)
tree112697150ab6dc76de3723cd370876c5f5d0fdfd /src/mem/ruby
parentf53287f9ad021c2b6b4f63f1cd89b3d07dd19e53 (diff)
downloadgem5-6d22db4eaa6cfb73b4a393c9f180867cebe2328f.tar.xz
ruby: Ruby support for LLSC
Diffstat (limited to 'src/mem/ruby')
-rw-r--r--src/mem/ruby/system/CacheMemory.cc17
-rw-r--r--src/mem/ruby/system/RubyPort.cc58
-rw-r--r--src/mem/ruby/system/SConscript2
-rw-r--r--src/mem/ruby/system/Sequencer.cc45
4 files changed, 102 insertions, 20 deletions
diff --git a/src/mem/ruby/system/CacheMemory.cc b/src/mem/ruby/system/CacheMemory.cc
index 110dce2d0..35625245a 100644
--- a/src/mem/ruby/system/CacheMemory.cc
+++ b/src/mem/ruby/system/CacheMemory.cc
@@ -252,6 +252,7 @@ void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
m_cache[cacheSet][i] = entry; // Init entry
m_cache[cacheSet][i]->m_Address = address;
m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid;
+ DPRINTF(RubyCache, "Allocate clearing lock for addr: %llx\n", address);
m_locked[cacheSet][i] = -1;
m_tag_index[address] = i;
@@ -273,6 +274,7 @@ void CacheMemory::deallocate(const Address& address)
if (location != -1){
delete m_cache[cacheSet][location];
m_cache[cacheSet][location] = NULL;
+ DPRINTF(RubyCache, "Deallocate clearing lock for addr: %llx\n", address);
m_locked[cacheSet][location] = -1;
m_tag_index.erase(address);
}
@@ -320,7 +322,10 @@ void CacheMemory::changePermission(const Address& address, AccessPermission new_
lookup(address).m_Permission = new_perm;
Index cacheSet = addressToCacheSet(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);
}
@@ -422,6 +427,10 @@ void CacheMemory::setMemoryValue(const Address& addr, char* value,
void
CacheMemory::setLocked(const Address& address, int context)
{
+ DPRINTF(RubyCache,
+ "Setting Lock for addr: %llx to %d\n",
+ address,
+ context);
assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
@@ -432,6 +441,7 @@ CacheMemory::setLocked(const Address& address, int context)
void
CacheMemory::clearLocked(const Address& address)
{
+ DPRINTF(RubyCache, "Clear Lock for addr: %llx\n", address);
assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
@@ -446,6 +456,11 @@ CacheMemory::isLocked(const Address& address, int context)
Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address);
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;
}
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index 07a06bd07..314f551d1 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -210,18 +210,33 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
pc = pkt->req->getPC();
}
- if (pkt->isRead()) {
- if (pkt->req->isInstFetch()) {
- type = RubyRequestType_IFETCH;
+ if (pkt->isLLSC()) {
+ if (pkt->isWrite()) {
+ DPRINTF(MemoryAccess, "Issuing SC\n");
+ type = RubyRequestType_Locked_Write;
} 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 {
- 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(),
@@ -234,10 +249,31 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
// Submit the 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;
}
-
+
DPRINTF(MemoryAccess,
"Request for address #x did not issue because %s\n",
pkt->getAddr(),
diff --git a/src/mem/ruby/system/SConscript b/src/mem/ruby/system/SConscript
index bd721e83d..715c9fb86 100644
--- a/src/mem/ruby/system/SConscript
+++ b/src/mem/ruby/system/SConscript
@@ -49,3 +49,5 @@ Source('RubyPort.cc')
Source('Sequencer.cc', Werror=False)
Source('System.cc')
Source('TimerTable.cc')
+
+TraceFlag('RubyCache')
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index b471a4b8b..d6dba08f9 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -334,11 +334,24 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
if (ruby_request.data != NULL) {
if ((type == RubyRequestType_LD) ||
(type == RubyRequestType_IFETCH) ||
- (type == RubyRequestType_RMW_Read)) {
- memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len);
+ (type == RubyRequestType_RMW_Read) ||
+ (type == RubyRequestType_Locked_Read)) {
+
+ memcpy(ruby_request.data,
+ data.getData(request_address.getOffset(), ruby_request.len),
+ ruby_request.len);
+
} 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);
if (!found) {
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
- if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), m_version)) {
- return RequestStatus_LlscFailed;
- }
+ //
+ // 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.
+ //
+ 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 {
m_dataCache_ptr->clearLocked(line_address(Address(request.paddr)));
}