mem: hmc: adds controller
authorErfan Azarkhish <erfan.azarkhish@unibo.it>
Tue, 3 Nov 2015 18:17:56 +0000 (12:17 -0600)
committerErfan Azarkhish <erfan.azarkhish@unibo.it>
Tue, 3 Nov 2015 18:17:56 +0000 (12:17 -0600)
This patch models a simple HMC Controller. It simply schedules the incoming
packets to HMC Serial Links using a round robin mechanism.  This patch should
be applied in series with other patches modeling a complete HMC device.

Committed by: Nilay Vaish <nilay@cs.wisc.edu>

src/mem/HMCController.py [new file with mode: 0644]
src/mem/SConscript
src/mem/hmc_controller.cc [new file with mode: 0644]
src/mem/hmc_controller.hh [new file with mode: 0644]

diff --git a/src/mem/HMCController.py b/src/mem/HMCController.py
new file mode 100644 (file)
index 0000000..e52438e
--- /dev/null
@@ -0,0 +1,73 @@
+# Copyright (c) 2012-2013 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# Copyright (c) 2015 The University of Bologna
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Erfan Azarkhish
+
+from m5.params import *
+from XBar import *
+
+# References:
+# [1] http://www.open-silicon.com/open-silicon-ips/hmc/
+# [2] Ahn, J.; Yoo, S.; Choi, K., "Low-Power Hybrid Memory Cubes With Link
+#   Power Management and Two-Level Prefetching," TVLSI 2015
+
+# The HMCController class highlights the fact that a component is required
+# between host and HMC to convert the host protocol (AXI for example) to the
+# serial links protocol. Moreover, this component should have large internal
+# queueing to hide the access latency of the HMC.
+# Plus, this controller can implement more advanced global scheduling policies
+# and can reorder and steer transactions if required. A good example of such
+# component is available in [1].
+# Also in [2] there is a similar component which is connected to all serial
+# links, and it schedules the requests to the ones which are not busy.
+# These two references clarify two things:
+# 1. The serial links support the same address range and packets can travel
+#  over any of them.
+# 2. One host can be connected to more than 1 serial link simply to achieve
+#  higher bandwidth, and not for any other reason.
+
+# In this model, we have used a round-robin counter, because it is the
+# simplest way to schedule packets over the non-busy serial links. However,
+# more advanced scheduling algorithms are possible and even host can dedicate
+# each serial link to a portion of the address space and interleave packets
+# over them. Yet in this model, we have not made any such assumptions on the
+# address space.
+
+class HMCController(NoncoherentXBar):
+        type = 'HMCController'
+        cxx_header = "mem/hmc_controller.hh"
index 404f4a90fd859b9039aefadc529ad7e27d3c833f..3b65131a2f05d5c8f2a8d6570d308680b89d76f5 100644 (file)
@@ -42,6 +42,7 @@ SimObject('ExternalSlave.py')
 SimObject('MemObject.py')
 SimObject('SimpleMemory.py')
 SimObject('XBar.py')
+SimObject('HMCController.py')
 
 Source('abstract_mem.cc')
 Source('addr_mapper.cc')
@@ -64,6 +65,7 @@ Source('snoop_filter.cc')
 Source('stack_dist_calc.cc')
 Source('tport.cc')
 Source('xbar.cc')
+Source('hmc_controller.cc')
 
 if env['TARGET_ISA'] != 'null':
     Source('fs_translating_port_proxy.cc')
@@ -101,6 +103,7 @@ DebugFlag('MemoryAccess')
 DebugFlag('PacketQueue')
 DebugFlag('StackDist')
 DebugFlag("DRAMSim2")
+DebugFlag('HMCController')
 
 DebugFlag("MemChecker")
 DebugFlag("MemCheckerMonitor")
