summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/example/ruby_mem_test.py1
-rw-r--r--src/mem/protocol/MESI_CMP_directory-L1cache.sm5
-rw-r--r--src/mem/protocol/MESI_CMP_directory-L2cache.sm5
-rw-r--r--src/mem/protocol/MESI_CMP_directory-dir.sm7
-rw-r--r--src/mem/protocol/MESI_CMP_directory-msg.sm53
-rw-r--r--src/mem/protocol/MI_example-cache.sm5
-rw-r--r--src/mem/protocol/MI_example-dir.sm13
-rw-r--r--src/mem/protocol/MI_example-msg.sm44
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-L1cache.sm12
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-L2cache.sm14
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-dir.sm3
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-msg.sm40
-rw-r--r--src/mem/protocol/MOESI_CMP_token-L1cache.sm2
-rw-r--r--src/mem/protocol/MOESI_CMP_token-dir.sm1
-rw-r--r--src/mem/protocol/MOESI_CMP_token-msg.sm47
-rw-r--r--src/mem/protocol/MOESI_hammer-cache.sm13
-rw-r--r--src/mem/protocol/MOESI_hammer-dir.sm27
-rw-r--r--src/mem/protocol/MOESI_hammer-msg.sm57
-rw-r--r--src/mem/protocol/Network_test-msg.sm4
-rw-r--r--src/mem/protocol/RubySlicc_Exports.sm21
-rw-r--r--src/mem/protocol/RubySlicc_MemControl.sm8
-rw-r--r--src/mem/ruby/buffers/MessageBuffer.cc66
-rw-r--r--src/mem/ruby/buffers/MessageBuffer.hh20
-rw-r--r--src/mem/ruby/buffers/MessageBufferNode.hh1
-rw-r--r--src/mem/ruby/network/Network.hh13
-rw-r--r--src/mem/ruby/network/simple/PerfectSwitch.cc1
-rw-r--r--src/mem/ruby/network/simple/SimpleNetwork.cc38
-rw-r--r--src/mem/ruby/network/simple/SimpleNetwork.hh3
-rw-r--r--src/mem/ruby/network/simple/Switch.cc22
-rw-r--r--src/mem/ruby/network/simple/Switch.hh3
-rw-r--r--src/mem/ruby/slicc_interface/AbstractController.hh10
-rw-r--r--src/mem/ruby/slicc_interface/Message.hh12
-rw-r--r--src/mem/ruby/slicc_interface/NetworkMessage.hh1
-rw-r--r--src/mem/ruby/slicc_interface/RubyRequest.cc37
-rw-r--r--src/mem/ruby/slicc_interface/RubyRequest.hh3
-rw-r--r--src/mem/ruby/slicc_interface/RubySlicc_Util.hh57
-rw-r--r--src/mem/ruby/system/MemoryControl.cc14
-rw-r--r--src/mem/ruby/system/MemoryControl.hh10
-rw-r--r--src/mem/ruby/system/RubyMemoryControl.cc88
-rw-r--r--src/mem/ruby/system/RubyMemoryControl.hh2
-rw-r--r--src/mem/ruby/system/System.cc110
-rw-r--r--src/mem/slicc/ast/TypeDeclAST.py3
-rw-r--r--src/mem/slicc/symbols/StateMachine.py36
-rw-r--r--src/mem/slicc/symbols/SymbolTable.py3
-rw-r--r--src/mem/slicc/symbols/Type.py5
45 files changed, 802 insertions, 138 deletions
diff --git a/configs/example/ruby_mem_test.py b/configs/example/ruby_mem_test.py
index 858d13ee8..1d3e20412 100644
--- a/configs/example/ruby_mem_test.py
+++ b/configs/example/ruby_mem_test.py
@@ -43,7 +43,6 @@ import Ruby
# Get paths we might need. It's expected this file is in m5/configs/example.
config_path = os.path.dirname(os.path.abspath(__file__))
config_root = os.path.dirname(config_path)
-m5_root = os.path.dirname(config_root)
parser = optparse.OptionParser()
Options.addCommonOptions(parser)
diff --git a/src/mem/protocol/MESI_CMP_directory-L1cache.sm b/src/mem/protocol/MESI_CMP_directory-L1cache.sm
index d54f7e71c..eb8e62d30 100644
--- a/src/mem/protocol/MESI_CMP_directory-L1cache.sm
+++ b/src/mem/protocol/MESI_CMP_directory-L1cache.sm
@@ -201,6 +201,11 @@ machine(L1Cache, "MESI Directory L1 Cache CMP")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := L1_TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getCacheEntry(addr).DataBlk;
}
diff --git a/src/mem/protocol/MESI_CMP_directory-L2cache.sm b/src/mem/protocol/MESI_CMP_directory-L2cache.sm
index 88053aeb8..fbdc10ac2 100644
--- a/src/mem/protocol/MESI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MESI_CMP_directory-L2cache.sm
@@ -232,6 +232,11 @@ machine(L2Cache, "MESI Directory L2 Cache CMP")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := L2_TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getCacheEntry(addr).DataBlk;
}
diff --git a/src/mem/protocol/MESI_CMP_directory-dir.sm b/src/mem/protocol/MESI_CMP_directory-dir.sm
index 7e1280337..d98326b34 100644
--- a/src/mem/protocol/MESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MESI_CMP_directory-dir.sm
@@ -110,7 +110,7 @@ machine(Directory, "MESI_CMP_filter_directory protocol")
void set_tbe(TBE tbe);
void unset_tbe();
void wakeUpBuffers(Address a);
-
+
Entry getDirectoryEntry(Address addr), return_by_pointer="yes" {
Entry dir_entry := static_cast(Entry, "pointer", directory[addr]);
@@ -170,6 +170,11 @@ machine(Directory, "MESI_CMP_filter_directory protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getDirectoryEntry(addr).DataBlk;
}
diff --git a/src/mem/protocol/MESI_CMP_directory-msg.sm b/src/mem/protocol/MESI_CMP_directory-msg.sm
index 67619f075..473012c61 100644
--- a/src/mem/protocol/MESI_CMP_directory-msg.sm
+++ b/src/mem/protocol/MESI_CMP_directory-msg.sm
@@ -35,11 +35,9 @@ enumeration(CoherenceRequestType, desc="...") {
GETS, desc="Get Shared";
GET_INSTR, desc="Get Instruction";
INV, desc="INValidate";
- PUTX, desc="replacement message";
+ PUTX, desc="Replacement message";
WB_ACK, desc="Writeback ack";
- WB_NACK, desc="Writeback neg. ack";
- FWD, desc="Generic FWD";
DMA_READ, desc="DMA Read";
DMA_WRITE, desc="DMA Write";
@@ -47,14 +45,14 @@ enumeration(CoherenceRequestType, desc="...") {
// CoherenceResponseType
enumeration(CoherenceResponseType, desc="...") {
- MEMORY_ACK, desc="Ack from memory controller";
- DATA, desc="Data";
- DATA_EXCLUSIVE, desc="Data";
- MEMORY_DATA, desc="Data";
- ACK, desc="Generic invalidate ack";
- WB_ACK, desc="writeback ack";
- UNBLOCK, desc="unblock";
- EXCLUSIVE_UNBLOCK, desc="exclusive unblock";
+ MEMORY_ACK, desc="Ack from memory controller";
+ DATA, desc="Data block for L1 cache in S state";
+ DATA_EXCLUSIVE, desc="Data block for L1 cache in M/E state";
+ MEMORY_DATA, desc="Data block from / to main memory";
+ ACK, desc="Generic invalidate ack";
+ WB_ACK, desc="writeback ack";
+ UNBLOCK, desc="unblock";
+ EXCLUSIVE_UNBLOCK, desc="exclusive unblock";
INV, desc="Invalidate from directory";
}
@@ -70,6 +68,21 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
int Len;
bool Dirty, default="false", desc="Dirty bit";
PrefetchBit Prefetch, desc="Is this a prefetch request";
+
+ bool functionalRead(Packet *pkt) {
+ // Only PUTX messages contains the data block
+ if (Type == CoherenceRequestType:PUTX) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check on message type required since the protocol should
+ // read data from those messages that contain the block
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
// ResponseMsg
@@ -82,4 +95,22 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
bool Dirty, default="false", desc="Dirty bit";
int AckCount, default="0", desc="number of acks in this message";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ // Valid data block is only present in message with following types
+ if (Type == CoherenceResponseType:DATA ||
+ Type == CoherenceResponseType:DATA_EXCLUSIVE ||
+ Type == CoherenceResponseType:MEMORY_DATA) {
+
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check on message type required since the protocol should
+ // read data from those messages that contain the block
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
diff --git a/src/mem/protocol/MI_example-cache.sm b/src/mem/protocol/MI_example-cache.sm
index cf5cf9505..5040eb85d 100644
--- a/src/mem/protocol/MI_example-cache.sm
+++ b/src/mem/protocol/MI_example-cache.sm
@@ -168,6 +168,11 @@ machine(L1Cache, "MI Example L1 Cache")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getCacheEntry(addr).DataBlk;
}
diff --git a/src/mem/protocol/MI_example-dir.sm b/src/mem/protocol/MI_example-dir.sm
index 241ad3b30..f15ccb14e 100644
--- a/src/mem/protocol/MI_example-dir.sm
+++ b/src/mem/protocol/MI_example-dir.sm
@@ -172,6 +172,11 @@ machine(Directory, "Directory protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getDirectoryEntry(addr).DataBlk;
}
@@ -506,7 +511,6 @@ machine(Directory, "Directory protocol")
out_msg.OriginalRequestorMachId := in_msg.Requestor;
out_msg.DataBlk := in_msg.DataBlk;
out_msg.MessageSize := in_msg.MessageSize;
- //out_msg.Prefetch := in_msg.Prefetch;
DPRINTF(RubySlicc,"%s\n", out_msg);
}
@@ -518,12 +522,8 @@ machine(Directory, "Directory protocol")
}
action(w_writeDataToMemoryFromTBE, "\w", desc="Write date to directory memory from TBE") {
- //getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk;
assert(is_valid(tbe));
- getDirectoryEntry(address).DataBlk.copyPartial(tbe.DataBlk,
- addressOffset(tbe.PhysicalAddress),
- tbe.Len);
-
+ getDirectoryEntry(address).DataBlk := TBEs[address].DataBlk;
}
// TRANSITIONS
@@ -633,7 +633,6 @@ machine(Directory, "Directory protocol")
}
transition(M, PUTX, MI) {
- l_writeDataToMemory;
c_clearOwner;
v_allocateTBEFromRequestNet;
l_queueMemoryWBRequest;
diff --git a/src/mem/protocol/MI_example-msg.sm b/src/mem/protocol/MI_example-msg.sm
index 2fb1c48ba..0645371f6 100644
--- a/src/mem/protocol/MI_example-msg.sm
+++ b/src/mem/protocol/MI_example-msg.sm
@@ -31,11 +31,9 @@ enumeration(CoherenceRequestType, desc="...") {
GETX, desc="Get eXclusive";
GETS, desc="Get Shared";
PUTX, desc="Put eXclusive";
- PUTO, desc="Put Owned";
WB_ACK, desc="Writeback ack";
WB_NACK, desc="Writeback neg. ack";
INV, desc="Invalidation";
- FWD, desc="Generic FWD";
}
// CoherenceResponseType
@@ -59,6 +57,20 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
NetDest Destination, desc="Multicast destination mask";
DataBlock DataBlk, desc="data for the cache line";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ // Valid data block is only present in PUTX messages
+ if (Type == CoherenceRequestType:PUTX) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check on message type required since the protocol should read
+ // data block from only those messages that contain valid data
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
// ResponseMsg (and also unblock requests)
@@ -70,6 +82,18 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
DataBlock DataBlk, desc="data for the cache line";
bool Dirty, desc="Is the data dirty (different than memory)?";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ // A check on message type should appear here so that only those
+ // messages that contain data
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check on message type required since the protocol should read
+ // data block from only those messages that contain valid data
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
@@ -93,6 +117,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
DataBlock DataBlk, desc="DataBlk attached to this request";
int Len, desc="The length of the request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(LineAddress, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
@@ -102,4 +134,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
NetDest Destination, desc="Destination";
DataBlock DataBlk, desc="DataBlk attached to this request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(LineAddress, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
diff --git a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
index 43c2def2e..6295f90fd 100644
--- a/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-L1cache.sm
@@ -219,7 +219,17 @@ machine(L1Cache, "Directory protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
- return getCacheEntry(addr).DataBlk;
+ Entry cache_entry := getCacheEntry(addr);
+ if(is_valid(cache_entry)) {
+ return cache_entry.DataBlk;
+ }
+
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
+ error("Data block missing!");
}
Event mandatory_request_type_to_event(RubyRequestType type) {
diff --git a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
index 6238953ad..2e4e66a7b 100644
--- a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
@@ -193,7 +193,7 @@ machine(L2Cache, "Token protocol")
// TBE fields
structure(TBE, desc="...") {
- Address Address, desc="Physical address for this TBE";
+ Address address, desc="Physical address for this TBE";
State TBEState, desc="Transient state";
Address PC, desc="Program counter of request";
DataBlock DataBlk, desc="Buffer for the data block";
@@ -512,11 +512,6 @@ machine(L2Cache, "Token protocol")
return L2Cache_State_to_permission(cache_entry.CacheState);
}
- else if (localDirectory.isTagPresent(addr)) {
- DPRINTF(RubySlicc, "%s\n", L2Cache_State_to_permission(localDirectory[addr].DirState));
- return L2Cache_State_to_permission(localDirectory[addr].DirState);
- }
-
DPRINTF(RubySlicc, "AccessPermission_NotPresent\n");
return AccessPermission:NotPresent;
}
@@ -528,6 +523,11 @@ machine(L2Cache, "Token protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
return getCacheEntry(addr).DataBlk;
}
@@ -1451,6 +1451,8 @@ machine(L2Cache, "Token protocol")
peek(responseNetwork_in, ResponseMsg) {
assert(is_valid(cache_entry));
cache_entry.DataBlk := in_msg.DataBlk;
+ DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
+ address, cache_entry.DataBlk);
if ((cache_entry.Dirty == false) && in_msg.Dirty) {
cache_entry.Dirty := in_msg.Dirty;
}
diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm
index 1635267f6..0dd4239a9 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm
@@ -473,6 +473,9 @@ machine(Directory, "Directory protocol")
// implementation. We include the data in the "dataless"
// message so we can assert the clean data matches the datablock
// in memory
+ DPRINTF(RubySlicc, "Address: %s, MsgDataBlock: %s MemoryDataBlock: %s\n",
+ in_msg.Address, in_msg.DataBlk,
+ getDirectoryEntry(in_msg.Address).DataBlk);
assert(getDirectoryEntry(in_msg.Address).DataBlk == in_msg.DataBlk);
}
}
diff --git a/src/mem/protocol/MOESI_CMP_directory-msg.sm b/src/mem/protocol/MOESI_CMP_directory-msg.sm
index 7b203537f..e428be7f7 100644
--- a/src/mem/protocol/MOESI_CMP_directory-msg.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-msg.sm
@@ -71,6 +71,16 @@ enumeration(TriggerType, desc="...") {
structure(TriggerMsg, desc="...", interface="Message") {
Address Address, desc="Physical address for this request";
TriggerType Type, desc="Type of trigger";
+
+ bool functionalRead(Packet *pkt) {
+ // Trigger message does not hold data
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // Trigger message does not hold data
+ return false;
+ }
}
// RequestMsg (and also forwarded requests)
@@ -86,6 +96,20 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
MessageSizeType MessageSize, desc="size category of the message";
RubyAccessMode AccessMode, desc="user/supervisor access type";
PrefetchBit Prefetch, desc="Is this a prefetch request";
+
+ bool functionalRead(Packet *pkt) {
+ // Read only those messages that contain the data
+ if (Type == CoherenceRequestType:DMA_READ ||
+ Type == CoherenceRequestType:DMA_WRITE) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check required since all messages are written
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
// ResponseMsg (and also unblock requests)
@@ -99,4 +123,20 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
bool Dirty, desc="Is the data dirty (different than memory)?";
int Acks, desc="How many acks to expect";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ // Read only those messages that contain the data
+ if (Type == CoherenceResponseType:DATA ||
+ Type == CoherenceResponseType:DATA_EXCLUSIVE ||
+ Type == CoherenceResponseType:WRITEBACK_CLEAN_DATA ||
+ Type == CoherenceResponseType:WRITEBACK_DIRTY_DATA) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check required since all messages are written
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
diff --git a/src/mem/protocol/MOESI_CMP_token-L1cache.sm b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
index b6de5a714..8cf40974e 100644
--- a/src/mem/protocol/MOESI_CMP_token-L1cache.sm
+++ b/src/mem/protocol/MOESI_CMP_token-L1cache.sm
@@ -139,7 +139,7 @@ machine(L1Cache, "Token protocol")
// TBE fields
structure(TBE, desc="...") {
- Address Address, desc="Physical address for this TBE";
+ Address address, desc="Physical address for this TBE";
State TBEState, desc="Transient state";
int IssueCount, default="0", desc="The number of times we've issued a request for this line.";
Address PC, desc="Program counter of request";
diff --git a/src/mem/protocol/MOESI_CMP_token-dir.sm b/src/mem/protocol/MOESI_CMP_token-dir.sm
index 8d78be40c..fd51e2924 100644
--- a/src/mem/protocol/MOESI_CMP_token-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_token-dir.sm
@@ -677,6 +677,7 @@ machine(Directory, "Token protocol")
enqueue(memQueue_out, MemoryMsg, latency="1") {
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
+ out_msg.DataBlk := getDirectoryEntry(address).DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
diff --git a/src/mem/protocol/MOESI_CMP_token-msg.sm b/src/mem/protocol/MOESI_CMP_token-msg.sm
index b1c3f4580..6a8d6c6bc 100644
--- a/src/mem/protocol/MOESI_CMP_token-msg.sm
+++ b/src/mem/protocol/MOESI_CMP_token-msg.sm
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
@@ -66,6 +65,16 @@ structure(PersistentMsg, desc="...", interface="NetworkMessage") {
MessageSizeType MessageSize, desc="size category of the message";
RubyAccessMode AccessMode, desc="user/supervisor access type";
PrefetchBit Prefetch, desc="Is this a prefetch request";
+
+ bool functionalRead(Packet *pkt) {
+ // No data in persistent messages
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No data in persistent messages
+ return false;
+ }
}
// RequestMsg
@@ -79,6 +88,16 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
MessageSizeType MessageSize, desc="size category of the message";
RubyAccessMode AccessMode, desc="user/supervisor access type";
PrefetchBit Prefetch, desc="Is this a prefetch request";
+
+ bool functionalRead(Packet *pkt) {
+ // No data in request messages
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No data in request messages
+ return false;
+ }
}
// ResponseMsg
@@ -91,6 +110,16 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
DataBlock DataBlk, desc="data for the cache line";
bool Dirty, desc="Is the data dirty (different than memory)?";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ // No check being carried out on the message type. Would be added later.
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // No check required since all messages are written.
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
@@ -114,6 +143,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
DataBlock DataBlk, desc="DataBlk attached to this request";
int Len, desc="The length of the request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
@@ -123,4 +160,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
NetDest Destination, desc="Destination";
DataBlock DataBlk, desc="DataBlk attached to this request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
diff --git a/src/mem/protocol/MOESI_hammer-cache.sm b/src/mem/protocol/MOESI_hammer-cache.sm
index 6eb0974b0..a3fa1219f 100644
--- a/src/mem/protocol/MOESI_hammer-cache.sm
+++ b/src/mem/protocol/MOESI_hammer-cache.sm
@@ -198,7 +198,17 @@ machine(L1Cache, "AMD Hammer-like protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
- return getCacheEntry(addr).DataBlk;
+ Entry cache_entry := getCacheEntry(addr);
+ if(is_valid(cache_entry)) {
+ return cache_entry.DataBlk;
+ }
+
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
+ error("Missing data block");
}
Entry getL2CacheEntry(Address address), return_by_pointer="yes" {
@@ -879,6 +889,7 @@ machine(L1Cache, "AMD Hammer-like protocol")
tbe.ForwardRequestTime,
tbe.FirstResponseTime);
}
+ DPRINTF(RubySlicc, "%s\n", cache_entry.DataBlk);
cache_entry.Dirty := true;
}
diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm
index ed1fb7669..22ca568a8 100644
--- a/src/mem/protocol/MOESI_hammer-dir.sm
+++ b/src/mem/protocol/MOESI_hammer-dir.sm
@@ -87,7 +87,7 @@ machine(Directory, "AMD Hammer-like protocol")
O_DR_B, AccessPermission:Busy, desc="Owner, Dma Read waiting for cache responses";
WB, AccessPermission:Busy, desc="Blocked on a writeback";
WB_O_W, AccessPermission:Busy, desc="Blocked on memory write, will go to O";
- WB_E_W, AccessPermission:Read_Write, desc="Blocked on memory write, will go to E";
+ WB_E_W, AccessPermission:Busy, desc="Blocked on memory write, will go to E";
NO_F, AccessPermission:Busy, desc="Blocked on a flush";
NO_F_W, AccessPermission:Busy, desc="Not Owner, Blocked, waiting for Dram";
@@ -199,7 +199,17 @@ machine(Directory, "AMD Hammer-like protocol")
}
DataBlock getDataBlock(Address addr), return_by_ref="yes" {
- return getDirectoryEntry(addr).DataBlk;
+ Entry dir_entry := getDirectoryEntry(addr);
+ if(is_valid(dir_entry)) {
+ return dir_entry.DataBlk;
+ }
+
+ TBE tbe := TBEs[addr];
+ if(is_valid(tbe)) {
+ return tbe.DataBlk;
+ }
+
+ error("Data block missing!");
}
PfEntry getProbeFilterEntry(Address addr), return_by_pointer="yes" {
@@ -222,7 +232,7 @@ machine(Directory, "AMD Hammer-like protocol")
return getDirectoryEntry(addr).DirectoryState;
}
}
-
+
void setState(TBE tbe, PfEntry pf_entry, Address addr, State state) {
if (is_valid(tbe)) {
tbe.TBEState := state;
@@ -1168,9 +1178,7 @@ machine(Directory, "AMD Hammer-like protocol")
}
action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
- peek(unblockNetwork_in, ResponseMsg) {
- assert(in_msg.Dirty);
- assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
+ peek(memQueue_in, MemoryMsg) {
getDirectoryEntry(address).DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "Address: %s, Data Block: %s\n",
in_msg.Address, in_msg.DataBlk);
@@ -1236,8 +1244,11 @@ machine(Directory, "AMD Hammer-like protocol")
action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
peek(unblockNetwork_in, ResponseMsg) {
enqueue(memQueue_out, MemoryMsg, latency="1") {
+ assert(in_msg.Dirty);
+ assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
out_msg.Address := address;
out_msg.Type := MemoryRequestType:MEMORY_WB;
+ out_msg.DataBlk := in_msg.DataBlk;
DPRINTF(RubySlicc, "%s\n", out_msg);
}
}
@@ -1854,26 +1865,26 @@ machine(Directory, "AMD Hammer-like protocol")
// WB State Transistions
transition(WB, Writeback_Dirty, WB_O_W) {
- l_writeDataToMemory;
rs_removeSharer;
l_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(WB, Writeback_Exclusive_Dirty, WB_E_W) {
- l_writeDataToMemory;
rs_removeSharer;
l_queueMemoryWBRequest;
j_popIncomingUnblockQueue;
}
transition(WB_E_W, Memory_Ack, E) {
+ l_writeDataToMemory;
pfd_probeFilterDeallocate;
k_wakeUpDependents;
l_popMemQueue;
}
transition(WB_O_W, Memory_Ack, O) {
+ l_writeDataToMemory;
k_wakeUpDependents;
l_popMemQueue;
}
diff --git a/src/mem/protocol/MOESI_hammer-msg.sm b/src/mem/protocol/MOESI_hammer-msg.sm
index 6ead7200a..41d176a9c 100644
--- a/src/mem/protocol/MOESI_hammer-msg.sm
+++ b/src/mem/protocol/MOESI_hammer-msg.sm
@@ -73,6 +73,16 @@ enumeration(TriggerType, desc="...") {
structure(TriggerMsg, desc="...", interface="Message") {
Address Address, desc="Physical address for this request";
TriggerType Type, desc="Type of trigger";
+
+ bool functionalRead(Packet *pkt) {
+ // Trigger messages do not hold any data!
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // Trigger messages do not hold any data!
+ return false;
+ }
}
// RequestMsg (and also forwarded requests)
@@ -87,6 +97,16 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
Time InitialRequestTime, default="0", desc="time the initial requests was sent from the L1Cache";
Time ForwardRequestTime, default="0", desc="time the dir forwarded the request";
int SilentAcks, default="0", desc="silent acks from the full-bit directory";
+
+ bool functionalRead(Packet *pkt) {
+ // Request messages do not hold any data
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // Request messages do not hold any data
+ return false;
+ }
}
// ResponseMsg (and also unblock requests)
@@ -103,6 +123,27 @@ structure(ResponseMsg, desc="...", interface="NetworkMessage") {
Time InitialRequestTime, default="0", desc="time the initial requests was sent from the L1Cache";
Time ForwardRequestTime, default="0", desc="time the dir forwarded the request";
int SilentAcks, default="0", desc="silent acks from the full-bit directory";
+
+ bool functionalRead(Packet *pkt) {
+ // The check below ensures that data is read only from messages that
+ // actually hold data.
+ if (Type == CoherenceResponseType:DATA ||
+ Type == CoherenceResponseType:DATA_SHARED ||
+ Type == CoherenceResponseType:DATA_EXCLUSIVE ||
+ Type == CoherenceResponseType:WB_DIRTY ||
+ Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ return false;
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ // Message type does not matter since all messages are written.
+ // If a protocol reads data from a packet that is not supposed
+ // to hold the data, then the fault lies with the protocol.
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
@@ -126,6 +167,14 @@ structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
DataBlock DataBlk, desc="DataBlk attached to this request";
int Len, desc="The length of the request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(LineAddress, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
@@ -135,4 +184,12 @@ structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
NetDest Destination, desc="Destination";
DataBlock DataBlk, desc="DataBlk attached to this request";
MessageSizeType MessageSize, desc="size category of the message";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(LineAddress, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(LineAddress, DataBlk, pkt);
+ }
}
diff --git a/src/mem/protocol/Network_test-msg.sm b/src/mem/protocol/Network_test-msg.sm
index 6492024d8..9e21d39bb 100644
--- a/src/mem/protocol/Network_test-msg.sm
+++ b/src/mem/protocol/Network_test-msg.sm
@@ -40,4 +40,8 @@ structure(RequestMsg, desc="...", interface="NetworkMessage") {
NetDest Destination, desc="Multicast destination mask";
DataBlock DataBlk, desc="data for the cache line";
MessageSizeType MessageSize, desc="size category of the message";
+
+ void functionalWrite(Packet *pkt) {
+ error("Network test does not support functional accesses!");
+ }
}
diff --git a/src/mem/protocol/RubySlicc_Exports.sm b/src/mem/protocol/RubySlicc_Exports.sm
index b42f9c3a9..2a4281757 100644
--- a/src/mem/protocol/RubySlicc_Exports.sm
+++ b/src/mem/protocol/RubySlicc_Exports.sm
@@ -27,24 +27,23 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * $Id$
- *
- */
-
-// defines
+// Declarations of external types that are common to all protocols
external_type(int, primitive="yes", default="0");
external_type(bool, primitive="yes", default="false");
external_type(std::string, primitive="yes");
external_type(uint64, primitive="yes");
external_type(Time, primitive="yes", default="0");
+external_type(PacketPtr, primitive="yes");
+external_type(Packet, primitive="yes");
external_type(Address);
+
structure(DataBlock, external = "yes", desc="..."){
void clear();
void copyPartial(DataBlock, int, int);
}
-// Declarations of external types that are common to all protocols
+bool testAndRead(Address addr, DataBlock datablk, Packet *pkt);
+bool testAndWrite(Address addr, DataBlock datablk, Packet *pkt);
// AccessPermission
// The following five states define the access permission of all memory blocks.
@@ -265,6 +264,14 @@ structure(SequencerMsg, desc="...", interface="Message") {
DataBlock DataBlk, desc="Data";
int Len, desc="size in bytes of access";
PrefetchBit Prefetch, desc="Is this a prefetch request";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(PhysicalAddress, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(PhysicalAddress, DataBlk, pkt);
+ }
}
// MaskPredictorType
diff --git a/src/mem/protocol/RubySlicc_MemControl.sm b/src/mem/protocol/RubySlicc_MemControl.sm
index 66bb37bca..08bff6e36 100644
--- a/src/mem/protocol/RubySlicc_MemControl.sm
+++ b/src/mem/protocol/RubySlicc_MemControl.sm
@@ -61,4 +61,12 @@ structure(MemoryMsg, desc="...", interface="Message") {
PrefetchBit Prefetch, desc="Is this a prefetch request";
bool ReadX, desc="Exclusive";
int Acks, desc="How many acks to expect";
+
+ bool functionalRead(Packet *pkt) {
+ return testAndRead(Address, DataBlk, pkt);
+ }
+
+ bool functionalWrite(Packet *pkt) {
+ return testAndWrite(Address, DataBlk, pkt);
+ }
}
diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc
index f0d372a52..f960cc033 100644
--- a/src/mem/ruby/buffers/MessageBuffer.cc
+++ b/src/mem/ruby/buffers/MessageBuffer.cc
@@ -435,3 +435,69 @@ MessageBuffer::printStats(ostream& out)
out << "MessageBuffer: " << m_name << " stats - msgs:" << m_msg_counter
<< " full:" << m_not_avail_count << endl;
}
+
+bool
+MessageBuffer::isReady() const
+{
+ return ((m_prio_heap.size() > 0) &&
+ (m_prio_heap.front().m_time <= g_system_ptr->getTime()));
+}
+
+bool
+MessageBuffer::functionalRead(Packet *pkt)
+{
+ // Check the priority heap and read any messages that may
+ // correspond to the address in the packet.
+ for (unsigned int i = 0; i < m_prio_heap.size(); ++i) {
+ Message *msg = m_prio_heap[i].m_msgptr.get();
+ if (msg->functionalRead(pkt)) return true;
+ }
+
+ // Read the messages in the stall queue that correspond
+ // to the address in the packet.
+ for (StallMsgMapType::iterator map_iter = m_stall_msg_map.begin();
+ map_iter != m_stall_msg_map.end();
+ ++map_iter) {
+
+ for (std::list<MsgPtr>::iterator it = (map_iter->second).begin();
+ it != (map_iter->second).end(); ++it) {
+
+ Message *msg = (*it).get();
+ if (msg->functionalRead(pkt)) return true;
+ }
+ }
+ return false;
+}
+
+uint32_t
+MessageBuffer::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ // Check the priority heap and write any messages that may
+ // correspond to the address in the packet.
+ for (unsigned int i = 0; i < m_prio_heap.size(); ++i) {
+ Message *msg = m_prio_heap[i].m_msgptr.get();
+ if (msg->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+
+ // Check the stall queue and write any messages that may
+ // correspond to the address in the packet.
+ for (StallMsgMapType::iterator map_iter = m_stall_msg_map.begin();
+ map_iter != m_stall_msg_map.end();
+ ++map_iter) {
+
+ for (std::list<MsgPtr>::iterator it = (map_iter->second).begin();
+ it != (map_iter->second).end(); ++it) {
+
+ Message *msg = (*it).get();
+ if (msg->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+ }
+
+ return num_functional_writes;
+}
diff --git a/src/mem/ruby/buffers/MessageBuffer.hh b/src/mem/ruby/buffers/MessageBuffer.hh
index cf7e77c2d..c4fd7165d 100644
--- a/src/mem/ruby/buffers/MessageBuffer.hh
+++ b/src/mem/ruby/buffers/MessageBuffer.hh
@@ -41,10 +41,10 @@
#include <string>
#include <vector>
+#include "mem/packet.hh"
#include "mem/ruby/buffers/MessageBufferNode.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/Message.hh"
class MessageBuffer
@@ -65,12 +65,7 @@ class MessageBuffer
void stallMessage(const Address& addr);
// TRUE if head of queue timestamp <= SystemTime
- bool
- isReady() const
- {
- return ((m_prio_heap.size() > 0) &&
- (m_prio_heap.front().m_time <= g_system_ptr->getTime()));
- }
+ bool isReady() const;
void
delayHead()
@@ -145,6 +140,17 @@ class MessageBuffer
void setIncomingLink(int link_id) { m_input_link_id = link_id; }
void setVnet(int net) { m_vnet_id = net; }
+ // Function for figuring out if any of the messages in the buffer can
+ // satisfy the read request for the address in the packet.
+ // Return value, if true, indicates that the request was fulfilled.
+ bool functionalRead(Packet *pkt);
+
+ // Function for figuring out if any of the messages in the buffer need
+ // to be updated with the data from the packet.
+ // Return value indicates the number of messages that were updated.
+ // This required for debugging the code.
+ uint32_t functionalWrite(Packet *pkt);
+
private:
//added by SS
int m_recycle_latency;
diff --git a/src/mem/ruby/buffers/MessageBufferNode.hh b/src/mem/ruby/buffers/MessageBufferNode.hh
index 70afa9831..5e7a52e12 100644
--- a/src/mem/ruby/buffers/MessageBufferNode.hh
+++ b/src/mem/ruby/buffers/MessageBufferNode.hh
@@ -31,7 +31,6 @@
#include <iostream>
-#include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/Message.hh"
class MessageBufferNode
diff --git a/src/mem/ruby/network/Network.hh b/src/mem/ruby/network/Network.hh
index e9c5a98b7..9236a2207 100644
--- a/src/mem/ruby/network/Network.hh
+++ b/src/mem/ruby/network/Network.hh
@@ -44,6 +44,7 @@
#include <string>
#include <vector>
+#include "mem/packet.hh"
#include "mem/protocol/LinkDirection.hh"
#include "mem/protocol/MessageSizeType.hh"
#include "mem/ruby/common/TypeDefines.hh"
@@ -81,7 +82,7 @@ class Network : public SimObject
bool isReconfiguration) = 0;
virtual void makeInLink(NodeID src, SwitchID dest, BasicLink* link,
LinkDirection direction,
- const NetDest& routing_table_entry,
+ const NetDest& routing_table_entry,
bool isReconfiguration) = 0;
virtual void makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
LinkDirection direction,
@@ -94,6 +95,16 @@ class Network : public SimObject
virtual void clearStats() = 0;
virtual void print(std::ostream& out) const = 0;
+ /*
+ * Virtual functions for functionally reading and writing packets in
+ * the network. Each network needs to implement these for functional
+ * accesses to work correctly.
+ */
+ virtual bool functionalRead(Packet *pkt)
+ { fatal("Functional read not implemented.\n"); }
+ virtual uint32_t functionalWrite(Packet *pkt)
+ { fatal("Functional write not implemented.\n"); }
+
protected:
// Private copy constructor and assignment operator
Network(const Network& obj);
diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc
index 2c845683d..b38b6d539 100644
--- a/src/mem/ruby/network/simple/PerfectSwitch.cc
+++ b/src/mem/ruby/network/simple/PerfectSwitch.cc
@@ -343,4 +343,3 @@ PerfectSwitch::print(std::ostream& out) const
{
out << "[PerfectSwitch " << m_switch_id << "]";
}
-
diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc
index 7aa8e62f9..9df9ed3a5 100644
--- a/src/mem/ruby/network/simple/SimpleNetwork.cc
+++ b/src/mem/ruby/network/simple/SimpleNetwork.cc
@@ -327,3 +327,41 @@ SimpleNetworkParams::create()
{
return new SimpleNetwork(this);
}
+
+/*
+ * The simple network has an array of switches. These switches have buffers
+ * that need to be accessed for functional reads and writes. Also the links
+ * between different switches have buffers that need to be accessed.
+ */
+bool
+SimpleNetwork::functionalRead(Packet *pkt)
+{
+ for (unsigned int i = 0; i < m_switch_ptr_vector.size(); i++) {
+ if (m_switch_ptr_vector[i]->functionalRead(pkt)) {
+ return true;
+ }
+ }
+
+ for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
+ if (m_buffers_to_free[i]->functionalRead(pkt)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint32_t
+SimpleNetwork::functionalWrite(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (unsigned int i = 0; i < m_switch_ptr_vector.size(); i++) {
+ num_functional_writes += m_switch_ptr_vector[i]->functionalWrite(pkt);
+ }
+
+ for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
+ num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt);
+ }
+ return num_functional_writes;
+}
diff --git a/src/mem/ruby/network/simple/SimpleNetwork.hh b/src/mem/ruby/network/simple/SimpleNetwork.hh
index 6dfaa2724..879446822 100644
--- a/src/mem/ruby/network/simple/SimpleNetwork.hh
+++ b/src/mem/ruby/network/simple/SimpleNetwork.hh
@@ -86,6 +86,9 @@ class SimpleNetwork : public Network
void print(std::ostream& out) const;
+ bool functionalRead(Packet *pkt);
+ uint32_t functionalWrite(Packet *pkt);
+
private:
void checkNetworkAllocation(NodeID id, bool ordered, int network_num);
void addLink(SwitchID src, SwitchID dest, int link_latency);
diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc
index 5c2f5a717..a0a27f758 100644
--- a/src/mem/ruby/network/simple/Switch.cc
+++ b/src/mem/ruby/network/simple/Switch.cc
@@ -217,6 +217,28 @@ Switch::print(std::ostream& out) const
// FIXME printing
out << "[Switch]";
}
+bool
+Switch::functionalRead(Packet *pkt)
+{
+ // Access the buffers in the switch for performing a functional read
+ for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
+ if (m_buffers_to_free[i]->functionalRead(pkt)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t
+Switch::functionalWrite(Packet *pkt)
+{
+ // Access the buffers in the switch for performing a functional write
+ uint32_t num_functional_writes = 0;
+ for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
+ num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt);
+ }
+ return num_functional_writes;
+}
Switch *
SwitchParams::create()
diff --git a/src/mem/ruby/network/simple/Switch.hh b/src/mem/ruby/network/simple/Switch.hh
index 9946e5cc1..05e90f278 100644
--- a/src/mem/ruby/network/simple/Switch.hh
+++ b/src/mem/ruby/network/simple/Switch.hh
@@ -74,6 +74,9 @@ class Switch : public BasicRouter
void print(std::ostream& out) const;
void init_net_ptr(SimpleNetwork* net_ptr) { m_network_ptr = net_ptr; }
+ bool functionalRead(Packet *);
+ uint32_t functionalWrite(Packet *);
+
private:
// Private copy constructor and assignment operator
Switch(const Switch& obj);
diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh
index 70b9968c7..c5cb46f1e 100644
--- a/src/mem/ruby/slicc_interface/AbstractController.hh
+++ b/src/mem/ruby/slicc_interface/AbstractController.hh
@@ -32,6 +32,7 @@
#include <iostream>
#include <string>
+#include "mem/packet.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
@@ -68,6 +69,15 @@ class AbstractController : public SimObject, public Consumer
virtual void clearStats() = 0;
virtual void recordCacheTrace(int cntrl, CacheRecorder* tr) = 0;
virtual Sequencer* getSequencer() const = 0;
+
+ //! These functions are used by ruby system to read/write the message
+ //! queues that exist with in the controller.
+ //! The boolean return value indicates if the read was performed
+ //! successfully.
+ virtual bool functionalReadBuffers(PacketPtr&) = 0;
+ //! The return value indicates the number of messages written with the
+ //! data from the packet.
+ virtual uint32_t functionalWriteBuffers(PacketPtr&) = 0;
};
#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
diff --git a/src/mem/ruby/slicc_interface/Message.hh b/src/mem/ruby/slicc_interface/Message.hh
index 48156a99a..7b94a01e2 100644
--- a/src/mem/ruby/slicc_interface/Message.hh
+++ b/src/mem/ruby/slicc_interface/Message.hh
@@ -61,6 +61,18 @@ class Message : public RefCounted
virtual void setIncomingLink(int) {}
virtual void setVnet(int) {}
+ /**
+ * The two functions below are used for reading / writing the message
+ * functionally. The methods return true if the address in the packet
+ * matches the address / address range in the message. Each message
+ * class that can be potentially searched for the address needs to
+ * implement these methods.
+ */
+ virtual bool functionalRead(Packet *pkt) = 0;
+ //{ fatal("Read functional access not implemented!"); }
+ virtual bool functionalWrite(Packet *pkt) = 0;
+ //{ fatal("Write functional access not implemented!"); }
+
void setDelayedCycles(const int& cycles) { m_DelayedCycles = cycles; }
const int& getDelayedCycles() const {return m_DelayedCycles;}
int& getDelayedCycles() {return m_DelayedCycles;}
diff --git a/src/mem/ruby/slicc_interface/NetworkMessage.hh b/src/mem/ruby/slicc_interface/NetworkMessage.hh
index a8f9c625b..d2bcb1241 100644
--- a/src/mem/ruby/slicc_interface/NetworkMessage.hh
+++ b/src/mem/ruby/slicc_interface/NetworkMessage.hh
@@ -33,7 +33,6 @@
#include "base/refcnt.hh"
#include "mem/protocol/MessageSizeType.hh"
-#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/slicc_interface/Message.hh"
diff --git a/src/mem/ruby/slicc_interface/RubyRequest.cc b/src/mem/ruby/slicc_interface/RubyRequest.cc
index 2aae61d7b..7ff2b75d8 100644
--- a/src/mem/ruby/slicc_interface/RubyRequest.cc
+++ b/src/mem/ruby/slicc_interface/RubyRequest.cc
@@ -18,3 +18,40 @@ RubyRequest::print(ostream& out) const
// out << "Time = " << getTime() << " ";
out << "]";
}
+
+bool
+RubyRequest::functionalRead(Packet *pkt)
+{
+ // This needs a little explanation. Initially I thought that this
+ // message should be read. But the way the memtester works for now,
+ // we should not be reading this message as memtester updates the
+ // functional memory only after a write has actually taken place.
+ return false;
+}
+
+bool
+RubyRequest::functionalWrite(Packet *pkt)
+{
+ // This needs a little explanation. I am not sure if this message
+ // should be written. Essentially the question is how are writes
+ // ordered. I am assuming that if a functional write is issued after
+ // a timing write to the same address, then the functional write
+ // has to overwrite the data for the timing request, even if the
+ // timing request has still not been ordered globally.
+
+ Address pktLineAddr(pkt->getAddr());
+ pktLineAddr.makeLineAddress();
+
+ if (pktLineAddr == m_LineAddress) {
+ uint8_t *pktData = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ unsigned startByte = pkt->getAddr() - m_LineAddress.getAddress();
+
+ for (unsigned i = 0; i < size_in_bytes; ++i) {
+ data[i + startByte] = pktData[i];
+ }
+
+ return true;
+ }
+ return false;
+}
diff --git a/src/mem/ruby/slicc_interface/RubyRequest.hh b/src/mem/ruby/slicc_interface/RubyRequest.hh
index 870ad1d0e..a4dadc7a7 100644
--- a/src/mem/ruby/slicc_interface/RubyRequest.hh
+++ b/src/mem/ruby/slicc_interface/RubyRequest.hh
@@ -126,6 +126,9 @@ class RubyRequest : public Message
}
void print(std::ostream& out) const;
+
+ bool functionalRead(Packet *pkt);
+ bool functionalWrite(Packet *pkt);
};
inline std::ostream&
diff --git a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
index 06372c9fc..06c540db5 100644
--- a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
+++ b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
@@ -35,6 +35,7 @@
#include <cassert>
+#include "debug/RubySlicc.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
@@ -129,4 +130,60 @@ mod(int val, int mod)
return val % mod;
}
+/**
+ * This function accepts an address, a data block and a packet. If the address
+ * range for the data block contains the address which the packet needs to
+ * read, then the data from the data block is written to the packet. True is
+ * returned if the data block was read, otherwise false is returned.
+ */
+inline bool
+testAndRead(Address addr, DataBlock& blk, Packet *pkt)
+{
+ Address pktLineAddr(pkt->getAddr());
+ pktLineAddr.makeLineAddress();
+
+ Address lineAddr = addr;
+ lineAddr.makeLineAddress();
+
+ if (pktLineAddr == lineAddr) {
+ uint8_t *data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ unsigned startByte = pkt->getAddr() - lineAddr.getAddress();
+
+ for (unsigned i = 0; i < size_in_bytes; ++i) {
+ data[i] = blk.getByte(i + startByte);
+ }
+ return true;
+ }
+ return false;
+}
+
+/**
+ * This function accepts an address, a data block and a packet. If the address
+ * range for the data block contains the address which the packet needs to
+ * write, then the data from the packet is written to the data block. True is
+ * returned if the data block was written, otherwise false is returned.
+ */
+inline bool
+testAndWrite(Address addr, DataBlock& blk, Packet *pkt)
+{
+ Address pktLineAddr(pkt->getAddr());
+ pktLineAddr.makeLineAddress();
+
+ Address lineAddr = addr;
+ lineAddr.makeLineAddress();
+
+ if (pktLineAddr == lineAddr) {
+ uint8_t *data = pkt->getPtr<uint8_t>(true);
+ unsigned int size_in_bytes = pkt->getSize();
+ unsigned startByte = pkt->getAddr() - lineAddr.getAddress();
+
+ for (unsigned i = 0; i < size_in_bytes; ++i) {
+ blk.setByte(i + startByte, data[i]);
+ }
+ return true;
+ }
+ return false;
+}
+
#endif // __MEM_RUBY_SLICC_INTERFACE_RUBYSLICCUTIL_HH__
diff --git a/src/mem/ruby/system/MemoryControl.cc b/src/mem/ruby/system/MemoryControl.cc
index c5ddb0c44..e58b36f63 100644
--- a/src/mem/ruby/system/MemoryControl.cc
+++ b/src/mem/ruby/system/MemoryControl.cc
@@ -27,18 +27,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "base/cast.hh"
-#include "base/cprintf.hh"
#include "debug/RubyStats.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/NetworkMessage.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/MemoryControl.hh"
-#include "mem/ruby/system/RubyMemoryControl.hh"
#include "mem/ruby/system/System.hh"
using namespace std;
@@ -55,9 +47,3 @@ MemoryControl::recordRequestType(MemoryControlRequestType request) {
DPRINTF(RubyStats, "Recorded request: %s\n",
MemoryControlRequestType_to_string(request));
}
-
-RubyMemoryControl *
-RubyMemoryControlParams::create()
-{
- return new RubyMemoryControl(this);
-}
diff --git a/src/mem/ruby/system/MemoryControl.hh b/src/mem/ruby/system/MemoryControl.hh
index 7bdc14cfc..8d15b8dec 100644
--- a/src/mem/ruby/system/MemoryControl.hh
+++ b/src/mem/ruby/system/MemoryControl.hh
@@ -35,19 +35,14 @@
#include <string>
#include "mem/protocol/MemoryControlRequestType.hh"
-#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/profiler/MemCntrlProfiler.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/ruby/system/MemoryNode.hh"
-#include "mem/ruby/system/System.hh"
#include "params/MemoryControl.hh"
#include "sim/clocked_object.hh"
//////////////////////////////////////////////////////////////////////////////
-class Consumer;
-
class MemoryControl : public ClockedObject, public Consumer
{
public:
@@ -97,6 +92,11 @@ class MemoryControl : public ClockedObject, public Consumer
virtual void recordRequestType(MemoryControlRequestType requestType);
+ virtual bool functionalReadBuffers(Packet *pkt)
+ { fatal("Functional read access not implemented!");}
+ virtual uint32_t functionalWriteBuffers(Packet *pkt)
+ { fatal("Functional read access not implemented!");}
+
protected:
class MemCntrlEvent : public Event
{
diff --git a/src/mem/ruby/system/RubyMemoryControl.cc b/src/mem/ruby/system/RubyMemoryControl.cc
index cfdaaaef7..c0e91c28b 100644
--- a/src/mem/ruby/system/RubyMemoryControl.cc
+++ b/src/mem/ruby/system/RubyMemoryControl.cc
@@ -708,3 +708,91 @@ RubyMemoryControl::wakeup()
}
}
+/**
+ * This function reads the different buffers that exist in the Ruby Memory
+ * Controller, and figures out if any of the buffers hold a message that
+ * contains the data for the address provided in the packet. True is returned
+ * if any of the messages was read, otherwise false is returned.
+ *
+ * I think we should move these buffers to being message buffers, instead of
+ * being lists.
+ */
+bool
+RubyMemoryControl::functionalReadBuffers(Packet *pkt)
+{
+ for (std::list<MemoryNode>::iterator it = m_input_queue.begin();
+ it != m_input_queue.end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalRead(pkt)) {
+ return true;
+ }
+ }
+
+ for (std::list<MemoryNode>::iterator it = m_response_queue.begin();
+ it != m_response_queue.end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalRead(pkt)) {
+ return true;
+ }
+ }
+
+ for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
+ for (std::list<MemoryNode>::iterator it = m_bankQueues[bank].begin();
+ it != m_bankQueues[bank].end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalRead(pkt)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * This function reads the different buffers that exist in the Ruby Memory
+ * Controller, and figures out if any of the buffers hold a message that
+ * needs to functionally written with the data in the packet.
+ *
+ * The number of messages written is returned at the end. This is required
+ * for debugging purposes.
+ */
+uint32_t
+RubyMemoryControl::functionalWriteBuffers(Packet *pkt)
+{
+ uint32_t num_functional_writes = 0;
+
+ for (std::list<MemoryNode>::iterator it = m_input_queue.begin();
+ it != m_input_queue.end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+
+ for (std::list<MemoryNode>::iterator it = m_response_queue.begin();
+ it != m_response_queue.end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+
+ for (uint32_t bank = 0; bank < m_total_banks; ++bank) {
+ for (std::list<MemoryNode>::iterator it = m_bankQueues[bank].begin();
+ it != m_bankQueues[bank].end(); ++it) {
+ Message* msg_ptr = (*it).m_msgptr.get();
+ if (msg_ptr->functionalWrite(pkt)) {
+ num_functional_writes++;
+ }
+ }
+ }
+
+ return num_functional_writes;
+}
+
+RubyMemoryControl *
+RubyMemoryControlParams::create()
+{
+ return new RubyMemoryControl(this);
+}
diff --git a/src/mem/ruby/system/RubyMemoryControl.hh b/src/mem/ruby/system/RubyMemoryControl.hh
index 98636e408..1f3a8acf5 100644
--- a/src/mem/ruby/system/RubyMemoryControl.hh
+++ b/src/mem/ruby/system/RubyMemoryControl.hh
@@ -96,6 +96,8 @@ class RubyMemoryControl : public MemoryControl
int getRanksPerDimm() { return m_ranks_per_dimm; };
int getDimmsPerChannel() { return m_dimms_per_channel; }
+ bool functionalReadBuffers(Packet *pkt);
+ uint32_t functionalWriteBuffers(Packet *pkt);
private:
void enqueueToDirectory(MemoryNode req, int latency);
diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc
index b41f2d727..5ee22e9f5 100644
--- a/src/mem/ruby/system/System.cc
+++ b/src/mem/ruby/system/System.cc
@@ -417,7 +417,7 @@ RubySystem::functionalRead(PacketPtr pkt)
// In this loop we count the number of controllers that have the given
// address in read only, read write and busy states.
- for (int i = 0; i < num_controllers; ++i) {
+ for (unsigned int i = 0; i < num_controllers; ++i) {
access_perm = m_abs_cntrl_vec[i]-> getAccessPermission(line_address);
if (access_perm == AccessPermission_Read_Only)
num_ro++;
@@ -452,7 +452,7 @@ RubySystem::functionalRead(PacketPtr pkt)
if (num_invalid == (num_controllers - 1) &&
num_backing_store == 1) {
DPRINTF(RubySystem, "only copy in Backing_Store memory, read from it\n");
- for (int i = 0; i < num_controllers; ++i) {
+ for (unsigned int i = 0; i < num_controllers; ++i) {
access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address);
if (access_perm == AccessPermission_Backing_Store) {
DataBlock& block = m_abs_cntrl_vec[i]->
@@ -466,7 +466,7 @@ RubySystem::functionalRead(PacketPtr pkt)
return true;
}
}
- } else {
+ } else if (num_ro > 0 || num_rw == 1) {
// In Broadcast/Snoop protocols, this covers if you know the block
// exists somewhere in the caching hierarchy, then you want to read any
// valid RO or RW block. In directory protocols, same thing, you want
@@ -476,7 +476,7 @@ RubySystem::functionalRead(PacketPtr pkt)
// In this loop, we try to figure which controller has a read only or
// a read write copy of the given address. Any valid copy would suffice
// for a functional read.
- for (int i = 0;i < num_controllers;++i) {
+ for (unsigned int i = 0;i < num_controllers;++i) {
access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address);
if (access_perm == AccessPermission_Read_Only ||
access_perm == AccessPermission_Read_Write) {
@@ -492,9 +492,34 @@ RubySystem::functionalRead(PacketPtr pkt)
}
}
}
+
+ // Since we are here, this means that none of the controllers hold this
+ // address in a stable/base state. The function searches through all the
+ // buffers that exist in different cache, directory and memory
+ // controllers, and in the network components and reads the data portion
+ // of the first message that holds address specified in the packet.
+ for (unsigned int i = 0; i < num_controllers;++i) {
+ if (m_abs_cntrl_vec[i]->functionalReadBuffers(pkt)) {
+ return true;
+ }
+ }
+
+ for (unsigned int i = 0; i < m_memory_controller_vec.size(); ++i) {
+ if (m_memory_controller_vec[i]->functionalReadBuffers(pkt)) {
+ return true;
+ }
+ }
+
+ if (m_network_ptr->functionalRead(pkt)) {
+ return true;
+ }
return false;
}
+// The function searches through all the buffers that exist in different
+// cache, directory and memory controllers, and in the network components
+// and writes the data portion of those that hold the address specified
+// in the packet.
bool
RubySystem::functionalWrite(PacketPtr pkt)
{
@@ -505,69 +530,36 @@ RubySystem::functionalWrite(PacketPtr pkt)
DPRINTF(RubySystem, "Functional Write request for %s\n",addr);
- unsigned int num_ro = 0;
- unsigned int num_rw = 0;
- unsigned int num_busy = 0;
- unsigned int num_backing_store = 0;
- unsigned int num_invalid = 0;
-
- // In this loop we count the number of controllers that have the given
- // address in read only, read write and busy states.
- for (int i = 0;i < num_controllers;++i) {
- access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr);
- if (access_perm == AccessPermission_Read_Only)
- num_ro++;
- else if (access_perm == AccessPermission_Read_Write)
- num_rw++;
- else if (access_perm == AccessPermission_Busy)
- num_busy++;
- else if (access_perm == AccessPermission_Backing_Store)
- // See RubySlicc_Exports.sm for details, but Backing_Store is meant
- // to represent blocks in memory *for Broadcast/Snooping protocols*,
- // where memory has no idea whether it has an exclusive copy of data
- // or not.
- num_backing_store++;
- else if (access_perm == AccessPermission_Invalid ||
- access_perm == AccessPermission_NotPresent)
- num_invalid++;
- }
-
- // If the number of read write copies is more than 1, then there is bug in
- // coherence protocol. Otherwise, if all copies are in stable states, i.e.
- // num_busy == 0, we update all the copies. If there is at least one copy
- // in busy state, then we check if there is read write copy. If yes, then
- // also we let the access go through. Or, if there is no copy in the cache
- // hierarchy at all, we still want to do the write to the memory
- // (Backing_Store) instead of failing.
-
- DPRINTF(RubySystem, "num_busy = %d, num_ro = %d, num_rw = %d\n",
- num_busy, num_ro, num_rw);
- assert(num_rw <= 1);
-
uint8_t *data = pkt->getPtr<uint8_t>(true);
unsigned int size_in_bytes = pkt->getSize();
unsigned startByte = addr.getAddress() - line_addr.getAddress();
- if ((num_busy == 0 && num_ro > 0) || num_rw == 1 ||
- (num_invalid == (num_controllers - 1) && num_backing_store == 1)) {
- for (int i = 0; i < num_controllers;++i) {
- access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr);
- if (access_perm == AccessPermission_Read_Only ||
- access_perm == AccessPermission_Read_Write||
- access_perm == AccessPermission_Maybe_Stale ||
- access_perm == AccessPermission_Backing_Store) {
+ for (unsigned int i = 0; i < num_controllers;++i) {
+ m_abs_cntrl_vec[i]->functionalWriteBuffers(pkt);
- DataBlock& block = m_abs_cntrl_vec[i]->getDataBlock(line_addr);
- DPRINTF(RubySystem, "%s\n",block);
- for (unsigned i = 0; i < size_in_bytes; ++i) {
- block.setByte(i + startByte, data[i]);
- }
- DPRINTF(RubySystem, "%s\n",block);
+ access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr);
+ if (access_perm != AccessPermission_Invalid &&
+ access_perm != AccessPermission_NotPresent) {
+
+ DataBlock& block = m_abs_cntrl_vec[i]->getDataBlock(line_addr);
+ DPRINTF(RubySystem, "%s\n",block);
+ for (unsigned i = 0; i < size_in_bytes; ++i) {
+ block.setByte(i + startByte, data[i]);
}
+ DPRINTF(RubySystem, "%s\n",block);
}
- return true;
}
- return false;
+
+ uint32_t M5_VAR_USED num_functional_writes = 0;
+ for (unsigned int i = 0; i < m_memory_controller_vec.size() ;++i) {
+ num_functional_writes +=
+ m_memory_controller_vec[i]->functionalWriteBuffers(pkt);
+ }
+
+ num_functional_writes += m_network_ptr->functionalWrite(pkt);
+ DPRINTF(RubySystem, "Messages written = %u\n", num_functional_writes);
+
+ return true;
}
#ifdef CHECK_COHERENCE
diff --git a/src/mem/slicc/ast/TypeDeclAST.py b/src/mem/slicc/ast/TypeDeclAST.py
index 983e86882..8a58853ac 100644
--- a/src/mem/slicc/ast/TypeDeclAST.py
+++ b/src/mem/slicc/ast/TypeDeclAST.py
@@ -60,7 +60,10 @@ class TypeDeclAST(DeclAST):
machine.addType(new_type)
self.symtab.newSymbol(new_type)
+ self.symtab.pushFrame()
# Add all of the fields of the type to it
for field in self.field_asts:
field.generate(new_type)
+
+ self.symtab.popFrame()
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
index bb69b70bf..427dbf700 100644
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -269,6 +269,9 @@ class $c_ident : public AbstractController
void recordCacheTrace(int cntrl, CacheRecorder* tr);
Sequencer* getSequencer() const;
+ bool functionalReadBuffers(PacketPtr&);
+ uint32_t functionalWriteBuffers(PacketPtr&);
+
private:
''')
@@ -987,6 +990,39 @@ $c_ident::${{action.ident}}(const Address& addr)
for func in self.functions:
code(func.generateCode())
+ # Function for functional reads from messages buffered in the controller
+ code('''
+bool
+$c_ident::functionalReadBuffers(PacketPtr& pkt)
+{
+''')
+ for var in self.objects:
+ vtype = var.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.c_ident
+ code('if ($vid->functionalRead(pkt)) { return true; }')
+ code('''
+ return false;
+}
+''')
+
+ # Function for functional writes to messages buffered in the controller
+ code('''
+uint32_t
+$c_ident::functionalWriteBuffers(PacketPtr& pkt)
+{
+ uint32_t num_functional_writes = 0;
+''')
+ for var in self.objects:
+ vtype = var.type
+ if vtype.isBuffer:
+ vid = "m_%s_ptr" % var.c_ident
+ code('num_functional_writes += $vid->functionalWrite(pkt);')
+ code('''
+ return num_functional_writes;
+}
+''')
+
code.write(path, "%s.cc" % c_ident)
def printCWakeup(self, path, includes):
diff --git a/src/mem/slicc/symbols/SymbolTable.py b/src/mem/slicc/symbols/SymbolTable.py
index d2c9337f1..43cfe8740 100644
--- a/src/mem/slicc/symbols/SymbolTable.py
+++ b/src/mem/slicc/symbols/SymbolTable.py
@@ -81,8 +81,7 @@ class SymbolTable(object):
if types is not None:
if not isinstance(symbol, types):
symbol.error("Symbol '%s' is not of types '%s'.",
- symbol,
- types)
+ symbol, types)
return symbol
diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py
index 383291911..19c144048 100644
--- a/src/mem/slicc/symbols/Type.py
+++ b/src/mem/slicc/symbols/Type.py
@@ -29,6 +29,7 @@ from m5.util import orderdict
from slicc.util import PairContainer
from slicc.symbols.Symbol import Symbol
+from slicc.symbols.Var import Var
class DataMember(PairContainer):
def __init__(self, ident, type, pairs, init_code):
@@ -151,6 +152,9 @@ class Type(Symbol):
member = DataMember(ident, type, pairs, init_code)
self.data_members[ident] = member
+ var = Var(self.symtab, ident, self.location, type,
+ "m_%s" % ident, {}, None)
+ self.symtab.registerSym(ident, var)
return True
def dataMemberType(self, ident):
@@ -415,6 +419,7 @@ operator<<(std::ostream& out, const ${{self.c_ident}}& obj)
#include <iostream>
#include "mem/protocol/${{self.c_ident}}.hh"
+#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
using namespace std;
''')