summaryrefslogtreecommitdiff
path: root/src/mem
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem')
-rw-r--r--src/mem/bridge.cc270
-rw-r--r--src/mem/bridge.hh214
-rw-r--r--src/mem/bus.cc60
-rw-r--r--src/mem/bus.hh18
-rw-r--r--src/mem/packet.cc50
-rw-r--r--src/mem/packet.hh138
-rw-r--r--src/mem/physical.cc30
-rw-r--r--src/mem/physical.hh2
-rw-r--r--src/mem/port.cc26
-rw-r--r--src/mem/port.hh29
-rw-r--r--src/mem/request.hh1
-rw-r--r--src/mem/translating_port.cc5
-rw-r--r--src/mem/translating_port.hh9
-rw-r--r--src/mem/vport.hh4
14 files changed, 478 insertions, 378 deletions
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index c4b137869..736e8dc81 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -31,209 +31,209 @@
* @file Definition of a simple bus bridge without buffering.
*/
+#include <algorithm>
#include "base/trace.hh"
#include "mem/bridge.hh"
#include "sim/builder.hh"
+Bridge::BridgePort::BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit)
+ : Port(_name), bridge(_bridge), otherPort(_otherPort),
+ delay(_delay), outstandingResponses(0),
+ queueLimit(_queueLimit), sendEvent(this)
+{
+}
+
+Bridge::Bridge(const std::string &n, int qsa, int qsb,
+ Tick _delay, int write_ack)
+ : MemObject(n),
+ portA(n + "-portA", this, &portB, _delay, qsa),
+ portB(n + "-portB", this, &portA, _delay, qsa),
+ ackWrites(write_ack)
+{
+}
+
+Port *
+Bridge::getPort(const std::string &if_name)
+{
+ BridgePort *port;
+
+ if (if_name == "side_a")
+ port = &portA;
+ else if (if_name == "side_b")
+ port = &portB;
+ else
+ return NULL;
+
+ if (port->getPeer() != NULL)
+ panic("bridge side %s already connected to.", if_name);
+ return port;
+}
+
+
void
Bridge::init()
{
// Make sure that both sides are connected to.
- if (sideA == NULL || sideB == NULL)
+ if (portA.getPeer() == NULL || portB.getPeer() == NULL)
panic("Both ports of bus bridge are not connected to a bus.\n");
}
-/** Function called by the port when the bus is recieving a Timing
+/** Function called by the port when the bus is receiving a Timing
* transaction.*/
bool
-Bridge::recvTiming(Packet *pkt, Side id)
+Bridge::BridgePort::recvTiming(Packet *pkt)
{
- if (blockedA && id == SideA)
- return false;
- if (blockedB && id == SideB)
- return false;
-
- if (delay) {
- if (!sendEvent.scheduled())
- sendEvent.schedule(curTick + delay);
- if (id == SideA) {
- inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
- blockCheck(SideA);
- } else {
- inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
- blockCheck(SideB);
- }
- } else {
- if (id == SideB) {
- sideA->sendPkt(pkt);
- blockCheck(SideB);
- } else {
- sideB->sendPkt(pkt);
- blockCheck(SideA);
- }
+ DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr());
+
+ if (pkt->isResponse()) {
+ // This is a response for a request we forwarded earlier. The
+ // corresponding PacketBuffer should be stored in the packet's
+ // senderState field.
+ PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
+ assert(buf != NULL);
+ // set up new packet dest & senderState based on values saved
+ // from original request
+ buf->fixResponse(pkt);
+ DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
+ delete buf;
}
- return true;
+ return otherPort->queueForSendTiming(pkt);
}
-void
-Bridge::blockCheck(Side id)
-{
- /* Check that we still have buffer space available. */
- if (id == SideB) {
- if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
- sideB->sendStatusChange(Port::Blocked);
- blockedB = true;
- } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
- sideB->sendStatusChange(Port::Unblocked);
- blockedB = false;
- }
- } else {
- if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
- sideA->sendStatusChange(Port::Blocked);
- blockedA = true;
- } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
- sideA->sendStatusChange(Port::Unblocked);
- blockedA = false;
- }
- }
-}
-void Bridge::timerEvent()
+bool
+Bridge::BridgePort::queueForSendTiming(Packet *pkt)
{
- Tick t = 0;
+ if (queueFull())
+ return false;
- assert(inboundA.size() || inboundB.size());
- if (inboundA.size()) {
- while (inboundA.front().second <= curTick + delay){
- sideB->sendPkt(inboundA.front());
- inboundA.pop_front();
- }
- if (inboundA.size())
- t = inboundA.front().second + delay;
- }
- if (inboundB.size()) {
- while (inboundB.front().second <= curTick + delay){
- sideB->sendPkt(inboundA.front());
- inboundB.pop_front();
- }
- if (inboundB.size())
- if (t == 0)
- t = inboundB.front().second + delay;
- else
- t = std::min(t,inboundB.front().second + delay);
- } else {
- panic("timerEvent() called but nothing to do?");
+ Tick readyTime = curTick + delay;
+ PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
+
+ // If we're about to put this packet at the head of the queue, we
+ // need to schedule an event to do the transmit. Otherwise there
+ // should already be an event scheduled for sending the head
+ // packet.
+ if (sendQueue.empty()) {
+ sendEvent.schedule(readyTime);
}
- if (t != 0)
- sendEvent.schedule(t);
+ sendQueue.push_back(buf);
+
+ // Did we just become blocked? If yes, let other side know.
+ if (queueFull())
+ otherPort->sendStatusChange(Port::Blocked);
+
+ return true;
}
void
-Bridge::BridgePort::sendPkt(Packet *pkt)
+Bridge::BridgePort::finishSend(PacketBuffer *buf)
{
- if (!sendTiming(pkt))
- outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick));
+ if (buf->expectResponse) {
+ // Must wait for response. We just need to count outstanding
+ // responses (in case we want to cap them); PacketBuffer
+ // pointer will be recovered on response.
+ ++outstandingResponses;
+ DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
+ outstandingResponses);
+ } else {
+ // no response expected... deallocate packet buffer now.
+ DPRINTF(BusBridge, " successful: no response expected\n");
+ delete buf;
+ }
+
+ // If there are more packets to send, schedule event to try again.
+ if (!sendQueue.empty()) {
+ buf = sendQueue.front();
+ sendEvent.schedule(std::max(buf->ready, curTick + 1));
+ }
}
+
void
-Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
+Bridge::BridgePort::trySend()
{
- if (!sendTiming(p.first))
- outbound.push_back(p);
+ assert(!sendQueue.empty());
+
+ PacketBuffer *buf = sendQueue.front();
+
+ assert(buf->ready <= curTick);
+
+ Packet *pkt = buf->pkt;
+
+ DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
+ buf->origSrc, pkt->getDest(), pkt->getAddr());
+
+ if (sendTiming(pkt)) {
+ // send successful
+ sendQueue.pop_front();
+ buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
+ finishSend(buf);
+ } else {
+ DPRINTF(BusBridge, " unsuccessful\n");
+ }
}
Packet *
Bridge::BridgePort::recvRetry()
{
- Packet *pkt;
- assert(outbound.size() > 0);
- assert(outbound.front().second >= curTick + bridge->delay);
- pkt = outbound.front().first;
- outbound.pop_front();
- bridge->blockCheck(side);
+ PacketBuffer *buf = sendQueue.front();
+ Packet *pkt = buf->pkt;
+ finishSend(buf);
return pkt;
}
-/** Function called by the port when the bus is recieving a Atomic
+/** Function called by the port when the bus is receiving a Atomic
* transaction.*/
Tick
-Bridge::recvAtomic(Packet *pkt, Side id)
+Bridge::BridgePort::recvAtomic(Packet *pkt)
{
- pkt->time += delay;
-
- if (id == SideA)
- return sideB->sendAtomic(pkt);
- else
- return sideA->sendAtomic(pkt);
+ return otherPort->sendAtomic(pkt) + delay;
}
-/** Function called by the port when the bus is recieving a Functional
+/** Function called by the port when the bus is receiving a Functional
* transaction.*/
void
-Bridge::recvFunctional(Packet *pkt, Side id)
+Bridge::BridgePort::recvFunctional(Packet *pkt)
{
- pkt->time += delay;
- std::list<std::pair<Packet*, Tick> >::iterator i;
+ std::list<PacketBuffer*>::iterator i;
bool pktContinue = true;
- for(i = inboundA.begin(); i != inboundA.end(); ++i) {
- if (pkt->intersect(i->first)) {
- pktContinue &= fixPacket(pkt, i->first);
- }
- }
-
- for(i = inboundB.begin(); i != inboundB.end(); ++i) {
- if (pkt->intersect(i->first)) {
- pktContinue &= fixPacket(pkt, i->first);
- }
- }
-
- for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
- if (pkt->intersect(i->first)) {
- pktContinue &= fixPacket(pkt, i->first);
- }
- }
-
- for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
- if (pkt->intersect(i->first)) {
- pktContinue &= fixPacket(pkt, i->first);
+ for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
+ if (pkt->intersect((*i)->pkt)) {
+ pktContinue &= fixPacket(pkt, (*i)->pkt);
}
}
if (pktContinue) {
- if (id == SideA)
- sideB->sendFunctional(pkt);
- else
- sideA->sendFunctional(pkt);
+ otherPort->sendFunctional(pkt);
}
}
-/** Function called by the port when the bus is recieving a status change.*/
+/** Function called by the port when the bus is receiving a status change.*/
void
-Bridge::recvStatusChange(Port::Status status, Side id)
+Bridge::BridgePort::recvStatusChange(Port::Status status)
{
if (status == Port::Blocked || status == Port::Unblocked)
- return ;
+ return;
- if (id == SideA)
- sideB->sendStatusChange(status);
- else
- sideA->sendStatusChange(status);
+ otherPort->sendStatusChange(status);
}
void
-Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
+Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop)
{
- if (id == SideA)
- sideB->getPeerAddressRanges(resp, snoop);
- else
- sideA->getPeerAddressRanges(resp, snoop);
+ otherPort->getPeerAddressRanges(resp, snoop);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index 5f19ded40..8a5cbf92a 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -46,132 +46,127 @@
class Bridge : public MemObject
{
- public:
- enum Side
+ protected:
+ /** Decleration of the buses port type, one will be instantiated for each
+ of the interfaces connecting to the bus. */
+ class BridgePort : public Port
{
- SideA,
- SideB
- };
+ /** A pointer to the bridge to which this port belongs. */
+ Bridge *bridge;
- protected:
- /** Function called by the port when the bus is recieving a Timing
- transaction.*/
- bool recvTiming(Packet *pkt, Side id);
+ /**
+ * Pointer to the port on the other side of the bridge
+ * (connected to the other bus).
+ */
+ BridgePort *otherPort;
- /** Function called by the port when the bus is recieving a Atomic
- transaction.*/
- Tick recvAtomic(Packet *pkt, Side id);
+ /** Minimum delay though this bridge. */
+ Tick delay;
- /** Function called by the port when the bus is recieving a Functional
- transaction.*/
- void recvFunctional(Packet *pkt, Side id);
+ class PacketBuffer : public Packet::SenderState {
- /** Function called by the port when the bus is recieving a status change.*/
- void recvStatusChange(Port::Status status, Side id);
+ public:
+ Tick ready;
+ Packet *pkt;
+ Packet::SenderState *origSenderState;
+ short origSrc;
+ bool expectResponse;
- /** Process address range request.
- * @param resp addresses that we can respond to
- * @param snoop addresses that we would like to snoop
- * @param id ide of the busport that made the request.
- */
- void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id);
+ PacketBuffer(Packet *_pkt, Tick t)
+ : ready(t), pkt(_pkt),
+ origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()),
+ expectResponse(_pkt->needsResponse())
+ {
+ pkt->senderState = this;
+ }
+ void fixResponse(Packet *pkt)
+ {
+ assert(pkt->senderState == this);
+ pkt->setDest(origSrc);
+ pkt->senderState = origSenderState;
+ }
+ };
- /** Event that the SendEvent calls when it fires. This code must reschedule
- * the send event as required. */
- void timerEvent();
+ /**
+ * Outbound packet queue. Packets are held in this queue for a
+ * specified delay to model the processing delay of the
+ * bridge.
+ */
+ std::list<PacketBuffer*> sendQueue;
- /** Decleration of the buses port type, one will be instantiated for each
- of the interfaces connecting to the bus. */
- class BridgePort : public Port
- {
- /** A pointer to the bus to which this port belongs. */
- Bridge *bridge;
+ int outstandingResponses;
+
+ /** Max queue size for outbound packets */
+ int queueLimit;
+
+ /**
+ * Is this side blocked from accepting outbound packets?
+ */
+ bool queueFull() { return (sendQueue.size() == queueLimit); }
+
+ bool queueForSendTiming(Packet *pkt);
+
+ void finishSend(PacketBuffer *buf);
+
+ /**
+ * Handle send event, scheduled when the packet at the head of
+ * the outbound queue is ready to transmit (for timing
+ * accesses only).
+ */
+ void trySend();
+
+ class SendEvent : public Event
+ {
+ BridgePort *port;
+
+ public:
+ SendEvent(BridgePort *p)
+ : Event(&mainEventQueue), port(p) {}
+
+ virtual void process() { port->trySend(); }
- /** A id to keep track of the intercafe ID this port is connected to. */
- Bridge::Side side;
+ virtual const char *description() { return "bridge send event"; }
+ };
+
+ SendEvent sendEvent;
public:
/** Constructor for the BusPort.*/
- BridgePort(Bridge *_bridge, Side _side)
- : bridge(_bridge), side(_side)
- { }
-
- int numQueued() { return outbound.size(); }
+ BridgePort(const std::string &_name,
+ Bridge *_bridge, BridgePort *_otherPort,
+ int _delay, int _queueLimit);
protected:
- /** Data this is waiting to be transmitted. */
- std::list<std::pair<Packet*, Tick> > outbound;
-
- void sendPkt(Packet *pkt);
- void sendPkt(std::pair<Packet*, Tick> p);
- /** When reciving a timing request from the peer port,
+ /** When receiving a timing request from the peer port,
pass it to the bridge. */
- virtual bool recvTiming(Packet *pkt)
- { return bridge->recvTiming(pkt, side); }
+ virtual bool recvTiming(Packet *pkt);
- /** When reciving a retry request from the peer port,
+ /** When receiving a retry request from the peer port,
pass it to the bridge. */
virtual Packet* recvRetry();
- /** When reciving a Atomic requestfrom the peer port,
+ /** When receiving a Atomic requestfrom the peer port,
pass it to the bridge. */
- virtual Tick recvAtomic(Packet *pkt)
- { return bridge->recvAtomic(pkt, side); }
+ virtual Tick recvAtomic(Packet *pkt);
- /** When reciving a Functional request from the peer port,
+ /** When receiving a Functional request from the peer port,
pass it to the bridge. */
- virtual void recvFunctional(Packet *pkt)
- { bridge->recvFunctional(pkt, side); }
+ virtual void recvFunctional(Packet *pkt);
- /** When reciving a status changefrom the peer port,
+ /** When receiving a status changefrom the peer port,
pass it to the bridge. */
- virtual void recvStatusChange(Status status)
- { bridge->recvStatusChange(status, side); }
+ virtual void recvStatusChange(Status status);
- /** When reciving a address range request the peer port,
+ /** When receiving a address range request the peer port,
pass it to the bridge. */
- virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
- { bridge->addressRanges(resp, snoop, side); }
-
- friend class Bridge;
- };
-
- class SendEvent : public Event
- {
- Bridge *bridge;
-
- SendEvent(Bridge *b)
- : Event(&mainEventQueue), bridge(b) {}
-
- virtual void process() { bridge->timerEvent(); }
-
- virtual const char *description() { return "bridge delay event"; }
- friend class Bridge;
+ virtual void getDeviceAddressRanges(AddrRangeList &resp,
+ AddrRangeList &snoop);
};
- SendEvent sendEvent;
-
- /** Sides of the bus bridges. */
- BridgePort* sideA;
- BridgePort* sideB;
-
- /** inbound queues on both sides. */
- std::list<std::pair<Packet*, Tick> > inboundA;
- std::list<std::pair<Packet*, Tick> > inboundB;
-
- /** The size of the queue for data coming into side a */
- int queueSizeA;
- int queueSizeB;
-
- /* if the side is blocked or not. */
- bool blockedA;
- bool blockedB;
-
- /** Miminum delay though this bridge. */
- Tick delay;
+ BridgePort portA, portB;
/** If this bridge should acknowledge writes. */
bool ackWrites;
@@ -179,36 +174,11 @@ class Bridge : public MemObject
public:
/** A function used to return the port associated with this bus object. */
- virtual Port *getPort(const std::string &if_name)
- {
- if (if_name == "side_a") {
- if (sideA != NULL)
- panic("bridge side a already connected to.");
- sideA = new BridgePort(this, SideA);
- return sideA;
- } else if (if_name == "side_b") {
- if (sideB != NULL)
- panic("bridge side b already connected to.");
- sideB = new BridgePort(this, SideB);
- return sideB;
- } else
- return NULL;
- }
+ virtual Port *getPort(const std::string &if_name);
virtual void init();
- Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack)
- : MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL),
- queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false),
- delay(_delay), ackWrites(write_ack)
- {}
-
- /** Check if the port should block/unblock after recieving/sending a packet.
- * */
- void blockCheck(Side id);
-
- friend class Bridge::SendEvent;
-
+ Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack);
};
#endif //__MEM_BUS_HH__
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index f7c2b874a..cfc99a64f 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -35,6 +35,16 @@
#include "mem/bus.hh"
#include "sim/builder.hh"
+Port *
+Bus::getPort(const std::string &if_name)
+{
+ // if_name ignored? forced to be empty?
+ int id = interfaces.size();
+ BusPort *bp = new BusPort(csprintf("%s-p%d", name(), id), this, id);
+ interfaces.push_back(bp);
+ return bp;
+}
+
/** Get the ranges of anyone that we are connected to. */
void
Bus::init()
@@ -45,17 +55,22 @@ Bus::init()
}
-/** Function called by the port when the bus is recieving a Timing
+/** Function called by the port when the bus is receiving a Timing
* transaction.*/
bool
Bus::recvTiming(Packet *pkt)
{
Port *port;
- if (pkt->dest == Packet::Broadcast) {
- port = findPort(pkt->addr, pkt->src);
+ DPRINTF(Bus, "recvTiming: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+
+ short dest = pkt->getDest();
+ if (dest == Packet::Broadcast) {
+ port = findPort(pkt->getAddr(), pkt->getSrc());
} else {
- assert(pkt->dest > 0 && pkt->dest < interfaces.size());
- port = interfaces[pkt->dest];
+ assert(dest >= 0 && dest < interfaces.size());
+ assert(dest != pkt->getSrc()); // catch infinite loops
+ port = interfaces[dest];
}
return port->sendTiming(pkt);
}
@@ -73,7 +88,7 @@ Bus::findPort(Addr addr, int id)
if (portList[i].range == addr) {
dest_id = portList[i].portId;
found = true;
- DPRINTF(Bus, "Found Addr: %llx on device %d\n", addr, dest_id);
+ DPRINTF(Bus, " found addr 0x%llx on device %d\n", addr, dest_id);
}
i++;
}
@@ -86,33 +101,37 @@ Bus::findPort(Addr addr, int id)
return interfaces[dest_id];
}
-/** Function called by the port when the bus is recieving a Atomic
+/** Function called by the port when the bus is receiving a Atomic
* transaction.*/
Tick
Bus::recvAtomic(Packet *pkt)
{
- assert(pkt->dest == Packet::Broadcast);
- return findPort(pkt->addr, pkt->src)->sendAtomic(pkt);
+ DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
}
-/** Function called by the port when the bus is recieving a Functional
+/** Function called by the port when the bus is receiving a Functional
* transaction.*/
void
Bus::recvFunctional(Packet *pkt)
{
- assert(pkt->dest == Packet::Broadcast);
- findPort(pkt->addr, pkt->src)->sendFunctional(pkt);
+ DPRINTF(Bus, "recvFunctional: packet src %d dest %d addr 0x%x cmd %s\n",
+ pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
+ assert(pkt->getDest() == Packet::Broadcast);
+ findPort(pkt->getAddr(), pkt->getSrc())->sendFunctional(pkt);
}
-/** Function called by the port when the bus is recieving a status change.*/
+/** Function called by the port when the bus is receiving a status change.*/
void
Bus::recvStatusChange(Port::Status status, int id)
{
- DPRINTF(Bus, "Bus %d recieved status change from device id %d\n",
- busId, id);
assert(status == Port::RangeChange &&
"The other statuses need to be implemented.");
+ DPRINTF(BusAddrRanges, "received RangeChange from device id %d\n", id);
+
assert(id < interfaces.size() && id >= 0);
int x;
Port *port = interfaces[id];
@@ -138,8 +157,8 @@ Bus::recvStatusChange(Port::Status status, int id)
dm.portId = id;
dm.range = *iter;
- DPRINTF(MMU, "Adding range %llx - %llx for id %d\n", dm.range.start,
- dm.range.end, id);
+ DPRINTF(BusAddrRanges, "Adding range %llx - %llx for id %d\n",
+ dm.range.start, dm.range.end, id);
portList.push_back(dm);
}
DPRINTF(MMU, "port list has %d entries\n", portList.size());
@@ -159,13 +178,12 @@ Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
resp.clear();
snoop.clear();
- DPRINTF(Bus, "Bus id %d recieved address range request returning\n",
- busId);
+ DPRINTF(BusAddrRanges, "received address range request, returning:\n");
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
if (portIter->portId != id) {
resp.push_back(portIter->range);
- DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start,
- portIter->range.end);
+ DPRINTF(BusAddrRanges, " -- %#llX : %#llX\n",
+ portIter->range.start, portIter->range.end);
}
}
}
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 38573e514..5eeb07904 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -100,8 +100,8 @@ class Bus : public MemObject
public:
/** Constructor for the BusPort.*/
- BusPort(Bus *_bus, int _id)
- : bus(_bus), id(_id)
+ BusPort(const std::string &_name, Bus *_bus, int _id)
+ : Port(_name), bus(_bus), id(_id)
{ }
protected:
@@ -109,17 +109,17 @@ class Bus : public MemObject
/** When reciving a timing request from the peer port (at id),
pass it to the bus. */
virtual bool recvTiming(Packet *pkt)
- { pkt->src = id; return bus->recvTiming(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)
- { pkt->src = id; return bus->recvAtomic(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)
- { pkt->src = id; bus->recvFunctional(pkt); }
+ { pkt->setSrc(id); bus->recvFunctional(pkt); }
/** When reciving a status changefrom the peer port (at id),
pass it to the bus. */
@@ -146,13 +146,7 @@ class Bus : public MemObject
public:
/** A function used to return the port associated with this bus object. */
- virtual Port *getPort(const std::string &if_name)
- {
- // if_name ignored? forced to be empty?
- int id = interfaces.size();
- interfaces.push_back(new BusPort(this, id));
- return interfaces.back();
- }
+ virtual Port *getPort(const std::string &if_name);
virtual void init();
diff --git a/src/mem/packet.cc b/src/mem/packet.cc
index a9be7ac51..3b415d77f 100644
--- a/src/mem/packet.cc
+++ b/src/mem/packet.cc
@@ -34,11 +34,31 @@
#include "base/misc.hh"
#include "mem/packet.hh"
+static const std::string ReadReqString("ReadReq");
+static const std::string WriteReqString("WriteReq");
+static const std::string WriteReqNoAckString("WriteReqNoAck");
+static const std::string ReadRespString("ReadResp");
+static const std::string WriteRespString("WriteResp");
+static const std::string OtherCmdString("<other>");
+
+const std::string &
+Packet::cmdString() const
+{
+ switch (cmd) {
+ case ReadReq: return ReadReqString;
+ case WriteReq: return WriteReqString;
+ case WriteReqNoAck: return WriteReqNoAckString;
+ case ReadResp: return ReadRespString;
+ case WriteResp: return WriteRespString;
+ default: return OtherCmdString;
+ }
+}
/** delete the data pointed to in the data pointer. Ok to call to matter how
* data was allocted. */
void
-Packet::deleteData() {
+Packet::deleteData()
+{
assert(staticData || dynamicData);
if (staticData)
return;
@@ -51,22 +71,24 @@ Packet::deleteData() {
/** If there isn't data in the packet, allocate some. */
void
-Packet::allocate() {
+Packet::allocate()
+{
if (data)
return;
assert(!staticData);
dynamicData = true;
arrayData = true;
- data = new uint8_t[size];
+ data = new uint8_t[getSize()];
}
/** Do the packet modify the same addresses. */
bool
-Packet::intersect(Packet *p) {
- Addr s1 = addr;
- Addr e1 = addr + size;
- Addr s2 = p->addr;
- Addr e2 = p->addr + p->size;
+Packet::intersect(Packet *p)
+{
+ Addr s1 = getAddr();
+ Addr e1 = getAddr() + getSize();
+ Addr s2 = p->getAddr();
+ Addr e2 = p->getAddr() + p->getSize();
if (s1 >= s2 && s1 < e2)
return true;
@@ -77,7 +99,8 @@ Packet::intersect(Packet *p) {
/** Minimally reset a packet so something like simple cpu can reuse it. */
void
-Packet::reset() {
+Packet::reset()
+{
result = Unknown;
if (dynamicData) {
deleteData();
@@ -88,7 +111,8 @@ Packet::reset() {
}
-
-
-bool fixPacket(Packet *func, Packet *timing)
-{ panic("Need to implement!"); }
+bool
+fixPacket(Packet *func, Packet *timing)
+{
+ panic("Need to implement!");
+}
diff --git a/src/mem/packet.hh b/src/mem/packet.hh
index e8a7b0c73..83f52ede5 100644
--- a/src/mem/packet.hh
+++ b/src/mem/packet.hh
@@ -43,24 +43,6 @@ struct Packet;
typedef Packet* PacketPtr;
typedef uint8_t* PacketDataPtr;
-/** List of all commands associated with a packet. */
-enum Command
-{
- Read,
- Write
-};
-
-/** The result of a particular pakets request. */
-enum PacketResult
-{
- Success,
- BadAddress,
- Unknown
-};
-
-class SenderState{};
-class Coherence{};
-
/**
* A Packet is the structure to handle requests between two levels
* of the memory system. The Request is a global object that trancends
@@ -74,7 +56,7 @@ class Coherence{};
* Packets are assumed to be returned in the case of a single response. If
* the transaction has no response, then the consumer will delete the packet.
*/
-struct Packet
+class Packet
{
private:
/** A pointer to the data being transfered. It can be differnt sizes
@@ -95,57 +77,132 @@ struct Packet
bool arrayData;
- public:
/** The address of the request, could be virtual or physical (depending on
cache configurations). */
Addr addr;
- /** Flag structure to hold flags for this particular packet */
- uint64_t flags;
+ /** Indicates the size of the request. */
+ int size;
+
+ /** A index of the source of the transaction. */
+ short src;
+
+ /** A index to the destination of the transaction. */
+ short dest;
+
+ bool addrValid;
+ bool sizeValid;
+ bool srcValid;
+
+ public:
+
+ static const short Broadcast = -1;
/** A pointer to the overall request. */
RequestPtr req;
+ class CoherenceState {
+ public:
+ virtual ~CoherenceState() {}
+ };
+
/** A virtual base opaque structure used to hold
coherence status messages. */
- Coherence *coherence; // virtual base opaque,
+ CoherenceState *coherence; // virtual base opaque,
// assert(dynamic_cast<Foo>) etc.
- /** A virtual base opaque structure used to hold the senders state. */
- void *senderState; // virtual base opaque,
- // assert(dynamic_cast<Foo>) etc.
-
- /** Indicates the size of the request. */
- int size;
+ class SenderState {
+ public:
+ virtual ~SenderState() {}
+ };
- /** A index of the source of the transaction. */
- short src;
+ /** A virtual base opaque structure used to hold the senders state. */
+ SenderState *senderState; // virtual base opaque,
+ // assert(dynamic_cast<Foo>) etc.
- static const short Broadcast = -1;
+ private:
+ /** List of command attributes. */
+ enum CommandAttribute
+ {
+ IsRead = 1 << 0,
+ IsWrite = 1 << 1,
+ IsPrefetch = 1 << 2,
+ IsInvalidate = 1 << 3,
+ IsRequest = 1 << 4,
+ IsResponse = 1 << 5,
+ NeedsResponse = 1 << 6,
+ };
- /** A index to the destination of the transaction. */
- short dest;
+ public:
+ /** List of all commands associated with a packet. */
+ enum Command
+ {
+ ReadReq = IsRead | IsRequest | NeedsResponse,
+ WriteReq = IsWrite | IsRequest | NeedsResponse,
+ WriteReqNoAck = IsWrite | IsRequest,
+ ReadResp = IsRead | IsResponse,
+ WriteResp = IsWrite | IsResponse
+ };
+
+ const std::string &cmdString() const;
/** The command of the transaction. */
Command cmd;
+ bool isRead() { return (cmd & IsRead) != 0; }
+ bool isRequest() { return (cmd & IsRequest) != 0; }
+ bool isResponse() { return (cmd & IsResponse) != 0; }
+ bool needsResponse() { return (cmd & NeedsResponse) != 0; }
+
+ void makeTimingResponse() {
+ assert(needsResponse());
+ int icmd = (int)cmd;
+ icmd &= ~(IsRequest | NeedsResponse);
+ icmd |= IsResponse;
+ cmd = (Command)icmd;
+ dest = src;
+ srcValid = false;
+ }
+
/** The time this request was responded to. Used to calculate latencies. */
Tick time;
+ /** The result of a particular packets request. */
+ enum Result
+ {
+ Success,
+ BadAddress,
+ Unknown
+ };
+
/** The result of the packet transaction. */
- PacketResult result;
+ Result result;
/** Accessor function that returns the source index of the packet. */
- short getSrc() const { return src; }
+ short getSrc() const { assert(srcValid); return src; }
+ void setSrc(short _src) { src = _src; srcValid = true; }
/** Accessor function that returns the destination index of
the packet. */
short getDest() const { return dest; }
+ void setDest(short _dest) { dest = _dest; }
+
+ Addr getAddr() const { assert(addrValid); return addr; }
+ void setAddr(Addr _addr) { addr = _addr; addrValid = true; }
+
+ int getSize() const { assert(sizeValid); return size; }
+ void setSize(int _size) { size = _size; sizeValid = true; }
- Packet()
+
+ Packet(Request *_req, Command _cmd, short _dest)
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
+ addr(_req->paddr), size(_req->size), dest(_dest),
+ addrValid(_req->validPaddr), sizeValid(_req->validSize),
+ srcValid(false),
+ req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
time(curTick), result(Unknown)
- {}
+ {
+ }
~Packet()
{ deleteData(); }
@@ -154,6 +211,11 @@ struct Packet
/** Minimally reset a packet so something like simple cpu can reuse it. */
void reset();
+ void reinitFromRequest() {
+ if (req->validPaddr) setAddr(req->paddr);
+ if (req->validSize) setSize(req->size);
+ }
+
/** Set the data pointer to the following value that should not be freed. */
template <typename T>
void dataStatic(T *p);
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index bc2500678..26dbef0cd 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -127,7 +127,8 @@ PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
{
doFunctionalAccess(pkt);
- pkt->dest = pkt->src;
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
response->schedule(curTick + lat);
@@ -145,16 +146,18 @@ PhysicalMemory::doAtomicAccess(Packet *pkt)
void
PhysicalMemory::doFunctionalAccess(Packet *pkt)
{
- assert(pkt->addr + pkt->size < pmem_size);
+ assert(pkt->getAddr() + pkt->getSize() < pmem_size);
switch (pkt->cmd) {
- case Read:
- memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr,
- pkt->size);
+ case Packet::ReadReq:
+ memcpy(pkt->getPtr<uint8_t>(),
+ pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getSize());
break;
- case Write:
- memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(),
- pkt->size);
+ case Packet::WriteReq:
+ memcpy(pmem_addr + pkt->getAddr() - base_addr,
+ pkt->getPtr<uint8_t>(),
+ pkt->getSize());
// temporary hack: will need to add real LL/SC implementation
// for cacheless systems later.
if (pkt->req->getFlags() & LOCKED) {
@@ -165,7 +168,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
panic("unimplemented");
}
- pkt->result = Success;
+ pkt->result = Packet::Success;
}
Port *
@@ -174,11 +177,11 @@ PhysicalMemory::getPort(const std::string &if_name)
if (if_name == "") {
if (port != NULL)
panic("PhysicalMemory::getPort: additional port requested to memory!");
- port = new MemoryPort(this);
+ port = new MemoryPort(name() + "-port", this);
return port;
} else if (if_name == "functional") {
/* special port for functional writes at startup. */
- return new MemoryPort(this);
+ return new MemoryPort(name() + "-funcport", this);
} else {
panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
}
@@ -189,8 +192,9 @@ PhysicalMemory::recvStatusChange(Port::Status status)
{
}
-PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
- : memory(_memory)
+PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
+ PhysicalMemory *_memory)
+ : Port(_name), memory(_memory)
{ }
void
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 1cf5444ab..2ced79045 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -51,7 +51,7 @@ class PhysicalMemory : public MemObject
public:
- MemoryPort(PhysicalMemory *_memory);
+ MemoryPort(const std::string &_name, PhysicalMemory *_memory);
protected:
diff --git a/src/mem/port.cc b/src/mem/port.cc
index fb3103ed1..651cb739a 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -31,22 +31,28 @@
*/
#include "base/chunk_generator.hh"
+#include "base/trace.hh"
#include "mem/packet_impl.hh"
#include "mem/port.hh"
void
-Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
+Port::setPeer(Port *port)
+{
+ DPRINTF(Config, "setting peer to %s\n", port->name());
+ peer = port;
+}
+
+void
+Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
{
Request req(false);
- Packet pkt;
- pkt.req = &req;
- pkt.cmd = cmd;
- pkt.dest = Packet::Broadcast;
+ Packet pkt(&req, cmd, Packet::Broadcast);
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
- req.setPaddr(pkt.addr = gen.addr());
- req.setSize(pkt.size = gen.size());
+ req.setPaddr(gen.addr());
+ req.setSize(gen.size());
+ pkt.reinitFromRequest();
pkt.dataStatic(p);
sendFunctional(&pkt);
p += gen.size();
@@ -56,13 +62,13 @@ Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
void
Port::writeBlob(Addr addr, uint8_t *p, int size)
{
- blobHelper(addr, p, size, Write);
+ blobHelper(addr, p, size, Packet::WriteReq);
}
void
Port::readBlob(Addr addr, uint8_t *p, int size)
{
- blobHelper(addr, p, size, Read);
+ blobHelper(addr, p, size, Packet::ReadReq);
}
void
@@ -72,7 +78,7 @@ Port::memsetBlob(Addr addr, uint8_t val, int size)
uint8_t *buf = new uint8_t[size];
memset(buf, val, size);
- blobHelper(addr, buf, size, Write);
+ blobHelper(addr, buf, size, Packet::WriteReq);
delete [] buf;
}
diff --git a/src/mem/port.hh b/src/mem/port.hh
index 1b1920c03..f9103865e 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -69,9 +69,28 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter;
*/
class Port
{
+ private:
+
+ /** Descriptive name (for DPRINTF output) */
+ const std::string portName;
+
public:
+ /**
+ * Constructor.
+ *
+ * @param _name Port name for DPRINTF output. Should include name
+ * of memory system object to which the port belongs.
+ */
+ Port(const std::string &_name)
+ : portName(_name)
+ { }
+
+ /** Return port name (for DPRINTF). */
+ const std::string &name() const { return portName; }
+
virtual ~Port() {};
+
// mey be better to use subclasses & RTTI?
/** Holds the ports status. Keeps track if it is blocked, or has
calculated a range change. */
@@ -93,9 +112,9 @@ class Port
/** Function to set the pointer for the peer port.
@todo should be called by the configuration stuff (python).
*/
- void setPeer(Port *port) { peer = port; }
+ void setPeer(Port *port);
- /** Function to set the pointer for the peer port.
+ /** Function to set the pointer for the peer port.
@todo should be called by the configuration stuff (python).
*/
Port *getPeer() { return peer; }
@@ -213,7 +232,7 @@ class Port
/** Internal helper function for read/writeBlob().
*/
- void blobHelper(Addr addr, uint8_t *p, int size, Command cmd);
+ void blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd);
};
/** A simple functional port that is only meant for one way communication to
@@ -224,6 +243,10 @@ class Port
class FunctionalPort : public Port
{
public:
+ FunctionalPort(const std::string &_name)
+ : Port(_name)
+ {}
+
virtual bool recvTiming(Packet *pkt) { panic("FuncPort is UniDir"); }
virtual Tick recvAtomic(Packet *pkt) { panic("FuncPort is UniDir"); }
virtual void recvFunctional(Packet *pkt) { panic("FuncPort is UniDir"); }
diff --git a/src/mem/request.hh b/src/mem/request.hh
index 2db7b7779..10550e859 100644
--- a/src/mem/request.hh
+++ b/src/mem/request.hh
@@ -195,6 +195,7 @@ class Request
/** Accesor function for pc.*/
void setPC(Addr _pc);
+ friend class Packet;
};
#endif // __MEM_REQUEST_HH__
diff --git a/src/mem/translating_port.cc b/src/mem/translating_port.cc
index 5dfeaff31..ee4d277b6 100644
--- a/src/mem/translating_port.cc
+++ b/src/mem/translating_port.cc
@@ -34,8 +34,9 @@
using namespace TheISA;
-TranslatingPort::TranslatingPort(PageTable *p_table, bool alloc)
- : pTable(p_table), allocating(alloc)
+TranslatingPort::TranslatingPort(const std::string &_name,
+ PageTable *p_table, bool alloc)
+ : FunctionalPort(_name), pTable(p_table), allocating(alloc)
{ }
TranslatingPort::~TranslatingPort()
diff --git a/src/mem/translating_port.hh b/src/mem/translating_port.hh
index 7611ac3c7..d078158a3 100644
--- a/src/mem/translating_port.hh
+++ b/src/mem/translating_port.hh
@@ -39,14 +39,11 @@ class TranslatingPort : public FunctionalPort
PageTable *pTable;
bool allocating;
- TranslatingPort(const TranslatingPort &specmem);
- const TranslatingPort &operator=(const TranslatingPort &specmem);
-
public:
- TranslatingPort(PageTable *p_table, bool alloc = false);
+ TranslatingPort(const std::string &_name,
+ PageTable *p_table, bool alloc = false);
virtual ~TranslatingPort();
- public:
bool tryReadBlob(Addr addr, uint8_t *p, int size);
bool tryWriteBlob(Addr addr, uint8_t *p, int size);
bool tryMemsetBlob(Addr addr, uint8_t val, int size);
@@ -56,9 +53,9 @@ class TranslatingPort : public FunctionalPort
virtual void readBlob(Addr addr, uint8_t *p, int size);
virtual void writeBlob(Addr addr, uint8_t *p, int size);
virtual void memsetBlob(Addr addr, uint8_t val, int size);
+
void writeString(Addr addr, const char *str);
void readString(std::string &str, Addr addr);
-
};
#endif
diff --git a/src/mem/vport.hh b/src/mem/vport.hh
index fbc230ba3..0f3b1f09e 100644
--- a/src/mem/vport.hh
+++ b/src/mem/vport.hh
@@ -53,8 +53,8 @@ class VirtualPort : public FunctionalPort
ExecContext *xc;
public:
- VirtualPort(ExecContext *_xc = NULL)
- : xc(_xc)
+ VirtualPort(const std::string &_name, ExecContext *_xc = NULL)
+ : FunctionalPort(_name), xc(_xc)
{}
/** Return true if we have an exec context. This is used to prevent someone