bridge.cc (2632:1bb2f91485ea) bridge.cc (2643:67ac7b611c56)
1
2/*
3 * Copyright (c) 2006 The Regents of The University of Michigan
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @file Definition of a simple bus bridge without buffering.
32 */
33
1
2/*
3 * Copyright (c) 2006 The Regents of The University of Michigan
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/**
31 * @file Definition of a simple bus bridge without buffering.
32 */
33
34#include <algorithm>
34
35#include "base/trace.hh"
36#include "mem/bridge.hh"
37#include "sim/builder.hh"
38
35
36#include "base/trace.hh"
37#include "mem/bridge.hh"
38#include "sim/builder.hh"
39
40Bridge::BridgePort::BridgePort(const std::string &_name,
41 Bridge *_bridge, BridgePort *_otherPort,
42 int _delay, int _queueLimit)
43 : Port(_name), bridge(_bridge), otherPort(_otherPort),
44 delay(_delay), outstandingResponses(0),
45 queueLimit(_queueLimit), sendEvent(this)
46{
47}
48
49Bridge::Bridge(const std::string &n, int qsa, int qsb,
50 Tick _delay, int write_ack)
51 : MemObject(n),
52 portA(n + "-portA", this, &portB, _delay, qsa),
53 portB(n + "-portB", this, &portA, _delay, qsa),
54 ackWrites(write_ack)
55{
56}
57
58Port *
59Bridge::getPort(const std::string &if_name)
60{
61 BridgePort *port;
62
63 if (if_name == "side_a")
64 port = &portA;
65 else if (if_name == "side_b")
66 port = &portB;
67 else
68 return NULL;
69
70 if (port->getPeer() != NULL)
71 panic("bridge side %s already connected to.", if_name);
72 return port;
73}
74
75
39void
40Bridge::init()
41{
42 // Make sure that both sides are connected to.
76void
77Bridge::init()
78{
79 // Make sure that both sides are connected to.
43 if (sideA == NULL || sideB == NULL)
80 if (portA.getPeer() == NULL || portB.getPeer() == NULL)
44 panic("Both ports of bus bridge are not connected to a bus.\n");
45}
46
47
81 panic("Both ports of bus bridge are not connected to a bus.\n");
82}
83
84
48/** Function called by the port when the bus is recieving a Timing
85/** Function called by the port when the bus is receiving a Timing
49 * transaction.*/
50bool
86 * transaction.*/
87bool
51Bridge::recvTiming(Packet *pkt, Side id)
88Bridge::BridgePort::recvTiming(Packet *pkt)
52{
89{
53 if (blockedA && id == SideA)
54 return false;
55 if (blockedB && id == SideB)
56 return false;
90 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n",
91 pkt->getSrc(), pkt->getDest(), pkt->getAddr());
57
92
58 if (delay) {
59 if (!sendEvent.scheduled())
60 sendEvent.schedule(curTick + delay);
61 if (id == SideA) {
62 inboundA.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
63 blockCheck(SideA);
64 } else {
65 inboundB.push_back(std::make_pair<Packet*, Tick>(pkt, curTick));
66 blockCheck(SideB);
67 }
68 } else {
69 if (id == SideB) {
70 sideA->sendPkt(pkt);
71 blockCheck(SideB);
72 } else {
73 sideB->sendPkt(pkt);
74 blockCheck(SideA);
75 }
93 if (pkt->isResponse()) {
94 // This is a response for a request we forwarded earlier. The
95 // corresponding PacketBuffer should be stored in the packet's
96 // senderState field.
97 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState);
98 assert(buf != NULL);
99 // set up new packet dest & senderState based on values saved
100 // from original request
101 buf->fixResponse(pkt);
102 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest());
103 delete buf;
76 }
104 }
77 return true;
78
105
106 return otherPort->queueForSendTiming(pkt);
79}
80
107}
108
81void
82Bridge::blockCheck(Side id)
83{
84 /* Check that we still have buffer space available. */
85 if (id == SideB) {
86 if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
87 sideB->sendStatusChange(Port::Blocked);
88 blockedB = true;
89 } else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
90 sideB->sendStatusChange(Port::Unblocked);
91 blockedB = false;
92 }
93 } else {
94 if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
95 sideA->sendStatusChange(Port::Blocked);
96 blockedA = true;
97 } else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
98 sideA->sendStatusChange(Port::Unblocked);
99 blockedA = false;
100 }
101 }
102}
103
109
104void Bridge::timerEvent()
110bool
111Bridge::BridgePort::queueForSendTiming(Packet *pkt)
105{
112{
106 Tick t = 0;
113 if (queueFull())
114 return false;
107
115
108 assert(inboundA.size() || inboundB.size());
109 if (inboundA.size()) {
110 while (inboundA.front().second <= curTick + delay){
111 sideB->sendPkt(inboundA.front());
112 inboundA.pop_front();
113 }
114 if (inboundA.size())
115 t = inboundA.front().second + delay;
116 Tick readyTime = curTick + delay;
117 PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
118
119 // If we're about to put this packet at the head of the queue, we
120 // need to schedule an event to do the transmit. Otherwise there
121 // should already be an event scheduled for sending the head
122 // packet.
123 if (sendQueue.empty()) {
124 sendEvent.schedule(readyTime);
116 }
125 }
117 if (inboundB.size()) {
118 while (inboundB.front().second <= curTick + delay){
119 sideB->sendPkt(inboundA.front());
120 inboundB.pop_front();
121 }
122 if (inboundB.size())
123 if (t == 0)
124 t = inboundB.front().second + delay;
125 else
126 t = std::min(t,inboundB.front().second + delay);
127 } else {
128 panic("timerEvent() called but nothing to do?");
129 }
130
126
131 if (t != 0)
132 sendEvent.schedule(t);
127 sendQueue.push_back(buf);
128
129 // Did we just become blocked? If yes, let other side know.
130 if (queueFull())
131 otherPort->sendStatusChange(Port::Blocked);
132
133 return true;
133}
134
135
136void
134}
135
136
137void
137Bridge::BridgePort::sendPkt(Packet *pkt)
138Bridge::BridgePort::finishSend(PacketBuffer *buf)
138{
139{
139 if (!sendTiming(pkt))
140 outbound.push_back(std::make_pair<Packet*,Tick>(pkt, curTick));
140 if (buf->expectResponse) {
141 // Must wait for response. We just need to count outstanding
142 // responses (in case we want to cap them); PacketBuffer
143 // pointer will be recovered on response.
144 ++outstandingResponses;
145 DPRINTF(BusBridge, " successful: awaiting response (%d)\n",
146 outstandingResponses);
147 } else {
148 // no response expected... deallocate packet buffer now.
149 DPRINTF(BusBridge, " successful: no response expected\n");
150 delete buf;
151 }
152
153 // If there are more packets to send, schedule event to try again.
154 if (!sendQueue.empty()) {
155 buf = sendQueue.front();
156 sendEvent.schedule(std::max(buf->ready, curTick + 1));
157 }
141}
142
158}
159
160
143void
161void
144Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
162Bridge::BridgePort::trySend()
145{
163{
146 if (!sendTiming(p.first))
147 outbound.push_back(p);
164 assert(!sendQueue.empty());
165
166 PacketBuffer *buf = sendQueue.front();
167
168 assert(buf->ready <= curTick);
169
170 Packet *pkt = buf->pkt;
171
172 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
173 buf->origSrc, pkt->getDest(), pkt->getAddr());
174
175 if (sendTiming(pkt)) {
176 // send successful
177 sendQueue.pop_front();
178 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
179 finishSend(buf);
180 } else {
181 DPRINTF(BusBridge, " unsuccessful\n");
182 }
148}
149
150
151Packet *
152Bridge::BridgePort::recvRetry()
153{
183}
184
185
186Packet *
187Bridge::BridgePort::recvRetry()
188{
154 Packet *pkt;
155 assert(outbound.size() > 0);
156 assert(outbound.front().second >= curTick + bridge->delay);
157 pkt = outbound.front().first;
158 outbound.pop_front();
159 bridge->blockCheck(side);
189 PacketBuffer *buf = sendQueue.front();
190 Packet *pkt = buf->pkt;
191 finishSend(buf);
160 return pkt;
161}
162
192 return pkt;
193}
194
163/** Function called by the port when the bus is recieving a Atomic
195/** Function called by the port when the bus is receiving a Atomic
164 * transaction.*/
165Tick
196 * transaction.*/
197Tick
166Bridge::recvAtomic(Packet *pkt, Side id)
198Bridge::BridgePort::recvAtomic(Packet *pkt)
167{
199{
168 pkt->time += delay;
169
170 if (id == SideA)
171 return sideB->sendAtomic(pkt);
172 else
173 return sideA->sendAtomic(pkt);
200 return otherPort->sendAtomic(pkt) + delay;
174}
175
201}
202
176/** Function called by the port when the bus is recieving a Functional
203/** Function called by the port when the bus is receiving a Functional
177 * transaction.*/
178void
204 * transaction.*/
205void
179Bridge::recvFunctional(Packet *pkt, Side id)
206Bridge::BridgePort::recvFunctional(Packet *pkt)
180{
207{
181 pkt->time += delay;
182 std::list<std::pair<Packet*, Tick> >::iterator i;
208 std::list<PacketBuffer*>::iterator i;
183 bool pktContinue = true;
184
209 bool pktContinue = true;
210
185 for(i = inboundA.begin(); i != inboundA.end(); ++i) {
186 if (pkt->intersect(i->first)) {
187 pktContinue &= fixPacket(pkt, i->first);
211 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) {
212 if (pkt->intersect((*i)->pkt)) {
213 pktContinue &= fixPacket(pkt, (*i)->pkt);
188 }
189 }
190
214 }
215 }
216
191 for(i = inboundB.begin(); i != inboundB.end(); ++i) {
192 if (pkt->intersect(i->first)) {
193 pktContinue &= fixPacket(pkt, i->first);
194 }
195 }
196
197 for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
198 if (pkt->intersect(i->first)) {
199 pktContinue &= fixPacket(pkt, i->first);
200 }
201 }
202
203 for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
204 if (pkt->intersect(i->first)) {
205 pktContinue &= fixPacket(pkt, i->first);
206 }
207 }
208
209 if (pktContinue) {
217 if (pktContinue) {
210 if (id == SideA)
211 sideB->sendFunctional(pkt);
212 else
213 sideA->sendFunctional(pkt);
218 otherPort->sendFunctional(pkt);
214 }
215}
216
219 }
220}
221
217/** Function called by the port when the bus is recieving a status change.*/
222/** Function called by the port when the bus is receiving a status change.*/
218void
223void
219Bridge::recvStatusChange(Port::Status status, Side id)
224Bridge::BridgePort::recvStatusChange(Port::Status status)
220{
221 if (status == Port::Blocked || status == Port::Unblocked)
225{
226 if (status == Port::Blocked || status == Port::Unblocked)
222 return ;
227 return;
223
228
224 if (id == SideA)
225 sideB->sendStatusChange(status);
226 else
227 sideA->sendStatusChange(status);
229 otherPort->sendStatusChange(status);
228}
229
230void
230}
231
232void
231Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
233Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
234 AddrRangeList &snoop)
232{
235{
233 if (id == SideA)
234 sideB->getPeerAddressRanges(resp, snoop);
235 else
236 sideA->getPeerAddressRanges(resp, snoop);
236 otherPort->getPeerAddressRanges(resp, snoop);
237}
238
239BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
240
241 Param<int> queue_size_a;
242 Param<int> queue_size_b;
243 Param<Tick> delay;
244 Param<bool> write_ack;

--- 19 unchanged lines hidden ---
237}
238
239BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
240
241 Param<int> queue_size_a;
242 Param<int> queue_size_b;
243 Param<Tick> delay;
244 Param<bool> write_ack;

--- 19 unchanged lines hidden ---