summaryrefslogtreecommitdiff
path: root/src/mem/ruby/slicc_interface
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2012-10-15 17:51:57 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2012-10-15 17:51:57 -0500
commit5ffc16593997b35f4f1abbd149e01169e6bbcff5 (patch)
tree647411a3d027f2bdfaf750f65107affb6d9c002d /src/mem/ruby/slicc_interface
parent07ce90f7aa28a507493da905ba1881972250bb3a (diff)
downloadgem5-5ffc16593997b35f4f1abbd149e01169e6bbcff5.tar.xz
ruby: improved support for functional accesses
This patch adds support to different entities in the ruby memory system for more reliable functional read/write accesses. Only the simple network has been augmented as of now. Later on Garnet will also support functional accesses. The patch adds functional access code to all the different types of messages that protocols can send around. These messages are functionally accessed by going through the buffers maintained by the network entities. The patch also rectifies some of the bugs found in coherence protocols while testing the patch. With this patch applied, functional writes always succeed. But functional reads can still fail.
Diffstat (limited to 'src/mem/ruby/slicc_interface')
-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
6 files changed, 119 insertions, 1 deletions
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__