xbar.hh revision 4894
113245Sgabeblack@google.com/* 213245Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan 313245Sgabeblack@google.com * All rights reserved. 413245Sgabeblack@google.com * 513245Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 613245Sgabeblack@google.com * modification, are permitted provided that the following conditions are 713245Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 813245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 913245Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1013245Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1113245Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1213245Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1313245Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1413245Sgabeblack@google.com * this software without specific prior written permission. 1513245Sgabeblack@google.com * 1613245Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1713245Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1813245Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1913245Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2013245Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2113245Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2213245Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2313245Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2413245Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2513245Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2613245Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2713245Sgabeblack@google.com * 2813245Sgabeblack@google.com * Authors: Ron Dreslinski 2913245Sgabeblack@google.com * Ali Saidi 3013245Sgabeblack@google.com */ 3113245Sgabeblack@google.com 3213245Sgabeblack@google.com/** 3313245Sgabeblack@google.com * @file 3413245Sgabeblack@google.com * Declaration of a bus object. 3513245Sgabeblack@google.com */ 3613245Sgabeblack@google.com 3713245Sgabeblack@google.com#ifndef __MEM_BUS_HH__ 3813245Sgabeblack@google.com#define __MEM_BUS_HH__ 3913245Sgabeblack@google.com 4013245Sgabeblack@google.com#include <string> 4113245Sgabeblack@google.com#include <list> 4213245Sgabeblack@google.com#include <inttypes.h> 4313245Sgabeblack@google.com 4413245Sgabeblack@google.com#include "base/range.hh" 4513245Sgabeblack@google.com#include "base/hashmap.hh" 4613245Sgabeblack@google.com#include "base/range_map.hh" 4713245Sgabeblack@google.com#include "mem/mem_object.hh" 4813245Sgabeblack@google.com#include "mem/packet.hh" 4913245Sgabeblack@google.com#include "mem/port.hh" 5013245Sgabeblack@google.com#include "mem/request.hh" 5113245Sgabeblack@google.com#include "sim/eventq.hh" 5213245Sgabeblack@google.com 5313245Sgabeblack@google.comclass Bus : public MemObject 5413245Sgabeblack@google.com{ 5513245Sgabeblack@google.com /** Declaration of the buses port type, one will be instantiated for each 5613245Sgabeblack@google.com of the interfaces connecting to the bus. */ 5713245Sgabeblack@google.com class BusPort : public Port 5813245Sgabeblack@google.com { 5913245Sgabeblack@google.com bool _onRetryList; 6013245Sgabeblack@google.com 6113245Sgabeblack@google.com /** A pointer to the bus to which this port belongs. */ 6213245Sgabeblack@google.com Bus *bus; 6313245Sgabeblack@google.com 6413245Sgabeblack@google.com /** A id to keep track of the intercafe ID this port is connected to. */ 6513245Sgabeblack@google.com int id; 6613245Sgabeblack@google.com 6713245Sgabeblack@google.com public: 6813245Sgabeblack@google.com 6913245Sgabeblack@google.com /** Constructor for the BusPort.*/ 7013245Sgabeblack@google.com BusPort(const std::string &_name, Bus *_bus, int _id) 7113245Sgabeblack@google.com : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id) 7213245Sgabeblack@google.com { } 7313245Sgabeblack@google.com 7413245Sgabeblack@google.com bool onRetryList() 7513245Sgabeblack@google.com { return _onRetryList; } 7613245Sgabeblack@google.com 7713245Sgabeblack@google.com void onRetryList(bool newVal) 7813245Sgabeblack@google.com { _onRetryList = newVal; } 7913245Sgabeblack@google.com 8013245Sgabeblack@google.com int getId() { return id; } 8113245Sgabeblack@google.com 8213245Sgabeblack@google.com protected: 8313245Sgabeblack@google.com 8413245Sgabeblack@google.com /** When reciving a timing request from the peer port (at id), 8513245Sgabeblack@google.com pass it to the bus. */ 8613245Sgabeblack@google.com virtual bool recvTiming(PacketPtr pkt) 8713245Sgabeblack@google.com { pkt->setSrc(id); return bus->recvTiming(pkt); } 8813245Sgabeblack@google.com 8913245Sgabeblack@google.com /** When reciving a Atomic requestfrom the peer port (at id), 9013245Sgabeblack@google.com pass it to the bus. */ 9113245Sgabeblack@google.com virtual Tick recvAtomic(PacketPtr pkt) 9213245Sgabeblack@google.com { pkt->setSrc(id); return bus->recvAtomic(pkt); } 9313245Sgabeblack@google.com 9413245Sgabeblack@google.com /** When reciving a Functional requestfrom the peer port (at id), 9513245Sgabeblack@google.com pass it to the bus. */ 9613245Sgabeblack@google.com virtual void recvFunctional(PacketPtr pkt) 9713245Sgabeblack@google.com { pkt->setSrc(id); bus->recvFunctional(pkt); } 9813245Sgabeblack@google.com 9913245Sgabeblack@google.com /** When reciving a status changefrom the peer port (at id), 10013245Sgabeblack@google.com pass it to the bus. */ 10113245Sgabeblack@google.com virtual void recvStatusChange(Status status) 10213245Sgabeblack@google.com { bus->recvStatusChange(status, id); } 10313245Sgabeblack@google.com 10413245Sgabeblack@google.com /** When reciving a retry from the peer port (at id), 10513245Sgabeblack@google.com pass it to the bus. */ 10613245Sgabeblack@google.com virtual void recvRetry() 10713245Sgabeblack@google.com { bus->recvRetry(id); } 10813245Sgabeblack@google.com 10913245Sgabeblack@google.com // This should return all the 'owned' addresses that are 11013245Sgabeblack@google.com // downstream from this bus, yes? That is, the union of all 11113245Sgabeblack@google.com // the 'owned' address ranges of all the other interfaces on 11213245Sgabeblack@google.com // this bus... 11313245Sgabeblack@google.com virtual void getDeviceAddressRanges(AddrRangeList &resp, 11413245Sgabeblack@google.com bool &snoop) 11513245Sgabeblack@google.com { bus->addressRanges(resp, snoop, id); } 11613245Sgabeblack@google.com 11713245Sgabeblack@google.com // Ask the bus to ask everyone on the bus what their block size is and 11813245Sgabeblack@google.com // take the max of it. This might need to be changed a bit if we ever 11913245Sgabeblack@google.com // support multiple block sizes. 12013245Sgabeblack@google.com virtual int deviceBlockSize() 12113245Sgabeblack@google.com { return bus->findBlockSize(id); } 12213245Sgabeblack@google.com 12313245Sgabeblack@google.com }; 12413245Sgabeblack@google.com 12513245Sgabeblack@google.com class BusFreeEvent : public Event 12613245Sgabeblack@google.com { 12713245Sgabeblack@google.com Bus * bus; 12813245Sgabeblack@google.com 12913245Sgabeblack@google.com public: 13013245Sgabeblack@google.com BusFreeEvent(Bus * _bus); 13113245Sgabeblack@google.com void process(); 13213245Sgabeblack@google.com const char *description(); 13313245Sgabeblack@google.com }; 13413245Sgabeblack@google.com 13513245Sgabeblack@google.com /** a globally unique id for this bus. */ 13613245Sgabeblack@google.com int busId; 13713245Sgabeblack@google.com /** the clock speed for the bus */ 13813245Sgabeblack@google.com int clock; 13913245Sgabeblack@google.com /** the width of the bus in bytes */ 14013245Sgabeblack@google.com int width; 14113245Sgabeblack@google.com /** the next tick at which the bus will be idle */ 14213245Sgabeblack@google.com Tick tickNextIdle; 14313245Sgabeblack@google.com 14413245Sgabeblack@google.com Event * drainEvent; 14513245Sgabeblack@google.com 14613245Sgabeblack@google.com 14713245Sgabeblack@google.com static const int defaultId = -3; //Make it unique from Broadcast 14813245Sgabeblack@google.com 14913245Sgabeblack@google.com typedef range_map<Addr,int>::iterator PortIter; 15013245Sgabeblack@google.com range_map<Addr, int> portMap; 15113245Sgabeblack@google.com 15213245Sgabeblack@google.com AddrRangeList defaultRange; 15313245Sgabeblack@google.com 15413245Sgabeblack@google.com typedef std::vector<BusPort*>::iterator SnoopIter; 15513245Sgabeblack@google.com std::vector<BusPort*> snoopPorts; 15613245Sgabeblack@google.com 15713245Sgabeblack@google.com /** Function called by the port when the bus is recieving a Timing 15813245Sgabeblack@google.com transaction.*/ 15913245Sgabeblack@google.com bool recvTiming(PacketPtr pkt); 16013245Sgabeblack@google.com 16113245Sgabeblack@google.com /** Function called by the port when the bus is recieving a Atomic 16213245Sgabeblack@google.com transaction.*/ 16313245Sgabeblack@google.com Tick recvAtomic(PacketPtr pkt); 16413245Sgabeblack@google.com 16513245Sgabeblack@google.com /** Function called by the port when the bus is recieving a Functional 16613245Sgabeblack@google.com transaction.*/ 16713245Sgabeblack@google.com void recvFunctional(PacketPtr pkt); 16813245Sgabeblack@google.com 16913245Sgabeblack@google.com /** Timing function called by port when it is once again able to process 17013245Sgabeblack@google.com * requests. */ 17113245Sgabeblack@google.com void recvRetry(int id); 17213245Sgabeblack@google.com 17313245Sgabeblack@google.com /** Function called by the port when the bus is recieving a status change.*/ 17413245Sgabeblack@google.com void recvStatusChange(Port::Status status, int id); 17513245Sgabeblack@google.com 17613245Sgabeblack@google.com /** Find which port connected to this bus (if any) should be given a packet 17713245Sgabeblack@google.com * with this address. 17813245Sgabeblack@google.com * @param addr Address to find port for. 17913245Sgabeblack@google.com * @return id of port that the packet should be sent out of. 18013245Sgabeblack@google.com */ 18113245Sgabeblack@google.com int findPort(Addr addr); 18213245Sgabeblack@google.com 18313245Sgabeblack@google.com /** Snoop all relevant ports functionally. */ 18413245Sgabeblack@google.com void functionalSnoop(PacketPtr pkt, Port *responder); 18513245Sgabeblack@google.com 18613245Sgabeblack@google.com /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want 18713245Sgabeblack@google.com * the snoop to happen 18813245Sgabeblack@google.com * @return True if succeds. 18913245Sgabeblack@google.com */ 19013245Sgabeblack@google.com bool timingSnoop(PacketPtr pkt, Port *responder); 19113245Sgabeblack@google.com 19213245Sgabeblack@google.com /** Process address range request. 19313245Sgabeblack@google.com * @param resp addresses that we can respond to 19413245Sgabeblack@google.com * @param snoop addresses that we would like to snoop 19513245Sgabeblack@google.com * @param id ide of the busport that made the request. 19613245Sgabeblack@google.com */ 19713245Sgabeblack@google.com void addressRanges(AddrRangeList &resp, bool &snoop, int id); 19813245Sgabeblack@google.com 19913245Sgabeblack@google.com /** Occupy the bus with transmitting the packet pkt */ 20013245Sgabeblack@google.com void occupyBus(PacketPtr pkt); 20113245Sgabeblack@google.com 20213245Sgabeblack@google.com /** Ask everyone on the bus what their size is 20313245Sgabeblack@google.com * @param id id of the busport that made the request 20413245Sgabeblack@google.com * @return the max of all the sizes 20513245Sgabeblack@google.com */ 20613245Sgabeblack@google.com int findBlockSize(int id); 20713245Sgabeblack@google.com 20813245Sgabeblack@google.com BusFreeEvent busIdle; 20913245Sgabeblack@google.com 21013245Sgabeblack@google.com bool inRetry; 21113245Sgabeblack@google.com 21213245Sgabeblack@google.com /** max number of bus ids we've handed out so far */ 21313245Sgabeblack@google.com short maxId; 21413245Sgabeblack@google.com 21513245Sgabeblack@google.com /** An array of pointers to the peer port interfaces 21613245Sgabeblack@google.com connected to this bus.*/ 21713245Sgabeblack@google.com m5::hash_map<short,BusPort*> interfaces; 21813245Sgabeblack@google.com 21913245Sgabeblack@google.com /** An array of pointers to ports that retry should be called on because the 22013245Sgabeblack@google.com * original send failed for whatever reason.*/ 22113245Sgabeblack@google.com std::list<BusPort*> retryList; 22213245Sgabeblack@google.com 22313245Sgabeblack@google.com void addToRetryList(BusPort * port) 22413245Sgabeblack@google.com { 22513245Sgabeblack@google.com if (!inRetry) { 22613245Sgabeblack@google.com // The device wasn't retrying a packet, or wasn't at an appropriate 22713245Sgabeblack@google.com // time. 22813245Sgabeblack@google.com assert(!port->onRetryList()); 22913245Sgabeblack@google.com port->onRetryList(true); 23013245Sgabeblack@google.com retryList.push_back(port); 23113245Sgabeblack@google.com } else { 23213245Sgabeblack@google.com if (port->onRetryList()) { 23313245Sgabeblack@google.com // The device was retrying a packet. It didn't work, so we'll leave 23413245Sgabeblack@google.com // it at the head of the retry list. 23513245Sgabeblack@google.com assert(port == retryList.front()); 23613245Sgabeblack@google.com inRetry = false; 23713245Sgabeblack@google.com } 23813245Sgabeblack@google.com else { 23913245Sgabeblack@google.com port->onRetryList(true); 24013245Sgabeblack@google.com retryList.push_back(port); 24113245Sgabeblack@google.com } 24213245Sgabeblack@google.com } 24313245Sgabeblack@google.com } 24413245Sgabeblack@google.com 24513245Sgabeblack@google.com /** Port that handles requests that don't match any of the interfaces.*/ 24613245Sgabeblack@google.com BusPort *defaultPort; 24713245Sgabeblack@google.com 24813245Sgabeblack@google.com BusPort *funcPort; 24913245Sgabeblack@google.com int funcPortId; 25013245Sgabeblack@google.com 25113245Sgabeblack@google.com /** Has the user specified their own default responder? */ 25213245Sgabeblack@google.com bool responderSet; 25313245Sgabeblack@google.com 25413245Sgabeblack@google.com int defaultBlockSize; 25513245Sgabeblack@google.com int cachedBlockSize; 25613245Sgabeblack@google.com bool cachedBlockSizeValid; 25713245Sgabeblack@google.com 25813245Sgabeblack@google.com public: 25913245Sgabeblack@google.com 26013245Sgabeblack@google.com /** A function used to return the port associated with this bus object. */ 26113245Sgabeblack@google.com virtual Port *getPort(const std::string &if_name, int idx = -1); 26213245Sgabeblack@google.com virtual void deletePortRefs(Port *p); 26313245Sgabeblack@google.com 26413245Sgabeblack@google.com virtual void init(); 26513245Sgabeblack@google.com virtual void startup(); 26613245Sgabeblack@google.com 26713245Sgabeblack@google.com unsigned int drain(Event *de); 26813245Sgabeblack@google.com 26913245Sgabeblack@google.com Bus(const std::string &n, int bus_id, int _clock, int _width, 27013245Sgabeblack@google.com bool responder_set, int dflt_blk_size) 27113245Sgabeblack@google.com : MemObject(n), busId(bus_id), clock(_clock), width(_width), 27213245Sgabeblack@google.com tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false), 27313245Sgabeblack@google.com maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4), 27413245Sgabeblack@google.com responderSet(responder_set), defaultBlockSize(dflt_blk_size), 27513245Sgabeblack@google.com cachedBlockSize(0), cachedBlockSizeValid(false) 27613245Sgabeblack@google.com { 27713245Sgabeblack@google.com //Both the width and clock period must be positive 27813245Sgabeblack@google.com if (width <= 0) 27913245Sgabeblack@google.com fatal("Bus width must be positive\n"); 28013245Sgabeblack@google.com if (clock <= 0) 28113245Sgabeblack@google.com fatal("Bus clock period must be positive\n"); 28213245Sgabeblack@google.com } 28313245Sgabeblack@google.com 28413245Sgabeblack@google.com}; 28513245Sgabeblack@google.com 28613245Sgabeblack@google.com#endif //__MEM_BUS_HH__ 28713245Sgabeblack@google.com