xbar.hh revision 5354
12381SN/A/*
22592SN/A * Copyright (c) 2002-2005 The Regents of The University of Michigan
37636Ssteve.reinhardt@amd.com * All rights reserved.
42381SN/A *
52381SN/A * Redistribution and use in source and binary forms, with or without
62381SN/A * modification, are permitted provided that the following conditions are
72381SN/A * met: redistributions of source code must retain the above copyright
82381SN/A * notice, this list of conditions and the following disclaimer;
92381SN/A * redistributions in binary form must reproduce the above copyright
102381SN/A * notice, this list of conditions and the following disclaimer in the
112381SN/A * documentation and/or other materials provided with the distribution;
122381SN/A * neither the name of the copyright holders nor the names of its
132381SN/A * contributors may be used to endorse or promote products derived from
142381SN/A * this software without specific prior written permission.
152381SN/A *
162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272381SN/A *
282665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
292665Ssaidi@eecs.umich.edu *          Ali Saidi
302665Ssaidi@eecs.umich.edu */
312665Ssaidi@eecs.umich.edu
322381SN/A/**
332381SN/A * @file
342381SN/A * Declaration of a bus object.
352381SN/A */
362662Sstever@eecs.umich.edu
372381SN/A#ifndef __MEM_BUS_HH__
382381SN/A#define __MEM_BUS_HH__
392381SN/A
402381SN/A#include <string>
412381SN/A#include <set>
428229Snate@binkert.org#include <list>
433348Sbinkertn@umich.edu#include <inttypes.h>
443348Sbinkertn@umich.edu
453348Sbinkertn@umich.edu#include "base/range.hh"
465735Snate@binkert.org#include "base/hashmap.hh"
474024Sbinkertn@umich.edu#include "base/range_map.hh"
484610Ssaidi@eecs.umich.edu#include "mem/mem_object.hh"
495735Snate@binkert.org#include "mem/packet.hh"
503940Ssaidi@eecs.umich.edu#include "mem/port.hh"
515314Sstever@gmail.com#include "mem/request.hh"
526216Snate@binkert.org#include "sim/eventq.hh"
532392SN/A#include "params/Bus.hh"
544167Sbinkertn@umich.edu
552394SN/Aclass Bus : public MemObject
562394SN/A{
573349Sbinkertn@umich.edu    /** Declaration of the buses port type, one will be instantiated for each
582394SN/A        of the interfaces connecting to the bus. */
592812Srdreslin@umich.edu    class BusPort : public Port
602812Srdreslin@umich.edu    {
614022Sstever@eecs.umich.edu        bool _onRetryList;
624022Sstever@eecs.umich.edu
635735Snate@binkert.org        /** A pointer to the bus to which this port belongs. */
645735Snate@binkert.org        Bus *bus;
654022Sstever@eecs.umich.edu
665735Snate@binkert.org        /** A id to keep track of the intercafe ID this port is connected to. */
675735Snate@binkert.org        int id;
685735Snate@binkert.org
694022Sstever@eecs.umich.edu      public:
704022Sstever@eecs.umich.edu
714022Sstever@eecs.umich.edu        /** Constructor for the BusPort.*/
724022Sstever@eecs.umich.edu        BusPort(const std::string &_name, Bus *_bus, int _id)
734473Sstever@eecs.umich.edu            : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
745319Sstever@gmail.com        { }
754022Sstever@eecs.umich.edu
764022Sstever@eecs.umich.edu        bool onRetryList()
774022Sstever@eecs.umich.edu        { return _onRetryList; }
784022Sstever@eecs.umich.edu
794022Sstever@eecs.umich.edu        void onRetryList(bool newVal)
804022Sstever@eecs.umich.edu        { _onRetryList = newVal; }
814022Sstever@eecs.umich.edu
824022Sstever@eecs.umich.edu        int getId() { return id; }
834022Sstever@eecs.umich.edu
844022Sstever@eecs.umich.edu      protected:
857465Ssteve.reinhardt@amd.com
864628Sstever@eecs.umich.edu        /** When reciving a timing request from the peer port (at id),
877465Ssteve.reinhardt@amd.com            pass it to the bus. */
887465Ssteve.reinhardt@amd.com        virtual bool recvTiming(PacketPtr pkt)
894022Sstever@eecs.umich.edu        { pkt->setSrc(id); return bus->recvTiming(pkt); }
904022Sstever@eecs.umich.edu
914626Sstever@eecs.umich.edu        /** When reciving a Atomic requestfrom the peer port (at id),
924626Sstever@eecs.umich.edu            pass it to the bus. */
937669Ssteve.reinhardt@amd.com        virtual Tick recvAtomic(PacketPtr pkt)
944626Sstever@eecs.umich.edu        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
954040Ssaidi@eecs.umich.edu
964040Ssaidi@eecs.umich.edu        /** When reciving a Functional requestfrom the peer port (at id),
975650Sgblack@eecs.umich.edu            pass it to the bus. */
985650Sgblack@eecs.umich.edu        virtual void recvFunctional(PacketPtr pkt)
994870Sstever@eecs.umich.edu        { pkt->setSrc(id); bus->recvFunctional(pkt); }
1004870Sstever@eecs.umich.edu
1014870Sstever@eecs.umich.edu        /** When reciving a status changefrom the peer port (at id),
1024870Sstever@eecs.umich.edu            pass it to the bus. */
1034870Sstever@eecs.umich.edu        virtual void recvStatusChange(Status status)
1044870Sstever@eecs.umich.edu        { bus->recvStatusChange(status, id); }
1054870Sstever@eecs.umich.edu
1068436SBrad.Beckmann@amd.com        /** When reciving a retry from the peer port (at id),
1078436SBrad.Beckmann@amd.com            pass it to the bus. */
1085314Sstever@gmail.com        virtual void recvRetry()
1095314Sstever@gmail.com        { bus->recvRetry(id); }
1108184Ssomayeh@cs.wisc.edu
1114022Sstever@eecs.umich.edu        // This should return all the 'owned' addresses that are
1124022Sstever@eecs.umich.edu        // downstream from this bus, yes?  That is, the union of all
1134022Sstever@eecs.umich.edu        // the 'owned' address ranges of all the other interfaces on
1144022Sstever@eecs.umich.edu        // this bus...
1155735Snate@binkert.org        virtual void getDeviceAddressRanges(AddrRangeList &resp,
1165735Snate@binkert.org                                            bool &snoop)
1175735Snate@binkert.org        { bus->addressRanges(resp, snoop, id); }
1184022Sstever@eecs.umich.edu
1194022Sstever@eecs.umich.edu        // Ask the bus to ask everyone on the bus what their block size is and
1204626Sstever@eecs.umich.edu        // take the max of it. This might need to be changed a bit if we ever
1214626Sstever@eecs.umich.edu        // support multiple block sizes.
1227465Ssteve.reinhardt@amd.com        virtual int deviceBlockSize()
1234626Sstever@eecs.umich.edu        { return bus->findBlockSize(id); }
1244022Sstever@eecs.umich.edu
1254626Sstever@eecs.umich.edu    };
1264626Sstever@eecs.umich.edu
1274626Sstever@eecs.umich.edu    class BusFreeEvent : public Event
1284626Sstever@eecs.umich.edu    {
1294022Sstever@eecs.umich.edu        Bus * bus;
1304022Sstever@eecs.umich.edu
1316076Sgblack@eecs.umich.edu      public:
1324626Sstever@eecs.umich.edu        BusFreeEvent(Bus * _bus);
1334870Sstever@eecs.umich.edu        void process();
1345314Sstever@gmail.com        const char *description() const;
1358184Ssomayeh@cs.wisc.edu    };
1364022Sstever@eecs.umich.edu
1374022Sstever@eecs.umich.edu    /** a globally unique id for this bus. */
1384022Sstever@eecs.umich.edu    int busId;
1395735Snate@binkert.org    /** the clock speed for the bus */
1405735Snate@binkert.org    int clock;
1415735Snate@binkert.org    /** cycles of overhead per transaction */
1425735Snate@binkert.org    int headerCycles;
1435735Snate@binkert.org    /** the width of the bus in bytes */
1445735Snate@binkert.org    int width;
1455735Snate@binkert.org    /** the next tick at which the bus will be idle */
1464022Sstever@eecs.umich.edu    Tick tickNextIdle;
1475735Snate@binkert.org
1485735Snate@binkert.org    Event * drainEvent;
1494022Sstever@eecs.umich.edu
1505735Snate@binkert.org
1514022Sstever@eecs.umich.edu    static const int defaultId = -3; //Make it unique from Broadcast
1524022Sstever@eecs.umich.edu
1534022Sstever@eecs.umich.edu    typedef range_map<Addr,int>::iterator PortIter;
1545735Snate@binkert.org    range_map<Addr, int> portMap;
1554022Sstever@eecs.umich.edu
1564022Sstever@eecs.umich.edu    AddrRangeList defaultRange;
1574022Sstever@eecs.umich.edu
1584022Sstever@eecs.umich.edu    typedef std::vector<BusPort*>::iterator SnoopIter;
1594022Sstever@eecs.umich.edu    std::vector<BusPort*> snoopPorts;
1604022Sstever@eecs.umich.edu
1615735Snate@binkert.org    /** Function called by the port when the bus is recieving a Timing
1625735Snate@binkert.org      transaction.*/
1635735Snate@binkert.org    bool recvTiming(PacketPtr pkt);
1644022Sstever@eecs.umich.edu
1654022Sstever@eecs.umich.edu    /** Function called by the port when the bus is recieving a Atomic
1664022Sstever@eecs.umich.edu      transaction.*/
1674022Sstever@eecs.umich.edu    Tick recvAtomic(PacketPtr pkt);
1684022Sstever@eecs.umich.edu
1694022Sstever@eecs.umich.edu    /** Function called by the port when the bus is recieving a Functional
1707465Ssteve.reinhardt@amd.com        transaction.*/
1717465Ssteve.reinhardt@amd.com    void recvFunctional(PacketPtr pkt);
1724022Sstever@eecs.umich.edu
1734022Sstever@eecs.umich.edu    /** Timing function called by port when it is once again able to process
1744870Sstever@eecs.umich.edu     * requests. */
1754022Sstever@eecs.umich.edu    void recvRetry(int id);
1764022Sstever@eecs.umich.edu
1774022Sstever@eecs.umich.edu    /** Function called by the port when the bus is recieving a status change.*/
1784626Sstever@eecs.umich.edu    void recvStatusChange(Port::Status status, int id);
1796102Sgblack@eecs.umich.edu
1804870Sstever@eecs.umich.edu    /** Find which port connected to this bus (if any) should be given a packet
1815314Sstever@gmail.com     * with this address.
1828184Ssomayeh@cs.wisc.edu     * @param addr Address to find port for.
1834022Sstever@eecs.umich.edu     * @return id of port that the packet should be sent out of.
1845735Snate@binkert.org     */
1855735Snate@binkert.org    int findPort(Addr addr);
1865735Snate@binkert.org
1874022Sstever@eecs.umich.edu    // Cache for the findPort function storing recently used ports from portMap
1884022Sstever@eecs.umich.edu    struct PortCache {
1894022Sstever@eecs.umich.edu        bool valid;
1905735Snate@binkert.org        int  id;
1915735Snate@binkert.org        Addr start;
1924022Sstever@eecs.umich.edu        Addr end;
1934022Sstever@eecs.umich.edu    };
1945735Snate@binkert.org
1955735Snate@binkert.org    PortCache portCache[3];
1965735Snate@binkert.org
1974022Sstever@eecs.umich.edu    // Checks the cache and returns the id of the port that has the requested
1985735Snate@binkert.org    // address within its range
1995735Snate@binkert.org    inline int checkPortCache(Addr addr) {
2004022Sstever@eecs.umich.edu        if (portCache[0].valid && addr >= portCache[0].start &&
2014022Sstever@eecs.umich.edu            addr < portCache[0].end) {
2022381SN/A            return portCache[0].id;
2032662Sstever@eecs.umich.edu        }
2042662Sstever@eecs.umich.edu        if (portCache[1].valid && addr >= portCache[1].start &&
2052662Sstever@eecs.umich.edu                   addr < portCache[1].end) {
2062662Sstever@eecs.umich.edu            return portCache[1].id;
2072662Sstever@eecs.umich.edu        }
2082381SN/A        if (portCache[2].valid && addr >= portCache[2].start &&
2095314Sstever@gmail.com            addr < portCache[2].end) {
2102381SN/A            return portCache[2].id;
2112813Srdreslin@umich.edu        }
2125735Snate@binkert.org
2135735Snate@binkert.org        return -1;
2145735Snate@binkert.org    }
2154022Sstever@eecs.umich.edu
2165735Snate@binkert.org    // Clears the earliest entry of the cache and inserts a new port entry
2175735Snate@binkert.org    inline void updatePortCache(short id, Addr start, Addr end) {
2185735Snate@binkert.org        portCache[2].valid = portCache[1].valid;
2195735Snate@binkert.org        portCache[2].id    = portCache[1].id;
2205735Snate@binkert.org        portCache[2].start = portCache[1].start;
2215735Snate@binkert.org        portCache[2].end   = portCache[1].end;
2225735Snate@binkert.org
2235735Snate@binkert.org        portCache[1].valid = portCache[0].valid;
2245735Snate@binkert.org        portCache[1].id    = portCache[0].id;
2255735Snate@binkert.org        portCache[1].start = portCache[0].start;
2265735Snate@binkert.org        portCache[1].end   = portCache[0].end;
2275735Snate@binkert.org
2285735Snate@binkert.org        portCache[0].valid = true;
2295735Snate@binkert.org        portCache[0].id    = id;
2305735Snate@binkert.org        portCache[0].start = start;
2315735Snate@binkert.org        portCache[0].end   = end;
2325735Snate@binkert.org    }
2335735Snate@binkert.org
2345735Snate@binkert.org    // Clears the cache. Needs to be called in constructor.
2355735Snate@binkert.org    inline void clearPortCache() {
2365735Snate@binkert.org        portCache[2].valid = false;
2375735Snate@binkert.org        portCache[1].valid = false;
2385735Snate@binkert.org        portCache[0].valid = false;
2395735Snate@binkert.org    }
2405735Snate@binkert.org
2415735Snate@binkert.org    /** Process address range request.
2425735Snate@binkert.org     * @param resp addresses that we can respond to
2435735Snate@binkert.org     * @param snoop addresses that we would like to snoop
2445735Snate@binkert.org     * @param id ide of the busport that made the request.
2458436SBrad.Beckmann@amd.com     */
2468436SBrad.Beckmann@amd.com    void addressRanges(AddrRangeList &resp, bool &snoop, int id);
2478436SBrad.Beckmann@amd.com
2485735Snate@binkert.org    /** Prepare a packet to be sent on the bus. The header finishes at tick
2495735Snate@binkert.org     *  headerTime
2505735Snate@binkert.org     */
2515735Snate@binkert.org    void preparePacket(PacketPtr pkt, Tick & headerTime);
2524022Sstever@eecs.umich.edu
2534022Sstever@eecs.umich.edu    /** Occupy the bus until until */
2545735Snate@binkert.org    void occupyBus(Tick until);
2554870Sstever@eecs.umich.edu
2564870Sstever@eecs.umich.edu    /** Ask everyone on the bus what their size is
2575735Snate@binkert.org     * @param id id of the busport that made the request
2584870Sstever@eecs.umich.edu     * @return the max of all the sizes
2594870Sstever@eecs.umich.edu     */
2602566SN/A    int findBlockSize(int id);
2615735Snate@binkert.org
2625735Snate@binkert.org    BusFreeEvent busIdle;
2635735Snate@binkert.org
2645735Snate@binkert.org    bool inRetry;
2655735Snate@binkert.org    std::set<int> inRecvStatusChange;
2665735Snate@binkert.org
2672566SN/A    /** max number of bus ids we've handed out so far */
2682566SN/A    short maxId;
2692566SN/A
2705735Snate@binkert.org    /** An array of pointers to the peer port interfaces
2715735Snate@binkert.org        connected to this bus.*/
2722381SN/A    m5::hash_map<short,BusPort*> interfaces;
2732381SN/A
2745735Snate@binkert.org    /** An array of pointers to ports that retry should be called on because the
2756227Snate@binkert.org     * original send failed for whatever reason.*/
2762381SN/A    std::list<BusPort*> retryList;
2775735Snate@binkert.org
2785735Snate@binkert.org    void addToRetryList(BusPort * port)
2795735Snate@binkert.org    {
2805735Snate@binkert.org        if (!inRetry) {
2815735Snate@binkert.org            // The device wasn't retrying a packet, or wasn't at an appropriate
2825735Snate@binkert.org            // time.
2835735Snate@binkert.org            assert(!port->onRetryList());
2842381SN/A            port->onRetryList(true);
2855735Snate@binkert.org            retryList.push_back(port);
2865735Snate@binkert.org        } else {
2875735Snate@binkert.org            if (port->onRetryList()) {
2885735Snate@binkert.org                // The device was retrying a packet. It didn't work, so we'll leave
2895735Snate@binkert.org                // it at the head of the retry list.
2905735Snate@binkert.org                assert(port == retryList.front());
2915735Snate@binkert.org                inRetry = false;
2925735Snate@binkert.org            }
2932641Sstever@eecs.umich.edu            else {
2945735Snate@binkert.org                port->onRetryList(true);
2955735Snate@binkert.org                retryList.push_back(port);
2964870Sstever@eecs.umich.edu            }
2974870Sstever@eecs.umich.edu        }
2984870Sstever@eecs.umich.edu    }
2994870Sstever@eecs.umich.edu
3004870Sstever@eecs.umich.edu    /** Port that handles requests that don't match any of the interfaces.*/
3014870Sstever@eecs.umich.edu    BusPort *defaultPort;
3028668Sgeoffrey.blake@arm.com
3038668Sgeoffrey.blake@arm.com    BusPort *funcPort;
3048668Sgeoffrey.blake@arm.com    int funcPortId;
3058668Sgeoffrey.blake@arm.com
3068668Sgeoffrey.blake@arm.com    /** Has the user specified their own default responder? */
3078668Sgeoffrey.blake@arm.com    bool responderSet;
3088668Sgeoffrey.blake@arm.com
3092641Sstever@eecs.umich.edu    int defaultBlockSize;
3105735Snate@binkert.org    int cachedBlockSize;
3112811Srdreslin@umich.edu    bool cachedBlockSizeValid;
3122811Srdreslin@umich.edu
3135735Snate@binkert.org   // Cache for the peer port interfaces
3143218Sgblack@eecs.umich.edu    struct BusCache {
3153218Sgblack@eecs.umich.edu        bool  valid;
3165735Snate@binkert.org        short id;
3173218Sgblack@eecs.umich.edu        BusPort  *port;
3183218Sgblack@eecs.umich.edu    };
3195735Snate@binkert.org
3205735Snate@binkert.org    BusCache busCache[3];
3215735Snate@binkert.org
3222623SN/A    // Checks the peer port interfaces cache for the port id and returns
3235735Snate@binkert.org    // a pointer to the matching port
3245735Snate@binkert.org    inline BusPort* checkBusCache(short id) {
3255735Snate@binkert.org        if (busCache[0].valid && id == busCache[0].id) {
3265735Snate@binkert.org            return busCache[0].port;
3275735Snate@binkert.org        }
3285735Snate@binkert.org        if (busCache[1].valid && id == busCache[1].id) {
3295735Snate@binkert.org            return busCache[1].port;
3305735Snate@binkert.org        }
3315735Snate@binkert.org        if (busCache[2].valid && id == busCache[2].id) {
3325735Snate@binkert.org            return busCache[2].port;
3335735Snate@binkert.org        }
3342641Sstever@eecs.umich.edu
3352641Sstever@eecs.umich.edu        return NULL;
3362641Sstever@eecs.umich.edu    }
3375315Sstever@gmail.com
3385315Sstever@gmail.com    // Replaces the earliest entry in the cache with a new entry
3395315Sstever@gmail.com    inline void updateBusCache(short id, BusPort *port) {
3405315Sstever@gmail.com        busCache[2].valid = busCache[1].valid;
3415735Snate@binkert.org        busCache[2].id    = busCache[1].id;
3425735Snate@binkert.org        busCache[2].port  = busCache[1].port;
3435735Snate@binkert.org
3445735Snate@binkert.org        busCache[1].valid = busCache[0].valid;
3455735Snate@binkert.org        busCache[1].id    = busCache[0].id;
3465735Snate@binkert.org        busCache[1].port  = busCache[0].port;
3475735Snate@binkert.org
3485735Snate@binkert.org        busCache[0].valid = true;
3495314Sstever@gmail.com        busCache[0].id    = id;
3505314Sstever@gmail.com        busCache[0].port  = port;
3515314Sstever@gmail.com    }
3525735Snate@binkert.org
3535314Sstever@gmail.com    // Invalidates the cache. Needs to be called in constructor.
3545314Sstever@gmail.com    inline void clearBusCache() {
3555314Sstever@gmail.com        busCache[2].valid = false;
3565314Sstever@gmail.com        busCache[1].valid = false;
3575314Sstever@gmail.com        busCache[0].valid = false;
3585314Sstever@gmail.com    }
3595314Sstever@gmail.com
3605314Sstever@gmail.com
3615314Sstever@gmail.com  public:
3625314Sstever@gmail.com
3635314Sstever@gmail.com    /** A function used to return the port associated with this bus object. */
3645314Sstever@gmail.com    virtual Port *getPort(const std::string &if_name, int idx = -1);
3655314Sstever@gmail.com    virtual void deletePortRefs(Port *p);
3665314Sstever@gmail.com
3675735Snate@binkert.org    virtual void init();
3685735Snate@binkert.org    virtual void startup();
3695735Snate@binkert.org
3705314Sstever@gmail.com    unsigned int drain(Event *de);
3715315Sstever@gmail.com
3725735Snate@binkert.org    Bus(const BusParams *p)
3735735Snate@binkert.org        : MemObject(p), busId(p->bus_id), clock(p->clock),
3745315Sstever@gmail.com          headerCycles(p->header_cycles), width(p->width), tickNextIdle(0),
3755735Snate@binkert.org          drainEvent(NULL), busIdle(this), inRetry(false), maxId(0),
3765735Snate@binkert.org          defaultPort(NULL), funcPort(NULL), funcPortId(-4),
3775314Sstever@gmail.com          responderSet(p->responder_set), defaultBlockSize(p->block_size),
3785314Sstever@gmail.com          cachedBlockSize(0), cachedBlockSizeValid(false)
3795735Snate@binkert.org    {
3805735Snate@binkert.org        //width, clock period, and header cycles must be positive
3815735Snate@binkert.org        if (width <= 0)
3825735Snate@binkert.org            fatal("Bus width must be positive\n");
3835314Sstever@gmail.com        if (clock <= 0)
3845735Snate@binkert.org            fatal("Bus clock period must be positive\n");
3855735Snate@binkert.org        if (headerCycles <= 0)
3865735Snate@binkert.org            fatal("Number of header cycles must be positive\n");
3875315Sstever@gmail.com        clearBusCache();
3885735Snate@binkert.org        clearPortCache();
3895735Snate@binkert.org    }
3905314Sstever@gmail.com
3915735Snate@binkert.org};
3925735Snate@binkert.org
3935735Snate@binkert.org#endif //__MEM_BUS_HH__
3945735Snate@binkert.org