summaryrefslogtreecommitdiff
path: root/src/mem/ruby
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2011-11-14 17:44:35 -0600
committerNilay Vaish <nilay@cs.wisc.edu>2011-11-14 17:44:35 -0600
commitf3b4d10a05d902f34ccd3bee7154b46ee8320fb6 (patch)
tree611091998480962f5cf0fd561382c0b58e78e745 /src/mem/ruby
parent2ee59cee1b6130359b127c4d74d3d10bd01853a9 (diff)
downloadgem5-f3b4d10a05d902f34ccd3bee7154b46ee8320fb6.tar.xz
Ruby: Process packet instead of RubyRequest in Sequencer
This patch changes the implementation of Ruby's recvTiming() function so that it pushes a packet in to the Sequencer instead of a RubyRequest. This requires changes in the Sequencer's makeRequest() and issueRequest() functions, as they also need to operate on a Packet instead of RubyRequest.
Diffstat (limited to 'src/mem/ruby')
-rw-r--r--src/mem/ruby/recorder/TraceRecord.cc8
-rw-r--r--src/mem/ruby/system/DMASequencer.cc23
-rw-r--r--src/mem/ruby/system/DMASequencer.hh2
-rw-r--r--src/mem/ruby/system/RubyPort.cc72
-rw-r--r--src/mem/ruby/system/RubyPort.hh2
-rw-r--r--src/mem/ruby/system/Sequencer.cc378
-rw-r--r--src/mem/ruby/system/Sequencer.hh17
7 files changed, 206 insertions, 296 deletions
diff --git a/src/mem/ruby/recorder/TraceRecord.cc b/src/mem/ruby/recorder/TraceRecord.cc
index aa54ee53c..79186d33b 100644
--- a/src/mem/ruby/recorder/TraceRecord.cc
+++ b/src/mem/ruby/recorder/TraceRecord.cc
@@ -73,17 +73,15 @@ void
TraceRecord::issueRequest() const
{
assert(m_sequencer_ptr != NULL);
-
- RubyRequest request(m_data_address.getAddress(), NULL,
- RubySystem::getBlockSizeBytes(), m_pc_address.getAddress(),
- m_type, RubyAccessMode_User, NULL);
+ Request req(m_data_address.getAddress(), 0, 0);
+ Packet *pkt = new Packet(&req, MemCmd(MemCmd::InvalidCmd), -1);
// Clear out the sequencer
while (!m_sequencer_ptr->empty()) {
g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 100);
}
- m_sequencer_ptr->makeRequest(request);
+ m_sequencer_ptr->makeRequest(pkt);
// Clear out the sequencer
while (!m_sequencer_ptr->empty()) {
diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc
index f8e4cf810..0e82ba3eb 100644
--- a/src/mem/ruby/system/DMASequencer.cc
+++ b/src/mem/ruby/system/DMASequencer.cc
@@ -48,27 +48,16 @@ DMASequencer::init()
}
RequestStatus
-DMASequencer::makeRequest(const RubyRequest &request)
+DMASequencer::makeRequest(PacketPtr pkt)
{
if (m_is_busy) {
return RequestStatus_BufferFull;
}
- uint64_t paddr = request.m_PhysicalAddress.getAddress();
- uint8_t* data = request.data;
- int len = request.m_Size;
- bool write = false;
- switch(request.m_Type) {
- case RubyRequestType_LD:
- write = false;
- break;
- case RubyRequestType_ST:
- write = true;
- break;
- default:
- panic("DMASequencer::makeRequest does not support RubyRequestType");
- return RequestStatus_NULL;
- }
+ uint64_t paddr = pkt->getAddr();
+ uint8_t* data = pkt->getPtr<uint8_t>(true);
+ int len = pkt->getSize();
+ bool write = pkt->isWrite();
assert(!m_is_busy); // only support one outstanding DMA request
m_is_busy = true;
@@ -79,7 +68,7 @@ DMASequencer::makeRequest(const RubyRequest &request)
active_request.len = len;
active_request.bytes_completed = 0;
active_request.bytes_issued = 0;
- active_request.pkt = request.pkt;
+ active_request.pkt = pkt;
SequencerMsg *msg = new SequencerMsg;
msg->getPhysicalAddress() = Address(paddr);
diff --git a/src/mem/ruby/system/DMASequencer.hh b/src/mem/ruby/system/DMASequencer.hh
index 61d7ef1c6..5f6b9f100 100644
--- a/src/mem/ruby/system/DMASequencer.hh
+++ b/src/mem/ruby/system/DMASequencer.hh
@@ -53,7 +53,7 @@ class DMASequencer : public RubyPort
DMASequencer(const Params *);
void init();
/* external interface */
- RequestStatus makeRequest(const RubyRequest & request);
+ RequestStatus makeRequest(PacketPtr pkt);
bool busy() { return m_is_busy;}
/* SLICC callback */
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index c2661bcf2..f7bde739e 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -26,10 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config/the_isa.hh"
-#if THE_ISA == X86_ISA
-#include "arch/x86/insts/microldstop.hh"
-#endif // X86_ISA
#include "cpu/testers/rubytest/RubyTester.hh"
#include "debug/Ruby.hh"
#include "mem/protocol/AccessPermission.hh"
@@ -199,73 +195,11 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
return ruby_port->pio_port->sendTiming(pkt);
}
- // For DMA and CPU requests, translate them to ruby requests before
- // sending them to our assigned ruby port.
- RubyRequestType type = RubyRequestType_NULL;
-
- // If valid, copy the pc to the ruby request
- Addr pc = 0;
- if (pkt->req->hasPC()) {
- pc = pkt->req->getPC();
- }
-
- if (pkt->isLLSC()) {
- if (pkt->isWrite()) {
- DPRINTF(RubyPort, "Issuing SC\n");
- type = RubyRequestType_Store_Conditional;
- } else {
- DPRINTF(RubyPort, "Issuing LL\n");
- assert(pkt->isRead());
- type = RubyRequestType_Load_Linked;
- }
- } else if (pkt->req->isLocked()) {
- if (pkt->isWrite()) {
- DPRINTF(RubyPort, "Issuing Locked RMW Write\n");
- type = RubyRequestType_Locked_RMW_Write;
- } else {
- DPRINTF(RubyPort, "Issuing Locked RMW Read\n");
- assert(pkt->isRead());
- type = RubyRequestType_Locked_RMW_Read;
- }
- } else {
- if (pkt->isRead()) {
- if (pkt->req->isInstFetch()) {
- type = RubyRequestType_IFETCH;
- } else {
-#if THE_ISA == X86_ISA
- uint32_t flags = pkt->req->getFlags();
- bool storeCheck = flags &
- (TheISA::StoreCheck << TheISA::FlagShift);
-#else
- bool storeCheck = false;
-#endif // X86_ISA
- if (storeCheck) {
- type = RubyRequestType_RMW_Read;
- } else {
- type = RubyRequestType_LD;
- }
- }
- } else if (pkt->isWrite()) {
- //
- // Note: M5 packets do not differentiate ST from RMW_Write
- //
- type = RubyRequestType_ST;
- } else if (pkt->isFlush()) {
- type = RubyRequestType_FLUSH;
- } else {
- panic("Unsupported ruby packet type\n");
- }
- }
-
- RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr<uint8_t>(true),
- pkt->getSize(), pc, type,
- RubyAccessMode_Supervisor, pkt);
-
- assert(ruby_request.m_PhysicalAddress.getOffset() + ruby_request.m_Size <=
- RubySystem::getBlockSizeBytes());
+ assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <=
+ RubySystem::getBlockSizeBytes());
// Submit the ruby request
- RequestStatus requestStatus = ruby_port->makeRequest(ruby_request);
+ RequestStatus requestStatus = ruby_port->makeRequest(pkt);
// If the request successfully issued then we should return true.
// Otherwise, we need to delete the senderStatus we just created and return
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index e1ba2f7d1..88e865766 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -114,7 +114,7 @@ class RubyPort : public MemObject
Port *getPort(const std::string &if_name, int idx);
- virtual RequestStatus makeRequest(const RubyRequest & request) = 0;
+ virtual RequestStatus makeRequest(PacketPtr pkt) = 0;
//
// Called by the controller to give the sequencer a pointer.
diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc
index 711ef12ed..9010178be 100644
--- a/src/mem/ruby/system/Sequencer.cc
+++ b/src/mem/ruby/system/Sequencer.cc
@@ -28,15 +28,21 @@
#include "base/misc.hh"
#include "base/str.hh"
+#include "config/the_isa.hh"
+#if THE_ISA == X86_ISA
+#include "arch/x86/insts/microldstop.hh"
+#endif // X86_ISA
#include "cpu/testers/rubytest/RubyTester.hh"
#include "debug/MemoryAccess.hh"
#include "debug/ProtocolTrace.hh"
+#include "debug/RubySequencer.hh"
+#include "mem/protocol/PrefetchBit.hh"
+#include "mem/protocol/RubyAccessMode.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/SubBlock.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/recorder/Tracer.hh"
-#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/slicc_interface/RubyRequest.hh"
#include "mem/ruby/system/CacheMemory.hh"
#include "mem/ruby/system/Sequencer.hh"
@@ -62,7 +68,6 @@ Sequencer::Sequencer(const Params *p)
m_outstanding_count = 0;
- m_max_outstanding_requests = 0;
m_deadlock_threshold = 0;
m_instCache_ptr = NULL;
m_dataCache_ptr = NULL;
@@ -103,7 +108,7 @@ Sequencer::wakeup()
panic("Possible Deadlock detected. Aborting!\n"
"version: %d request.paddr: 0x%x m_readRequestTable: %d "
"current time: %u issue_time: %d difference: %d\n", m_version,
- request->ruby_request.m_PhysicalAddress, m_readRequestTable.size(),
+ Address(request->pkt->getAddr()), m_readRequestTable.size(),
current_time, request->issue_time,
current_time - request->issue_time);
}
@@ -118,7 +123,7 @@ Sequencer::wakeup()
panic("Possible Deadlock detected. Aborting!\n"
"version: %d request.paddr: 0x%x m_writeRequestTable: %d "
"current time: %u issue_time: %d difference: %d\n", m_version,
- request->ruby_request.m_PhysicalAddress, m_writeRequestTable.size(),
+ Address(request->pkt->getAddr()), m_writeRequestTable.size(),
current_time, request->issue_time,
current_time - request->issue_time);
}
@@ -213,8 +218,8 @@ Sequencer::printConfig(ostream& out) const
// Insert the request on the correct request table. Return true if
// the entry was already present.
-bool
-Sequencer::insertRequest(SequencerRequest* request)
+RequestStatus
+Sequencer::insertRequest(PacketPtr pkt, RubyRequestType request_type)
{
int total_outstanding =
m_writeRequestTable.size() + m_readRequestTable.size();
@@ -226,52 +231,64 @@ Sequencer::insertRequest(SequencerRequest* request)
schedule(deadlockCheckEvent, m_deadlock_threshold + curTick());
}
- Address line_addr(request->ruby_request.m_PhysicalAddress);
+ Address line_addr(pkt->getAddr());
line_addr.makeLineAddress();
- if ((request->ruby_request.m_Type == RubyRequestType_ST) ||
- (request->ruby_request.m_Type == RubyRequestType_ATOMIC) ||
- (request->ruby_request.m_Type == RubyRequestType_RMW_Read) ||
- (request->ruby_request.m_Type == RubyRequestType_RMW_Write) ||
- (request->ruby_request.m_Type == RubyRequestType_Load_Linked) ||
- (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) ||
- (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) ||
- (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) ||
- (request->ruby_request.m_Type == RubyRequestType_FLUSH)) {
+ if ((request_type == RubyRequestType_ST) ||
+ (request_type == RubyRequestType_RMW_Read) ||
+ (request_type == RubyRequestType_RMW_Write) ||
+ (request_type == RubyRequestType_Load_Linked) ||
+ (request_type == RubyRequestType_Store_Conditional) ||
+ (request_type == RubyRequestType_Locked_RMW_Read) ||
+ (request_type == RubyRequestType_Locked_RMW_Write) ||
+ (request_type == RubyRequestType_FLUSH)) {
+
+ // Check if there is any outstanding read request for the same
+ // cache line.
+ if (m_readRequestTable.count(line_addr) > 0) {
+ m_store_waiting_on_load_cycles++;
+ return RequestStatus_Aliased;
+ }
+
pair<RequestTable::iterator, bool> r =
m_writeRequestTable.insert(RequestTable::value_type(line_addr, 0));
- bool success = r.second;
- RequestTable::iterator i = r.first;
- if (!success) {
- i->second = request;
- // return true;
-
- // drh5: isn't this an error? do you lose the initial request?
- assert(0);
+ if (r.second) {
+ RequestTable::iterator i = r.first;
+ i->second = new SequencerRequest(pkt, request_type,
+ g_eventQueue_ptr->getTime());
+ m_outstanding_count++;
+ } else {
+ // There is an outstanding write request for the cache line
+ m_store_waiting_on_store_cycles++;
+ return RequestStatus_Aliased;
}
- i->second = request;
- m_outstanding_count++;
} else {
+ // Check if there is any outstanding write request for the same
+ // cache line.
+ if (m_writeRequestTable.count(line_addr) > 0) {
+ m_load_waiting_on_store_cycles++;
+ return RequestStatus_Aliased;
+ }
+
pair<RequestTable::iterator, bool> r =
m_readRequestTable.insert(RequestTable::value_type(line_addr, 0));
- bool success = r.second;
- RequestTable::iterator i = r.first;
- if (!success) {
- i->second = request;
- // return true;
-
- // drh5: isn't this an error? do you lose the initial request?
- assert(0);
+
+ if (r.second) {
+ RequestTable::iterator i = r.first;
+ i->second = new SequencerRequest(pkt, request_type,
+ g_eventQueue_ptr->getTime());
+ m_outstanding_count++;
+ } else {
+ // There is an outstanding read request for the cache line
+ m_load_waiting_on_load_cycles++;
+ return RequestStatus_Aliased;
}
- i->second = request;
- m_outstanding_count++;
}
g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
-
total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
assert(m_outstanding_count == total_outstanding);
- return false;
+ return RequestStatus_Ready;
}
void
@@ -288,16 +305,15 @@ Sequencer::removeRequest(SequencerRequest* srequest)
assert(m_outstanding_count ==
m_writeRequestTable.size() + m_readRequestTable.size());
- const RubyRequest & ruby_request = srequest->ruby_request;
- Address line_addr(ruby_request.m_PhysicalAddress);
+ Address line_addr(srequest->pkt->getAddr());
line_addr.makeLineAddress();
- if ((ruby_request.m_Type == RubyRequestType_ST) ||
- (ruby_request.m_Type == RubyRequestType_RMW_Read) ||
- (ruby_request.m_Type == RubyRequestType_RMW_Write) ||
- (ruby_request.m_Type == RubyRequestType_Load_Linked) ||
- (ruby_request.m_Type == RubyRequestType_Store_Conditional) ||
- (ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) ||
- (ruby_request.m_Type == RubyRequestType_Locked_RMW_Write)) {
+ if ((srequest->m_type == RubyRequestType_ST) ||
+ (srequest->m_type == RubyRequestType_RMW_Read) ||
+ (srequest->m_type == RubyRequestType_RMW_Write) ||
+ (srequest->m_type == RubyRequestType_Load_Linked) ||
+ (srequest->m_type == RubyRequestType_Store_Conditional) ||
+ (srequest->m_type == RubyRequestType_Locked_RMW_Read) ||
+ (srequest->m_type == RubyRequestType_Locked_RMW_Write)) {
m_writeRequestTable.erase(line_addr);
} else {
m_readRequestTable.erase(line_addr);
@@ -315,32 +331,33 @@ Sequencer::handleLlsc(const Address& address, SequencerRequest* request)
// longer locked.
//
bool success = true;
- if (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) {
+ if (request->m_type == RubyRequestType_Store_Conditional) {
if (!m_dataCache_ptr->isLocked(address, m_version)) {
//
// For failed SC requests, indicate the failure to the cpu by
// setting the extra data to zero.
//
- request->ruby_request.pkt->req->setExtraData(0);
+ request->pkt->req->setExtraData(0);
success = false;
} else {
//
// For successful SC requests, indicate the success to the cpu by
// setting the extra data to one.
//
- request->ruby_request.pkt->req->setExtraData(1);
+ request->pkt->req->setExtraData(1);
}
//
// Independent of success, all SC operations must clear the lock
//
m_dataCache_ptr->clearLocked(address);
- } else if (request->ruby_request.m_Type == RubyRequestType_Load_Linked) {
+ } else if (request->m_type == RubyRequestType_Load_Linked) {
//
// Note: To fully follow Alpha LLSC semantics, should the LL clear any
// previously locked cache lines?
//
m_dataCache_ptr->setLocked(address, m_version);
- } else if ((m_dataCache_ptr->isTagPresent(address)) && (m_dataCache_ptr->isLocked(address, m_version))) {
+ } else if ((m_dataCache_ptr->isTagPresent(address)) &&
+ (m_dataCache_ptr->isLocked(address, m_version))) {
//
// Normal writes should clear the locked address
//
@@ -381,15 +398,15 @@ Sequencer::writeCallback(const Address& address,
m_writeRequestTable.erase(i);
markRemoved();
- assert((request->ruby_request.m_Type == RubyRequestType_ST) ||
- (request->ruby_request.m_Type == RubyRequestType_ATOMIC) ||
- (request->ruby_request.m_Type == RubyRequestType_RMW_Read) ||
- (request->ruby_request.m_Type == RubyRequestType_RMW_Write) ||
- (request->ruby_request.m_Type == RubyRequestType_Load_Linked) ||
- (request->ruby_request.m_Type == RubyRequestType_Store_Conditional) ||
- (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) ||
- (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) ||
- (request->ruby_request.m_Type == RubyRequestType_FLUSH));
+ assert((request->m_type == RubyRequestType_ST) ||
+ (request->m_type == RubyRequestType_ATOMIC) ||
+ (request->m_type == RubyRequestType_RMW_Read) ||
+ (request->m_type == RubyRequestType_RMW_Write) ||
+ (request->m_type == RubyRequestType_Load_Linked) ||
+ (request->m_type == RubyRequestType_Store_Conditional) ||
+ (request->m_type == RubyRequestType_Locked_RMW_Read) ||
+ (request->m_type == RubyRequestType_Locked_RMW_Write) ||
+ (request->m_type == RubyRequestType_FLUSH));
//
@@ -402,9 +419,9 @@ Sequencer::writeCallback(const Address& address,
if(!m_usingNetworkTester)
success = handleLlsc(address, request);
- if (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Read) {
+ if (request->m_type == RubyRequestType_Locked_RMW_Read) {
m_controller->blockOnQueue(address, m_mandatory_q_ptr);
- } else if (request->ruby_request.m_Type == RubyRequestType_Locked_RMW_Write) {
+ } else if (request->m_type == RubyRequestType_Locked_RMW_Write) {
m_controller->unblock(address);
}
@@ -444,8 +461,8 @@ Sequencer::readCallback(const Address& address,
m_readRequestTable.erase(i);
markRemoved();
- assert((request->ruby_request.m_Type == RubyRequestType_LD) ||
- (request->ruby_request.m_Type == RubyRequestType_IFETCH));
+ assert((request->m_type == RubyRequestType_LD) ||
+ (request->m_type == RubyRequestType_IFETCH));
hitCallback(request, mach, data, true,
initialRequestTime, forwardRequestTime, firstResponseTime);
@@ -460,11 +477,11 @@ Sequencer::hitCallback(SequencerRequest* srequest,
Time forwardRequestTime,
Time firstResponseTime)
{
- const RubyRequest & ruby_request = srequest->ruby_request;
- Address request_address(ruby_request.m_PhysicalAddress);
- Address request_line_address(ruby_request.m_PhysicalAddress);
+ PacketPtr pkt = srequest->pkt;
+ Address request_address(pkt->getAddr());
+ Address request_line_address(pkt->getAddr());
request_line_address.makeLineAddress();
- RubyRequestType type = ruby_request.m_Type;
+ RubyRequestType type = srequest->m_type;
Time issued_time = srequest->issue_time;
// Set this cache entry to the most recently used
@@ -502,22 +519,22 @@ Sequencer::hitCallback(SequencerRequest* srequest,
DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %d cycles\n",
curTick(), m_version, "Seq",
success ? "Done" : "SC_Failed", "", "",
- ruby_request.m_PhysicalAddress, miss_latency);
+ request_address, miss_latency);
}
// update the data
- if (ruby_request.data != NULL) {
+ if (pkt->getPtr<uint8_t>(true) != NULL) {
if ((type == RubyRequestType_LD) ||
(type == RubyRequestType_IFETCH) ||
(type == RubyRequestType_RMW_Read) ||
(type == RubyRequestType_Locked_RMW_Read) ||
(type == RubyRequestType_Load_Linked)) {
- memcpy(ruby_request.data,
- data.getData(request_address.getOffset(), ruby_request.m_Size),
- ruby_request.m_Size);
+ memcpy(pkt->getPtr<uint8_t>(true),
+ data.getData(request_address.getOffset(), pkt->getSize()),
+ pkt->getSize());
} else {
- data.setData(ruby_request.data, request_address.getOffset(),
- ruby_request.m_Size);
+ data.setData(pkt->getPtr<uint8_t>(true),
+ request_address.getOffset(), pkt->getSize());
}
} else {
DPRINTF(MemoryAccess,
@@ -532,50 +549,16 @@ Sequencer::hitCallback(SequencerRequest* srequest,
// RubyTester.
if (m_usingRubyTester) {
RubyPort::SenderState *requestSenderState =
- safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState);
+ safe_cast<RubyPort::SenderState*>(pkt->senderState);
RubyTester::SenderState* testerSenderState =
safe_cast<RubyTester::SenderState*>(requestSenderState->saved);
testerSenderState->subBlock->mergeFrom(data);
}
- ruby_hit_callback(ruby_request.pkt);
+ ruby_hit_callback(pkt);
delete srequest;
}
-// Returns true if the sequencer already has a load or store outstanding
-RequestStatus
-Sequencer::getRequestStatus(const RubyRequest& request)
-{
- bool is_outstanding_store =
- !!m_writeRequestTable.count(line_address(request.m_PhysicalAddress));
- bool is_outstanding_load =
- !!m_readRequestTable.count(line_address(request.m_PhysicalAddress));
- if (is_outstanding_store) {
- if ((request.m_Type == RubyRequestType_LD) ||
- (request.m_Type == RubyRequestType_IFETCH) ||
- (request.m_Type == RubyRequestType_RMW_Read)) {
- m_store_waiting_on_load_cycles++;
- } else {
- m_store_waiting_on_store_cycles++;
- }
- return RequestStatus_Aliased;
- } else if (is_outstanding_load) {
- if ((request.m_Type == RubyRequestType_ST) ||
- (request.m_Type == RubyRequestType_RMW_Write)) {
- m_load_waiting_on_store_cycles++;
- } else {
- m_load_waiting_on_load_cycles++;
- }
- return RequestStatus_Aliased;
- }
-
- if (m_outstanding_count >= m_max_outstanding_requests) {
- return RequestStatus_BufferFull;
- }
-
- return RequestStatus_Ready;
-}
-
bool
Sequencer::empty() const
{
@@ -583,109 +566,118 @@ Sequencer::empty() const
}
RequestStatus
-Sequencer::makeRequest(const RubyRequest &request)
+Sequencer::makeRequest(PacketPtr pkt)
{
- assert(request.m_PhysicalAddress.getOffset() + request.m_Size <=
- RubySystem::getBlockSizeBytes());
- RequestStatus status = getRequestStatus(request);
- if (status != RequestStatus_Ready)
- return status;
+ if (m_outstanding_count >= m_max_outstanding_requests) {
+ return RequestStatus_BufferFull;
+ }
- SequencerRequest *srequest =
- new SequencerRequest(request, g_eventQueue_ptr->getTime());
- bool found = insertRequest(srequest);
- if (found) {
- panic("Sequencer::makeRequest should never be called if the "
- "request is already outstanding\n");
- return RequestStatus_NULL;
+ RubyRequestType primary_type = RubyRequestType_NULL;
+ RubyRequestType secondary_type = RubyRequestType_NULL;
+
+ if (pkt->isLLSC()) {
+ //
+ // Alpha LL/SC instructions need to be handled carefully by the cache
+ // coherence protocol to ensure they follow the proper semantics. In
+ // particular, by identifying the operations as atomic, the protocol
+ // should understand that migratory sharing optimizations should not
+ // be performed (i.e. a load between the LL and SC should not steal
+ // away exclusive permission).
+ //
+ if (pkt->isWrite()) {
+ DPRINTF(RubySequencer, "Issuing SC\n");
+ primary_type = RubyRequestType_Store_Conditional;
+ } else {
+ DPRINTF(RubySequencer, "Issuing LL\n");
+ assert(pkt->isRead());
+ primary_type = RubyRequestType_Load_Linked;
+ }
+ secondary_type = RubyRequestType_ATOMIC;
+ } else if (pkt->req->isLocked()) {
+ //
+ // x86 locked instructions are translated to store cache coherence
+ // requests because these requests should always be treated as read
+ // exclusive operations and should leverage any migratory sharing
+ // optimization built into the protocol.
+ //
+ if (pkt->isWrite()) {
+ DPRINTF(RubySequencer, "Issuing Locked RMW Write\n");
+ primary_type = RubyRequestType_Locked_RMW_Write;
+ } else {
+ DPRINTF(RubySequencer, "Issuing Locked RMW Read\n");
+ assert(pkt->isRead());
+ primary_type = RubyRequestType_Locked_RMW_Read;
+ }
+ secondary_type = RubyRequestType_ST;
+ } else {
+ if (pkt->isRead()) {
+ if (pkt->req->isInstFetch()) {
+ primary_type = secondary_type = RubyRequestType_IFETCH;
+ } else {
+#if THE_ISA == X86_ISA
+ uint32_t flags = pkt->req->getFlags();
+ bool storeCheck = flags &
+ (TheISA::StoreCheck << TheISA::FlagShift);
+#else
+ bool storeCheck = false;
+#endif // X86_ISA
+ if (storeCheck) {
+ primary_type = RubyRequestType_RMW_Read;
+ secondary_type = RubyRequestType_ST;
+ } else {
+ primary_type = secondary_type = RubyRequestType_LD;
+ }
+ }
+ } else if (pkt->isWrite()) {
+ //
+ // Note: M5 packets do not differentiate ST from RMW_Write
+ //
+ primary_type = secondary_type = RubyRequestType_ST;
+ } else if (pkt->isFlush()) {
+ primary_type = secondary_type = RubyRequestType_FLUSH;
+ } else {
+ panic("Unsupported ruby packet type\n");
+ }
}
- issueRequest(request);
+ RequestStatus status = insertRequest(pkt, primary_type);
+ if (status != RequestStatus_Ready)
+ return status;
+
+ issueRequest(pkt, secondary_type);
// TODO: issue hardware prefetches here
return RequestStatus_Issued;
}
void
-Sequencer::issueRequest(const RubyRequest& request)
+Sequencer::issueRequest(PacketPtr pkt, RubyRequestType secondary_type)
{
- // TODO: Eliminate RubyRequest being copied again.
-
- RubyRequestType ctype = RubyRequestType_NUM;
- switch(request.m_Type) {
- case RubyRequestType_IFETCH:
- ctype = RubyRequestType_IFETCH;
- break;
- case RubyRequestType_LD:
- ctype = RubyRequestType_LD;
- break;
- case RubyRequestType_FLUSH:
- ctype = RubyRequestType_FLUSH;
- break;
- case RubyRequestType_ST:
- case RubyRequestType_RMW_Read:
- case RubyRequestType_RMW_Write:
- //
- // x86 locked instructions are translated to store cache coherence
- // requests because these requests should always be treated as read
- // exclusive operations and should leverage any migratory sharing
- // optimization built into the protocol.
- //
- case RubyRequestType_Locked_RMW_Read:
- case RubyRequestType_Locked_RMW_Write:
- ctype = RubyRequestType_ST;
- break;
- //
- // Alpha LL/SC instructions need to be handled carefully by the cache
- // coherence protocol to ensure they follow the proper semantics. In
- // particular, by identifying the operations as atomic, the protocol
- // should understand that migratory sharing optimizations should not be
- // performed (i.e. a load between the LL and SC should not steal away
- // exclusive permission).
- //
- case RubyRequestType_Load_Linked:
- case RubyRequestType_Store_Conditional:
- case RubyRequestType_ATOMIC:
- ctype = RubyRequestType_ATOMIC;
- break;
- default:
- assert(0);
+ int proc_id = -1;
+ if (pkt != NULL && pkt->req->hasContextId()) {
+ proc_id = pkt->req->contextId();
}
- RubyAccessMode amtype = RubyAccessMode_NUM;
- switch(request.m_AccessMode){
- case RubyAccessMode_User:
- amtype = RubyAccessMode_User;
- break;
- case RubyAccessMode_Supervisor:
- amtype = RubyAccessMode_Supervisor;
- break;
- case RubyAccessMode_Device:
- amtype = RubyAccessMode_User;
- break;
- default:
- assert(0);
+ // If valid, copy the pc to the ruby request
+ Addr pc = 0;
+ if (pkt->req->hasPC()) {
+ pc = pkt->req->getPC();
}
- Address line_addr(request.m_PhysicalAddress);
- line_addr.makeLineAddress();
- int proc_id = -1;
- if (request.pkt != NULL && request.pkt->req->hasContextId()) {
- proc_id = request.pkt->req->contextId();
- }
- RubyRequest *msg = new RubyRequest(request.m_PhysicalAddress.getAddress(),
- request.data, request.m_Size,
- request.m_ProgramCounter.getAddress(),
- ctype, amtype, request.pkt,
+ RubyRequest *msg = new RubyRequest(pkt->getAddr(),
+ pkt->getPtr<uint8_t>(true),
+ pkt->getSize(), pc, secondary_type,
+ RubyAccessMode_Supervisor, pkt,
PrefetchBit_No, proc_id);
DPRINTFR(ProtocolTrace, "%15s %3s %10s%20s %6s>%-6s %s %s\n",
curTick(), m_version, "Seq", "Begin", "", "",
- request.m_PhysicalAddress, RubyRequestType_to_string(request.m_Type));
+ msg->getPhysicalAddress(),
+ RubyRequestType_to_string(secondary_type));
Time latency = 0; // initialzed to an null value
- if (request.m_Type == RubyRequestType_IFETCH)
+ if (secondary_type == RubyRequestType_IFETCH)
latency = m_instCache_ptr->getLatency();
else
latency = m_dataCache_ptr->getLatency();
diff --git a/src/mem/ruby/system/Sequencer.hh b/src/mem/ruby/system/Sequencer.hh
index 0589d8bbc..7c2d0af13 100644
--- a/src/mem/ruby/system/Sequencer.hh
+++ b/src/mem/ruby/system/Sequencer.hh
@@ -33,12 +33,9 @@
#include "base/hashmap.hh"
#include "mem/protocol/GenericMachineType.hh"
-#include "mem/protocol/PrefetchBit.hh"
-#include "mem/protocol/RubyAccessMode.hh"
#include "mem/protocol/RubyRequestType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/RubyPort.hh"
class DataBlock;
@@ -50,11 +47,12 @@ class RubySequencerParams;
struct SequencerRequest
{
- RubyRequest ruby_request;
+ PacketPtr pkt;
+ RubyRequestType m_type;
Time issue_time;
- SequencerRequest(const RubyRequest & _ruby_request, Time _issue_time)
- : ruby_request(_ruby_request), issue_time(_issue_time)
+ SequencerRequest(PacketPtr _pkt, RubyRequestType _m_type, Time _issue_time)
+ : pkt(_pkt), m_type(_m_type), issue_time(_issue_time)
{}
};
@@ -100,8 +98,7 @@ class Sequencer : public RubyPort, public Consumer
Time forwardRequestTime,
Time firstResponseTime);
- RequestStatus makeRequest(const RubyRequest & request);
- RequestStatus getRequestStatus(const RubyRequest& request);
+ RequestStatus makeRequest(PacketPtr pkt);
bool empty() const;
void print(std::ostream& out) const;
@@ -112,7 +109,7 @@ class Sequencer : public RubyPort, public Consumer
void removeRequest(SequencerRequest* request);
private:
- void issueRequest(const RubyRequest& request);
+ void issueRequest(PacketPtr pkt, RubyRequestType type);
void hitCallback(SequencerRequest* request,
GenericMachineType mach,
@@ -122,7 +119,7 @@ class Sequencer : public RubyPort, public Consumer
Time forwardRequestTime,
Time firstResponseTime);
- bool insertRequest(SequencerRequest* request);
+ RequestStatus insertRequest(PacketPtr pkt, RubyRequestType request_type);
bool handleLlsc(const Address& address, SequencerRequest* request);