2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * Copyright (c) 2010 Advanced Micro Devices, Inc.
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.
35 * Definition of the Packet Class, a packet is a transaction occuring
36 * between a single level of the memory heirarchy (ie L1->L2).
41 #include "base/cprintf.hh"
42 #include "base/misc.hh"
43 #include "base/trace.hh"
44 #include "mem/packet.hh"
48 // The one downside to bitsets is that static initializers can get ugly.
49 #define SET1(a1) (1 << (a1))
50 #define SET2(a1, a2) (SET1(a1) | SET1(a2))
51 #define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3))
52 #define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4))
53 #define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5))
54 #define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))
56 const MemCmd::CommandInfo
57 MemCmd::commandInfo
[] =
60 { 0, InvalidCmd
, "InvalidCmd" },
62 { SET3(IsRead
, IsRequest
, NeedsResponse
), ReadResp
, "ReadReq" },
64 { SET3(IsRead
, IsResponse
, HasData
), InvalidCmd
, "ReadResp" },
65 /* ReadRespWithInvalidate */
66 { SET4(IsRead
, IsResponse
, HasData
, IsInvalidate
),
67 InvalidCmd
, "ReadRespWithInvalidate" },
69 { SET5(IsWrite
, NeedsExclusive
, IsRequest
, NeedsResponse
, HasData
),
70 WriteResp
, "WriteReq" },
72 { SET3(IsWrite
, NeedsExclusive
, IsResponse
), InvalidCmd
, "WriteResp" },
74 { SET4(IsWrite
, NeedsExclusive
, IsRequest
, HasData
),
75 InvalidCmd
, "Writeback" },
77 { SET4(IsRead
, IsRequest
, IsSWPrefetch
, NeedsResponse
),
78 SoftPFResp
, "SoftPFReq" },
80 { SET4(IsRead
, IsRequest
, IsHWPrefetch
, NeedsResponse
),
81 HardPFResp
, "HardPFReq" },
83 { SET4(IsRead
, IsResponse
, IsSWPrefetch
, HasData
),
84 InvalidCmd
, "SoftPFResp" },
86 { SET4(IsRead
, IsResponse
, IsHWPrefetch
, HasData
),
87 InvalidCmd
, "HardPFResp" },
88 /* WriteInvalidateReq */
89 { SET6(IsWrite
, NeedsExclusive
, IsInvalidate
,
90 IsRequest
, HasData
, NeedsResponse
),
91 WriteInvalidateResp
, "WriteInvalidateReq" },
92 /* WriteInvalidateResp */
93 { SET3(IsWrite
, NeedsExclusive
, IsResponse
),
94 InvalidCmd
, "WriteInvalidateResp" },
96 { SET5(IsInvalidate
, NeedsExclusive
, IsUpgrade
, IsRequest
, NeedsResponse
),
97 UpgradeResp
, "UpgradeReq" },
98 /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */
99 { SET6(IsInvalidate
, NeedsExclusive
, IsUpgrade
, IsLlsc
,
100 IsRequest
, NeedsResponse
),
101 UpgradeResp
, "SCUpgradeReq" },
103 { SET3(NeedsExclusive
, IsUpgrade
, IsResponse
),
104 InvalidCmd
, "UpgradeResp" },
105 /* SCUpgradeFailReq: generates UpgradeFailResp ASAP */
106 { SET5(IsInvalidate
, NeedsExclusive
, IsLlsc
,
107 IsRequest
, NeedsResponse
),
108 UpgradeFailResp
, "SCUpgradeFailReq" },
109 /* UpgradeFailResp */
110 { SET2(NeedsExclusive
, IsResponse
),
111 InvalidCmd
, "UpgradeFailResp" },
113 { SET5(IsRead
, NeedsExclusive
, IsInvalidate
, IsRequest
, NeedsResponse
),
114 ReadExResp
, "ReadExReq" },
116 { SET4(IsRead
, NeedsExclusive
, IsResponse
, HasData
),
117 InvalidCmd
, "ReadExResp" },
118 /* LoadLockedReq: note that we use plain ReadResp as response, so that
119 * we can also use ReadRespWithInvalidate when needed */
120 { SET4(IsRead
, IsLlsc
, IsRequest
, NeedsResponse
),
121 ReadResp
, "LoadLockedReq" },
123 { SET6(IsWrite
, NeedsExclusive
, IsLlsc
,
124 IsRequest
, NeedsResponse
, HasData
),
125 StoreCondResp
, "StoreCondReq" },
126 /* StoreCondFailReq: generates failing StoreCondResp ASAP */
127 { SET6(IsWrite
, NeedsExclusive
, IsLlsc
,
128 IsRequest
, NeedsResponse
, HasData
),
129 StoreCondResp
, "StoreCondFailReq" },
131 { SET4(IsWrite
, NeedsExclusive
, IsLlsc
, IsResponse
),
132 InvalidCmd
, "StoreCondResp" },
133 /* SwapReq -- for Swap ldstub type operations */
134 { SET6(IsRead
, IsWrite
, NeedsExclusive
, IsRequest
, HasData
, NeedsResponse
),
135 SwapResp
, "SwapReq" },
136 /* SwapResp -- for Swap ldstub type operations */
137 { SET5(IsRead
, IsWrite
, NeedsExclusive
, IsResponse
, HasData
),
138 InvalidCmd
, "SwapResp" },
139 /* IntReq -- for interrupts */
140 { SET4(IsWrite
, IsRequest
, NeedsResponse
, HasData
),
141 MessageResp
, "MessageReq" },
142 /* IntResp -- for interrupts */
143 { SET2(IsWrite
, IsResponse
), InvalidCmd
, "MessageResp" },
144 /* NetworkNackError -- nacked at network layer (not by protocol) */
145 { SET2(IsResponse
, IsError
), InvalidCmd
, "NetworkNackError" },
146 /* InvalidDestError -- packet dest field invalid */
147 { SET2(IsResponse
, IsError
), InvalidCmd
, "InvalidDestError" },
148 /* BadAddressError -- memory address invalid */
149 { SET2(IsResponse
, IsError
), InvalidCmd
, "BadAddressError" },
151 { SET2(IsRequest
, IsPrint
), InvalidCmd
, "PrintReq" }
155 Packet::checkFunctional(Printable
*obj
, Addr addr
, int size
, uint8_t *data
)
157 Addr func_start
= getAddr();
158 Addr func_end
= getAddr() + getSize() - 1;
159 Addr val_start
= addr
;
160 Addr val_end
= val_start
+ size
- 1;
162 if (func_start
> val_end
|| val_start
> func_end
) {
167 // check print first since it doesn't require data
169 dynamic_cast<PrintReqState
*>(senderState
)->printObj(obj
);
173 // if there's no data, there's no need to look further
178 // offset of functional request into supplied value (could be
179 // negative if partial overlap)
180 int offset
= func_start
- val_start
;
183 if (func_start
>= val_start
&& func_end
<= val_end
) {
185 memcpy(getPtr
<uint8_t>(), data
+ offset
, getSize());
188 // In this case the timing packet only partially satisfies
189 // the request, so we would need more information to make
190 // this work. Like bytes valid in the packet or
191 // something, so the request could continue and get this
192 // bit of possibly newer data along with the older data
193 // not written to yet.
194 panic("Memory value only partially satisfies the functional "
195 "request. Now what?");
197 } else if (isWrite()) {
199 memcpy(data
+ offset
, getPtr
<uint8_t>(),
200 (min(func_end
, val_end
) - func_start
) + 1);
202 // val_start > func_start
203 memcpy(data
, getPtr
<uint8_t>() - offset
,
204 (min(func_end
, val_end
) - val_start
) + 1);
207 panic("Don't know how to handle command %s\n", cmdString());
210 // keep going with request by default
215 Packet::print(ostream
&o
, const int verbosity
, const string
&prefix
) const
217 ccprintf(o
, "%s[%x:%x] %s\n", prefix
,
218 getAddr(), getAddr() + getSize() - 1, cmdString());
221 Packet::PrintReqState::PrintReqState(ostream
&_os
, int _verbosity
)
222 : curPrefixPtr(new string("")), os(_os
), verbosity(_verbosity
)
224 labelStack
.push_back(LabelStackEntry("", curPrefixPtr
));
227 Packet::PrintReqState::~PrintReqState()
229 labelStack
.pop_back();
230 assert(labelStack
.empty());
234 Packet::PrintReqState::
235 LabelStackEntry::LabelStackEntry(const string
&_label
, string
*_prefix
)
236 : label(_label
), prefix(_prefix
), labelPrinted(false)
241 Packet::PrintReqState::pushLabel(const string
&lbl
, const string
&prefix
)
243 labelStack
.push_back(LabelStackEntry(lbl
, curPrefixPtr
));
244 curPrefixPtr
= new string(*curPrefixPtr
);
245 *curPrefixPtr
+= prefix
;
249 Packet::PrintReqState::popLabel()
252 curPrefixPtr
= labelStack
.back().prefix
;
253 labelStack
.pop_back();
254 assert(!labelStack
.empty());
258 Packet::PrintReqState::printLabels()
260 if (!labelStack
.back().labelPrinted
) {
261 LabelStack::iterator i
= labelStack
.begin();
262 LabelStack::iterator end
= labelStack
.end();
264 if (!i
->labelPrinted
) {
265 ccprintf(os
, "%s%s\n", *(i
->prefix
), i
->label
);
266 i
->labelPrinted
= true;
275 Packet::PrintReqState::printObj(Printable
*obj
)
278 obj
->print(os
, verbosity
, curPrefix());