changeset 21fbf0412e0d in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=21fbf0412e0d
description:
ruby: new atomics implementation
This patch changes the way that Ruby handles atomic RMW instructions.
This implementation, unlike the prior one, is protocol independent. It works by
locking an address from the sequencer immediately after the read portion of an
RMW completes. When that address is locked, the coherence controller will only
satisfy requests coming from one port (e.g., the mandatory queue) and will
ignore all others. After the write portion completed, the line is unlocked.
This should also work with multi-line atomics, as long as the blocks are always
acquired in the same order.
diffstat:
14 files changed, 59 insertions(+), 216 deletions(-)
src/mem/protocol/MESI_CMP_directory-L1cache.sm | 6
src/mem/protocol/MI_example-cache.sm | 6
src/mem/protocol/MOESI_CMP_directory-L1cache.sm | 6
src/mem/ruby/buffers/MessageBuffer.hh | 5
src/mem/ruby/config/MI_example-homogeneous.rb | 2
src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb | 6
src/mem/ruby/config/cfg.rb | 12 -
src/mem/ruby/libruby.cc | 3
src/mem/ruby/slicc_interface/AbstractController.hh | 5
src/mem/ruby/system/Sequencer.cc | 47 ------
src/mem/ruby/system/Sequencer.hh | 2
src/mem/slicc/ast/PeekStatementAST.py | 15 +
src/mem/slicc/parser.py | 4
src/mem/slicc/symbols/StateMachine.py | 156 +-------------------
diffs (truncated from 576 to 300 lines):
diff -r 3d308cbd1657 -r 21fbf0412e0d
src/mem/protocol/MESI_CMP_directory-L1cache.sm
--- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm Tue Jan 19 15:48:12
2010 -0600
+++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm Tue Jan 19 17:11:36
2010 -0600
@@ -238,7 +238,7 @@
// Response IntraChip L1 Network - response msg to this L1 cache
in_port(responseIntraChipL1Network_in, ResponseMsg, responseToL1Cache) {
if (responseIntraChipL1Network_in.isReady()) {
- peek(responseIntraChipL1Network_in, ResponseMsg) {
+ peek(responseIntraChipL1Network_in, ResponseMsg, block_on="Address") {
assert(in_msg.Destination.isElement(machineID));
if(in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
trigger(Event:Data_Exclusive, in_msg.Address);
@@ -271,7 +271,7 @@
// Request InterChip network - request from this L1 cache to the shared L2
in_port(requestIntraChipL1Network_in, RequestMsg, requestToL1Cache) {
if(requestIntraChipL1Network_in.isReady()) {
- peek(requestIntraChipL1Network_in, RequestMsg) {
+ peek(requestIntraChipL1Network_in, RequestMsg, block_on="Address") {
assert(in_msg.Destination.isElement(machineID));
if (in_msg.Type == CoherenceRequestType:INV) {
trigger(Event:Inv, in_msg.Address);
@@ -292,7 +292,7 @@
// Mandatory Queue betweens Node's CPU and it's L1 caches
in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
if (mandatoryQueue_in.isReady()) {
- peek(mandatoryQueue_in, CacheMsg) {
+ peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
// Check for data access to blocks in I-cache and ifetchs to blocks in
D-cache
diff -r 3d308cbd1657 -r 21fbf0412e0d src/mem/protocol/MI_example-cache.sm
--- a/src/mem/protocol/MI_example-cache.sm Tue Jan 19 15:48:12 2010 -0600
+++ b/src/mem/protocol/MI_example-cache.sm Tue Jan 19 17:11:36 2010 -0600
@@ -138,7 +138,7 @@
in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) {
if (forwardRequestNetwork_in.isReady()) {
- peek(forwardRequestNetwork_in, RequestMsg) {
+ peek(forwardRequestNetwork_in, RequestMsg, block_on="Address") {
if (in_msg.Type == CoherenceRequestType:GETX) {
trigger(Event:Fwd_GETX, in_msg.Address);
}
@@ -160,7 +160,7 @@
in_port(responseNetwork_in, ResponseMsg, responseToCache) {
if (responseNetwork_in.isReady()) {
- peek(responseNetwork_in, ResponseMsg) {
+ peek(responseNetwork_in, ResponseMsg, block_on="Address") {
if (in_msg.Type == CoherenceResponseType:DATA) {
trigger(Event:Data, in_msg.Address);
}
@@ -174,7 +174,7 @@
// Mandatory Queue
in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
if (mandatoryQueue_in.isReady()) {
- peek(mandatoryQueue_in, CacheMsg) {
+ peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
if (cacheMemory.isTagPresent(in_msg.LineAddress) == false &&
diff -r 3d308cbd1657 -r 21fbf0412e0d
src/mem/protocol/MOESI_CMP_directory-L1cache.sm
--- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm Tue Jan 19 15:48:12
2010 -0600
+++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm Tue Jan 19 17:11:36
2010 -0600
@@ -306,7 +306,7 @@
// Request Network
in_port(requestNetwork_in, RequestMsg, requestToL1Cache) {
if (requestNetwork_in.isReady()) {
- peek(requestNetwork_in, RequestMsg) {
+ peek(requestNetwork_in, RequestMsg, block_on="Address") {
assert(in_msg.Destination.isElement(machineID));
DEBUG_EXPR("MRM_DEBUG: L1 received");
DEBUG_EXPR(in_msg.Type);
@@ -338,7 +338,7 @@
// Response Network
in_port(responseToL1Cache_in, ResponseMsg, responseToL1Cache) {
if (responseToL1Cache_in.isReady()) {
- peek(responseToL1Cache_in, ResponseMsg) {
+ peek(responseToL1Cache_in, ResponseMsg, block_on="Address") {
if (in_msg.Type == CoherenceResponseType:ACK) {
trigger(Event:Ack, in_msg.Address);
} else if (in_msg.Type == CoherenceResponseType:DATA) {
@@ -356,7 +356,7 @@
// Mandatory Queue betweens Node's CPU and it's L1 caches
in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
if (mandatoryQueue_in.isReady()) {
- peek(mandatoryQueue_in, CacheMsg) {
+ peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
// Check for data access to blocks in I-cache and ifetchs to blocks in
D-cache
diff -r 3d308cbd1657 -r 21fbf0412e0d src/mem/ruby/buffers/MessageBuffer.hh
--- a/src/mem/ruby/buffers/MessageBuffer.hh Tue Jan 19 15:48:12 2010 -0600
+++ b/src/mem/ruby/buffers/MessageBuffer.hh Tue Jan 19 17:11:36 2010 -0600
@@ -64,6 +64,11 @@
(m_prio_heap.peekMin().m_time <= g_eventQueue_ptr->getTime()));
}
+ void delayHead() {
+ MessageBufferNode node = m_prio_heap.extractMin();
+ enqueue(node.m_msgptr, 1);
+ }
+
bool areNSlotsAvailable(int n);
int getPriority() { return m_priority_rank; }
void setPriority(int rank) { m_priority_rank = rank; }
diff -r 3d308cbd1657 -r 21fbf0412e0d
src/mem/ruby/config/MI_example-homogeneous.rb
--- a/src/mem/ruby/config/MI_example-homogeneous.rb Tue Jan 19 15:48:12
2010 -0600
+++ b/src/mem/ruby/config/MI_example-homogeneous.rb Tue Jan 19 17:11:36
2010 -0600
@@ -13,7 +13,7 @@
# default values
num_cores = 2
-l1_cache_size_kb = 32768
+l1_cache_size_bytes = 32768
l1_cache_assoc = 8
l1_cache_latency = 1
num_memories = 2
diff -r 3d308cbd1657 -r 21fbf0412e0d
src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb
--- a/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb Tue Jan 19 15:48:12
2010 -0600
+++ b/src/mem/ruby/config/TwoLevel_SplitL1UnifiedL2.rb Tue Jan 19 17:11:36
2010 -0600
@@ -68,8 +68,8 @@
require protocol+".rb"
num_cores.times { |n|
- icache = SetAssociativeCache.new("l1i_"+n.to_s, l1_icache_size_kb,
l1_icache_latency, l1_icache_assoc, "PSEUDO_LRU")
- dcache = SetAssociativeCache.new("l1d_"+n.to_s, l1_dcache_size_kb,
l1_dcache_latency, l1_dcache_assoc, "PSEUDO_LRU")
+ icache = SetAssociativeCache.new("l1i_"+n.to_s, l1_icache_size_kb*1024,
l1_icache_latency, l1_icache_assoc, "PSEUDO_LRU")
+ dcache = SetAssociativeCache.new("l1d_"+n.to_s, l1_dcache_size_kb*1024,
l1_dcache_latency, l1_dcache_assoc, "PSEUDO_LRU")
sequencer = Sequencer.new("Sequencer_"+n.to_s, icache, dcache)
iface_ports << sequencer
if protocol == "MOESI_CMP_directory"
@@ -87,7 +87,7 @@
end
}
num_l2_banks.times { |n|
- cache = SetAssociativeCache.new("l2u_"+n.to_s,
l2_cache_size_kb/num_l2_banks, l2_cache_latency, l2_cache_assoc, "PSEUDO_LRU")
+ cache = SetAssociativeCache.new("l2u_"+n.to_s,
(l2_cache_size_kb*1024)/num_l2_banks, l2_cache_latency, l2_cache_assoc,
"PSEUDO_LRU")
if protocol == "MOESI_CMP_directory"
net_ports <<
MOESI_CMP_directory_L2CacheController.new("L2CacheController_"+n.to_s,
"L2Cache",
diff -r 3d308cbd1657 -r 21fbf0412e0d src/mem/ruby/config/cfg.rb
--- a/src/mem/ruby/config/cfg.rb Tue Jan 19 15:48:12 2010 -0600
+++ b/src/mem/ruby/config/cfg.rb Tue Jan 19 17:11:36 2010 -0600
@@ -385,12 +385,12 @@
end
class Cache < LibRubyObject
- param :size_kb, Integer
+ param :size, Integer
param :latency, Integer
param :controller, NetPort
- def initialize(obj_name, size_kb, latency)
+ def initialize(obj_name, size, latency)
super(obj_name)
- self.size_kb = size_kb
+ self.size = size
self.latency = latency
# controller must be set manually by the configuration script
# because there is a cyclic dependence
@@ -406,8 +406,8 @@
# when an integer, it represents the number of cycles for a hit
# when a float, it represents the cache access time in ns
# when set to "auto", libruby will attempt to find a realistic latency by
running CACTI
- def initialize(obj_name, size_kb, latency, assoc, replacement_policy)
- super(obj_name, size_kb, latency)
+ def initialize(obj_name, size, latency, assoc, replacement_policy)
+ super(obj_name, size, latency)
self.assoc = assoc
self.replacement_policy = replacement_policy
end
@@ -415,7 +415,7 @@
def calculateLatency()
if self.latency == "auto"
cacti_args = Array.new()
- cacti_args << (self.size_kb*1024) << RubySystem.block_size_bytes <<
self.assoc
+ cacti_args << (self.size*1024) << RubySystem.block_size_bytes <<
self.assoc
cacti_args << 1 << 0 << 0 << 0 << 1
cacti_args << RubySystem.tech_nm << RubySystem.block_size_bytes*8
cacti_args << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 1
diff -r 3d308cbd1657 -r 21fbf0412e0d src/mem/ruby/libruby.cc
--- a/src/mem/ruby/libruby.cc Tue Jan 19 15:48:12 2010 -0600
+++ b/src/mem/ruby/libruby.cc Tue Jan 19 17:11:36 2010 -0600
@@ -58,11 +58,8 @@
ostream& operator<<(ostream& out, const RubyRequestType& obj)
{
- cerr << "in op" << endl;
out << RubyRequestType_to_string(obj);
- cerr << "flushing" << endl;
out << flush;
- cerr << "done" << endl;
return out;
}
diff -r 3d308cbd1657 -r 21fbf0412e0d
src/mem/ruby/slicc_interface/AbstractController.hh
--- a/src/mem/ruby/slicc_interface/AbstractController.hh Tue Jan 19
15:48:12 2010 -0600
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh Tue Jan 19
17:11:36 2010 -0600
@@ -21,9 +21,8 @@
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(Address addr) = 0;
- virtual void reset_atomics() = 0;
+ virtual void blockOnQueue(Address, MessageBuffer*) = 0;
+ virtual void unblock(Address) = 0;
virtual void print(ostream & out) const = 0;
virtual void printStats(ostream & out) const = 0;
diff -r 3d308cbd1657 -r 21fbf0412e0d src/mem/ruby/system/Sequencer.cc
--- a/src/mem/ruby/system/Sequencer.cc Tue Jan 19 15:48:12 2010 -0600
+++ b/src/mem/ruby/system/Sequencer.cc Tue Jan 19 17:11:36 2010 -0600
@@ -66,8 +66,6 @@
m_instCache_ptr = NULL;
m_dataCache_ptr = NULL;
m_controller = NULL;
- m_atomic_reads = 0;
- m_atomic_writes = 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"
@@ -285,15 +283,15 @@
(request->ruby_request.type == RubyRequestType_RMW_Write) ||
(request->ruby_request.type == RubyRequestType_Locked_Read) ||
(request->ruby_request.type == RubyRequestType_Locked_Write));
- // POLINA: the assumption is that atomics are only on data cache and not
instruction cache
+
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);
+ m_controller->blockOnQueue(address, m_mandatory_q_ptr);
}
else if (request->ruby_request.type == RubyRequestType_RMW_Write) {
- m_controller->clear_atomic(address);
+ m_controller->unblock(address);
}
hitCallback(request, data);
@@ -438,42 +436,12 @@
CacheRequestType ctype;
switch(request.type) {
case RubyRequestType_IFETCH:
- if (m_atomic_reads > 0 && m_atomic_writes == 0) {
- m_controller->reset_atomics();
- m_atomic_writes = 0;
- m_atomic_reads = 0;
- }
- else if (m_atomic_writes > 0) {
- assert(m_atomic_reads > m_atomic_writes);
- cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but
only received: " << m_atomic_writes << endl;
- assert(false);
- }
ctype = CacheRequestType_IFETCH;
break;
case RubyRequestType_LD:
- if (m_atomic_reads > 0 && m_atomic_writes == 0) {
- m_controller->reset_atomics();
- m_atomic_writes = 0;
- m_atomic_reads = 0;
- }
- else if (m_atomic_writes > 0) {
- assert(m_atomic_reads > m_atomic_writes);
- cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but
only received: " << m_atomic_writes << endl;
- assert(false);
- }
ctype = CacheRequestType_LD;
break;
case RubyRequestType_ST:
- if (m_atomic_reads > 0 && m_atomic_writes == 0) {
- m_controller->reset_atomics();
- m_atomic_writes = 0;
- m_atomic_reads = 0;
- }
- else if (m_atomic_writes > 0) {
- assert(m_atomic_reads > m_atomic_writes);
- cerr << "WARNING: Expected: " << m_atomic_reads << " RMW_Writes, but
only received: " << m_atomic_writes << endl;
- assert(false);
- }
ctype = CacheRequestType_ST;
break;
case RubyRequestType_Locked_Read:
@@ -481,18 +449,9 @@
ctype = CacheRequestType_ATOMIC;
break;
case RubyRequestType_RMW_Read:
- assert(m_atomic_writes == 0);
- m_atomic_reads++;
ctype = CacheRequestType_ATOMIC;
break;
case RubyRequestType_RMW_Write:
- assert(m_atomic_reads > 0);
- assert(m_atomic_writes < m_atomic_reads);
- m_atomic_writes++;
- if (m_atomic_reads == m_atomic_writes) {
- m_atomic_reads = 0;
- m_atomic_writes = 0;
- }
ctype = CacheRequestType_ATOMIC;
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev