changeset 4eec7bdde5b0 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=4eec7bdde5b0
description:
        ruby: route all packets through ruby port
        Currently, the interrupt controller in x86 is connected to the io bus
        directly.  Therefore the packets between the io devices and the 
interrupt
        controller do not go through ruby.  This patch changes ruby port so that
        these packets arrive at the ruby port first, which then routes them to 
their
        destination.  Note that the patch does not make these packets go 
through the
        ruby network.  That would happen in a subsequent patch.

diffstat:

 configs/example/ruby_fs.py             |    9 +-
 configs/ruby/MESI_Two_Level.py         |    4 +-
 src/mem/ruby/system/RubyPort.cc        |  193 ++++++++++++++++++++++----------
 src/mem/ruby/system/RubyPort.hh        |   82 ++++++++++---
 src/mem/ruby/system/Sequencer.py       |   12 +-
 tests/configs/pc-simple-timing-ruby.py |    6 +-
 6 files changed, 216 insertions(+), 90 deletions(-)

diffs (truncated from 610 to 300 lines):

diff -r bc3126a05a7f -r 4eec7bdde5b0 configs/example/ruby_fs.py
--- a/configs/example/ruby_fs.py        Sun Feb 23 19:16:16 2014 -0600
+++ b/configs/example/ruby_fs.py        Sun Feb 23 19:16:16 2014 -0600
@@ -122,14 +122,17 @@
     cpu.clk_domain = system.cpu_clk_domain
     cpu.createThreads()
     cpu.createInterruptController()
+
     cpu.icache_port = system.ruby._cpu_ruby_ports[i].slave
     cpu.dcache_port = system.ruby._cpu_ruby_ports[i].slave
+
     if buildEnv['TARGET_ISA'] == "x86":
         cpu.itb.walker.port = system.ruby._cpu_ruby_ports[i].slave
         cpu.dtb.walker.port = system.ruby._cpu_ruby_ports[i].slave
-        cpu.interrupts.pio = system.piobus.master
-        cpu.interrupts.int_master = system.piobus.slave
-        cpu.interrupts.int_slave = system.piobus.master
+
+        cpu.interrupts.pio = system.ruby._cpu_ruby_ports[i].master
+        cpu.interrupts.int_master = system.ruby._cpu_ruby_ports[i].slave
+        cpu.interrupts.int_slave = system.ruby._cpu_ruby_ports[i].master
 
     system.ruby._cpu_ruby_ports[i].access_phys_mem = True
 
diff -r bc3126a05a7f -r 4eec7bdde5b0 configs/ruby/MESI_Two_Level.py
--- a/configs/ruby/MESI_Two_Level.py    Sun Feb 23 19:16:16 2014 -0600
+++ b/configs/ruby/MESI_Two_Level.py    Sun Feb 23 19:16:16 2014 -0600
@@ -106,7 +106,9 @@
         l1_cntrl.sequencer = cpu_seq
 
         if piobus != None:
-            cpu_seq.pio_port = piobus.slave
+            cpu_seq.pio_master_port = piobus.slave
+            cpu_seq.mem_master_port = piobus.slave
+            cpu_seq.pio_slave_port = piobus.master
 
         exec("ruby_system.l1_cntrl%d = l1_cntrl" % i)
 
diff -r bc3126a05a7f -r 4eec7bdde5b0 src/mem/ruby/system/RubyPort.cc
--- a/src/mem/ruby/system/RubyPort.cc   Sun Feb 23 19:16:16 2014 -0600
+++ b/src/mem/ruby/system/RubyPort.cc   Sun Feb 23 19:16:16 2014 -0600
@@ -50,25 +50,28 @@
 
 RubyPort::RubyPort(const Params *p)
     : MemObject(p), m_version(p->version), m_controller(NULL),
-      m_mandatory_q_ptr(NULL),
-      pio_port(csprintf("%s-pio-port", name()), this),
-      m_usingRubyTester(p->using_ruby_tester),
-      drainManager(NULL), ruby_system(p->ruby_system), system(p->system),
+      m_mandatory_q_ptr(NULL), m_usingRubyTester(p->using_ruby_tester),
+      pioMasterPort(csprintf("%s.pio-master-port", name()), this),
+      pioSlavePort(csprintf("%s.pio-slave-port", name()), this),
+      memMasterPort(csprintf("%s.mem-master-port", name()), this),
+      memSlavePort(csprintf("%s-mem-slave-port", name()), this,
+          p->ruby_system, p->access_phys_mem, -1),
+      gotAddrRanges(p->port_master_connection_count), drainManager(NULL),
+      ruby_system(p->ruby_system), system(p->system),
       access_phys_mem(p->access_phys_mem)
 {
     assert(m_version != -1);
 
     // create the slave ports based on the number of connected ports
     for (size_t i = 0; i < p->port_slave_connection_count; ++i) {
-        slave_ports.push_back(new M5Port(csprintf("%s-slave%d", name(), i),
-                                         this, ruby_system,
-                                         access_phys_mem, i));
+        slave_ports.push_back(new MemSlavePort(csprintf("%s.slave%d", name(),
+            i), this, ruby_system, access_phys_mem, i));
     }
 
     // create the master ports based on the number of connected ports
     for (size_t i = 0; i < p->port_master_connection_count; ++i) {
-        master_ports.push_back(new PioPort(csprintf("%s-master%d", name(), i),
-                                           this));
+        master_ports.push_back(new PioMasterPort(csprintf("%s.master%d",
+            name(), i), this));
     }
 }
 
