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).
42 #include "base/cprintf.hh"
43 #include "base/misc.hh"
44 #include "base/trace.hh"
45 #include "mem/packet.hh"
49 // The one downside to bitsets is that static initializers can get ugly.
50 #define SET1(a1) (1 << (a1))
51 #define SET2(a1, a2) (SET1(a1) | SET1(a2))
52 #define SET3(a1, a2, a3) (SET2(a1, a2) | SET1(a3))
53 #define SET4(a1, a2, a3, a4) (SET3(a1, a2, a3) | SET1(a4))
54 #define SET5(a1, a2, a3, a4, a5) (SET4(a1, a2, a3, a4) | SET1(a5))
55 #define SET6(a1, a2, a3, a4, a5, a6) (SET5(a1, a2, a3, a4, a5) | SET1(a6))
57 const MemCmd::CommandInfo
58 MemCmd::commandInfo
[] =
61 { 0, InvalidCmd
, "InvalidCmd" },
63 { SET3(IsRead
, IsRequest
, NeedsResponse
), ReadResp
, "ReadReq" },
65 { SET3(IsRead
, IsResponse
, HasData
), InvalidCmd
, "ReadResp" },
66 /* ReadRespWithInvalidate */
67 { SET4(IsRead
, IsResponse
, HasData
, IsInvalidate
),
68 InvalidCmd
, "ReadRespWithInvalidate" },
70 { SET5(IsWrite
, NeedsExclusive
, IsRequest
, NeedsResponse
, HasData
),
71 WriteResp
, "WriteReq" },
73 { SET3(IsWrite
, NeedsExclusive
, IsResponse
), InvalidCmd
, "WriteResp" },
75 { SET4(IsWrite
, NeedsExclusive
, IsRequest
, HasData
),
76 InvalidCmd
, "Writeback" },
78 { SET4(IsRead
, IsRequest
, IsSWPrefetch
, NeedsResponse
),
79 SoftPFResp
, "SoftPFReq" },
81 { SET4(IsRead
, IsRequest
, IsHWPrefetch
, NeedsResponse
),
82 HardPFResp
, "HardPFReq" },
84 { SET4(IsRead
, IsResponse
, IsSWPrefetch
, HasData
),
85 InvalidCmd
, "SoftPFResp" },
87 { SET4(IsRead
, IsResponse
, IsHWPrefetch
, HasData
),
88 InvalidCmd
, "HardPFResp" },
89 /* WriteInvalidateReq */
90 { SET6(IsWrite
, NeedsExclusive
, IsInvalidate
,
91 IsRequest
, HasData
, NeedsResponse
),
92 WriteInvalidateResp
, "WriteInvalidateReq" },
93 /* WriteInvalidateResp */
94 { SET3(IsWrite
, NeedsExclusive
, IsResponse
),
95 InvalidCmd
, "WriteInvalidateResp" },
97 { SET5(IsInvalidate
, NeedsExclusive
, IsUpgrade
, IsRequest
, NeedsResponse
),
98 UpgradeResp
, "UpgradeReq" },
99 /* SCUpgradeReq: response could be UpgradeResp or UpgradeFailResp */
100 { SET6(IsInvalidate
, NeedsExclusive
, IsUpgrade
, IsLlsc
,
101 IsRequest
, NeedsResponse
),
102 UpgradeResp
, "SCUpgradeReq" },
104 { SET3(NeedsExclusive
, IsUpgrade
, IsResponse
),
105 InvalidCmd
, "UpgradeResp" },
106 /* SCUpgradeFailReq: generates UpgradeFailResp ASAP */
107 { SET5(IsInvalidate
, NeedsExclusive
, IsLlsc
,
108 IsRequest
, NeedsResponse
),
109 UpgradeFailResp
, "SCUpgradeFailReq" },
110 /* UpgradeFailResp */
111 { SET2(NeedsExclusive
, IsResponse
),
112 InvalidCmd
, "UpgradeFailResp" },
114 { SET5(IsRead
, NeedsExclusive
, IsInvalidate
, IsRequest
, NeedsResponse
),
115 ReadExResp
, "ReadExReq" },
117 { SET4(IsRead
, NeedsExclusive
, IsResponse
, HasData
),
118 InvalidCmd
, "ReadExResp" },
119 /* LoadLockedReq: note that we use plain ReadResp as response, so that
120 * we can also use ReadRespWithInvalidate when needed */
121 { SET4(IsRead
, IsLlsc
, IsRequest
, NeedsResponse
),
122 ReadResp
, "LoadLockedReq" },
124 { SET6(IsWrite
, NeedsExclusive
, IsLlsc
,
125 IsRequest
, NeedsResponse
, HasData
),
126 StoreCondResp
, "StoreCondReq" },
127 /* StoreCondFailReq: generates failing StoreCondResp ASAP */
128 { SET6(IsWrite
, NeedsExclusive
, IsLlsc
,
129 IsRequest
, NeedsResponse
, HasData
),
130 StoreCondResp
, "StoreCondFailReq" },
132 { SET4(IsWrite
, NeedsExclusive
, IsLlsc
, IsResponse
),
133 InvalidCmd
, "StoreCondResp" },
134 /* SwapReq -- for Swap ldstub type operations */
135 { SET6(IsRead
, IsWrite
, NeedsExclusive
, IsRequest
, HasData
, NeedsResponse
),
136 SwapResp
, "SwapReq" },
137 /* SwapResp -- for Swap ldstub type operations */
138 { SET5(IsRead
, IsWrite
, NeedsExclusive
, IsResponse
, HasData
),
139 InvalidCmd
, "SwapResp" },
140 /* IntReq -- for interrupts */
141 { SET4(IsWrite
, IsRequest
, NeedsResponse
, HasData
),
142 MessageResp
, "MessageReq" },
143 /* IntResp -- for interrupts */
144 { SET2(IsWrite
, IsResponse
), InvalidCmd
, "MessageResp" },
145 /* NetworkNackError -- nacked at network layer (not by protocol) */
146 { SET2(IsResponse
, IsError
), InvalidCmd
, "NetworkNackError" },
147 /* InvalidDestError -- packet dest field invalid */
148 { SET2(IsResponse
, IsError
), InvalidCmd
, "InvalidDestError" },
149 /* BadAddressError -- memory address invalid */
150 { SET2(IsResponse
, IsError
), InvalidCmd
, "BadAddressError" },
151 /* FunctionalReadError */
152 { SET3(IsRead
, IsResponse
, IsError
), InvalidCmd
, "FunctionalReadError" },
153 /* FunctionalWriteError */
154 { SET3(IsWrite
, IsResponse
, IsError
), InvalidCmd
, "FunctionalWriteError" },
156 { SET2(IsRequest
, IsPrint
), InvalidCmd
, "PrintReq" },
158 { SET3(IsRequest
, IsFlush
, NeedsExclusive
), InvalidCmd
, "FlushReq" },
162 Packet::checkFunctional(Printable
*obj
, Addr addr
, int size
, uint8_t *data
)
164 Addr func_start
= getAddr();
165 Addr func_end
= getAddr() + getSize() - 1;
166 Addr val_start
= addr
;
167 Addr val_end
= val_start
+ size
- 1;
169 if (func_start
> val_end
|| val_start
> func_end
) {
174 // check print first since it doesn't require data
176 dynamic_cast<PrintReqState
*>(senderState
)->printObj(obj
);
180 // if there's no data, there's no need to look further
185 // offset of functional request into supplied value (could be
186 // negative if partial overlap)
187 int offset
= func_start
- val_start
;
190 if (func_start
>= val_start
&& func_end
<= val_end
) {
192 memcpy(getPtr
<uint8_t>(), data
+ offset
, getSize());
195 // In this case the timing packet only partially satisfies
196 // the request, so we would need more information to make
197 // this work. Like bytes valid in the packet or
198 // something, so the request could continue and get this
199 // bit of possibly newer data along with the older data
200 // not written to yet.
201 panic("Memory value only partially satisfies the functional "
202 "request. Now what?");
204 } else if (isWrite()) {
206 memcpy(data
+ offset
, getPtr
<uint8_t>(),
207 (min(func_end
, val_end
) - func_start
) + 1);
209 // val_start > func_start
210 memcpy(data
, getPtr
<uint8_t>() - offset
,
211 (min(func_end
, val_end
) - val_start
) + 1);
214 panic("Don't know how to handle command %s\n", cmdString());
217 // keep going with request by default
222 Packet::print(ostream
&o
, const int verbosity
, const string
&prefix
) const
224 ccprintf(o
, "%s[%x:%x] %s\n", prefix
,
225 getAddr(), getAddr() + getSize() - 1, cmdString());
228 Packet::PrintReqState::PrintReqState(ostream
&_os
, int _verbosity
)
229 : curPrefixPtr(new string("")), os(_os
), verbosity(_verbosity
)
231 labelStack
.push_back(LabelStackEntry("", curPrefixPtr
));
234 Packet::PrintReqState::~PrintReqState()
236 labelStack
.pop_back();
237 assert(labelStack
.empty());
241 Packet::PrintReqState::
242 LabelStackEntry::LabelStackEntry(const string
&_label
, string
*_prefix
)
243 : label(_label
), prefix(_prefix
), labelPrinted(false)
248 Packet::PrintReqState::pushLabel(const string
&lbl
, const string
&prefix
)
250 labelStack
.push_back(LabelStackEntry(lbl
, curPrefixPtr
));
251 curPrefixPtr
= new string(*curPrefixPtr
);
252 *curPrefixPtr
+= prefix
;
256 Packet::PrintReqState::popLabel()
259 curPrefixPtr
= labelStack
.back().prefix
;
260 labelStack
.pop_back();
261 assert(!labelStack
.empty());
265 Packet::PrintReqState::printLabels()
267 if (!labelStack
.back().labelPrinted
) {
268 LabelStack::iterator i
= labelStack
.begin();
269 LabelStack::iterator end
= labelStack
.end();
271 if (!i
->labelPrinted
) {
272 ccprintf(os
, "%s%s\n", *(i
->prefix
), i
->label
);
273 i
->labelPrinted
= true;
282 Packet::PrintReqState::printObj(Printable
*obj
)
285 obj
->print(os
, verbosity
, curPrefix());