#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
+#include "sim/eventq.hh"
class Bus : public MemObject
{
/** a globally unique id for this bus. */
int busId;
+ /** the clock speed for the bus */
+ int clock;
+ /** the width of the bus in bytes */
+ int width;
+ /** the next tick at which the bus will be idle */
+ Tick tickNextIdle;
- static const int defaultId = -1;
+ static const int defaultId = -3; //Make it unique from Broadcast
struct DevMap {
int portId;
/** Function called by the port when the bus is recieving a Timing
transaction.*/
- bool recvTiming(Packet *pkt);
+ bool recvTiming(PacketPtr pkt);
/** Function called by the port when the bus is recieving a Atomic
transaction.*/
- Tick recvAtomic(Packet *pkt);
+ Tick recvAtomic(PacketPtr pkt);
/** Function called by the port when the bus is recieving a Functional
transaction.*/
- void recvFunctional(Packet *pkt);
+ void recvFunctional(PacketPtr pkt);
/** Timing function called by port when it is once again able to process
* requests. */
std::vector<int> findSnoopPorts(Addr addr, int id);
/** Snoop all relevant ports atomicly. */
- void atomicSnoop(Packet *pkt);
+ Tick atomicSnoop(PacketPtr pkt);
+
+ /** Snoop all relevant ports functionally. */
+ void functionalSnoop(PacketPtr pkt);
/** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
* the snoop to happen
* @return True if succeds.
*/
- bool timingSnoop(Packet *pkt);
+ bool timingSnoop(PacketPtr pkt);
/** Process address range request.
* @param resp addresses that we can respond to
*/
void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id);
+ /** Occupy the bus with transmitting the packet pkt */
+ void occupyBus(PacketPtr pkt);
/** Declaration of the buses port type, one will be instantiated for each
of the interfaces connecting to the bus. */
class BusPort : public Port
{
+ bool _onRetryList;
+
/** A pointer to the bus to which this port belongs. */
Bus *bus;
/** Constructor for the BusPort.*/
BusPort(const std::string &_name, Bus *_bus, int _id)
- : Port(_name), bus(_bus), id(_id)
+ : Port(_name), _onRetryList(false), bus(_bus), id(_id)
{ }
+ bool onRetryList()
+ { return _onRetryList; }
+
+ void onRetryList(bool newVal)
+ { _onRetryList = newVal; }
+
protected:
/** When reciving a timing request from the peer port (at id),
pass it to the bus. */
- virtual bool recvTiming(Packet *pkt)
+ virtual bool recvTiming(PacketPtr pkt)
{ pkt->setSrc(id); return bus->recvTiming(pkt); }
/** When reciving a Atomic requestfrom the peer port (at id),
pass it to the bus. */
- virtual Tick recvAtomic(Packet *pkt)
+ virtual Tick recvAtomic(PacketPtr pkt)
{ pkt->setSrc(id); return bus->recvAtomic(pkt); }
/** When reciving a Functional requestfrom the peer port (at id),
pass it to the bus. */
- virtual void recvFunctional(Packet *pkt)
+ virtual void recvFunctional(PacketPtr pkt)
{ pkt->setSrc(id); bus->recvFunctional(pkt); }
/** When reciving a status changefrom the peer port (at id),
};
+ class BusFreeEvent : public Event
+ {
+ Bus * bus;
+
+ public:
+ BusFreeEvent(Bus * _bus);
+ void process();
+ const char *description();
+ };
+
+ BusFreeEvent busIdle;
+
+ bool inRetry;
+
/** An array of pointers to the peer port interfaces
connected to this bus.*/
- std::vector<Port*> interfaces;
+ std::vector<BusPort*> interfaces;
/** An array of pointers to ports that retry should be called on because the
* original send failed for whatever reason.*/
- std::list<Port*> retryList;
+ std::list<BusPort*> retryList;
+
+ void addToRetryList(BusPort * port)
+ {
+ if (!inRetry) {
+ // The device wasn't retrying a packet, or wasn't at an appropriate
+ // time.
+ assert(!port->onRetryList());
+ port->onRetryList(true);
+ retryList.push_back(port);
+ } else {
+ if (port->onRetryList()) {
+ // The device was retrying a packet. It didn't work, so we'll leave
+ // it at the head of the retry list.
+ assert(port == retryList.front());
+ inRetry = false;
+ }
+ else {
+ port->onRetryList(true);
+ retryList.push_back(port);
+ }
+ }
+ }
/** Port that handles requests that don't match any of the interfaces.*/
- Port *defaultPort;
+ BusPort *defaultPort;
public:
virtual void init();
- Bus(const std::string &n, int bus_id)
- : MemObject(n), busId(bus_id), defaultPort(NULL) {}
+ Bus(const std::string &n, int bus_id, int _clock, int _width)
+ : MemObject(n), busId(bus_id), clock(_clock), width(_width),
+ tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL)
+ {
+ //Both the width and clock period must be positive
+ if (width <= 0)
+ fatal("Bus width must be positive\n");
+ if (clock <= 0)
+ fatal("Bus clock period must be positive\n");
+ }
};