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 // The one downside to bitsets is that static initializers can get ugly.
45 #define SET1(a1) (1 << (a1))
46 #define SET2(a1, a2) (SET1(a1) | SET1(a2))
47 #define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3))
48 #define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4))
49 #define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5))
50 #define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))
52 const MemCmd::CommandInfo
53 MemCmd::commandInfo
[] =
56 { 0, InvalidCmd
, "InvalidCmd" },
58 { SET3(IsRead
, IsRequest
, NeedsResponse
), ReadResp
, "ReadReq" },
60 { SET3(IsRead
, IsResponse
, HasData
), InvalidCmd
, "ReadResp" },
62 { SET5(IsWrite
, NeedsExclusive
, IsRequest
, NeedsResponse
, HasData
),
63 WriteResp
, "WriteReq" },
65 { SET3(IsWrite
, NeedsExclusive
, IsResponse
), InvalidCmd
, "WriteResp" },
67 { SET4(IsWrite
, NeedsExclusive
, IsRequest
, HasData
),
68 InvalidCmd
, "Writeback" },
70 { SET4(IsRead
, IsRequest
, IsSWPrefetch
, NeedsResponse
),
71 SoftPFResp
, "SoftPFReq" },
73 { SET4(IsRead
, IsRequest
, IsHWPrefetch
, NeedsResponse
),
74 HardPFResp
, "HardPFReq" },
76 { SET4(IsRead
, IsResponse
, IsSWPrefetch
, HasData
),
77 InvalidCmd
, "SoftPFResp" },
79 { SET4(IsRead
, IsResponse
, IsHWPrefetch
, HasData
),
80 InvalidCmd
, "HardPFResp" },
81 /* WriteInvalidateReq */
82 { SET6(IsWrite
, NeedsExclusive
, IsInvalidate
,
83 IsRequest
, HasData
, NeedsResponse
),
84 WriteInvalidateResp
, "WriteInvalidateReq" },
85 /* WriteInvalidateResp */
86 { SET4(IsWrite
, NeedsExclusive
, IsInvalidate
, IsResponse
),
87 InvalidCmd
, "WriteInvalidateResp" },
89 { SET4(IsInvalidate
, NeedsExclusive
, IsRequest
, NeedsResponse
),
90 UpgradeResp
, "UpgradeReq" },
92 { SET3(IsInvalidate
, NeedsExclusive
, IsResponse
),
93 InvalidCmd
, "UpgradeResp" },
95 { SET5(IsRead
, NeedsExclusive
, IsInvalidate
, IsRequest
, NeedsResponse
),
96 ReadExResp
, "ReadExReq" },
98 { SET5(IsRead
, NeedsExclusive
, IsInvalidate
, IsResponse
, HasData
),
99 InvalidCmd
, "ReadExResp" },
101 { SET4(IsRead
, IsLocked
, IsRequest
, NeedsResponse
),
102 ReadResp
, "LoadLockedReq" },
104 { SET4(IsRead
, IsLocked
, IsResponse
, HasData
),
105 InvalidCmd
, "LoadLockedResp" },
107 { SET6(IsWrite
, NeedsExclusive
, IsLocked
,
108 IsRequest
, NeedsResponse
, HasData
),
109 StoreCondResp
, "StoreCondReq" },
111 { SET4(IsWrite
, NeedsExclusive
, IsLocked
, IsResponse
),
112 InvalidCmd
, "StoreCondResp" },
113 /* SwapReq -- for Swap ldstub type operations */
114 { SET6(IsRead
, IsWrite
, NeedsExclusive
, IsRequest
, HasData
, NeedsResponse
),
115 SwapResp
, "SwapReq" },
116 /* SwapResp -- for Swap ldstub type operations */
117 { SET5(IsRead
, IsWrite
, NeedsExclusive
, IsResponse
, HasData
),
118 InvalidCmd
, "SwapResp" },
119 /* NetworkNackError -- nacked at network layer (not by protocol) */
120 { SET2(IsRequest
, IsError
), InvalidCmd
, "NetworkNackError" },
121 /* InvalidDestError -- packet dest field invalid */
122 { SET2(IsRequest
, IsError
), InvalidCmd
, "InvalidDestError" },
123 /* BadAddressError -- memory address invalid */
124 { SET2(IsRequest
, IsError
), InvalidCmd
, "BadAddressError" }
128 /** delete the data pointed to in the data pointer. Ok to call to matter how
129 * data was allocted. */
133 assert(staticData
|| dynamicData
);
143 /** If there isn't data in the packet, allocate some. */
152 data
= new uint8_t[getSize()];
155 /** Do the packet modify the same addresses. */
157 Packet::intersect(PacketPtr p
)
160 Addr e1
= getAddr() + getSize() - 1;
161 Addr s2
= p
->getAddr();
162 Addr e2
= p
->getAddr() + p
->getSize() - 1;
164 return !(s1
> e2
|| e1
< s2
);
169 Packet::checkFunctional(Addr addr
, int size
, uint8_t *data
)
171 Addr func_start
= getAddr();
172 Addr func_end
= getAddr() + getSize() - 1;
173 Addr val_start
= addr
;
174 Addr val_end
= val_start
+ size
- 1;
176 if (func_start
> val_end
|| val_start
> func_end
) {
181 // offset of functional request into supplied value (could be
182 // negative if partial overlap)
183 int offset
= func_start
- val_start
;
186 if (func_start
>= val_start
&& func_end
<= val_end
) {
188 std::memcpy(getPtr
<uint8_t>(), data
+ offset
, getSize());
192 // In this case the timing packet only partially satisfies
193 // the request, so we would need more information to make
194 // this work. Like bytes valid in the packet or
195 // something, so the request could continue and get this
196 // bit of possibly newer data along with the older data
197 // not written to yet.
198 panic("Memory value only partially satisfies the functional "
199 "request. Now what?");
201 } else if (isWrite()) {
203 std::memcpy(data
+ offset
, getPtr
<uint8_t>(),
204 (std::min(func_end
, val_end
) - func_start
) + 1);
205 } else { // val_start > func_start
206 std::memcpy(data
, getPtr
<uint8_t>() - offset
,
207 (std::min(func_end
, val_end
) - val_start
) + 1);
209 // we always want to keep going with a write
212 panic("Don't know how to handle command %s\n", cmdString());
217 operator<<(std::ostream
&o
, const Packet
&p
)
221 o
.setf(std::ios_base::hex
, std::ios_base::showbase
);
223 o
.unsetf(std::ios_base::hex
| std::ios_base::showbase
);
225 o
.setf(std::ios_base::hex
, std::ios_base::showbase
);
226 o
<< p
.getAddr() + p
.getSize() - 1 << "] ";
227 o
.unsetf(std::ios_base::hex
| std::ios_base::showbase
);
233 if (p
.isInvalidate())