# HG changeset patch
# User Brad Beckmann <brad.beckm...@amd.com>
# Date 1260657435 28800
# Node ID f164db9baf4ad51cf790ea3b134fed28f4e3d026
# Parent  5d3a90f0ef4c0f69f61fd262028a32fa5e632f8e
ruby: Copy M5 Port code from RubyMemory to RubyPort.

diff -r 5d3a90f0ef4c -r f164db9baf4a src/mem/ruby/system/RubyPort.cc
--- a/src/mem/ruby/system/RubyPort.cc   Sat Dec 12 14:37:14 2009 -0800
+++ b/src/mem/ruby/system/RubyPort.cc   Sat Dec 12 14:37:15 2009 -0800
@@ -5,8 +5,11 @@
 //void (*RubyPort::m_hit_callback)(int64_t) = NULL;
 uint16_t RubyPort::m_num_ports = 0;
 
+RubyPort::RequestMap RubyPort::pending_requests;
+
 RubyPort::RubyPort(const Params *p)
-    : MemObject(p)
+    : MemObject(p),
+      funcMemPort(csprintf("%s-funcmem_port", name()), this)
 {
     m_version = p->version;
     assert(m_version != -1);
@@ -24,5 +27,196 @@
 Port *
 RubyPort::getPort(const std::string &if_name, int idx)
 {
+    if (if_name == "port") {
+        return new M5Port(csprintf("%s-port%d", name(), idx), this);
+    } else if (if_name == "funcmem_port") {
+        return &funcMemPort;
+    }
     return NULL;
 }
+
+RubyPort::M5Port::M5Port(const std::string &_name, 
+                         RubyPort *_port)
+    : SimpleTimingPort(_name, _port)
+{
+    DPRINTF(Ruby, "creating port to ruby memory %s\n", _name);
+    ruby_port = _port;
+}
+
+Tick
+RubyPort::M5Port::recvAtomic(PacketPtr pkt)
+{
+    panic("RubyPort::M5Port::recvAtomic() not implemented!\n");
+    return 0;
+}
+
+
+bool
+RubyPort::M5Port::recvTiming(PacketPtr pkt)
+{
+    DPRINTF(MemoryAccess, 
+            "Timing access caught for address %#x\n",
+            pkt->getAddr());
+
+    //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 
+    // I'm pretty sure it didn't work correctly with the drain code, 
+    // so that would need to be fixed if we ever added it back.
+    //
+    assert(pkt->isRequest());
+
+    if (pkt->memInhibitAsserted()) {
+        warn("memInhibitAsserted???");
+        // snooper will supply based on copy of packet
+        // still target's responsibility to delete packet
+        delete pkt;
+        return true;
+    }
+
+    //
+    // Check for pio requests and directly send them to the dedicated
+    // pio_port.
+    //
+#if 0
+    if (isPioAddress(pkt->getAddr()) != false) {
+        return ruby_mem->pio_port->sendTiming(pkt);
+    }
+#endif
+
+    //
+    // For DMA and CPU requests, translate them to ruby requests before
+    // sending them to our assigned ruby port.
+    //
+    RubyRequestType type = RubyRequestType_NULL;
+    Addr pc = 0;
+    if (pkt->isRead()) {
+        if (pkt->req->isInstFetch()) {
+            type = RubyRequestType_IFETCH;
+            pc = pkt->req->getPC();
+        } else {
+            type = RubyRequestType_LD; 
+        }
+    } else if (pkt->isWrite()) {
+        type = RubyRequestType_ST;
+    } else if (pkt->isReadWrite()) {
+      //        type = RubyRequestType_RMW;
+    }
+
+    RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr<uint8_t>(),
+                             pkt->getSize(), pc, type,
+                             RubyAccessMode_Supervisor);
+
+    // Submit the ruby request
+    int64_t req_id = ruby_port->makeRequest(ruby_request);
+    if (req_id == -1) {
+        return false;
+    }
+
+    // Save the request for the callback
+    RubyPort::pending_requests[req_id] = new RequestCookie(pkt, this);
+
+    return true;
+}
+
+void
+RubyPort::ruby_hit_callback(int64_t req_id)
+{
+    //
+    // 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.
+    //
+    RequestMap::iterator i = pending_requests.find(req_id);
+    if (i == pending_requests.end())
+        panic("could not find pending request %d\n", req_id);
+
+    RequestCookie *cookie = i->second;
+    pending_requests.erase(i);
+
+    Packet *pkt = cookie->pkt;
+    M5Port *port = cookie->m5Port;
+    delete cookie;
+
+    port->hitCallback(pkt);
+}
+
+void
+RubyPort::M5Port::hitCallback(PacketPtr pkt)
+{
+
+    bool needsResponse = pkt->needsResponse();
+
+    DPRINTF(MemoryAccess, "Hit callback needs response %d\n",
+            needsResponse);
+
+    ruby_port->funcMemPort.sendFunctional(pkt);
+
+    // turn packet around to go back to requester if response expected
+    if (needsResponse) {
+        // recvAtomic() should already have turned packet into
+        // atomic response
+        assert(pkt->isResponse());
+        DPRINTF(MemoryAccess, "Sending packet back over port\n");
+        sendTiming(pkt);
+    } else {
+        delete pkt;
+    }
+    DPRINTF(MemoryAccess, "Hit callback done!\n");
+}
+
+bool
+RubyPort::M5Port::sendTiming(PacketPtr pkt)
+{
+    schedSendTiming(pkt, curTick + 1); //minimum latency, must be > 0
+    return true;
+}
+
+bool
+RubyPort::M5Port::isPioAddress(Addr addr)
+{
+#if 0
+    AddrRangeList pioAddrList;
+    bool snoop = false;
+    if (ruby_mem->pio_port == NULL) {
+        return false;
+    }
+  
+    ruby_mem->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 5d3a90f0ef4c -r f164db9baf4a src/mem/ruby/system/RubyPort.hh
--- a/src/mem/ruby/system/RubyPort.hh   Sat Dec 12 14:37:14 2009 -0800
+++ b/src/mem/ruby/system/RubyPort.hh   Sat Dec 12 14:37:15 2009 -0800
@@ -17,6 +17,28 @@
 
 class RubyPort : public MemObject {
 public:
+
+    class M5Port : public SimpleTimingPort
+    {
+
+        RubyPort *ruby_port;
+
+      public:
+        M5Port(const std::string &_name, 
+               RubyPort *_port);
+        bool sendTiming(PacketPtr pkt);
+        void hitCallback(PacketPtr pkt);
+
+      protected:
+        virtual bool recvTiming(PacketPtr pkt);
+        virtual Tick recvAtomic(PacketPtr pkt);
+
+      private:
+        bool isPioAddress(Addr addr);
+    };
+
+    friend class M5Port;
+
     typedef RubyPortParams Params;
     RubyPort(const Params *p);
   virtual ~RubyPort() {}
@@ -63,6 +85,20 @@
   static uint16_t m_num_ports;
   uint16_t m_port_id;
   uint64_t m_request_cnt;
+
+    struct RequestCookie {
+        Packet *pkt;
+        M5Port *m5Port;
+        RequestCookie(Packet *p, M5Port *m5p)
+            : pkt(p), m5Port(m5p)
+        {}
+    };
+
+    typedef std::map<int64_t, RequestCookie*> RequestMap;
+    static RequestMap pending_requests;
+    static void ruby_hit_callback(int64_t req_id);
+
+    FunctionalPort funcMemPort;
 };
 
 #endif

_______________________________________________
m5-dev mailing list
m5-dev@m5sim.org
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to