# HG changeset patch
# User Brad Beckmann <brad.beckm...@amd.com>
# 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
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to