--- /dev/null
+# 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"
SimObject('MemObject.py')
SimObject('SimpleMemory.py')
SimObject('XBar.py')
+SimObject('HMCController.py')
Source('abstract_mem.cc')
Source('addr_mapper.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')
DebugFlag('PacketQueue')
DebugFlag('StackDist')
DebugFlag("DRAMSim2")
+DebugFlag('HMCController')
DebugFlag("MemChecker")
DebugFlag("MemCheckerMonitor")
--- /dev/null
+#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;
+}
--- /dev/null
+/*
+ * 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__