summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mem/Bus.py3
-rw-r--r--src/mem/bus.cc48
-rw-r--r--src/mem/bus.hh22
3 files changed, 43 insertions, 30 deletions
diff --git a/src/mem/Bus.py b/src/mem/Bus.py
index 247a1fe31..f4ea9a73b 100644
--- a/src/mem/Bus.py
+++ b/src/mem/Bus.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2005-2007 The Regents of The University of Michigan
+# Copyright (c) 2005-2008 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@ class Bus(MemObject):
port = VectorPort("vector port for connecting devices")
bus_id = Param.Int(0, "blah")
clock = Param.Clock("1GHz", "bus clock speed")
+ header_cycles = Param.Int(1, "cycles of overhead per transaction")
width = Param.Int(64, "bus width (bytes)")
responder_set = Param.Bool(False, "Did the user specify a default responder.")
block_size = Param.Int(64, "The default block size if one isn't set by a device attached to the bus.")
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index f47d48d0b..ff4512aca 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -110,7 +110,7 @@ const char * Bus::BusFreeEvent::description() const
return "bus became available";
}
-void Bus::occupyBus(PacketPtr pkt)
+void Bus::preparePacket(PacketPtr pkt, Tick & headerTime)
{
//Bring tickNextIdle up to the present tick
//There is some potential ambiguity where a cycle starts, which might make
@@ -124,34 +124,30 @@ void Bus::occupyBus(PacketPtr pkt)
tickNextIdle = curTick - (curTick % clock) + clock;
}
+ headerTime = tickNextIdle + headerCycles * clock;
+
// The packet will be sent. Figure out how long it occupies the bus, and
// how much of that time is for the first "word", aka bus width.
int numCycles = 0;
- // Requests need one cycle to send an address
- if (pkt->isRequest())
- numCycles++;
- else if (pkt->isResponse() || pkt->hasData()) {
+ if (pkt->hasData()) {
// If a packet has data, it needs ceil(size/width) cycles to send it
- // We're using the "adding instead of dividing" trick again here
- if (pkt->hasData()) {
- int dataSize = pkt->getSize();
- numCycles += dataSize/width;
- if (dataSize % width)
- numCycles++;
- } else {
- // If the packet didn't have data, it must have been a response.
- // Those use the bus for one cycle to send their data.
+ int dataSize = pkt->getSize();
+ numCycles += dataSize/width;
+ if (dataSize % width)
numCycles++;
- }
}
// The first word will be delivered after the current tick, the delivery
// of the address if any, and one bus cycle to deliver the data
- pkt->firstWordTime = tickNextIdle + (pkt->isRequest() ? clock : 0) + clock;
+ pkt->firstWordTime = headerTime + clock;
+
+ pkt->finishTime = headerTime + numCycles * clock;
+}
+
+void Bus::occupyBus(Tick until)
+{
+ tickNextIdle = until;
- //Advance it numCycles bus cycles.
- //XXX Should this use the repeated addition trick as well?
- tickNextIdle += (numCycles * clock);
if (!busIdle.scheduled()) {
busIdle.schedule(tickNextIdle);
} else {
@@ -159,9 +155,6 @@ void Bus::occupyBus(PacketPtr pkt)
}
DPRINTF(Bus, "The bus is now occupied from tick %d to %d\n",
curTick, tickNextIdle);
-
- // The bus will become idle once the current packet is delivered.
- pkt->finishTime = tickNextIdle;
}
/** Function called by the port when the bus is receiving a Timing
@@ -197,8 +190,10 @@ Bus::recvTiming(PacketPtr pkt)
DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x\n",
src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
+ Tick headerTime = 0;
+
if (!pkt->isExpressSnoop()) {
- occupyBus(pkt);
+ preparePacket(pkt, headerTime);
}
short dest = pkt->getDest();
@@ -248,11 +243,18 @@ Bus::recvTiming(PacketPtr pkt)
DPRINTF(Bus, "recvTiming: src %d dst %d %s 0x%x TGT RETRY\n",
src, pkt->getDest(), pkt->cmdString(), pkt->getAddr());
addToRetryList(src_port);
+ if (!pkt->isExpressSnoop()) {
+ occupyBus(headerTime);
+ }
return false;
}
// send OK, fall through
}
+ if (!pkt->isExpressSnoop()) {
+ occupyBus(pkt->finishTime);
+ }
+
// Packet was successfully sent.
// Also take care of retries
if (inRetry) {
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 0c23175f1..274c02de4 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -138,6 +138,8 @@ class Bus : public MemObject
int busId;
/** the clock speed for the bus */
int clock;
+ /** cycles of overhead per transaction */
+ int headerCycles;
/** the width of the bus in bytes */
int width;
/** the next tick at which the bus will be idle */
@@ -243,8 +245,13 @@ class Bus : public MemObject
*/
void addressRanges(AddrRangeList &resp, bool &snoop, int id);
- /** Occupy the bus with transmitting the packet pkt */
- void occupyBus(PacketPtr pkt);
+ /** Prepare a packet to be sent on the bus. The header finishes at tick
+ * headerTime
+ */
+ void preparePacket(PacketPtr pkt, Tick & headerTime);
+
+ /** Occupy the bus until until */
+ void occupyBus(Tick until);
/** Ask everyone on the bus what their size is
* @param id id of the busport that made the request
@@ -363,17 +370,20 @@ class Bus : public MemObject
unsigned int drain(Event *de);
Bus(const BusParams *p)
- : MemObject(p), busId(p->bus_id), clock(p->clock), width(p->width),
- tickNextIdle(0), drainEvent(NULL), busIdle(this), inRetry(false),
- maxId(0), defaultPort(NULL), funcPort(NULL), funcPortId(-4),
+ : MemObject(p), busId(p->bus_id), clock(p->clock),
+ headerCycles(p->header_cycles), width(p->width), tickNextIdle(0),
+ drainEvent(NULL), busIdle(this), inRetry(false), maxId(0),
+ defaultPort(NULL), funcPort(NULL), funcPortId(-4),
responderSet(p->responder_set), defaultBlockSize(p->block_size),
cachedBlockSize(0), cachedBlockSizeValid(false)
{
- //Both the width and clock period must be positive
+ //width, clock period, and header cycles must be positive
if (width <= 0)
fatal("Bus width must be positive\n");
if (clock <= 0)
fatal("Bus clock period must be positive\n");
+ if (headerCycles <= 0)
+ fatal("Number of header cycles must be positive\n");
clearBusCache();
clearPortCache();
}