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 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. 16 * 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. 28 */ 29 30/** 31 * @file Definition of a simple bus bridge without buffering. 32 */ 33 34#include <algorithm> 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 76void 77Bridge::init() 78{ 79 // Make sure that both sides are connected to. 80 if (portA.getPeer() == NULL || portB.getPeer() == NULL) 81 panic("Both ports of bus bridge are not connected to a bus.\n"); 82} 83 84 85/** Function called by the port when the bus is receiving a Timing 86 * transaction.*/ 87bool 88Bridge::BridgePort::recvTiming(Packet *pkt) 89{ 90 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 91 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 92
| 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 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. 16 * 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. 28 */ 29 30/** 31 * @file Definition of a simple bus bridge without buffering. 32 */ 33 34#include <algorithm> 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 76void 77Bridge::init() 78{ 79 // Make sure that both sides are connected to. 80 if (portA.getPeer() == NULL || portB.getPeer() == NULL) 81 panic("Both ports of bus bridge are not connected to a bus.\n"); 82} 83 84 85/** Function called by the port when the bus is receiving a Timing 86 * transaction.*/ 87bool 88Bridge::BridgePort::recvTiming(Packet *pkt) 89{ 90 DPRINTF(BusBridge, "recvTiming: src %d dest %d addr 0x%x\n", 91 pkt->getSrc(), pkt->getDest(), pkt->getAddr()); 92
|
93 if (pkt->isResponse()) {
| 93 return otherPort->queueForSendTiming(pkt); 94} 95 96 97bool 98Bridge::BridgePort::queueForSendTiming(Packet *pkt) 99{ 100 if (queueFull()) 101 return false; 102 103 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);
| 104 // This is a response for a request we forwarded earlier. The 105 // corresponding PacketBuffer should be stored in the packet's 106 // senderState field. 107 PacketBuffer *buf = dynamic_cast<PacketBuffer*>(pkt->senderState); 108 assert(buf != NULL); 109 // set up new packet dest & senderState based on values saved 110 // from original request 111 buf->fixResponse(pkt);
|
| 112 DPRINTF(BusBridge, "restoring sender state: %#X, from packet buffer: %#X\n", 113 pkt->senderState, buf);
|
102 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); 103 delete buf; 104 } 105
| 114 DPRINTF(BusBridge, " is response, new dest %d\n", pkt->getDest()); 115 delete buf; 116 } 117
|
106 return otherPort->queueForSendTiming(pkt); 107} 108 109 110bool 111Bridge::BridgePort::queueForSendTiming(Packet *pkt) 112{ 113 if (queueFull()) 114 return false; 115
| |
116 Tick readyTime = curTick + delay; 117 PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
| 118 Tick readyTime = curTick + delay; 119 PacketBuffer *buf = new PacketBuffer(pkt, readyTime);
|
| 120 DPRINTF(BusBridge, "old sender state: %#X, new sender state: %#X\n", 121 buf->origSenderState, buf);
|
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); 125 } 126 127 sendQueue.push_back(buf); 128
| 122 123 // If we're about to put this packet at the head of the queue, we 124 // need to schedule an event to do the transmit. Otherwise there 125 // should already be an event scheduled for sending the head 126 // packet. 127 if (sendQueue.empty()) { 128 sendEvent.schedule(readyTime); 129 } 130 131 sendQueue.push_back(buf); 132
|
129 // Did we just become blocked? If yes, let other side know. 130 if (queueFull()) 131 otherPort->sendStatusChange(Port::Blocked); 132
| |
133 return true; 134} 135
| 133 return true; 134} 135
|
136
| |
137void
| 136void
|
138Bridge::BridgePort::finishSend(PacketBuffer *buf) 139{ 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 } 158} 159 160 161void
| |
162Bridge::BridgePort::trySend() 163{ 164 assert(!sendQueue.empty()); 165
| 137Bridge::BridgePort::trySend() 138{ 139 assert(!sendQueue.empty()); 140
|
| 141 bool was_full = queueFull(); 142
|
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
| 143 PacketBuffer *buf = sendQueue.front(); 144 145 assert(buf->ready <= curTick); 146 147 Packet *pkt = buf->pkt; 148 149 DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n", 150 buf->origSrc, pkt->getDest(), pkt->getAddr()); 151 152 if (sendTiming(pkt)) { 153 // send successful 154 sendQueue.pop_front(); 155 buf->pkt = NULL; // we no longer own packet, so it's not safe to look at it
|
179 finishSend(buf);
| 156 157 if (buf->expectResponse) { 158 // Must wait for response. We just need to count outstanding 159 // responses (in case we want to cap them); PacketBuffer 160 // pointer will be recovered on response. 161 ++outstandingResponses; 162 DPRINTF(BusBridge, " successful: awaiting response (%d)\n", 163 outstandingResponses); 164 } else { 165 // no response expected... deallocate packet buffer now. 166 DPRINTF(BusBridge, " successful: no response expected\n"); 167 delete buf; 168 } 169 170 // If there are more packets to send, schedule event to try again. 171 if (!sendQueue.empty()) { 172 buf = sendQueue.front(); 173 sendEvent.schedule(std::max(buf->ready, curTick + 1)); 174 } 175 // Let things start sending again 176 if (was_full) { 177 DPRINTF(BusBridge, "Queue was full, sending retry\n"); 178 otherPort->sendRetry(); 179 } 180
|
180 } else { 181 DPRINTF(BusBridge, " unsuccessful\n"); 182 } 183} 184 185
| 181 } else { 182 DPRINTF(BusBridge, " unsuccessful\n"); 183 } 184} 185 186
|
186Packet *
| 187void
|
187Bridge::BridgePort::recvRetry() 188{
| 188Bridge::BridgePort::recvRetry() 189{
|
189 PacketBuffer *buf = sendQueue.front(); 190 Packet *pkt = buf->pkt; 191 finishSend(buf); 192 return pkt;
| 190 trySend();
|
193} 194 195/** Function called by the port when the bus is receiving a Atomic 196 * transaction.*/ 197Tick 198Bridge::BridgePort::recvAtomic(Packet *pkt) 199{ 200 return otherPort->sendAtomic(pkt) + delay; 201} 202 203/** Function called by the port when the bus is receiving a Functional 204 * transaction.*/ 205void 206Bridge::BridgePort::recvFunctional(Packet *pkt) 207{ 208 std::list<PacketBuffer*>::iterator i; 209 bool pktContinue = true; 210 211 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { 212 if (pkt->intersect((*i)->pkt)) { 213 pktContinue &= fixPacket(pkt, (*i)->pkt); 214 } 215 } 216 217 if (pktContinue) { 218 otherPort->sendFunctional(pkt); 219 } 220} 221 222/** Function called by the port when the bus is receiving a status change.*/ 223void 224Bridge::BridgePort::recvStatusChange(Port::Status status) 225{
| 191} 192 193/** Function called by the port when the bus is receiving a Atomic 194 * transaction.*/ 195Tick 196Bridge::BridgePort::recvAtomic(Packet *pkt) 197{ 198 return otherPort->sendAtomic(pkt) + delay; 199} 200 201/** Function called by the port when the bus is receiving a Functional 202 * transaction.*/ 203void 204Bridge::BridgePort::recvFunctional(Packet *pkt) 205{ 206 std::list<PacketBuffer*>::iterator i; 207 bool pktContinue = true; 208 209 for (i = sendQueue.begin(); i != sendQueue.end(); ++i) { 210 if (pkt->intersect((*i)->pkt)) { 211 pktContinue &= fixPacket(pkt, (*i)->pkt); 212 } 213 } 214 215 if (pktContinue) { 216 otherPort->sendFunctional(pkt); 217 } 218} 219 220/** Function called by the port when the bus is receiving a status change.*/ 221void 222Bridge::BridgePort::recvStatusChange(Port::Status status) 223{
|
226 if (status == Port::Blocked || status == Port::Unblocked) 227 return; 228
| |
229 otherPort->sendStatusChange(status); 230} 231 232void 233Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 234 AddrRangeList &snoop) 235{ 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; 245 246END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 247 248BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 249 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.") 254 255END_INIT_SIM_OBJECT_PARAMS(Bridge) 256 257CREATE_SIM_OBJECT(Bridge) 258{ 259 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 260 write_ack); 261} 262 263REGISTER_SIM_OBJECT("Bridge", Bridge)
| 224 otherPort->sendStatusChange(status); 225} 226 227void 228Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp, 229 AddrRangeList &snoop) 230{ 231 otherPort->getPeerAddressRanges(resp, snoop); 232} 233 234BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge) 235 236 Param<int> queue_size_a; 237 Param<int> queue_size_b; 238 Param<Tick> delay; 239 Param<bool> write_ack; 240 241END_DECLARE_SIM_OBJECT_PARAMS(Bridge) 242 243BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge) 244 245 INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"), 246 INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"), 247 INIT_PARAM(delay, "The miminum delay to cross this bridge"), 248 INIT_PARAM(write_ack, "Acknowledge any writes that are received.") 249 250END_INIT_SIM_OBJECT_PARAMS(Bridge) 251 252CREATE_SIM_OBJECT(Bridge) 253{ 254 return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay, 255 write_ack); 256} 257 258REGISTER_SIM_OBJECT("Bridge", Bridge)
|