1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Ali Saidi 29 * Steve Reinhardt 30 */ 31 32/** 33 * @file 34 * Declaration of a simple bus bridge object with no buffering 35 */ 36 37#ifndef __MEM_BRIDGE_HH__ 38#define __MEM_BRIDGE_HH__ 39 40#include <string> 41#include <list> 42#include <inttypes.h> 43#include <queue> 44 45#include "mem/mem_object.hh" 46#include "mem/packet.hh" 47#include "mem/port.hh" 48#include "sim/eventq.hh" 49 50class Bridge : public MemObject 51{ 52 protected: 53 /** Declaration of the buses port type, one will be instantiated for each 54 of the interfaces connecting to the bus. */ 55 class BridgePort : public Port 56 { 57 /** A pointer to the bridge to which this port belongs. */ 58 Bridge *bridge; 59 60 /** 61 * Pointer to the port on the other side of the bridge 62 * (connected to the other bus). 63 */ 64 BridgePort *otherPort; 65 66 /** Minimum delay though this bridge. */ 67 Tick delay; 68 69 /** Min delay to respond to a nack. */ 70 Tick nackDelay; 71 72 bool fixPartialWrite; 73 74 class PacketBuffer : public Packet::SenderState { 75 76 public: 77 Tick ready; 78 PacketPtr pkt; 79 Packet::SenderState *origSenderState; 80 short origSrc; 81 bool expectResponse; 82 83 bool partialWriteFixed; 84 PacketPtr oldPkt; 85 86 PacketBuffer(PacketPtr _pkt, Tick t, bool nack = false) 87 : ready(t), pkt(_pkt), 88 origSenderState(_pkt->senderState), origSrc(_pkt->getSrc()), 89 expectResponse(_pkt->needsResponse() && !nack), 90 partialWriteFixed(false) 91 92 { 93 if (!pkt->isResponse() && !nack && pkt->result != Packet::Nacked) 94 pkt->senderState = this; 95 } 96 97 void fixResponse(PacketPtr pkt) 98 { 99 assert(pkt->senderState == this); 100 pkt->setDest(origSrc); 101 pkt->senderState = origSenderState; 102 if (partialWriteFixed) 103 delete oldPkt; 104 } 105 106 void partialWriteFix(Port *port) 107 { 108 assert(!partialWriteFixed); 109 assert(expectResponse); 110
|
111 int pbs = port->peerBlockSize();
|
111 Addr pbs = port->peerBlockSize(); 112 Addr blockAddr = pkt->getAddr() & ~(pbs-1); |
113 partialWriteFixed = true; 114 PacketDataPtr data; 115 116 data = new uint8_t[pbs];
|
116 PacketPtr funcPkt = new Packet(pkt->req, MemCmd::ReadReq,
117 Packet::Broadcast, pbs);
118
119 funcPkt->dataStatic(data);
120 port->sendFunctional(funcPkt);
121 assert(funcPkt->result == Packet::Success);
|
117 RequestPtr funcReq = new Request(blockAddr, 4, 0); 118 PacketPtr funcPkt = new Packet(funcReq, MemCmd::ReadReq, 119 Packet::Broadcast); 120 for (int x = 0; x < pbs; x+=4) { 121 funcReq->setPhys(blockAddr + x, 4, 0); 122 funcPkt->reinitFromRequest(); 123 funcPkt->dataStatic(data + x); 124 port->sendFunctional(funcPkt); 125 assert(funcPkt->result == Packet::Success); 126 } |
127 delete funcPkt;
|
128 delete funcReq; |
129 130 oldPkt = pkt; 131 memcpy(data + oldPkt->getOffset(pbs), pkt->getPtr<uint8_t>(), 132 pkt->getSize()); 133 pkt = new Packet(oldPkt->req, MemCmd::WriteInvalidateReq, 134 Packet::Broadcast, pbs); 135 pkt->dataDynamicArray(data); 136 pkt->senderState = oldPkt->senderState; 137 } 138 139 void undoPartialWriteFix() 140 { 141 if (!partialWriteFixed) 142 return; 143 delete pkt; 144 pkt = oldPkt; 145 partialWriteFixed = false; 146 } 147 148 }; 149 150 /** 151 * Outbound packet queue. Packets are held in this queue for a 152 * specified delay to model the processing delay of the 153 * bridge. 154 */ 155 std::list<PacketBuffer*> sendQueue; 156 157 int outstandingResponses; 158 int queuedRequests; 159 160 /** If we're waiting for a retry to happen.*/ 161 bool inRetry; 162 163 /** Max queue size for outbound packets */ 164 int reqQueueLimit; 165 166 /** Max queue size for reserved responses. */ 167 int respQueueLimit; 168 169 /** 170 * Is this side blocked from accepting outbound packets? 171 */ 172 bool respQueueFull(); 173 bool reqQueueFull(); 174 175 void queueForSendTiming(PacketPtr pkt); 176 177 void finishSend(PacketBuffer *buf); 178 179 void nackRequest(PacketPtr pkt); 180 181 /** 182 * Handle send event, scheduled when the packet at the head of 183 * the outbound queue is ready to transmit (for timing 184 * accesses only). 185 */ 186 void trySend(); 187 188 class SendEvent : public Event 189 { 190 BridgePort *port; 191 192 public: 193 SendEvent(BridgePort *p) 194 : Event(&mainEventQueue), port(p) {} 195 196 virtual void process() { port->trySend(); } 197 198 virtual const char *description() { return "bridge send event"; } 199 }; 200 201 SendEvent sendEvent; 202 203 public: 204 /** Constructor for the BusPort.*/ 205 BridgePort(const std::string &_name, Bridge *_bridge, 206 BridgePort *_otherPort, int _delay, int _nack_delay, 207 int _req_limit, int _resp_limit, bool fix_partial_write); 208 209 protected: 210 211 /** When receiving a timing request from the peer port, 212 pass it to the bridge. */ 213 virtual bool recvTiming(PacketPtr pkt); 214 215 /** When receiving a retry request from the peer port, 216 pass it to the bridge. */ 217 virtual void recvRetry(); 218 219 /** When receiving a Atomic requestfrom the peer port, 220 pass it to the bridge. */ 221 virtual Tick recvAtomic(PacketPtr pkt); 222 223 /** When receiving a Functional request from the peer port, 224 pass it to the bridge. */ 225 virtual void recvFunctional(PacketPtr pkt); 226 227 /** When receiving a status changefrom the peer port, 228 pass it to the bridge. */ 229 virtual void recvStatusChange(Status status); 230 231 /** When receiving a address range request the peer port, 232 pass it to the bridge. */ 233 virtual void getDeviceAddressRanges(AddrRangeList &resp, 234 AddrRangeList &snoop); 235 }; 236 237 BridgePort portA, portB; 238 239 /** If this bridge should acknowledge writes. */ 240 bool ackWrites; 241 242 public: 243 struct Params 244 { 245 std::string name; 246 int req_size_a; 247 int req_size_b; 248 int resp_size_a; 249 int resp_size_b; 250 Tick delay; 251 Tick nack_delay; 252 bool write_ack; 253 bool fix_partial_write_a; 254 bool fix_partial_write_b; 255 }; 256 257 protected: 258 Params *_params; 259 260 public: 261 const Params *params() const { return _params; } 262 263 /** A function used to return the port associated with this bus object. */ 264 virtual Port *getPort(const std::string &if_name, int idx = -1); 265 266 virtual void init(); 267 268 Bridge(Params *p); 269}; 270 271#endif //__MEM_BUS_HH__
|