xbar.hh revision 10405
12381SN/A/* 210405Sandreas.hansson@arm.com * Copyright (c) 2011-2014 ARM Limited 38711SN/A * All rights reserved 48711SN/A * 58711SN/A * The license below extends only to copyright in the software and shall 68711SN/A * not be construed as granting a license to any other intellectual 78711SN/A * property including but not limited to intellectual property relating 88711SN/A * to a hardware implementation of the functionality of the software 98711SN/A * licensed hereunder. You may use the software subject to the license 108711SN/A * terms below provided that you ensure that this notice is replicated 118711SN/A * unmodified and in its entirety in all distributions of the software, 128711SN/A * modified or unmodified, in source code or in binary form. 138711SN/A * 142381SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 152381SN/A * All rights reserved. 162381SN/A * 172381SN/A * Redistribution and use in source and binary forms, with or without 182381SN/A * modification, are permitted provided that the following conditions are 192381SN/A * met: redistributions of source code must retain the above copyright 202381SN/A * notice, this list of conditions and the following disclaimer; 212381SN/A * redistributions in binary form must reproduce the above copyright 222381SN/A * notice, this list of conditions and the following disclaimer in the 232381SN/A * documentation and/or other materials provided with the distribution; 242381SN/A * neither the name of the copyright holders nor the names of its 252381SN/A * contributors may be used to endorse or promote products derived from 262381SN/A * this software without specific prior written permission. 272381SN/A * 282381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392665SN/A * 402665SN/A * Authors: Ron Dreslinski 412772SN/A * Ali Saidi 428715SN/A * Andreas Hansson 438922SN/A * William Wang 442381SN/A */ 452381SN/A 462381SN/A/** 472982SN/A * @file 4810405Sandreas.hansson@arm.com * Declaration of an abstract crossbar base class. 492381SN/A */ 502381SN/A 5110405Sandreas.hansson@arm.com#ifndef __MEM_XBAR_HH__ 5210405Sandreas.hansson@arm.com#define __MEM_XBAR_HH__ 532381SN/A 549291SN/A#include <deque> 552381SN/A 569235SN/A#include "base/addr_range_map.hh" 576215SN/A#include "base/types.hh" 582381SN/A#include "mem/mem_object.hh" 5910405Sandreas.hansson@arm.com#include "params/BaseXBar.hh" 609712SN/A#include "sim/stats.hh" 612381SN/A 629036SN/A/** 6310405Sandreas.hansson@arm.com * The base crossbar contains the common elements of the non-coherent 6410405Sandreas.hansson@arm.com * and coherent crossbar. It is an abstract class that does not have 6510405Sandreas.hansson@arm.com * any of the functionality relating to the actual reception and 6610405Sandreas.hansson@arm.com * transmission of packets, as this is left for the subclasses. 679036SN/A * 6810405Sandreas.hansson@arm.com * The BaseXBar is responsible for the basic flow control (busy or 699036SN/A * not), the administration of retries, and the address decoding. 709036SN/A */ 7110405Sandreas.hansson@arm.comclass BaseXBar : public MemObject 722381SN/A{ 739031SN/A 749036SN/A protected: 752381SN/A 769091SN/A /** 7710405Sandreas.hansson@arm.com * A layer is an internal crossbar arbitration point with its own 7810405Sandreas.hansson@arm.com * flow control. Each layer is a converging multiplexer tree. By 7910405Sandreas.hansson@arm.com * instantiating one layer per destination port (and per packet 8010405Sandreas.hansson@arm.com * type, i.e. request, response, snoop request and snoop 8110405Sandreas.hansson@arm.com * response), we model full crossbar structures like AXI, ACE, 8210405Sandreas.hansson@arm.com * PCIe, etc. 839093SN/A * 849093SN/A * The template parameter, PortClass, indicates the destination 8510405Sandreas.hansson@arm.com * port type for the layer. The retry list holds either master 8610405Sandreas.hansson@arm.com * ports or slave ports, depending on the direction of the 8710405Sandreas.hansson@arm.com * layer. Thus, a request layer has a retry list containing slave 8810405Sandreas.hansson@arm.com * ports, whereas a response layer holds master ports. 899091SN/A */ 909715SN/A template <typename SrcType, typename DstType> 919342SN/A class Layer : public Drainable 929092SN/A { 939091SN/A 949092SN/A public: 959092SN/A 969092SN/A /** 9710405Sandreas.hansson@arm.com * Create a layer and give it a name. The layer uses 9810405Sandreas.hansson@arm.com * the crossbar an event manager. 999092SN/A * 1009715SN/A * @param _port destination port the layer converges at 10110405Sandreas.hansson@arm.com * @param _xbar the crossbar this layer belongs to 1029092SN/A * @param _name the layer's name 1039092SN/A */ 10410405Sandreas.hansson@arm.com Layer(DstType& _port, BaseXBar& _xbar, const std::string& _name); 1059092SN/A 1069092SN/A /** 10710405Sandreas.hansson@arm.com * Drain according to the normal semantics, so that the crossbar 1089092SN/A * can tell the layer to drain, and pass an event to signal 1099092SN/A * back when drained. 1109092SN/A * 1119092SN/A * @param de drain event to call once drained 1129092SN/A * 1139092SN/A * @return 1 if busy or waiting to retry, or 0 if idle 1149092SN/A */ 1159342SN/A unsigned int drain(DrainManager *dm); 1169092SN/A 1179092SN/A /** 11810405Sandreas.hansson@arm.com * Get the crossbar layer's name 1199092SN/A */ 12010405Sandreas.hansson@arm.com const std::string name() const { return xbar.name() + _name; } 1219092SN/A 1229092SN/A 1239092SN/A /** 12410405Sandreas.hansson@arm.com * Determine if the layer accepts a packet from a specific 1259092SN/A * port. If not, the port in question is also added to the 1269612SN/A * retry list. In either case the state of the layer is 1279714SN/A * updated accordingly. 1289092SN/A * 1299612SN/A * @param port Source port presenting the packet 1309092SN/A * 13110405Sandreas.hansson@arm.com * @return True if the layer accepts the packet 1329092SN/A */ 1339715SN/A bool tryTiming(SrcType* src_port); 1349092SN/A 1359092SN/A /** 1369092SN/A * Deal with a destination port accepting a packet by potentially 1379092SN/A * removing the source port from the retry list (if retrying) and 13810405Sandreas.hansson@arm.com * occupying the layer accordingly. 1399092SN/A * 1409092SN/A * @param busy_time Time to spend as a result of a successful send 1419092SN/A */ 1429092SN/A void succeededTiming(Tick busy_time); 1439092SN/A 1449092SN/A /** 1459092SN/A * Deal with a destination port not accepting a packet by 1469092SN/A * potentially adding the source port to the retry list (if 14710405Sandreas.hansson@arm.com * not already at the front) and occupying the layer 1489092SN/A * accordingly. 1499092SN/A * 1509612SN/A * @param src_port Source port 1519092SN/A * @param busy_time Time to spend as a result of a failed send 1529092SN/A */ 1539715SN/A void failedTiming(SrcType* src_port, Tick busy_time); 1549092SN/A 15510405Sandreas.hansson@arm.com /** Occupy the layer until until */ 1569092SN/A void occupyLayer(Tick until); 1579092SN/A 1589092SN/A /** 1599612SN/A * Send a retry to the port at the head of waitingForLayer. The 1609092SN/A * caller must ensure that the list is not empty. 1619092SN/A */ 1629092SN/A void retryWaiting(); 1639092SN/A 1649092SN/A /** 1659612SN/A * Handle a retry from a neighbouring module. This wraps 1669092SN/A * retryWaiting by verifying that there are ports waiting 1679092SN/A * before calling retryWaiting. 1689092SN/A */ 1699715SN/A void recvRetry(); 1709092SN/A 1719712SN/A /** 1729712SN/A * Register stats for the layer 1739712SN/A */ 1749712SN/A void regStats(); 1759712SN/A 1769092SN/A private: 1779092SN/A 1789715SN/A /** The destination port this layer converges at. */ 1799715SN/A DstType& port; 1809715SN/A 18110405Sandreas.hansson@arm.com /** The crossbar this layer is a part of. */ 18210405Sandreas.hansson@arm.com BaseXBar& xbar; 1839092SN/A 1849092SN/A /** A name for this layer. */ 1859092SN/A std::string _name; 1869092SN/A 1879092SN/A /** 18810405Sandreas.hansson@arm.com * We declare an enum to track the state of the layer. The 18910405Sandreas.hansson@arm.com * starting point is an idle state where the layer is waiting 19010405Sandreas.hansson@arm.com * for a packet to arrive. Upon arrival, the layer 1919092SN/A * transitions to the busy state, where it remains either 1929092SN/A * until the packet transfer is done, or the header time is 19310405Sandreas.hansson@arm.com * spent. Once the layer leaves the busy state, it can 1949092SN/A * either go back to idle, if no packets have arrived while it 19510405Sandreas.hansson@arm.com * was busy, or the layer goes on to retry the first port 1969612SN/A * in waitingForLayer. A similar transition takes place from 19710405Sandreas.hansson@arm.com * idle to retry if the layer receives a retry from one of 1989092SN/A * its connected ports. The retry state lasts until the port 1999092SN/A * in questions calls sendTiming and returns control to the 20010405Sandreas.hansson@arm.com * layer, or goes to a busy state if the port does not 2019092SN/A * immediately react to the retry by calling sendTiming. 2029092SN/A */ 2039092SN/A enum State { IDLE, BUSY, RETRY }; 2049092SN/A 20510405Sandreas.hansson@arm.com /** track the state of the layer */ 2069092SN/A State state; 2079092SN/A 2089342SN/A /** manager to signal when drained */ 2099342SN/A DrainManager *drainManager; 2109092SN/A 2119092SN/A /** 2129612SN/A * A deque of ports that retry should be called on because 2139612SN/A * the original send was delayed due to a busy layer. 2149092SN/A */ 2159715SN/A std::deque<SrcType*> waitingForLayer; 2169092SN/A 2179092SN/A /** 2189715SN/A * Track who is waiting for the retry when receiving it from a 2199715SN/A * peer. If no port is waiting NULL is stored. 2209612SN/A */ 2219715SN/A SrcType* waitingForPeer; 2229612SN/A 2239612SN/A /** 22410405Sandreas.hansson@arm.com * Release the layer after being occupied and return to an 2259092SN/A * idle state where we proceed to send a retry to any 2269092SN/A * potential waiting port, or drain if asked to do so. 2279092SN/A */ 2289092SN/A void releaseLayer(); 2299092SN/A 2309092SN/A /** event used to schedule a release of the layer */ 2319092SN/A EventWrapper<Layer, &Layer::releaseLayer> releaseEvent; 2329092SN/A 2339712SN/A /** 2349712SN/A * Stats for occupancy and utilization. These stats capture 23510405Sandreas.hansson@arm.com * the time the layer spends in the busy state and are thus only 2369712SN/A * relevant when the memory system is in timing mode. 2379712SN/A */ 2389712SN/A Stats::Scalar occupancy; 2399712SN/A Stats::Formula utilization; 2409712SN/A 2419092SN/A }; 2429091SN/A 2435354SN/A /** cycles of overhead per transaction */ 2449240SN/A const Cycles headerCycles; 24510405Sandreas.hansson@arm.com /** the width of the xbar in bytes */ 2469240SN/A const uint32_t width; 2474475SN/A 2489235SN/A AddrRangeMap<PortID> portMap; 2494475SN/A 25010405Sandreas.hansson@arm.com /** all contigous ranges seen by this crossbar */ 25110405Sandreas.hansson@arm.com AddrRangeList xbarRanges; 2529564SN/A 2539279SN/A AddrRange defaultRange; 2544475SN/A 2558948SN/A /** 25610405Sandreas.hansson@arm.com * Function called by the port when the crossbar is recieving a 25710405Sandreas.hansson@arm.com * range change. 2589032SN/A * 2599032SN/A * @param master_port_id id of the port that received the change 2609032SN/A */ 2619032SN/A void recvRangeChange(PortID master_port_id); 2624475SN/A 26310405Sandreas.hansson@arm.com /** Find which port connected to this crossbar (if any) should be 26410405Sandreas.hansson@arm.com * given a packet with this address. 26510405Sandreas.hansson@arm.com * 2664475SN/A * @param addr Address to find port for. 2674894SN/A * @return id of port that the packet should be sent out of. 2684475SN/A */ 2699031SN/A PortID findPort(Addr addr); 2704475SN/A 2714958SN/A // Cache for the findPort function storing recently used ports from portMap 2724958SN/A struct PortCache { 2734958SN/A bool valid; 2749031SN/A PortID id; 2759279SN/A AddrRange range; 2764958SN/A }; 2774958SN/A 2784958SN/A PortCache portCache[3]; 2794958SN/A 2804958SN/A // Checks the cache and returns the id of the port that has the requested 2814958SN/A // address within its range 2829279SN/A inline PortID checkPortCache(Addr addr) const { 2839405SN/A if (portCache[0].valid && portCache[0].range.contains(addr)) { 2844963SN/A return portCache[0].id; 2854963SN/A } 2869405SN/A if (portCache[1].valid && portCache[1].range.contains(addr)) { 2874963SN/A return portCache[1].id; 2884963SN/A } 2899405SN/A if (portCache[2].valid && portCache[2].range.contains(addr)) { 2904963SN/A return portCache[2].id; 2914958SN/A } 2924958SN/A 2939031SN/A return InvalidPortID; 2944958SN/A } 2954958SN/A 2964958SN/A // Clears the earliest entry of the cache and inserts a new port entry 2979279SN/A inline void updatePortCache(short id, const AddrRange& range) { 2984958SN/A portCache[2].valid = portCache[1].valid; 2994958SN/A portCache[2].id = portCache[1].id; 3009279SN/A portCache[2].range = portCache[1].range; 3014958SN/A 3024958SN/A portCache[1].valid = portCache[0].valid; 3034958SN/A portCache[1].id = portCache[0].id; 3049279SN/A portCache[1].range = portCache[0].range; 3054958SN/A 3064958SN/A portCache[0].valid = true; 3074958SN/A portCache[0].id = id; 3089279SN/A portCache[0].range = range; 3094958SN/A } 3104958SN/A 3114958SN/A // Clears the cache. Needs to be called in constructor. 3124958SN/A inline void clearPortCache() { 3134958SN/A portCache[2].valid = false; 3144958SN/A portCache[1].valid = false; 3154958SN/A portCache[0].valid = false; 3164958SN/A } 3174958SN/A 3188711SN/A /** 31910405Sandreas.hansson@arm.com * Return the address ranges the crossbar is responsible for. 3208711SN/A * 3218711SN/A * @return a list of non-overlapping address ranges 3224475SN/A */ 3239090SN/A AddrRangeList getAddrRanges() const; 3248711SN/A 3259547SN/A /** 3269547SN/A * Calculate the timing parameters for the packet. Updates the 32710405Sandreas.hansson@arm.com * firstWordDelay and lastWordDelay fields of the packet 3289547SN/A * object with the relative number of ticks required to transmit 3299547SN/A * the header and the first word, and the last word, respectively. 3305354SN/A */ 3319547SN/A void calcPacketTiming(PacketPtr pkt); 3325354SN/A 3339032SN/A /** 33410405Sandreas.hansson@arm.com * Remember for each of the master ports of the crossbar if we got 33510405Sandreas.hansson@arm.com * an address range from the connected slave. For convenience, 33610405Sandreas.hansson@arm.com * also keep track of if we got ranges from all the slave modules 33710405Sandreas.hansson@arm.com * or not. 3389279SN/A */ 3399279SN/A std::vector<bool> gotAddrRanges; 3409279SN/A bool gotAllAddrRanges; 3413159SN/A 34210405Sandreas.hansson@arm.com /** The master and slave ports of the crossbar */ 3438966SN/A std::vector<SlavePort*> slavePorts; 3448966SN/A std::vector<MasterPort*> masterPorts; 3458966SN/A 3462846SN/A /** Port that handles requests that don't match any of the interfaces.*/ 3479031SN/A PortID defaultPortID; 3482846SN/A 3497523SN/A /** If true, use address range provided by default device. Any 3507523SN/A address not handled by another port and not in default device's 3517523SN/A range will cause a fatal error. If false, just send all 3527523SN/A addresses not handled by another port to default device. */ 3539240SN/A const bool useDefaultRange; 3543489SN/A 35510405Sandreas.hansson@arm.com BaseXBar(const BaseXBarParams *p); 3569036SN/A 35710405Sandreas.hansson@arm.com virtual ~BaseXBar(); 3589036SN/A 3599712SN/A /** 3609712SN/A * Stats for transaction distribution and data passing through the 36110405Sandreas.hansson@arm.com * crossbar. The transaction distribution is globally counting 3629712SN/A * different types of commands. The packet count and total packet 36310405Sandreas.hansson@arm.com * size are two-dimensional vectors that are indexed by the 3649712SN/A * slave port and master port id (thus the neighbouring master and 3659712SN/A * neighbouring slave), summing up both directions (request and 3669712SN/A * response). 3679712SN/A */ 3689712SN/A Stats::Vector transDist; 3699712SN/A Stats::Vector2d pktCount; 37010405Sandreas.hansson@arm.com Stats::Vector2d pktSize; 3719712SN/A 3722381SN/A public: 3732381SN/A 3749278SN/A virtual void init(); 3759278SN/A 37610405Sandreas.hansson@arm.com /** A function used to return the port associated with this object. */ 3779294SN/A BaseMasterPort& getMasterPort(const std::string& if_name, 3789294SN/A PortID idx = InvalidPortID); 3799294SN/A BaseSlavePort& getSlavePort(const std::string& if_name, 3809294SN/A PortID idx = InvalidPortID); 3812568SN/A 3829342SN/A virtual unsigned int drain(DrainManager *dm) = 0; 3833470SN/A 3849712SN/A virtual void regStats(); 3859712SN/A 3862381SN/A}; 3872381SN/A 38810405Sandreas.hansson@arm.com#endif //__MEM_XBAR_HH__ 389