diff --git a/src/mem/hmc_controller.cc b/src/mem/hmc_controller.cc
new file mode 100644 (file)
index 0000000..c6fd362
--- /dev/null
@@ -0,0 +1,120 @@
+#include "base/random.hh"
+#include "debug/HMCController.hh"
+#include "mem/hmc_controller.hh"
+
+HMCController::HMCController(const HMCControllerParams* p) :
+    NoncoherentXBar(p),
+    n_master_ports(p->port_master_connection_count),
+    rr_counter(0)
+{
+    assert(p->port_slave_connection_count == 1);
+}
+
+HMCController*
+HMCControllerParams::create()
+{
+    return new HMCController(this);
+}
+
+// Since this module is a load distributor, all its master ports have the same
+//  range so we should keep only one of the ranges and ignore the others
+void HMCController::recvRangeChange(PortID master_port_id)
+{
+    if (master_port_id == 0)
+    {
+       gotAllAddrRanges = true;
+       BaseXBar::recvRangeChange(master_port_id);
+    }
+    else
+        gotAddrRanges[master_port_id] = true;
+}
+
+int HMCController::rotate_counter()
+{
+    int current_value = rr_counter;
+    rr_counter++;
+    if (rr_counter == n_master_ports)
+        rr_counter = 0;
+    return current_value;
+}
+
+bool HMCController::recvTimingReq(PacketPtr pkt, PortID slave_port_id)
+{
+    // determine the source port based on the id
+    SlavePort *src_port = slavePorts[slave_port_id];
+
+    // we should never see express snoops on a non-coherent component
+    assert(!pkt->isExpressSnoop());
+
+    // For now, this is a simple round robin counter, for distribution the
+    //  load among the serial links
+    PortID master_port_id = rotate_counter();
+
+    // test if the layer should be considered occupied for the current
+    // port
+    if (!reqLayers[master_port_id]->tryTiming(src_port)) {
+        DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x BUSY\n",
+                src_port->name(), pkt->cmdString(), pkt->getAddr());
+        return false;
+    }
+
+    DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x\n",
+            src_port->name(), pkt->cmdString(), pkt->getAddr());
+
+    // store size and command as they might be modified when
+    // forwarding the packet
+    unsigned int pkt_size = pkt->hasData() ? pkt->getSize() : 0;
+    unsigned int pkt_cmd = pkt->cmdToIndex();
+
+    // store the old header delay so we can restore it if needed
+    Tick old_header_delay = pkt->headerDelay;
+
+    // a request sees the frontend and forward latency
+    Tick xbar_delay = (frontendLatency + forwardLatency) * clockPeriod();
+
+    // set the packet header and payload delay
+    calcPacketTiming(pkt, xbar_delay);
+
+    // determine how long to be layer is busy
+    Tick packetFinishTime = clockEdge(Cycles(1)) + pkt->payloadDelay;
+
+    // before forwarding the packet (and possibly altering it),
+    // remember if we are expecting a response
+    const bool expect_response = pkt->needsResponse() &&
+        !pkt->memInhibitAsserted();
+
+    // since it is a normal request, attempt to send the packet
+    bool success = masterPorts[master_port_id]->sendTimingReq(pkt);
+
+    if (!success)  {
+        // inhibited packets should never be forced to retry
+        assert(!pkt->memInhibitAsserted());
+
+        DPRINTF(HMCController, "recvTimingReq: src %s %s 0x%x RETRY\n",
+                src_port->name(), pkt->cmdString(), pkt->getAddr());
+
+        // restore the header delay as it is additive
+        pkt->headerDelay = old_header_delay;
+
+        // occupy until the header is sent
+        reqLayers[master_port_id]->failedTiming(src_port,
+                                                clockEdge(Cycles(1)));
+
+        return false;
+    }
+
+    // remember where to route the response to
+    if (expect_response) {
+        assert(routeTo.find(pkt->req) == routeTo.end());
+        routeTo[pkt->req] = slave_port_id;
+    }
+
+    reqLayers[master_port_id]->succeededTiming(packetFinishTime);
+
+    // stats updates
+    pktCount[slave_port_id][master_port_id]++;
+    pktSize[slave_port_id][master_port_id] += pkt_size;
+    transDist[pkt_cmd]++;
+
+    return true;
+}
diff --git a/src/mem/hmc_controller.hh b/src/mem/hmc_controller.hh
new file mode 100644 (file)
index 0000000..cec9425
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2015 The University of Bologna
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Erfan Azarkhish
+ */
+
+
+/**
+ * @file
+ * HMCController declaration
+ */
+
+#ifndef __HMC_CONTROLLER__
+#define __HMC_CONTROLLER__
+
+#include "mem/noncoherent_xbar.hh"
+#include "mem/port.hh"
+#include "params/HMCController.hh"
+
+/**
+ * HMC Controller, in general, is responsible for translating the host
+ * protocol (AXI for example) to serial links protocol. Plus, it should have
+ * large internal buffers to hide the access latency of the cube. It is also
+ * inferred from the standard [1] and the literature [2] that serial links
+ * share the same address range and packets can travel over any of them, so a
+ * load distribution mechanism is required.
+ * This model simply queues the incoming transactions (using a Bridge) and
+ * schedules them to the serial links using a simple round robin mechanism to
+ * balance the load among them. More advanced global scheduling policies and
+ * reordering and steering of transactions can be added to this model if
+ * required [3].
+ * [1] http://www.hybridmemorycube.org/specification-download/
+ * [2] Low-Power Hybrid Memory Cubes With Link Power Manageme and Two-Level
+ * Prefetching (J. Ahn et. al)
+ * [3] The Open-Silicon HMC Controller IP
+ * http://www.open-silicon.com/open-silicon-ips/hmc/
+ */
+
+class HMCController : public NoncoherentXBar
+{
+public:
+
+    HMCController(const HMCControllerParams *p);
+
+private:
+
+    // Receive range change only on one of the ports (because they all have
+    //  the same range)
+    virtual void recvRangeChange(PortID master_port_id);
+
+    // Receive a request and distribute it among slave ports
+    //  Simply forwards the packet to the next serial link based on a
+    //  Round-robin counter
+    virtual bool recvTimingReq(PacketPtr pkt, PortID slave_port_id);
+
+    int n_master_ports;
+
+    // The round-robin counter
+    int rr_counter;
+    /**
+     * Function for rotating the round robin counter
+     * @return the next value of the counter
+     */
+    int rotate_counter();
+};
+
+#endif //__HMC_CONTROLLER__