2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * Copyright (c) 2010 Advancec 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" },
127 { SET4(IsWrite
, NeedsExclusive
, IsLlsc
, IsResponse
),
128 InvalidCmd
, "StoreCondResp" },
129 /* SwapReq -- for Swap ldstub type operations */
130 { SET6(IsRead
, IsWrite
, NeedsExclusive
, IsRequest
, HasData
, NeedsResponse
),
131 SwapResp
, "SwapReq" },
132 /* SwapResp -- for Swap ldstub type operations */
133 { SET5(IsRead
, IsWrite
, NeedsExclusive
, IsResponse
, HasData
),
134 InvalidCmd
, "SwapResp" },
135 /* IntReq -- for interrupts */
136 { SET4(IsWrite
, IsRequest
, NeedsResponse
, HasData
),
137 MessageResp
, "MessageReq" },
138 /* IntResp -- for interrupts */
139 { SET2(IsWrite
, IsResponse
), InvalidCmd
, "MessageResp" },
140 /* NetworkNackError -- nacked at network layer (not by protocol) */
141 { SET2(IsResponse
, IsError
), InvalidCmd
, "NetworkNackError" },
142 /* InvalidDestError -- packet dest field invalid */
143 { SET2(IsResponse
, IsError
), InvalidCmd
, "InvalidDestError" },
144 /* BadAddressError -- memory address invalid */
145 { SET2(IsResponse
, IsError
), InvalidCmd
, "BadAddressError" },
147 { SET2(IsRequest
, IsPrint
), InvalidCmd
, "PrintReq" }
151 Packet::checkFunctional(Printable
*obj
, Addr addr
, int size
, uint8_t *data
)
153 Addr func_start
= getAddr();
154 Addr func_end
= getAddr() + getSize() - 1;
155 Addr val_start
= addr
;
156 Addr val_end
= val_start
+ size
- 1;
158 if (func_start
> val_end
|| val_start
> func_end
) {
163 // check print first since it doesn't require data
165 dynamic_cast<PrintReqState
*>(senderState
)->printObj(obj
);
169 // if there's no data, there's no need to look further
174 // offset of functional request into supplied value (could be
175 // negative if partial overlap)
176 int offset
= func_start
- val_start
;
179 if (func_start
>= val_start
&& func_end
<= val_end
) {
181 memcpy(getPtr
<uint8_t>(), data
+ offset
, getSize());
185 // In this case the timing packet only partially satisfies
186 // the request, so we would need more information to make
187 // this work. Like bytes valid in the packet or
188 // something, so the request could continue and get this
189 // bit of possibly newer data along with the older data
190 // not written to yet.
191 panic("Memory value only partially satisfies the functional "
192 "request. Now what?");
194 } else if (isWrite()) {
196 memcpy(data
+ offset
, getPtr
<uint8_t>(),
197 (min(func_end
, val_end
) - func_start
) + 1);
199 // val_start > func_start
200 memcpy(data
, getPtr
<uint8_t>() - offset
,
201 (min(func_end
, val_end
) - val_start
) + 1);
204 panic("Don't know how to handle command %s\n", cmdString());
207 // keep going with request by default
212 Packet::print(ostream
&o
, const int verbosity
, const string
&prefix
) const
214 ccprintf(o
, "%s[%x:%x] %s\n", prefix
,
215 getAddr(), getAddr() + getSize() - 1, cmdString());
218 Packet::PrintReqState::PrintReqState(ostream
&_os
, int _verbosity
)
219 : curPrefixPtr(new string("")), os(_os
), verbosity(_verbosity
)
221 labelStack
.push_back(LabelStackEntry("", curPrefixPtr
));
224 Packet::PrintReqState::~PrintReqState()
226 labelStack
.pop_back();
227 assert(labelStack
.empty());
231 Packet::PrintReqState::
232 LabelStackEntry::LabelStackEntry(const string
&_label
, string
*_prefix
)
233 : label(_label
), prefix(_prefix
), labelPrinted(false)
238 Packet::PrintReqState::pushLabel(const string
&lbl
, const string
&prefix
)
240 labelStack
.push_back(LabelStackEntry(lbl
, curPrefixPtr
));
241 curPrefixPtr
= new string(*curPrefixPtr
);
242 *curPrefixPtr
+= prefix
;
246 Packet::PrintReqState::popLabel()
249 curPrefixPtr
= labelStack
.back().prefix
;
250 labelStack
.pop_back();
251 assert(!labelStack
.empty());
255 Packet::PrintReqState::printLabels()
257 if (!labelStack
.back().labelPrinted
) {
258 LabelStack::iterator i
= labelStack
.begin();
259 LabelStack::iterator end
= labelStack
.end();
261 if (!i
->labelPrinted
) {
262 ccprintf(os
, "%s%s\n", *(i
->prefix
), i
->label
);
263 i
->labelPrinted
= true;
272 Packet::PrintReqState::printObj(Printable
*obj
)
275 obj
->print(os
, verbosity
, curPrefix());