#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
+#include "sim/eventq.hh"
class Bus : public MemObject
{
int busId;
/** the clock speed for the bus */
int clock;
- /** the width of the bus in bits */
+ /** the width of the bus in bytes */
int width;
- /** the last tick the address bus was used */
- Tick tickAddrLastUsed;
- /** the last tick the data bus was used */
- Tick tickDataLastUsed;
+ /** the next tick at which the bus will be idle */
+ Tick tickNextIdle;
static const int defaultId = -1;
AddrRangeList defaultRange;
std::vector<DevMap> portSnoopList;
- std::vector<int> snoopCallbacks;
-
-
/** Function called by the port when the bus is recieving a Timing
transaction.*/
bool recvTiming(Packet *pkt);
std::vector<int> findSnoopPorts(Addr addr, int id);
/** Snoop all relevant ports atomicly. */
- void atomicSnoop(Packet *pkt);
+ Tick atomicSnoop(Packet *pkt);
- /** Snoop for NACK and Blocked in phase 1
- * @return True if succeds.
- */
- bool timingSnoopPhase1(Packet *pkt);
+ /** Snoop all relevant ports functionally. */
+ void functionalSnoop(Packet *pkt);
- /** @todo Don't need to commit all snoops just those that need it
- *(register somehow). */
- /** Commit all snoops now that we know if any of them would have blocked.
+ /** Call snoop on caches, be sure to set SNOOP_COMMIT bit if you want
+ * the snoop to happen
+ * @return True if succeds.
*/
- void timingSnoopPhase2(Packet *pkt);
+ bool timingSnoop(Packet *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),
};
+ 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 {
+ retryList.push_back(port);
+ }
+ }
+ }
/** Port that handles requests that don't match any of the interfaces.*/
Port *defaultPort;
Bus(const std::string &n, int bus_id, int _clock, int _width)
: MemObject(n), busId(bus_id), clock(_clock), width(_width),
- tickAddrLastUsed(0), tickDataLastUsed(0), defaultPort(NULL)
+ tickNextIdle(0), busIdle(this), inRetry(false), defaultPort(NULL)
{
- assert(width);
+ //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");
}
};