c4b137869bd552aed0303182a821a1f65a083410
3 * Copyright (c) 2006 The Regents of The University of Michigan
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
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
31 * @file Definition of a simple bus bridge without buffering.
35 #include "base/trace.hh"
36 #include "mem/bridge.hh"
37 #include "sim/builder.hh"
42 // Make sure that both sides are connected to.
43 if (sideA
== NULL
|| sideB
== NULL
)
44 panic("Both ports of bus bridge are not connected to a bus.\n");
48 /** Function called by the port when the bus is recieving a Timing
51 Bridge::recvTiming(Packet
*pkt
, Side id
)
53 if (blockedA
&& id
== SideA
)
55 if (blockedB
&& id
== SideB
)
59 if (!sendEvent
.scheduled())
60 sendEvent
.schedule(curTick
+ delay
);
62 inboundA
.push_back(std::make_pair
<Packet
*, Tick
>(pkt
, curTick
));
65 inboundB
.push_back(std::make_pair
<Packet
*, Tick
>(pkt
, curTick
));
82 Bridge::blockCheck(Side id
)
84 /* Check that we still have buffer space available. */
86 if (sideA
->numQueued() + inboundB
.size() >= queueSizeA
&& !blockedB
) {
87 sideB
->sendStatusChange(Port::Blocked
);
89 } else if (sideA
->numQueued() + inboundB
.size() < queueSizeA
&& blockedB
) {
90 sideB
->sendStatusChange(Port::Unblocked
);
94 if (sideB
->numQueued() + inboundA
.size() >= queueSizeB
&& !blockedA
) {
95 sideA
->sendStatusChange(Port::Blocked
);
97 } else if (sideB
->numQueued() + inboundA
.size() < queueSizeB
&& blockedA
) {
98 sideA
->sendStatusChange(Port::Unblocked
);
104 void Bridge::timerEvent()
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();
115 t
= inboundA
.front().second
+ delay
;
117 if (inboundB
.size()) {
118 while (inboundB
.front().second
<= curTick
+ delay
){
119 sideB
->sendPkt(inboundA
.front());
120 inboundB
.pop_front();
124 t
= inboundB
.front().second
+ delay
;
126 t
= std::min(t
,inboundB
.front().second
+ delay
);
128 panic("timerEvent() called but nothing to do?");
132 sendEvent
.schedule(t
);
137 Bridge::BridgePort::sendPkt(Packet
*pkt
)
139 if (!sendTiming(pkt
))
140 outbound
.push_back(std::make_pair
<Packet
*,Tick
>(pkt
, curTick
));
144 Bridge::BridgePort::sendPkt(std::pair
<Packet
*, Tick
> p
)
146 if (!sendTiming(p
.first
))
147 outbound
.push_back(p
);
152 Bridge::BridgePort::recvRetry()
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
);
163 /** Function called by the port when the bus is recieving a Atomic
166 Bridge::recvAtomic(Packet
*pkt
, Side id
)
171 return sideB
->sendAtomic(pkt
);
173 return sideA
->sendAtomic(pkt
);
176 /** Function called by the port when the bus is recieving a Functional
179 Bridge::recvFunctional(Packet
*pkt
, Side id
)
182 std::list
<std::pair
<Packet
*, Tick
> >::iterator i
;
183 bool pktContinue
= true;
185 for(i
= inboundA
.begin(); i
!= inboundA
.end(); ++i
) {
186 if (pkt
->intersect(i
->first
)) {
187 pktContinue
&= fixPacket(pkt
, i
->first
);
191 for(i
= inboundB
.begin(); i
!= inboundB
.end(); ++i
) {
192 if (pkt
->intersect(i
->first
)) {
193 pktContinue
&= fixPacket(pkt
, i
->first
);
197 for(i
= sideA
->outbound
.begin(); i
!= sideA
->outbound
.end(); ++i
) {
198 if (pkt
->intersect(i
->first
)) {
199 pktContinue
&= fixPacket(pkt
, i
->first
);
203 for(i
= sideB
->outbound
.begin(); i
!= sideB
->outbound
.end(); ++i
) {
204 if (pkt
->intersect(i
->first
)) {
205 pktContinue
&= fixPacket(pkt
, i
->first
);
211 sideB
->sendFunctional(pkt
);
213 sideA
->sendFunctional(pkt
);
217 /** Function called by the port when the bus is recieving a status change.*/
219 Bridge::recvStatusChange(Port::Status status
, Side id
)
221 if (status
== Port::Blocked
|| status
== Port::Unblocked
)
225 sideB
->sendStatusChange(status
);
227 sideA
->sendStatusChange(status
);
231 Bridge::addressRanges(AddrRangeList
&resp
, AddrRangeList
&snoop
, Side id
)
234 sideB
->getPeerAddressRanges(resp
, snoop
);
236 sideA
->getPeerAddressRanges(resp
, snoop
);
239 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge
)
241 Param
<int> queue_size_a
;
242 Param
<int> queue_size_b
;
244 Param
<bool> write_ack
;
246 END_DECLARE_SIM_OBJECT_PARAMS(Bridge
)
248 BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge
)
250 INIT_PARAM(queue_size_a
, "The size of the queue for data coming into side a"),
251 INIT_PARAM(queue_size_b
, "The size of the queue for data coming into side b"),
252 INIT_PARAM(delay
, "The miminum delay to cross this bridge"),
253 INIT_PARAM(write_ack
, "Acknowledge any writes that are received.")
255 END_INIT_SIM_OBJECT_PARAMS(Bridge
)
257 CREATE_SIM_OBJECT(Bridge
)
259 return new Bridge(getInstanceName(), queue_size_a
, queue_size_b
, delay
,
263 REGISTER_SIM_OBJECT("Bridge", Bridge
)