diff options
-rw-r--r-- | src/mem/HMCController.py | 73 | ||||
-rw-r--r-- | src/mem/SConscript | 3 | ||||
-rw-r--r-- | src/mem/hmc_controller.cc | 120 | ||||
-rw-r--r-- | src/mem/hmc_controller.hh | 103 |
4 files changed, 299 insertions, 0 deletions
diff --git a/src/mem/HMCController.py b/src/mem/HMCController.py new file mode 100644 index 000000000..e52438e98 --- /dev/null +++ b/src/mem/HMCController.py @@ -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" diff --git a/src/mem/SConscript b/src/mem/SConscript index 404f4a90f..3b65131a2 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -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 index 000000000..c6fd36206 --- /dev/null +++ b/src/mem/hmc_controller.cc @@ -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 index 000000000..cec9425d8 --- /dev/null +++ b/src/mem/hmc_controller.hh @@ -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__ |