noncoherent_xbar.hh revision 4475
110259SAndrew.Bardsley@arm.com/* 212355Snikos.nikoleris@arm.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 310259SAndrew.Bardsley@arm.com * All rights reserved. 410259SAndrew.Bardsley@arm.com * 510259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without 610259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are 710259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright 810259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer; 910259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright 1010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the 1110259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution; 1210259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its 1310259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from 1410259SAndrew.Bardsley@arm.com * this software without specific prior written permission. 1510259SAndrew.Bardsley@arm.com * 1610259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710259SAndrew.Bardsley@arm.com * 2810259SAndrew.Bardsley@arm.com * Authors: Ron Dreslinski 2910259SAndrew.Bardsley@arm.com * Ali Saidi 3010259SAndrew.Bardsley@arm.com */ 3110259SAndrew.Bardsley@arm.com 3210259SAndrew.Bardsley@arm.com/** 3310259SAndrew.Bardsley@arm.com * @file 3410259SAndrew.Bardsley@arm.com * Declaration of a bus object. 3510259SAndrew.Bardsley@arm.com */ 3610259SAndrew.Bardsley@arm.com 3710259SAndrew.Bardsley@arm.com#ifndef __MEM_BUS_HH__ 3810259SAndrew.Bardsley@arm.com#define __MEM_BUS_HH__ 3910259SAndrew.Bardsley@arm.com 4011793Sbrandon.potter@amd.com#include <string> 4111793Sbrandon.potter@amd.com#include <list> 4210259SAndrew.Bardsley@arm.com#include <inttypes.h> 4310259SAndrew.Bardsley@arm.com 4410259SAndrew.Bardsley@arm.com#include "base/range.hh" 4510259SAndrew.Bardsley@arm.com#include "base/hashmap.hh" 4610259SAndrew.Bardsley@arm.com#include "base/range_map.hh" 4710259SAndrew.Bardsley@arm.com#include "mem/mem_object.hh" 4810259SAndrew.Bardsley@arm.com#include "mem/packet.hh" 4910259SAndrew.Bardsley@arm.com#include "mem/port.hh" 5010259SAndrew.Bardsley@arm.com#include "mem/request.hh" 5110259SAndrew.Bardsley@arm.com#include "sim/eventq.hh" 5210259SAndrew.Bardsley@arm.com 5310259SAndrew.Bardsley@arm.comclass Bus : public MemObject 5410259SAndrew.Bardsley@arm.com{ 5510259SAndrew.Bardsley@arm.com /** Declaration of the buses port type, one will be instantiated for each 5610259SAndrew.Bardsley@arm.com of the interfaces connecting to the bus. */ 5710259SAndrew.Bardsley@arm.com class BusPort : public Port 5810259SAndrew.Bardsley@arm.com { 5910259SAndrew.Bardsley@arm.com bool _onRetryList; 6010259SAndrew.Bardsley@arm.com 6110259SAndrew.Bardsley@arm.com /** A pointer to the bus to which this port belongs. */ 6210259SAndrew.Bardsley@arm.com Bus *bus; 6310259SAndrew.Bardsley@arm.com 6410259SAndrew.Bardsley@arm.com /** A id to keep track of the intercafe ID this port is connected to. */ 6510259SAndrew.Bardsley@arm.com int id; 6610259SAndrew.Bardsley@arm.com 6710259SAndrew.Bardsley@arm.com public: 6810259SAndrew.Bardsley@arm.com 6910259SAndrew.Bardsley@arm.com /** Constructor for the BusPort.*/ 7010259SAndrew.Bardsley@arm.com BusPort(const std::string &_name, Bus *_bus, int _id) 7110259SAndrew.Bardsley@arm.com : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 7210259SAndrew.Bardsley@arm.com { } 7310259SAndrew.Bardsley@arm.com 7410259SAndrew.Bardsley@arm.com bool onRetryList() 7510259SAndrew.Bardsley@arm.com { return _onRetryList; } 7610259SAndrew.Bardsley@arm.com 7710259SAndrew.Bardsley@arm.com void onRetryList(bool newVal) 7810259SAndrew.Bardsley@arm.com { _onRetryList = newVal; } 7910259SAndrew.Bardsley@arm.com 8010259SAndrew.Bardsley@arm.com int getId() { return id; } 8110259SAndrew.Bardsley@arm.com 8210259SAndrew.Bardsley@arm.com protected: 8310259SAndrew.Bardsley@arm.com 8410259SAndrew.Bardsley@arm.com /** When reciving a timing request from the peer port (at id), 8510259SAndrew.Bardsley@arm.com pass it to the bus. */ 8610259SAndrew.Bardsley@arm.com virtual bool recvTiming(PacketPtr pkt) 8710259SAndrew.Bardsley@arm.com { pkt->setSrc(id); return bus->recvTiming(pkt); } 8810259SAndrew.Bardsley@arm.com 8910259SAndrew.Bardsley@arm.com /** When reciving a Atomic requestfrom the peer port (at id), 9010259SAndrew.Bardsley@arm.com pass it to the bus. */ 9110259SAndrew.Bardsley@arm.com virtual Tick recvAtomic(PacketPtr pkt) 9210259SAndrew.Bardsley@arm.com { pkt->setSrc(id); return bus->recvAtomic(pkt); } 9310259SAndrew.Bardsley@arm.com 9410259SAndrew.Bardsley@arm.com /** When reciving a Functional requestfrom the peer port (at id), 9510259SAndrew.Bardsley@arm.com pass it to the bus. */ 9610259SAndrew.Bardsley@arm.com virtual void recvFunctional(PacketPtr pkt) 9710259SAndrew.Bardsley@arm.com { pkt->setSrc(id); bus->recvFunctional(pkt); } 9810259SAndrew.Bardsley@arm.com 9910259SAndrew.Bardsley@arm.com /** When reciving a status changefrom the peer port (at id), 10012179Spau.cabre@metempsy.com pass it to the bus. */ 10110259SAndrew.Bardsley@arm.com virtual void recvStatusChange(Status status) 10210259SAndrew.Bardsley@arm.com { bus->recvStatusChange(status, id); } 10310259SAndrew.Bardsley@arm.com 10410259SAndrew.Bardsley@arm.com /** When reciving a retry from the peer port (at id), 10510259SAndrew.Bardsley@arm.com pass it to the bus. */ 10610259SAndrew.Bardsley@arm.com virtual void recvRetry() 10710259SAndrew.Bardsley@arm.com { bus->recvRetry(id); } 10810259SAndrew.Bardsley@arm.com 10910259SAndrew.Bardsley@arm.com // This should return all the 'owned' addresses that are 11010259SAndrew.Bardsley@arm.com // downstream from this bus, yes? That is, the union of all 11110259SAndrew.Bardsley@arm.com // the 'owned' address ranges of all the other interfaces on 11210259SAndrew.Bardsley@arm.com // this bus... 11310259SAndrew.Bardsley@arm.com virtual void getDeviceAddressRanges(AddrRangeList &resp, 11410259SAndrew.Bardsley@arm.com bool &snoop) 11510259SAndrew.Bardsley@arm.com { bus->addressRanges(resp, snoop, id); } 11610259SAndrew.Bardsley@arm.com 11710259SAndrew.Bardsley@arm.com // Ask the bus to ask everyone on the bus what their block size is and 11810259SAndrew.Bardsley@arm.com // take the max of it. This might need to be changed a bit if we ever 11910259SAndrew.Bardsley@arm.com // support multiple block sizes. 12010259SAndrew.Bardsley@arm.com virtual int deviceBlockSize() 12110259SAndrew.Bardsley@arm.com { return bus->findBlockSize(id); } 12210259SAndrew.Bardsley@arm.com 12310259SAndrew.Bardsley@arm.com }; 12410259SAndrew.Bardsley@arm.com 12510259SAndrew.Bardsley@arm.com class BusFreeEvent : public Event 12610259SAndrew.Bardsley@arm.com { 12710259SAndrew.Bardsley@arm.com Bus * bus; 12810259SAndrew.Bardsley@arm.com 12910259SAndrew.Bardsley@arm.com public: 13010259SAndrew.Bardsley@arm.com BusFreeEvent(Bus * _bus); 13110259SAndrew.Bardsley@arm.com void process(); 13210259SAndrew.Bardsley@arm.com const char *description(); 13310259SAndrew.Bardsley@arm.com }; 13410259SAndrew.Bardsley@arm.com 13510259SAndrew.Bardsley@arm.com /** a globally unique id for this bus. */ 13610259SAndrew.Bardsley@arm.com int busId; 13710259SAndrew.Bardsley@arm.com /** the clock speed for the bus */ 13810259SAndrew.Bardsley@arm.com int clock; 13910259SAndrew.Bardsley@arm.com /** the width of the bus in bytes */ 14010259SAndrew.Bardsley@arm.com int width; 14110259SAndrew.Bardsley@arm.com /** the next tick at which the bus will be idle */ 14210259SAndrew.Bardsley@arm.com Tick tickNextIdle; 14310259SAndrew.Bardsley@arm.com 14410259SAndrew.Bardsley@arm.com Event * drainEvent; 14510259SAndrew.Bardsley@arm.com 14610259SAndrew.Bardsley@arm.com 14710259SAndrew.Bardsley@arm.com static const int defaultId = -3; //Make it unique from Broadcast 14810259SAndrew.Bardsley@arm.com 14910259SAndrew.Bardsley@arm.com typedef range_map<Addr,int>::iterator PortIter; 15010259SAndrew.Bardsley@arm.com range_map<Addr, int> portMap; 15110259SAndrew.Bardsley@arm.com 15210259SAndrew.Bardsley@arm.com AddrRangeList defaultRange; 15310259SAndrew.Bardsley@arm.com 15410259SAndrew.Bardsley@arm.com typedef std::vector<BusPort*>::iterator SnoopIter; 15510259SAndrew.Bardsley@arm.com std::vector<BusPort*> snoopPorts; 15610259SAndrew.Bardsley@arm.com 15710259SAndrew.Bardsley@arm.com /** Function called by the port when the bus is recieving a Timing 15810259SAndrew.Bardsley@arm.com transaction.*/ 15910259SAndrew.Bardsley@arm.com bool recvTiming(PacketPtr pkt); 16010259SAndrew.Bardsley@arm.com 16110259SAndrew.Bardsley@arm.com /** Function called by the port when the bus is recieving a Atomic 16210259SAndrew.Bardsley@arm.com transaction.*/ 16310259SAndrew.Bardsley@arm.com Tick recvAtomic(PacketPtr pkt); 16410259SAndrew.Bardsley@arm.com 16510259SAndrew.Bardsley@arm.com /** Function called by the port when the bus is recieving a Functional 16610259SAndrew.Bardsley@arm.com transaction.*/ 16710259SAndrew.Bardsley@arm.com void recvFunctional(PacketPtr pkt); 16810259SAndrew.Bardsley@arm.com 16910259SAndrew.Bardsley@arm.com /** Timing function called by port when it is once again able to process 17010259SAndrew.Bardsley@arm.com * requests. */ 17110259SAndrew.Bardsley@arm.com void recvRetry(int id); 17210259SAndrew.Bardsley@arm.com 17310259SAndrew.Bardsley@arm.com /** Function called by the port when the bus is recieving a status change.*/ 17410259SAndrew.Bardsley@arm.com void recvStatusChange(Port::Status status, int id); 17510259SAndrew.Bardsley@arm.com 17610259SAndrew.Bardsley@arm.com /** Find which port connected to this bus (if any) should be given a packet 17710259SAndrew.Bardsley@arm.com * with this address. 17810259SAndrew.Bardsley@arm.com * @param addr Address to find port for. 17910259SAndrew.Bardsley@arm.com * @param id Id of the port this packet was received from (to prevent 18010259SAndrew.Bardsley@arm.com * loops) 18110259SAndrew.Bardsley@arm.com * @return pointer to port that the packet should be sent out of. 18210259SAndrew.Bardsley@arm.com */ 18310259SAndrew.Bardsley@arm.com Port *findPort(Addr addr, int id); 18410259SAndrew.Bardsley@arm.com 18510259SAndrew.Bardsley@arm.com /** Snoop all relevant ports atomicly. */ 18610259SAndrew.Bardsley@arm.com Tick atomicSnoop(PacketPtr pkt, Port* responder); 18710259SAndrew.Bardsley@arm.com 18810259SAndrew.Bardsley@arm.com /** Snoop all relevant ports functionally. */ 18910259SAndrew.Bardsley@arm.com void functionalSnoop(PacketPtr pkt, Port *responder); 19010259SAndrew.Bardsley@arm.com 19110259SAndrew.Bardsley@arm.com /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 19210259SAndrew.Bardsley@arm.com * the snoop to happen 19310259SAndrew.Bardsley@arm.com * @return True if succeds. 19410259SAndrew.Bardsley@arm.com */ 19510259SAndrew.Bardsley@arm.com bool timingSnoop(PacketPtr pkt, Port *responder); 19610259SAndrew.Bardsley@arm.com 19710259SAndrew.Bardsley@arm.com /** Process address range request. 19810259SAndrew.Bardsley@arm.com * @param resp addresses that we can respond to 19910259SAndrew.Bardsley@arm.com * @param snoop addresses that we would like to snoop 20010259SAndrew.Bardsley@arm.com * @param id ide of the busport that made the request. 20110259SAndrew.Bardsley@arm.com */ 20210259SAndrew.Bardsley@arm.com void addressRanges(AddrRangeList &resp, bool &snoop, int id); 20310259SAndrew.Bardsley@arm.com 20410259SAndrew.Bardsley@arm.com /** Occupy the bus with transmitting the packet pkt */ 20510259SAndrew.Bardsley@arm.com void occupyBus(PacketPtr pkt); 20610259SAndrew.Bardsley@arm.com 20710259SAndrew.Bardsley@arm.com /** Ask everyone on the bus what their size is 20810259SAndrew.Bardsley@arm.com * @param id id of the busport that made the request 20910259SAndrew.Bardsley@arm.com * @return the max of all the sizes 21010259SAndrew.Bardsley@arm.com */ 21110259SAndrew.Bardsley@arm.com int findBlockSize(int id); 21210259SAndrew.Bardsley@arm.com 21310259SAndrew.Bardsley@arm.com BusFreeEvent busIdle; 21410259SAndrew.Bardsley@arm.com 21510259SAndrew.Bardsley@arm.com bool inRetry; 21610259SAndrew.Bardsley@arm.com 21710259SAndrew.Bardsley@arm.com /** max number of bus ids we've handed out so far */ 21810259SAndrew.Bardsley@arm.com short maxId; 21910259SAndrew.Bardsley@arm.com 22011567Smitch.hayenga@arm.com /** An array of pointers to the peer port interfaces 22111567Smitch.hayenga@arm.com connected to this bus.*/ 22210259SAndrew.Bardsley@arm.com m5::hash_map<short,BusPort*> interfaces; 22310259SAndrew.Bardsley@arm.com 22410259SAndrew.Bardsley@arm.com /** An array of pointers to ports that retry should be called on because the 22510259SAndrew.Bardsley@arm.com * original send failed for whatever reason.*/ 22610259SAndrew.Bardsley@arm.com std::list<BusPort*> retryList; 22711567Smitch.hayenga@arm.com 22810259SAndrew.Bardsley@arm.com void addToRetryList(BusPort * port) 22910259SAndrew.Bardsley@arm.com { 23010259SAndrew.Bardsley@arm.com if (!inRetry) { 23110379Sandreas.hansson@arm.com // The device wasn't retrying a packet, or wasn't at an appropriate 23210379Sandreas.hansson@arm.com // time. 23310259SAndrew.Bardsley@arm.com assert(!port->onRetryList()); 23410259SAndrew.Bardsley@arm.com port->onRetryList(true); 23510259SAndrew.Bardsley@arm.com retryList.push_back(port); 23610259SAndrew.Bardsley@arm.com } else { 23710259SAndrew.Bardsley@arm.com if (port->onRetryList()) { 23810259SAndrew.Bardsley@arm.com // The device was retrying a packet. It didn't work, so we'll leave 23910259SAndrew.Bardsley@arm.com // it at the head of the retry list. 24010259SAndrew.Bardsley@arm.com assert(port == retryList.front()); 24110259SAndrew.Bardsley@arm.com inRetry = false; 24210259SAndrew.Bardsley@arm.com } 24310259SAndrew.Bardsley@arm.com else { 24410259SAndrew.Bardsley@arm.com port->onRetryList(true); 24510259SAndrew.Bardsley@arm.com retryList.push_back(port); 24610259SAndrew.Bardsley@arm.com } 24710259SAndrew.Bardsley@arm.com } 24810259SAndrew.Bardsley@arm.com } 24910259SAndrew.Bardsley@arm.com 25010259SAndrew.Bardsley@arm.com /** Port that handles requests that don't match any of the interfaces.*/ 25110259SAndrew.Bardsley@arm.com BusPort *defaultPort; 25210259SAndrew.Bardsley@arm.com 25310259SAndrew.Bardsley@arm.com BusPort *funcPort; 25410259SAndrew.Bardsley@arm.com int funcPortId; 25510259SAndrew.Bardsley@arm.com 25610259SAndrew.Bardsley@arm.com /** Has the user specified their own default responder? */ 25710259SAndrew.Bardsley@arm.com bool responderSet; 25810259SAndrew.Bardsley@arm.com 25910259SAndrew.Bardsley@arm.com int defaultBlockSize; 26010259SAndrew.Bardsley@arm.com int cachedBlockSize; 26110259SAndrew.Bardsley@arm.com bool cachedBlockSizeValid; 26210259SAndrew.Bardsley@arm.com 26310259SAndrew.Bardsley@arm.com public: 26410259SAndrew.Bardsley@arm.com 26510259SAndrew.Bardsley@arm.com /** A function used to return the port associated with this bus object. */ 26610259SAndrew.Bardsley@arm.com virtual Port *getPort(const std::string &if_name, int idx = -1); 26710259SAndrew.Bardsley@arm.com virtual void deletePortRefs(Port *p); 26810259SAndrew.Bardsley@arm.com 26910259SAndrew.Bardsley@arm.com virtual void init(); 27010259SAndrew.Bardsley@arm.com 27110259SAndrew.Bardsley@arm.com unsigned int drain(Event *de); 27210259SAndrew.Bardsley@arm.com 27310259SAndrew.Bardsley@arm.com Bus(const std::string &n, int bus_id, int _clock, int _width, 27410259SAndrew.Bardsley@arm.com bool responder_set, int dflt_blk_size) 27510259SAndrew.Bardsley@arm.com : MemObject(n), busId(bus_id), clock(_clock), width(_width), 27610259SAndrew.Bardsley@arm.com tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false), 27710259SAndrew.Bardsley@arm.com maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4), 27810379Sandreas.hansson@arm.com responderSet(responder_set), defaultBlockSize(dflt_blk_size), 27910379Sandreas.hansson@arm.com cachedBlockSize(0), cachedBlockSizeValid(false) 28010259SAndrew.Bardsley@arm.com { 28110259SAndrew.Bardsley@arm.com //Both the width and clock period must be positive 28210259SAndrew.Bardsley@arm.com if (width <= 0) 28310259SAndrew.Bardsley@arm.com fatal("Bus width must be positive\n"); 28410259SAndrew.Bardsley@arm.com if (clock <= 0) 28510259SAndrew.Bardsley@arm.com fatal("Bus clock period must be positive\n"); 28610259SAndrew.Bardsley@arm.com } 28710259SAndrew.Bardsley@arm.com 28810259SAndrew.Bardsley@arm.com}; 28910259SAndrew.Bardsley@arm.com 29010259SAndrew.Bardsley@arm.com#endif //__MEM_BUS_HH__ 29110259SAndrew.Bardsley@arm.com