xbar.hh revision 3470
12SN/A/* 21762SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski 292665Ssaidi@eecs.umich.edu * Ali Saidi 302SN/A */ 312SN/A 322SN/A/** 332SN/A * @file 342SN/A * Declaration of a bus object. 352SN/A */ 361354SN/A 371354SN/A#ifndef __MEM_BUS_HH__ 382SN/A#define __MEM_BUS_HH__ 392SN/A 405501Snate@binkert.org#include <string> 415546Snate@binkert.org#include <list> 427004Snate@binkert.org#include <inttypes.h> 432SN/A 442SN/A#include "base/range.hh" 455769Snate@binkert.org#include "mem/mem_object.hh" 462361SN/A#include "mem/packet.hh" 471354SN/A#include "mem/port.hh" 486216Snate@binkert.org#include "mem/request.hh" 498232Snate@binkert.org#include "sim/eventq.hh" 5056SN/A 512SN/Aclass Bus : public MemObject 525543Ssaidi@eecs.umich.edu{ 532SN/A /** a globally unique id for this bus. */ 541354SN/A int busId; 551354SN/A /** the clock speed for the bus */ 562SN/A int clock; 572SN/A /** the width of the bus in bytes */ 582SN/A int width; 592SN/A /** the next tick at which the bus will be idle */ 605501Snate@binkert.org Tick tickNextIdle; 615501Snate@binkert.org 622SN/A Event * drainEvent; 639044SAli.Saidi@ARM.com 642SN/A static const int defaultId = -3; //Make it unique from Broadcast 652SN/A 662SN/A struct DevMap { 675769Snate@binkert.org int portId; 688902Sandreas.hansson@arm.com Range<Addr> range; 695769Snate@binkert.org }; 705769Snate@binkert.org std::vector<DevMap> portList; 717059Snate@binkert.org AddrRangeList defaultRange; 727059Snate@binkert.org std::vector<DevMap> portSnoopList; 737059Snate@binkert.org 747059Snate@binkert.org /** Function called by the port when the bus is recieving a Timing 757059Snate@binkert.org transaction.*/ 767059Snate@binkert.org bool recvTiming(PacketPtr pkt); 777059Snate@binkert.org 787059Snate@binkert.org /** Function called by the port when the bus is recieving a Atomic 797059Snate@binkert.org transaction.*/ 807059Snate@binkert.org Tick recvAtomic(PacketPtr pkt); 817059Snate@binkert.org 827059Snate@binkert.org /** Function called by the port when the bus is recieving a Functional 837059Snate@binkert.org transaction.*/ 847059Snate@binkert.org void recvFunctional(PacketPtr pkt); 857059Snate@binkert.org 867059Snate@binkert.org /** Timing function called by port when it is once again able to process 875769Snate@binkert.org * requests. */ 887058Snate@binkert.org void recvRetry(int id); 897058Snate@binkert.org 907058Snate@binkert.org /** Function called by the port when the bus is recieving a status change.*/ 912SN/A void recvStatusChange(Port::Status status, int id); 925502Snate@binkert.org 935502Snate@binkert.org /** Find which port connected to this bus (if any) should be given a packet 945502Snate@binkert.org * with this address. 955503Snate@binkert.org * @param addr Address to find port for. 965503Snate@binkert.org * @param id Id of the port this packet was received from (to prevent 975502Snate@binkert.org * loops) 985502Snate@binkert.org * @return pointer to port that the packet should be sent out of. 995502Snate@binkert.org */ 1005502Snate@binkert.org Port *findPort(Addr addr, int id); 1015502Snate@binkert.org 1025502Snate@binkert.org /** Find all ports with a matching snoop range, except src port. Keep in mind 1035502Snate@binkert.org * that the ranges shouldn't overlap or you will get a double snoop to the same 1045602Snate@binkert.org * interface.and the cache will assert out. 1055602Snate@binkert.org * @param addr Address to find snoop prts for. 1065501Snate@binkert.org * @param id Id of the src port of the request to avoid calling snoop on src 1075543Ssaidi@eecs.umich.edu * @return vector of IDs to snoop on 1087058Snate@binkert.org */ 1095769Snate@binkert.org std::vector<int> findSnoopPorts(Addr addr, int id); 1104016Sstever@eecs.umich.edu 1114016Sstever@eecs.umich.edu /** Snoop all relevant ports atomicly. */ 1124016Sstever@eecs.umich.edu Tick atomicSnoop(PacketPtr pkt); 1134016Sstever@eecs.umich.edu 1144016Sstever@eecs.umich.edu /** Snoop all relevant ports functionally. */ 1154016Sstever@eecs.umich.edu void functionalSnoop(PacketPtr pkt); 1164016Sstever@eecs.umich.edu 1174016Sstever@eecs.umich.edu /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 1184016Sstever@eecs.umich.edu * the snoop to happen 1195501Snate@binkert.org * @return True if succeds. 1205605Snate@binkert.org */ 1215605Snate@binkert.org bool timingSnoop(PacketPtr pkt); 1225605Snate@binkert.org 1235605Snate@binkert.org /** Process address range request. 1245501Snate@binkert.org * @param resp addresses that we can respond to 1254016Sstever@eecs.umich.edu * @param snoop addresses that we would like to snoop 1265577SSteve.Reinhardt@amd.com * @param id ide of the busport that made the request. 1275501Snate@binkert.org */ 1285501Snate@binkert.org void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id); 1295501Snate@binkert.org 1305502Snate@binkert.org /** Occupy the bus with transmitting the packet pkt */ 1315502Snate@binkert.org void occupyBus(PacketPtr pkt); 1325605Snate@binkert.org 1335502Snate@binkert.org /** Declaration of the buses port type, one will be instantiated for each 1345502Snate@binkert.org of the interfaces connecting to the bus. */ 1355605Snate@binkert.org class BusPort : public Port 1365605Snate@binkert.org { 1375605Snate@binkert.org bool _onRetryList; 1385577SSteve.Reinhardt@amd.com 1397823Ssteve.reinhardt@amd.com /** A pointer to the bus to which this port belongs. */ 1405502Snate@binkert.org Bus *bus; 1415502Snate@binkert.org 1425502Snate@binkert.org /** A id to keep track of the intercafe ID this port is connected to. */ 1432SN/A int id; 1445769Snate@binkert.org 1455769Snate@binkert.org public: 1465769Snate@binkert.org 1475769Snate@binkert.org /** Constructor for the BusPort.*/ 1485769Snate@binkert.org BusPort(const std::string &_name, Bus *_bus, int _id) 1495769Snate@binkert.org : Port(_name), _onRetryList(false), bus(_bus), id(_id) 1502SN/A { } 1518581Ssteve.reinhardt@amd.com 1528581Ssteve.reinhardt@amd.com bool onRetryList() 1535769Snate@binkert.org { return _onRetryList; } 1547059Snate@binkert.org 1555769Snate@binkert.org void onRetryList(bool newVal) 1565769Snate@binkert.org { _onRetryList = newVal; } 1572SN/A 1585769Snate@binkert.org protected: 1595769Snate@binkert.org 1605769Snate@binkert.org /** When reciving a timing request from the peer port (at id), 1615769Snate@binkert.org pass it to the bus. */ 1625769Snate@binkert.org virtual bool recvTiming(PacketPtr pkt) 1635769Snate@binkert.org { pkt->setSrc(id); return bus->recvTiming(pkt); } 1645769Snate@binkert.org 1655769Snate@binkert.org /** When reciving a Atomic requestfrom the peer port (at id), 1665769Snate@binkert.org pass it to the bus. */ 1675769Snate@binkert.org virtual Tick recvAtomic(PacketPtr pkt) 1685769Snate@binkert.org { pkt->setSrc(id); return bus->recvAtomic(pkt); } 1695769Snate@binkert.org 1705769Snate@binkert.org /** When reciving a Functional requestfrom the peer port (at id), 1715769Snate@binkert.org pass it to the bus. */ 1725769Snate@binkert.org virtual void recvFunctional(PacketPtr pkt) 1735769Snate@binkert.org { pkt->setSrc(id); bus->recvFunctional(pkt); } 1745769Snate@binkert.org 1755769Snate@binkert.org /** When reciving a status changefrom the peer port (at id), 1765769Snate@binkert.org pass it to the bus. */ 1775769Snate@binkert.org virtual void recvStatusChange(Status status) 1785769Snate@binkert.org { bus->recvStatusChange(status, id); } 1795501Snate@binkert.org 1805543Ssaidi@eecs.umich.edu /** When reciving a retry from the peer port (at id), 1812SN/A pass it to the bus. */ 1822SN/A virtual void recvRetry() 183396SN/A { bus->recvRetry(id); } 184396SN/A 185396SN/A // This should return all the 'owned' addresses that are 186396SN/A // downstream from this bus, yes? That is, the union of all 1875501Snate@binkert.org // the 'owned' address ranges of all the other interfaces on 1887058Snate@binkert.org // this bus... 1897058Snate@binkert.org virtual void getDeviceAddressRanges(AddrRangeList &resp, 1903329Sstever@eecs.umich.edu AddrRangeList &snoop) 1917058Snate@binkert.org { bus->addressRanges(resp, snoop, id); } 1927058Snate@binkert.org 1937058Snate@binkert.org // Hack to make translating port work without changes 1947058Snate@binkert.org virtual int deviceBlockSize() { return 32; } 195396SN/A 1967058Snate@binkert.org }; 1977058Snate@binkert.org 1987058Snate@binkert.org class BusFreeEvent : public Event 1997058Snate@binkert.org { 2003329Sstever@eecs.umich.edu Bus * bus; 2017058Snate@binkert.org 2027058Snate@binkert.org public: 2037058Snate@binkert.org BusFreeEvent(Bus * _bus); 2047058Snate@binkert.org void process(); 2057058Snate@binkert.org const char *description(); 206396SN/A }; 2077058Snate@binkert.org 2087058Snate@binkert.org BusFreeEvent busIdle; 2097058Snate@binkert.org 2107058Snate@binkert.org bool inRetry; 211396SN/A 2127058Snate@binkert.org /** An array of pointers to the peer port interfaces 2137058Snate@binkert.org connected to this bus.*/ 214396SN/A std::vector<BusPort*> interfaces; 2157058Snate@binkert.org 2167058Snate@binkert.org /** An array of pointers to ports that retry should be called on because the 2177058Snate@binkert.org * original send failed for whatever reason.*/ 2187058Snate@binkert.org std::list<BusPort*> retryList; 219396SN/A 2207058Snate@binkert.org void addToRetryList(BusPort * port) 2217058Snate@binkert.org { 2227058Snate@binkert.org if (!inRetry) { 223396SN/A // The device wasn't retrying a packet, or wasn't at an appropriate 2247058Snate@binkert.org // time. 2257058Snate@binkert.org assert(!port->onRetryList()); 2267058Snate@binkert.org port->onRetryList(true); 2274075Sbinkertn@umich.edu retryList.push_back(port); 2287058Snate@binkert.org } else { 2297058Snate@binkert.org if (port->onRetryList()) { 2305501Snate@binkert.org // The device was retrying a packet. It didn't work, so we'll leave 2317058Snate@binkert.org // it at the head of the retry list. 2327058Snate@binkert.org assert(port == retryList.front()); 2337058Snate@binkert.org inRetry = false; 2347058Snate@binkert.org } 2357058Snate@binkert.org else { 2367058Snate@binkert.org port->onRetryList(true); 237396SN/A retryList.push_back(port); 2382SN/A } 2392SN/A } 2402SN/A } 2412SN/A 2428581Ssteve.reinhardt@amd.com /** Port that handles requests that don't match any of the interfaces.*/ 2438581Ssteve.reinhardt@amd.com BusPort *defaultPort; 2448581Ssteve.reinhardt@amd.com 245224SN/A public: 2468581Ssteve.reinhardt@amd.com 2474016Sstever@eecs.umich.edu /** A function used to return the port associated with this bus object. */ 2485501Snate@binkert.org virtual Port *getPort(const std::string &if_name, int idx = -1); 2495605Snate@binkert.org 2505501Snate@binkert.org virtual void init(); 2515501Snate@binkert.org 2527823Ssteve.reinhardt@amd.com unsigned int drain(Event *de); 2535501Snate@binkert.org 2544016Sstever@eecs.umich.edu Bus(const std::string &n, int bus_id, int _clock, int _width) 255224SN/A : MemObject(n), busId(bus_id), clock(_clock), width(_width), 256224SN/A tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL) 2575768Snate@binkert.org { 2585768Snate@binkert.org //Both the width and clock period must be positive 259265SN/A if (width <= 0) 2605501Snate@binkert.org fatal("Bus width must be positive\n"); 2615501Snate@binkert.org if (clock <= 0) 2625501Snate@binkert.org fatal("Bus clock period must be positive\n"); 2635501Snate@binkert.org } 2645501Snate@binkert.org 2655501Snate@binkert.org}; 2665501Snate@binkert.org 2675501Snate@binkert.org#endif //__MEM_BUS_HH__ 2685501Snate@binkert.org