# HG changeset patch
# User Brad Beckmann <[email protected]>
# Date 1260657437 28800
# Node ID fa98d755bc7afb680785e9fb2cb711c42514b815
# Parent d9f2104b2c11b32657c6fd30623a2a881a6e93ed
ruby: Added pio port support to Ruby Port
Added a pio port to RubyPort so that pio requests from the cpus can be
routed to m5 devices. The code compiles, but has not yet been tested.
diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/RubyPort.cc
--- a/src/mem/ruby/system/RubyPort.cc Sat Dec 12 14:37:16 2009 -0800
+++ b/src/mem/ruby/system/RubyPort.cc Sat Dec 12 14:37:17 2009 -0800
@@ -2,10 +2,9 @@
#include "mem/ruby/system/RubyPort.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
-//void (*RubyPort::m_hit_callback)(int64_t) = NULL;
uint16_t RubyPort::m_num_ports = 0;
-RubyPort::RequestMap RubyPort::pending_requests;
+RubyPort::RequestMap RubyPort::pending_cpu_requests;
RubyPort::RubyPort(const Params *p)
: MemObject(p),
@@ -20,6 +19,7 @@
m_port_id = m_num_ports++;
m_request_cnt = 0;
m_hit_callback = NULL;
+ pio_port = NULL;
assert(m_num_ports <= 2048); // see below for reason
}
@@ -34,21 +34,47 @@
{
if (if_name == "port") {
return new M5Port(csprintf("%s-port%d", name(), idx), this);
+ } else if (if_name == "pio_port") {
+ //
+ // ensure there is only one pio port
+ //
+ assert(pio_port == NULL);
+
+ pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx),
+ this);
+
+ return pio_port;
} else if (if_name == "funcmem_port") {
return &funcMemPort;
}
return NULL;
}
+RubyPort::PioPort::PioPort(const std::string &_name,
+ RubyPort *_port)
+ : SimpleTimingPort(_name, _port)
+{
+ DPRINTF(Ruby, "creating port to ruby sequencer to cpu %s\n", _name);
+ ruby_port = _port;
+}
+
RubyPort::M5Port::M5Port(const std::string &_name,
RubyPort *_port)
: SimpleTimingPort(_name, _port)
{
- DPRINTF(Ruby, "creating port to ruby memory %s\n", _name);
+ DPRINTF(Ruby, "creating port from ruby sequcner to cpu %s\n", _name);
ruby_port = _port;
}
Tick
+RubyPort::PioPort::recvAtomic(PacketPtr pkt)
+{
+ panic("RubyPort::PioPort::recvAtomic() not implemented!\n");
+ return 0;
+}
+
+
+Tick
RubyPort::M5Port::recvAtomic(PacketPtr pkt)
{
panic("RubyPort::M5Port::recvAtomic() not implemented!\n");
@@ -57,6 +83,36 @@
bool
+RubyPort::PioPort::recvTiming(PacketPtr pkt)
+{
+ //
+ // In FS mode, ruby memory will receive pio responses from devices and
+ // it must forward these responses back to the particular CPU.
+ //
+ DPRINTF(MemoryAccess,
+ "Pio response for address %#x\n",
+ pkt->getAddr());
+
+ assert(pkt->isResponse());
+
+ //
+ // First we must retrieve the request port from the sender State
+ //
+ RubyPort::SenderState *senderState =
+ safe_cast<RubyPort::SenderState *>(pkt->senderState);
+ M5Port *port = senderState->port;
+ assert(port != NULL);
+
+ // pop the sender state from the packet
+ pkt->senderState = senderState->saved;
+ delete senderState;
+
+ port->sendTiming(pkt);
+
+ return true;
+}
+
+bool
RubyPort::M5Port::recvTiming(PacketPtr pkt)
{
DPRINTF(MemoryAccess,
@@ -66,28 +122,6 @@
//dsm: based on SimpleTimingPort::recvTiming(pkt);
//
- // In FS mode, ruby memory will receive pio responses from devices and
- // it must forward these responses back to the particular CPU.
- //
-#if 0
- if (pkt->isResponse() != false && isPioAddress(pkt->getAddr()) != false) {
- DPRINTF(MemoryAccess,
- "Pio Response callback %#x\n",
- pkt->getAddr());
- SenderState *senderState = safe_cast<SenderState *>(pkt->senderState);
- M5Port *port = senderState->port;
-
- // pop the sender state from the packet
- pkt->senderState = senderState->saved;
- delete senderState;
-
- port->sendTiming(pkt);
-
- return true;
- }
-#endif
-
- //
// After checking for pio responses, the remainder of packets
// received by ruby should only be M5 requests, which should never
// get nacked. There used to be code to hanldle nacks here, but
@@ -106,13 +140,19 @@
//
// Check for pio requests and directly send them to the dedicated
- // pio_port.
+ // pio port.
//
-#if 0
- if (isPioAddress(pkt->getAddr()) != false) {
- return ruby_mem->pio_port->sendTiming(pkt);
+ if (!isPhysMemAddress(pkt->getAddr())) {
+ assert(ruby_port->pio_port != NULL);
+
+ //
+ // Save the port in the sender state object to be used later to
+ // route the response
+ //
+ pkt->senderState = new SenderState(this, pkt->senderState);
+
+ return ruby_port->pio_port->sendTiming(pkt);
}
-#endif
//
// For DMA and CPU requests, translate them to ruby requests before
@@ -144,7 +184,7 @@
}
// Save the request for the callback
- RubyPort::pending_requests[req_id] = new RequestCookie(pkt, this);
+ RubyPort::pending_cpu_requests[req_id] = new RequestCookie(pkt, this);
return true;
}
@@ -154,16 +194,14 @@
{
//
// Note: This single fuction can be called by cpu and dma ports,
- // as well as the functional port. The functional port prevents
- // us from replacing this single function with separate port
- // functions.
+ // as well as the functional port.
//
- RequestMap::iterator i = pending_requests.find(req_id);
- if (i == pending_requests.end())
+ RequestMap::iterator i = pending_cpu_requests.find(req_id);
+ if (i == pending_cpu_requests.end())
panic("could not find pending request %d\n", req_id);
RequestCookie *cookie = i->second;
- pending_requests.erase(i);
+ pending_cpu_requests.erase(i);
Packet *pkt = cookie->pkt;
M5Port *port = cookie->m5Port;
@@ -204,24 +242,50 @@
}
bool
+RubyPort::PioPort::sendTiming(PacketPtr pkt)
+{
+ schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0
+ return true;
+}
+
+bool
+RubyPort::M5Port::isPhysMemAddress(Addr addr)
+{
+ AddrRangeList physMemAddrList;
+ bool snoop = false;
+ ruby_port->funcMemPort.getPeerAddressRanges(physMemAddrList, snoop);
+ for(AddrRangeIter iter = physMemAddrList.begin();
+ iter != physMemAddrList.end();
+ iter++) {
+ if (addr >= iter->start && addr <= iter->end) {
+ DPRINTF(MemoryAccess, "Request found in %#llx - %#llx range\n",
+ iter->start, iter->end);
+ return true;
+ }
+ }
+ assert(isPioAddress(addr));
+ return false;
+}
+
+bool
RubyPort::M5Port::isPioAddress(Addr addr)
{
-#if 0
AddrRangeList pioAddrList;
bool snoop = false;
- if (ruby_mem->pio_port == NULL) {
+ if (ruby_port->pio_port == NULL) {
return false;
}
- ruby_mem->pio_port->getPeerAddressRanges(pioAddrList, snoop);
- for(AddrRangeIter iter = pioAddrList.begin(); iter != pioAddrList.end();
iter++) {
+ ruby_port->pio_port->getPeerAddressRanges(pioAddrList, snoop);
+ for(AddrRangeIter iter = pioAddrList.begin();
+ iter != pioAddrList.end();
+ iter++) {
if (addr >= iter->start && addr <= iter->end) {
DPRINTF(MemoryAccess, "Pio request found in %#llx - %#llx range\n",
iter->start, iter->end);
return true;
}
}
-#endif
return false;
}
diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/RubyPort.hh
--- a/src/mem/ruby/system/RubyPort.hh Sat Dec 12 14:37:16 2009 -0800
+++ b/src/mem/ruby/system/RubyPort.hh Sat Dec 12 14:37:17 2009 -0800
@@ -35,10 +35,39 @@
private:
bool isPioAddress(Addr addr);
+ bool isPhysMemAddress(Addr addr);
};
friend class M5Port;
+ class PioPort : public SimpleTimingPort
+ {
+
+ RubyPort *ruby_port;
+
+ public:
+ PioPort(const std::string &_name,
+ RubyPort *_port);
+ bool sendTiming(PacketPtr pkt);
+
+ protected:
+ virtual bool recvTiming(PacketPtr pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
+ };
+
+ friend class PioPort;
+
+ struct SenderState : public Packet::SenderState
+ {
+ M5Port* port;
+ Packet::SenderState *saved;
+
+ SenderState(M5Port* _port,
+ Packet::SenderState *sender_state = NULL)
+ : port(_port), saved(sender_state)
+ {}
+ };
+
typedef RubyPortParams Params;
RubyPort(const Params *p);
virtual ~RubyPort() {}
@@ -89,6 +118,7 @@
int m_version;
AbstractController* m_controller;
MessageBuffer* m_mandatory_q_ptr;
+ PioPort* pio_port;
private:
static uint16_t m_num_ports;
@@ -104,7 +134,7 @@
};
typedef std::map<int64_t, RequestCookie*> RequestMap;
- static RequestMap pending_requests;
+ static RequestMap pending_cpu_requests;
FunctionalPort funcMemPort;
};
diff -r d9f2104b2c11 -r fa98d755bc7a src/mem/ruby/system/Sequencer.py
--- a/src/mem/ruby/system/Sequencer.py Sat Dec 12 14:37:16 2009 -0800
+++ b/src/mem/ruby/system/Sequencer.py Sat Dec 12 14:37:17 2009 -0800
@@ -7,6 +7,7 @@
abstract = True
port = VectorPort("M5 port")
version = Param.Int(0, "")
+ pio_port = Port("Ruby_pio_port")
class RubySequencer(RubyPort):
type = 'RubySequencer'
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev