xbar.hh revision 3489
11689SN/A/* 210785Sgope@wisc.edu * Copyright (c) 2002-2005 The Regents of The University of Michigan 39480Snilay@cs.wisc.edu * All rights reserved. 49480Snilay@cs.wisc.edu * 510785Sgope@wisc.edu * Redistribution and use in source and binary forms, with or without 610785Sgope@wisc.edu * modification, are permitted provided that the following conditions are 710785Sgope@wisc.edu * met: redistributions of source code must retain the above copyright 810785Sgope@wisc.edu * notice, this list of conditions and the following disclaimer; 910785Sgope@wisc.edu * redistributions in binary form must reproduce the above copyright 1010785Sgope@wisc.edu * notice, this list of conditions and the following disclaimer in the 1110785Sgope@wisc.edu * documentation and/or other materials provided with the distribution; 1210785Sgope@wisc.edu * neither the name of the copyright holders nor the names of its 1310785Sgope@wisc.edu * contributors may be used to endorse or promote products derived from 1410785Sgope@wisc.edu * this software without specific prior written permission. 1510785Sgope@wisc.edu * 1610785Sgope@wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A * 281689SN/A * Authors: Ron Dreslinski 291689SN/A * Ali Saidi 301689SN/A */ 311689SN/A 321689SN/A/** 331689SN/A * @file 341689SN/A * Declaration of a bus object. 351689SN/A */ 361689SN/A 371689SN/A#ifndef __MEM_BUS_HH__ 381689SN/A#define __MEM_BUS_HH__ 391689SN/A 401689SN/A#include <string> 412665SN/A#include <list> 422665SN/A#include <inttypes.h> 431689SN/A 441061SN/A#include "base/range.hh" 4510785Sgope@wisc.edu#include "mem/mem_object.hh" 461061SN/A#include "mem/packet.hh" 4710785Sgope@wisc.edu#include "mem/port.hh" 4810785Sgope@wisc.edu#include "mem/request.hh" 4910785Sgope@wisc.edu#include "sim/eventq.hh" 5010785Sgope@wisc.edu 5110785Sgope@wisc.educlass Bus : public MemObject 5210785Sgope@wisc.edu{ 5310785Sgope@wisc.edu /** a globally unique id for this bus. */ 5410785Sgope@wisc.edu int busId; 5510785Sgope@wisc.edu /** the clock speed for the bus */ 5610785Sgope@wisc.edu int clock; 5710785Sgope@wisc.edu /** the width of the bus in bytes */ 5810785Sgope@wisc.edu int width; 5910785Sgope@wisc.edu /** the next tick at which the bus will be idle */ 6010785Sgope@wisc.edu Tick tickNextIdle; 6110785Sgope@wisc.edu 6211432Smitch.hayenga@arm.com static const int defaultId = -3; //Make it unique from Broadcast 6311432Smitch.hayenga@arm.com 6410785Sgope@wisc.edu struct DevMap { 6510785Sgope@wisc.edu int portId; 669480Snilay@cs.wisc.edu Range<Addr> range; 6710785Sgope@wisc.edu }; 6810785Sgope@wisc.edu std::vector<DevMap> portList; 6910785Sgope@wisc.edu AddrRangeList defaultRange; 7010785Sgope@wisc.edu std::vector<DevMap> portSnoopList; 7110785Sgope@wisc.edu 7210785Sgope@wisc.edu /** Function called by the port when the bus is recieving a Timing 7310785Sgope@wisc.edu transaction.*/ 7410785Sgope@wisc.edu bool recvTiming(PacketPtr pkt); 7510785Sgope@wisc.edu 7610785Sgope@wisc.edu /** Function called by the port when the bus is recieving a Atomic 7710785Sgope@wisc.edu transaction.*/ 7810785Sgope@wisc.edu Tick recvAtomic(PacketPtr pkt); 7910785Sgope@wisc.edu 8010785Sgope@wisc.edu /** Function called by the port when the bus is recieving a Functional 8110785Sgope@wisc.edu transaction.*/ 8210785Sgope@wisc.edu void recvFunctional(PacketPtr pkt); 8310785Sgope@wisc.edu 8410785Sgope@wisc.edu /** Timing function called by port when it is once again able to process 8510785Sgope@wisc.edu * requests. */ 8610785Sgope@wisc.edu void recvRetry(int id); 8710785Sgope@wisc.edu 8810785Sgope@wisc.edu /** Function called by the port when the bus is recieving a status change.*/ 8910785Sgope@wisc.edu void recvStatusChange(Port::Status status, int id); 9010785Sgope@wisc.edu 9110785Sgope@wisc.edu /** Find which port connected to this bus (if any) should be given a packet 9210785Sgope@wisc.edu * with this address. 9310785Sgope@wisc.edu * @param addr Address to find port for. 9410785Sgope@wisc.edu * @param id Id of the port this packet was received from (to prevent 9510785Sgope@wisc.edu * loops) 9610785Sgope@wisc.edu * @return pointer to port that the packet should be sent out of. 9710785Sgope@wisc.edu */ 9810785Sgope@wisc.edu Port *findPort(Addr addr, int id); 9910785Sgope@wisc.edu 10010785Sgope@wisc.edu /** Find all ports with a matching snoop range, except src port. Keep in mind 10110785Sgope@wisc.edu * that the ranges shouldn't overlap or you will get a double snoop to the same 10210785Sgope@wisc.edu * interface.and the cache will assert out. 10310785Sgope@wisc.edu * @param addr Address to find snoop prts for. 10410785Sgope@wisc.edu * @param id Id of the src port of the request to avoid calling snoop on src 10510785Sgope@wisc.edu * @return vector of IDs to snoop on 10610785Sgope@wisc.edu */ 10710785Sgope@wisc.edu std::vector<int> findSnoopPorts(Addr addr, int id); 10810785Sgope@wisc.edu 10910785Sgope@wisc.edu /** Snoop all relevant ports atomicly. */ 11010785Sgope@wisc.edu Tick atomicSnoop(PacketPtr pkt); 11110785Sgope@wisc.edu 11210785Sgope@wisc.edu /** Snoop all relevant ports functionally. */ 11310785Sgope@wisc.edu void functionalSnoop(PacketPtr pkt); 11410785Sgope@wisc.edu 11510785Sgope@wisc.edu /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 11610785Sgope@wisc.edu * the snoop to happen 11710785Sgope@wisc.edu * @return True if succeds. 11810785Sgope@wisc.edu */ 11910785Sgope@wisc.edu bool timingSnoop(PacketPtr pkt); 12010785Sgope@wisc.edu 12110785Sgope@wisc.edu /** Process address range request. 12210785Sgope@wisc.edu * @param resp addresses that we can respond to 12310785Sgope@wisc.edu * @param snoop addresses that we would like to snoop 12410785Sgope@wisc.edu * @param id ide of the busport that made the request. 12510785Sgope@wisc.edu */ 12610785Sgope@wisc.edu void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id); 12710785Sgope@wisc.edu 12810785Sgope@wisc.edu /** Occupy the bus with transmitting the packet pkt */ 12910785Sgope@wisc.edu void occupyBus(PacketPtr pkt); 13010785Sgope@wisc.edu 13110785Sgope@wisc.edu /** Declaration of the buses port type, one will be instantiated for each 13210785Sgope@wisc.edu of the interfaces connecting to the bus. */ 13310785Sgope@wisc.edu class BusPort : public Port 13410785Sgope@wisc.edu { 13510785Sgope@wisc.edu bool _onRetryList; 13610785Sgope@wisc.edu 13710785Sgope@wisc.edu /** A pointer to the bus to which this port belongs. */ 13810785Sgope@wisc.edu Bus *bus; 13910785Sgope@wisc.edu 14010785Sgope@wisc.edu /** A id to keep track of the intercafe ID this port is connected to. */ 14110785Sgope@wisc.edu int id; 14210785Sgope@wisc.edu 14310785Sgope@wisc.edu public: 14410785Sgope@wisc.edu 14510785Sgope@wisc.edu /** Constructor for the BusPort.*/ 14610785Sgope@wisc.edu BusPort(const std::string &_name, Bus *_bus, int _id) 14710785Sgope@wisc.edu : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 14810785Sgope@wisc.edu { } 14910785Sgope@wisc.edu 15010785Sgope@wisc.edu bool onRetryList() 15110785Sgope@wisc.edu { return _onRetryList; } 15210785Sgope@wisc.edu 15310785Sgope@wisc.edu void onRetryList(bool newVal) 15410785Sgope@wisc.edu { _onRetryList = newVal; } 15510785Sgope@wisc.edu 15610785Sgope@wisc.edu protected: 15710785Sgope@wisc.edu 15810785Sgope@wisc.edu /** When reciving a timing request from the peer port (at id), 15910785Sgope@wisc.edu pass it to the bus. */ 16010785Sgope@wisc.edu virtual bool recvTiming(PacketPtr pkt) 16110785Sgope@wisc.edu { pkt->setSrc(id); return bus->recvTiming(pkt); } 16210785Sgope@wisc.edu 16310785Sgope@wisc.edu /** When reciving a Atomic requestfrom the peer port (at id), 16410785Sgope@wisc.edu pass it to the bus. */ 16510785Sgope@wisc.edu virtual Tick recvAtomic(PacketPtr pkt) 16610785Sgope@wisc.edu { pkt->setSrc(id); return bus->recvAtomic(pkt); } 16710785Sgope@wisc.edu 16811429Sandreas.sandberg@arm.com /** When reciving a Functional requestfrom the peer port (at id), 1699480Snilay@cs.wisc.edu pass it to the bus. */ 17010785Sgope@wisc.edu virtual void recvFunctional(PacketPtr pkt) 17111429Sandreas.sandberg@arm.com { pkt->setSrc(id); bus->recvFunctional(pkt); } 17210785Sgope@wisc.edu 17310785Sgope@wisc.edu /** When reciving a status changefrom the peer port (at id), 17410785Sgope@wisc.edu pass it to the bus. */ 17510785Sgope@wisc.edu virtual void recvStatusChange(Status status) 17610785Sgope@wisc.edu { bus->recvStatusChange(status, id); } 17710785Sgope@wisc.edu 17810785Sgope@wisc.edu /** When reciving a retry from the peer port (at id), 17910785Sgope@wisc.edu pass it to the bus. */ 18010785Sgope@wisc.edu virtual void recvRetry() 18110785Sgope@wisc.edu { bus->recvRetry(id); } 18210785Sgope@wisc.edu 18310785Sgope@wisc.edu // This should return all the 'owned' addresses that are 18410785Sgope@wisc.edu // downstream from this bus, yes? That is, the union of all 18510785Sgope@wisc.edu // the 'owned' address ranges of all the other interfaces on 18610785Sgope@wisc.edu // this bus... 18710785Sgope@wisc.edu virtual void getDeviceAddressRanges(AddrRangeList &resp, 18810785Sgope@wisc.edu AddrRangeList &snoop) 18910785Sgope@wisc.edu { bus->addressRanges(resp, snoop, id); } 19010785Sgope@wisc.edu 19110785Sgope@wisc.edu // Hack to make translating port work without changes 19210785Sgope@wisc.edu virtual int deviceBlockSize() { return 32; } 19310785Sgope@wisc.edu 19410785Sgope@wisc.edu }; 19510785Sgope@wisc.edu 19610785Sgope@wisc.edu class BusFreeEvent : public Event 19710785Sgope@wisc.edu { 19810785Sgope@wisc.edu Bus * bus; 19910785Sgope@wisc.edu 20010785Sgope@wisc.edu public: 20110785Sgope@wisc.edu BusFreeEvent(Bus * _bus); 20210785Sgope@wisc.edu void process(); 20310785Sgope@wisc.edu const char *description(); 20410785Sgope@wisc.edu }; 20510785Sgope@wisc.edu 20610785Sgope@wisc.edu BusFreeEvent busIdle; 20710785Sgope@wisc.edu 20810785Sgope@wisc.edu bool inRetry; 20910785Sgope@wisc.edu 21010785Sgope@wisc.edu /** An array of pointers to the peer port interfaces 21110785Sgope@wisc.edu connected to this bus.*/ 21210785Sgope@wisc.edu std::vector<BusPort*> interfaces; 21310785Sgope@wisc.edu 21410785Sgope@wisc.edu /** An array of pointers to ports that retry should be called on because the 21510785Sgope@wisc.edu * original send failed for whatever reason.*/ 21610785Sgope@wisc.edu std::list<BusPort*> retryList; 21710785Sgope@wisc.edu 21810785Sgope@wisc.edu void addToRetryList(BusPort * port) 21911429Sandreas.sandberg@arm.com { 22011429Sandreas.sandberg@arm.com if (!inRetry) { 22110785Sgope@wisc.edu // The device wasn't retrying a packet, or wasn't at an appropriate 22211429Sandreas.sandberg@arm.com // time. 22311429Sandreas.sandberg@arm.com assert(!port->onRetryList()); 22410785Sgope@wisc.edu port->onRetryList(true); 22511429Sandreas.sandberg@arm.com retryList.push_back(port); 22611429Sandreas.sandberg@arm.com } else { 22710785Sgope@wisc.edu if (port->onRetryList()) { 22811429Sandreas.sandberg@arm.com // The device was retrying a packet. It didn't work, so we'll leave 22911429Sandreas.sandberg@arm.com // it at the head of the retry list. 23011429Sandreas.sandberg@arm.com assert(port == retryList.front()); 23111429Sandreas.sandberg@arm.com inRetry = false; 23211429Sandreas.sandberg@arm.com } 23311429Sandreas.sandberg@arm.com else { 23411429Sandreas.sandberg@arm.com port->onRetryList(true); 23511429Sandreas.sandberg@arm.com retryList.push_back(port); 23611429Sandreas.sandberg@arm.com } 23711429Sandreas.sandberg@arm.com } 23811429Sandreas.sandberg@arm.com } 23911429Sandreas.sandberg@arm.com 24011429Sandreas.sandberg@arm.com /** Port that handles requests that don't match any of the interfaces.*/ 24111429Sandreas.sandberg@arm.com BusPort *defaultPort; 24211426Smitch.hayenga@arm.com 24311429Sandreas.sandberg@arm.com /** Has the user specified their own default responder? */ 24410785Sgope@wisc.edu bool responderSet; 24510785Sgope@wisc.edu 24610785Sgope@wisc.edu public: 24710785Sgope@wisc.edu 24810785Sgope@wisc.edu /** A function used to return the port associated with this bus object. */ 24910785Sgope@wisc.edu virtual Port *getPort(const std::string &if_name, int idx = -1); 25010785Sgope@wisc.edu 25110785Sgope@wisc.edu virtual void init(); 25210785Sgope@wisc.edu 25310785Sgope@wisc.edu Bus(const std::string &n, int bus_id, int _clock, int _width, 25410785Sgope@wisc.edu bool responder_set) 25510785Sgope@wisc.edu : MemObject(n), busId(bus_id), clock(_clock), width(_width), 25610785Sgope@wisc.edu tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL), 25710785Sgope@wisc.edu responderSet(responder_set) 25810785Sgope@wisc.edu { 25910785Sgope@wisc.edu //Both the width and clock period must be positive 26010785Sgope@wisc.edu if (width <= 0) 26110785Sgope@wisc.edu fatal("Bus width must be positive\n"); 26210785Sgope@wisc.edu if (clock <= 0) 26310785Sgope@wisc.edu fatal("Bus clock period must be positive\n"); 26410785Sgope@wisc.edu } 26510785Sgope@wisc.edu 26610785Sgope@wisc.edu}; 26710785Sgope@wisc.edu 26810785Sgope@wisc.edu#endif //__MEM_BUS_HH__ 26910785Sgope@wisc.edu