2 * Copyright (c) 2006 The Regents of The University of Michigan
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.
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.
34 * Definition of the Packet Class, a packet is a transaction occuring
35 * between a single level of the memory heirarchy (ie L1->L2).
40 #include "base/misc.hh"
41 #include "base/trace.hh"
42 #include "mem/packet.hh"
44 static const std::string
ReadReqString("ReadReq");
45 static const std::string
WriteReqString("WriteReq");
46 static const std::string
WriteReqNoAckString("WriteReqNoAck|Writeback");
47 static const std::string
ReadRespString("ReadResp");
48 static const std::string
WriteRespString("WriteResp");
49 static const std::string
SoftPFReqString("SoftPFReq");
50 static const std::string
SoftPFRespString("SoftPFResp");
51 static const std::string
HardPFReqString("HardPFReq");
52 static const std::string
HardPFRespString("HardPFResp");
53 static const std::string
InvalidateReqString("InvalidateReq");
54 static const std::string
WriteInvalidateReqString("WriteInvalidateReq");
55 static const std::string
WriteInvalidateRespString("WriteInvalidateResp");
56 static const std::string
UpgradeReqString("UpgradeReq");
57 static const std::string
ReadExReqString("ReadExReq");
58 static const std::string
ReadExRespString("ReadExResp");
59 static const std::string
OtherCmdString("<other>");
62 Packet::cmdString() const
65 case ReadReq
: return ReadReqString
;
66 case WriteReq
: return WriteReqString
;
67 case WriteReqNoAck
: return WriteReqNoAckString
;
68 case ReadResp
: return ReadRespString
;
69 case WriteResp
: return WriteRespString
;
70 case SoftPFReq
: return SoftPFReqString
;
71 case SoftPFResp
: return SoftPFRespString
;
72 case HardPFReq
: return HardPFReqString
;
73 case HardPFResp
: return HardPFRespString
;
74 case InvalidateReq
: return InvalidateReqString
;
75 case WriteInvalidateReq
:return WriteInvalidateReqString
;
76 case WriteInvalidateResp
:return WriteInvalidateRespString
;
77 case UpgradeReq
: return UpgradeReqString
;
78 case ReadExReq
: return ReadExReqString
;
79 case ReadExResp
: return ReadExRespString
;
80 default: return OtherCmdString
;
85 Packet::cmdIdxToString(Packet::Command idx
)
88 case ReadReq
: return ReadReqString
;
89 case WriteReq
: return WriteReqString
;
90 case WriteReqNoAck
: return WriteReqNoAckString
;
91 case ReadResp
: return ReadRespString
;
92 case WriteResp
: return WriteRespString
;
93 case SoftPFReq
: return SoftPFReqString
;
94 case SoftPFResp
: return SoftPFRespString
;
95 case HardPFReq
: return HardPFReqString
;
96 case HardPFResp
: return HardPFRespString
;
97 case InvalidateReq
: return InvalidateReqString
;
98 case WriteInvalidateReq
:return WriteInvalidateReqString
;
99 case WriteInvalidateResp
:return WriteInvalidateRespString
;
100 case UpgradeReq
: return UpgradeReqString
;
101 case ReadExReq
: return ReadExReqString
;
102 case ReadExResp
: return ReadExRespString
;
103 default: return OtherCmdString
;
107 /** delete the data pointed to in the data pointer. Ok to call to matter how
108 * data was allocted. */
112 assert(staticData
|| dynamicData
);
122 /** If there isn't data in the packet, allocate some. */
131 data
= new uint8_t[getSize()];
134 /** Do the packet modify the same addresses. */
136 Packet::intersect(PacketPtr p
)
139 Addr e1
= getAddr() + getSize() - 1;
140 Addr s2
= p
->getAddr();
141 Addr e2
= p
->getAddr() + p
->getSize() - 1;
143 return !(s1
> e2
|| e1
< s2
);
147 fixDelayedResponsePacket(PacketPtr func
, PacketPtr timing
)
151 if (timing
->isRead() || timing
->isWrite()) {
152 timing
->toggleData();
153 result
= fixPacket(func
, timing
);
154 timing
->toggleData();
157 //Don't toggle if it isn't a read/write response
158 result
= fixPacket(func
, timing
);
165 fixPacket(PacketPtr func
, PacketPtr timing
)
167 Addr funcStart
= func
->getAddr();
168 Addr funcEnd
= func
->getAddr() + func
->getSize() - 1;
169 Addr timingStart
= timing
->getAddr();
170 Addr timingEnd
= timing
->getAddr() + timing
->getSize() - 1;
172 assert(!(funcStart
> timingEnd
|| timingStart
> funcEnd
));
174 if (DTRACE(FunctionalAccess
)) {
176 DebugOut() << timing
;
179 // this packet can't solve our problem, continue on
180 if (!timing
->hasData())
183 if (func
->isRead()) {
184 if (funcStart
>= timingStart
&& funcEnd
<= timingEnd
) {
186 memcpy(func
->getPtr
<uint8_t>(), timing
->getPtr
<uint8_t>() +
187 funcStart
- timingStart
, func
->getSize());
188 func
->result
= Packet::Success
;
189 func
->flags
|= SATISFIED
;
192 // In this case the timing packet only partially satisfies the
193 // requset, so we would need more information to make this work.
194 // Like bytes valid in the packet or something, so the request could
195 // continue and get this bit of possibly newer data along with the
196 // older data not written to yet.
197 panic("Timing packet only partially satisfies the functional"
198 "request. Now what?");
200 } else if (func
->isWrite()) {
201 if (funcStart
>= timingStart
) {
202 memcpy(timing
->getPtr
<uint8_t>() + (funcStart
- timingStart
),
203 func
->getPtr
<uint8_t>(),
204 (std::min(funcEnd
, timingEnd
) - funcStart
) + 1);
205 } else { // timingStart > funcStart
206 memcpy(timing
->getPtr
<uint8_t>(),
207 func
->getPtr
<uint8_t>() + (timingStart
- funcStart
),
208 (std::min(funcEnd
, timingEnd
) - timingStart
) + 1);
210 // we always want to keep going with a write
213 panic("Don't know how to handle command type %#x\n",
220 operator<<(std::ostream
&o
, const Packet
&p
)
224 o
.setf(std::ios_base::hex
, std::ios_base::showbase
);
226 o
.unsetf(std::ios_base::hex
| std::ios_base::showbase
);
228 o
.setf(std::ios_base::hex
, std::ios_base::showbase
);
229 o
<< p
.getAddr() + p
.getSize() - 1 << "] ";
230 o
.unsetf(std::ios_base::hex
| std::ios_base::showbase
);
232 if (p
.result
== Packet::Success
)
234 if (p
.result
== Packet::BadAddress
)
236 if (p
.result
== Packet::Nacked
)
238 if (p
.result
== Packet::Unknown
)
245 if (p
.isInvalidate())