@@ -83,8 +86,12 @@
 BaseMasterPort &
 RubyPort::getMasterPort(const std::string &if_name, PortID idx)
 {
-    if (if_name == "pio_port") {
-        return pio_port;
+    if (if_name == "mem_master_port") {
+        return memMasterPort;
+    }
+
+    if (if_name == "pio_master_port") {
+        return pioMasterPort;
     }
 
     // used by the x86 CPUs to connect the interrupt PIO and interrupt slave
@@ -104,6 +111,13 @@
 BaseSlavePort &
 RubyPort::getSlavePort(const std::string &if_name, PortID idx)
 {
+    if (if_name == "mem_slave_port") {
+        return memSlavePort;
+    }
+
+    if (if_name == "pio_slave_port")
+        return pioSlavePort;
+
     // used by the CPUs to connect the caches to the interconnect, and
     // for the x86 case also the interrupt master
     if (if_name != "slave") {
@@ -118,32 +132,48 @@
     }
 }
 
-RubyPort::PioPort::PioPort(const std::string &_name,
+RubyPort::PioMasterPort::PioMasterPort(const std::string &_name,
                            RubyPort *_port)
-    : QueuedMasterPort(_name, _port, queue), queue(*_port, *this),
-      ruby_port(_port)
+    : QueuedMasterPort(_name, _port, queue), queue(*_port, *this)
 {
-    DPRINTF(RubyPort, "creating master port on ruby sequencer %s\n", _name);
+    DPRINTF(RubyPort, "Created master pioport on sequencer %s\n", _name);
 }
 
-RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port,
+RubyPort::PioSlavePort::PioSlavePort(const std::string &_name,
+                           RubyPort *_port)
+    : QueuedSlavePort(_name, _port, queue), queue(*_port, *this)
+{
+    DPRINTF(RubyPort, "Created slave pioport on sequencer %s\n", _name);
+}
+
+RubyPort::MemMasterPort::MemMasterPort(const std::string &_name,
+                           RubyPort *_port)
+    : QueuedMasterPort(_name, _port, queue), queue(*_port, *this)
+{
+    DPRINTF(RubyPort, "Created master memport on ruby sequencer %s\n", _name);
+}
+
+RubyPort::MemSlavePort::MemSlavePort(const std::string &_name, RubyPort *_port,
                          RubySystem *_system, bool _access_phys_mem, PortID id)
     : QueuedSlavePort(_name, _port, queue, id), queue(*_port, *this),
-      ruby_port(_port), ruby_system(_system),
-      access_phys_mem(_access_phys_mem)
+      ruby_system(_system), access_phys_mem(_access_phys_mem)
 {
-    DPRINTF(RubyPort, "creating slave port on ruby sequencer %s\n", _name);
-}
-
-Tick
-RubyPort::M5Port::recvAtomic(PacketPtr pkt)
-{
-    panic("RubyPort::M5Port::recvAtomic() not implemented!\n");
-    return 0;
+    DPRINTF(RubyPort, "Created slave memport on ruby sequencer %s\n", _name);
 }
 
 bool
-RubyPort::recvTimingResp(PacketPtr pkt, PortID master_port_id)
+RubyPort::PioMasterPort::recvTimingResp(PacketPtr pkt)
+{
+    RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
+    DPRINTF(RubyPort, "Response for address: 0x%#x\n", pkt->getAddr());
+
+    // send next cycle
+    ruby_port->pioSlavePort.schedTimingResp(
+            pkt, curTick() + g_system_ptr->clockPeriod());
+    return true;
+}
+
+bool RubyPort::MemMasterPort::recvTimingResp(PacketPtr pkt)
 {
     // got a response from a device
     assert(pkt->isResponse());
@@ -153,43 +183,66 @@
     DPRINTF(RubyPort,  "Pio response for address %#x, going to %d\n",
             pkt->getAddr(), pkt->getDest());
 
-    // Retrieve the port from the destination field
-    assert(pkt->getDest() < slave_ports.size());
+    // First we must retrieve the request port from the sender State
+    RubyPort::SenderState *senderState =
+        safe_cast<RubyPort::SenderState *>(pkt->popSenderState());
+    MemSlavePort *port = senderState->port;
+    assert(port != NULL);
+    delete senderState;
 
     // attempt to send the response in the next cycle
-    slave_ports[pkt->getDest()]->schedTimingResp(pkt, curTick() +
-                                                 g_system_ptr->clockPeriod());
+    port->schedTimingResp(pkt, curTick() + g_system_ptr->clockPeriod());
 
     return true;
 }
 
 bool
-RubyPort::M5Port::recvTimingReq(PacketPtr pkt)
+RubyPort::PioSlavePort::recvTimingReq(PacketPtr pkt)
 {
-    DPRINTF(RubyPort,
-            "Timing access for address %#x on port %d\n", pkt->getAddr(),
-            id);
+    RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
+
+    for (size_t i = 0; i < ruby_port->master_ports.size(); ++i) {
+        AddrRangeList l = ruby_port->master_ports[i]->getAddrRanges();
+        for (auto it = l.begin(); it != l.end(); ++it) {
+            if (it->contains(pkt->getAddr())) {
+                ruby_port->master_ports[i]->sendTimingReq(pkt);
+                return true;
+            }
+        }
+    }
+    panic("Should never reach here!\n");
+}
+
+bool
+RubyPort::MemSlavePort::recvTimingReq(PacketPtr pkt)
+{
+    DPRINTF(RubyPort, "Timing request for address %#x on port %d\n",
+            pkt->getAddr(), id);
+    RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
 
     if (pkt->memInhibitAsserted())
         panic("RubyPort should never see an inhibited request\n");
 
-    // Save the port id to be used later to route the response
-    pkt->setSrc(id);
-
     // Check for pio requests and directly send them to the dedicated
     // pio port.
     if (!isPhysMemAddress(pkt->getAddr())) {
-        assert(ruby_port->pio_port.isConnected());
-        DPRINTF(RubyPort,
-                "Request for address 0x%#x is assumed to be a pio request\n",
+        assert(ruby_port->memMasterPort.isConnected());
+        DPRINTF(RubyPort, "Request address %#x assumed to be a pio address\n",
                 pkt->getAddr());
 
+        // Save the port in the sender state object to be used later to
+        // route the response
+        pkt->pushSenderState(new SenderState(this));
+
         // send next cycle
-        ruby_port->pio_port.schedTimingReq(pkt,
+        ruby_port->memMasterPort.schedTimingReq(pkt,
             curTick() + g_system_ptr->clockPeriod());
         return true;
     }
 
+    // Save the port id to be used later to route the response
+    pkt->setSrc(id);
+
     assert(Address(pkt->getAddr()).getOffset() + pkt->getSize() <=
            RubySystem::getBlockSizeBytes());
 
@@ -213,26 +266,24 @@
         ruby_port->addToRetryList(this);
     }
 
-    DPRINTF(RubyPort,
-            "Request for address %#x did not issue because %s\n",
+    DPRINTF(RubyPort, "Request for address %#x did not issued because %s\n",
             pkt->getAddr(), RequestStatus_to_string(requestStatus));
 
     return false;
 }
 
 void
-RubyPort::M5Port::recvFunctional(PacketPtr pkt)
+RubyPort::MemSlavePort::recvFunctional(PacketPtr pkt)
 {
-    DPRINTF(RubyPort, "Functional access caught for address %#x\n",
-                                                           pkt->getAddr());
+    DPRINTF(RubyPort, "Functional access for address: %#x\n", pkt->getAddr());
+    RubyPort *ruby_port = static_cast<RubyPort *>(&owner);
 
     // Check for pio requests and directly send them to the dedicated
     // pio port.
     if (!isPhysMemAddress(pkt->getAddr())) {
-        assert(ruby_port->pio_port.isConnected());
-        DPRINTF(RubyPort, "Request for address 0x%#x is a pio request\n",
-                                                           pkt->getAddr());
-        panic("RubyPort::PioPort::recvFunctional() not implemented!\n");
+        assert(ruby_port->memMasterPort.isConnected());
+        DPRINTF(RubyPort, "Pio Request for address: 0x%#x\n", pkt->getAddr());
+        panic("RubyPort::PioMasterPort::recvFunctional() not implemented!\n");
     }
 
     assert(pkt->getAddr() + pkt->getSize() <=
@@ -248,8 +299,7 @@
     } else if (pkt->isWrite()) {
         accessSucceeded = ruby_system->functionalWrite(pkt);
     } else {
-        panic("RubyPort: unsupported functional command %s\n",
-              pkt->cmdString());
+        panic("Unsupported functional command %s\n", pkt->cmdString());
     }
 
     // Unless the requester explicitly said otherwise, generate an error if
@@ -298,7 +348,7 @@
_______________________________________________
gem5-dev mailing list
gem5-dev@gem5.org
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to