cpu_impl.hh (8832:247fee427324) cpu_impl.hh (8887:20ea02da9c53)
1/*
2 * Copyright (c) 2011 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Geoffrey Blake
42 */
43
44#include <list>
45#include <string>
46
47#include "arch/vtophys.hh"
48#include "base/refcnt.hh"
49#include "config/the_isa.hh"
50#include "cpu/base_dyn_inst.hh"
51#include "cpu/exetrace.hh"
52#include "cpu/simple_thread.hh"
53#include "cpu/static_inst.hh"
54#include "cpu/thread_context.hh"
55#include "cpu/checker/cpu.hh"
56#include "debug/Checker.hh"
57#include "sim/full_system.hh"
58#include "sim/sim_object.hh"
59#include "sim/stats.hh"
60
61using namespace std;
62using namespace TheISA;
63
64template <class Impl>
65void
66Checker<Impl>::advancePC(Fault fault)
67{
68 if (fault != NoFault) {
69 curMacroStaticInst = StaticInst::nullStaticInstPtr;
70 fault->invoke(tc, curStaticInst);
71 predecoder.reset();
72 } else {
73 if (curStaticInst) {
74 if (curStaticInst->isLastMicroop())
75 curMacroStaticInst = StaticInst::nullStaticInstPtr;
76 TheISA::PCState pcState = thread->pcState();
77 TheISA::advancePC(pcState, curStaticInst);
78 thread->pcState(pcState);
79 DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState());
80 }
81 }
82}
83//////////////////////////////////////////////////
84
85template <class Impl>
86void
87Checker<Impl>::handlePendingInt()
88{
89 DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n",
90 thread->pcState(), instList.size());
91 DynInstPtr boundaryInst = NULL;
92 if (!instList.empty()) {
93 // Set the instructions as completed and verify as much as possible.
94 DynInstPtr inst;
95 typename std::list<DynInstPtr>::iterator itr;
96
97 for (itr = instList.begin(); itr != instList.end(); itr++) {
98 (*itr)->setCompleted();
99 }
100
101 inst = instList.front();
102 boundaryInst = instList.back();
103 verify(inst); // verify the instructions
104 inst = NULL;
105 }
106 if ((!boundaryInst && curMacroStaticInst &&
107 curStaticInst->isDelayedCommit() &&
108 !curStaticInst->isLastMicroop()) ||
109 (boundaryInst && boundaryInst->isDelayedCommit() &&
110 !boundaryInst->isLastMicroop())) {
111 panic("%lli: Trying to take an interrupt in middle of "
112 "a non-interuptable instruction!", curTick());
113 }
114 boundaryInst = NULL;
115 predecoder.reset();
116 curMacroStaticInst = StaticInst::nullStaticInstPtr;
117}
118
119template <class Impl>
120void
121Checker<Impl>::verify(DynInstPtr &completed_inst)
122{
123 DynInstPtr inst;
124
125 // Make sure serializing instructions are actually
126 // seen as serializing to commit. instList should be
127 // empty in these cases.
128 if ((completed_inst->isSerializing() ||
129 completed_inst->isSerializeBefore()) &&
130 (!instList.empty() ?
131 (instList.front()->seqNum != completed_inst->seqNum) : 0)) {
132 panic("%lli: Instruction sn:%lli at PC %s is serializing before but is"
133 " entering instList with other instructions\n", curTick(),
134 completed_inst->seqNum, completed_inst->pcState());
135 }
136
137 // Either check this instruction, or add it to a list of
138 // instructions waiting to be checked. Instructions must be
139 // checked in program order, so if a store has committed yet not
140 // completed, there may be some instructions that are waiting
141 // behind it that have completed and must be checked.
142 if (!instList.empty()) {
143 if (youngestSN < completed_inst->seqNum) {
144 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
145 completed_inst->seqNum, completed_inst->pcState());
146 instList.push_back(completed_inst);
147 youngestSN = completed_inst->seqNum;
148 }
149
150 if (!instList.front()->isCompleted()) {
151 return;
152 } else {
153 inst = instList.front();
154 instList.pop_front();
155 }
156 } else {
157 if (!completed_inst->isCompleted()) {
158 if (youngestSN < completed_inst->seqNum) {
159 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
160 completed_inst->seqNum, completed_inst->pcState());
161 instList.push_back(completed_inst);
162 youngestSN = completed_inst->seqNum;
163 }
164 return;
165 } else {
166 if (youngestSN < completed_inst->seqNum) {
167 inst = completed_inst;
168 youngestSN = completed_inst->seqNum;
169 } else {
170 return;
171 }
172 }
173 }
174
175 // Make sure a serializing instruction is actually seen as
176 // serializing. instList should be empty here
177 if (inst->isSerializeAfter() && !instList.empty()) {
178 panic("%lli: Instruction sn:%lli at PC %s is serializing after but is"
179 " exiting instList with other instructions\n", curTick(),
180 completed_inst->seqNum, completed_inst->pcState());
181 }
182 unverifiedInst = inst;
183 inst = NULL;
184
185 // Try to check all instructions that are completed, ending if we
186 // run out of instructions to check or if an instruction is not
187 // yet completed.
188 while (1) {
189 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n",
190 unverifiedInst->seqNum, unverifiedInst->pcState());
191 unverifiedReq = NULL;
192 unverifiedReq = unverifiedInst->reqToVerify;
193 unverifiedMemData = unverifiedInst->memData;
194 // Make sure results queue is empty
195 while (!result.empty()) {
196 result.pop();
197 }
198 numCycles++;
199
200 Fault fault = NoFault;
201
202 // maintain $r0 semantics
203 thread->setIntReg(ZeroReg, 0);
204#ifdef TARGET_ALPHA
205 thread->setFloatRegDouble(ZeroReg, 0.0);
206#endif // TARGET_ALPHA
207
208 // Check if any recent PC changes match up with anything we
209 // expect to happen. This is mostly to check if traps or
210 // PC-based events have occurred in both the checker and CPU.
211 if (changedPC) {
212 DPRINTF(Checker, "Changed PC recently to %s\n",
213 thread->pcState());
214 if (willChangePC) {
215 if (newPCState == thread->pcState()) {
216 DPRINTF(Checker, "Changed PC matches expected PC\n");
217 } else {
218 warn("%lli: Changed PC does not match expected PC, "
219 "changed: %s, expected: %s",
220 curTick(), thread->pcState(), newPCState);
221 CheckerCPU::handleError();
222 }
223 willChangePC = false;
224 }
225 changedPC = false;
226 }
227 if (changedNextPC) {
228 DPRINTF(Checker, "Changed NextPC recently to %#x\n",
229 thread->nextInstAddr());
230 changedNextPC = false;
231 }
232
233 // Try to fetch the instruction
234 uint64_t fetchOffset = 0;
235 bool fetchDone = false;
236
237 while (!fetchDone) {
238 Addr fetch_PC = thread->instAddr();
239 fetch_PC = (fetch_PC & PCMask) + fetchOffset;
240
241 // If not in the middle of a macro instruction
242 if (!curMacroStaticInst) {
243 // set up memory request for instruction fetch
244 memReq = new Request(unverifiedInst->threadNumber, fetch_PC,
245 sizeof(MachInst),
246 0,
1/*
2 * Copyright (c) 2011 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 * Geoffrey Blake
42 */
43
44#include <list>
45#include <string>
46
47#include "arch/vtophys.hh"
48#include "base/refcnt.hh"
49#include "config/the_isa.hh"
50#include "cpu/base_dyn_inst.hh"
51#include "cpu/exetrace.hh"
52#include "cpu/simple_thread.hh"
53#include "cpu/static_inst.hh"
54#include "cpu/thread_context.hh"
55#include "cpu/checker/cpu.hh"
56#include "debug/Checker.hh"
57#include "sim/full_system.hh"
58#include "sim/sim_object.hh"
59#include "sim/stats.hh"
60
61using namespace std;
62using namespace TheISA;
63
64template <class Impl>
65void
66Checker<Impl>::advancePC(Fault fault)
67{
68 if (fault != NoFault) {
69 curMacroStaticInst = StaticInst::nullStaticInstPtr;
70 fault->invoke(tc, curStaticInst);
71 predecoder.reset();
72 } else {
73 if (curStaticInst) {
74 if (curStaticInst->isLastMicroop())
75 curMacroStaticInst = StaticInst::nullStaticInstPtr;
76 TheISA::PCState pcState = thread->pcState();
77 TheISA::advancePC(pcState, curStaticInst);
78 thread->pcState(pcState);
79 DPRINTF(Checker, "Advancing PC to %s.\n", thread->pcState());
80 }
81 }
82}
83//////////////////////////////////////////////////
84
85template <class Impl>
86void
87Checker<Impl>::handlePendingInt()
88{
89 DPRINTF(Checker, "IRQ detected at PC: %s with %d insts in buffer\n",
90 thread->pcState(), instList.size());
91 DynInstPtr boundaryInst = NULL;
92 if (!instList.empty()) {
93 // Set the instructions as completed and verify as much as possible.
94 DynInstPtr inst;
95 typename std::list<DynInstPtr>::iterator itr;
96
97 for (itr = instList.begin(); itr != instList.end(); itr++) {
98 (*itr)->setCompleted();
99 }
100
101 inst = instList.front();
102 boundaryInst = instList.back();
103 verify(inst); // verify the instructions
104 inst = NULL;
105 }
106 if ((!boundaryInst && curMacroStaticInst &&
107 curStaticInst->isDelayedCommit() &&
108 !curStaticInst->isLastMicroop()) ||
109 (boundaryInst && boundaryInst->isDelayedCommit() &&
110 !boundaryInst->isLastMicroop())) {
111 panic("%lli: Trying to take an interrupt in middle of "
112 "a non-interuptable instruction!", curTick());
113 }
114 boundaryInst = NULL;
115 predecoder.reset();
116 curMacroStaticInst = StaticInst::nullStaticInstPtr;
117}
118
119template <class Impl>
120void
121Checker<Impl>::verify(DynInstPtr &completed_inst)
122{
123 DynInstPtr inst;
124
125 // Make sure serializing instructions are actually
126 // seen as serializing to commit. instList should be
127 // empty in these cases.
128 if ((completed_inst->isSerializing() ||
129 completed_inst->isSerializeBefore()) &&
130 (!instList.empty() ?
131 (instList.front()->seqNum != completed_inst->seqNum) : 0)) {
132 panic("%lli: Instruction sn:%lli at PC %s is serializing before but is"
133 " entering instList with other instructions\n", curTick(),
134 completed_inst->seqNum, completed_inst->pcState());
135 }
136
137 // Either check this instruction, or add it to a list of
138 // instructions waiting to be checked. Instructions must be
139 // checked in program order, so if a store has committed yet not
140 // completed, there may be some instructions that are waiting
141 // behind it that have completed and must be checked.
142 if (!instList.empty()) {
143 if (youngestSN < completed_inst->seqNum) {
144 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
145 completed_inst->seqNum, completed_inst->pcState());
146 instList.push_back(completed_inst);
147 youngestSN = completed_inst->seqNum;
148 }
149
150 if (!instList.front()->isCompleted()) {
151 return;
152 } else {
153 inst = instList.front();
154 instList.pop_front();
155 }
156 } else {
157 if (!completed_inst->isCompleted()) {
158 if (youngestSN < completed_inst->seqNum) {
159 DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%s to list\n",
160 completed_inst->seqNum, completed_inst->pcState());
161 instList.push_back(completed_inst);
162 youngestSN = completed_inst->seqNum;
163 }
164 return;
165 } else {
166 if (youngestSN < completed_inst->seqNum) {
167 inst = completed_inst;
168 youngestSN = completed_inst->seqNum;
169 } else {
170 return;
171 }
172 }
173 }
174
175 // Make sure a serializing instruction is actually seen as
176 // serializing. instList should be empty here
177 if (inst->isSerializeAfter() && !instList.empty()) {
178 panic("%lli: Instruction sn:%lli at PC %s is serializing after but is"
179 " exiting instList with other instructions\n", curTick(),
180 completed_inst->seqNum, completed_inst->pcState());
181 }
182 unverifiedInst = inst;
183 inst = NULL;
184
185 // Try to check all instructions that are completed, ending if we
186 // run out of instructions to check or if an instruction is not
187 // yet completed.
188 while (1) {
189 DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%s.\n",
190 unverifiedInst->seqNum, unverifiedInst->pcState());
191 unverifiedReq = NULL;
192 unverifiedReq = unverifiedInst->reqToVerify;
193 unverifiedMemData = unverifiedInst->memData;
194 // Make sure results queue is empty
195 while (!result.empty()) {
196 result.pop();
197 }
198 numCycles++;
199
200 Fault fault = NoFault;
201
202 // maintain $r0 semantics
203 thread->setIntReg(ZeroReg, 0);
204#ifdef TARGET_ALPHA
205 thread->setFloatRegDouble(ZeroReg, 0.0);
206#endif // TARGET_ALPHA
207
208 // Check if any recent PC changes match up with anything we
209 // expect to happen. This is mostly to check if traps or
210 // PC-based events have occurred in both the checker and CPU.
211 if (changedPC) {
212 DPRINTF(Checker, "Changed PC recently to %s\n",
213 thread->pcState());
214 if (willChangePC) {
215 if (newPCState == thread->pcState()) {
216 DPRINTF(Checker, "Changed PC matches expected PC\n");
217 } else {
218 warn("%lli: Changed PC does not match expected PC, "
219 "changed: %s, expected: %s",
220 curTick(), thread->pcState(), newPCState);
221 CheckerCPU::handleError();
222 }
223 willChangePC = false;
224 }
225 changedPC = false;
226 }
227 if (changedNextPC) {
228 DPRINTF(Checker, "Changed NextPC recently to %#x\n",
229 thread->nextInstAddr());
230 changedNextPC = false;
231 }
232
233 // Try to fetch the instruction
234 uint64_t fetchOffset = 0;
235 bool fetchDone = false;
236
237 while (!fetchDone) {
238 Addr fetch_PC = thread->instAddr();
239 fetch_PC = (fetch_PC & PCMask) + fetchOffset;
240
241 // If not in the middle of a macro instruction
242 if (!curMacroStaticInst) {
243 // set up memory request for instruction fetch
244 memReq = new Request(unverifiedInst->threadNumber, fetch_PC,
245 sizeof(MachInst),
246 0,
247 masterId,
247 fetch_PC, thread->contextId(),
248 unverifiedInst->threadNumber);
249 memReq->setVirt(0, fetch_PC, sizeof(MachInst),
250 Request::INST_FETCH, masterId, thread->instAddr());
251
252
253 fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
254
255 if (fault != NoFault) {
256 if (unverifiedInst->getFault() == NoFault) {
257 // In this case the instruction was not a dummy
258 // instruction carrying an ITB fault. In the single
259 // threaded case the ITB should still be able to
260 // translate this instruction; in the SMT case it's
261 // possible that its ITB entry was kicked out.
262 warn("%lli: Instruction PC %s was not found in the "
263 "ITB!", curTick(), thread->pcState());
264 handleError(unverifiedInst);
265
266 // go to the next instruction
267 advancePC(NoFault);
268
269 // Give up on an ITB fault..
270 delete memReq;
271 unverifiedInst = NULL;
272 return;
273 } else {
274 // The instruction is carrying an ITB fault. Handle
275 // the fault and see if our results match the CPU on
276 // the next tick().
277 fault = unverifiedInst->getFault();
278 delete memReq;
279 break;
280 }
281 } else {
282 PacketPtr pkt = new Packet(memReq,
283 MemCmd::ReadReq,
284 Packet::Broadcast);
285
286 pkt->dataStatic(&machInst);
287 icachePort->sendFunctional(pkt);
288 machInst = gtoh(machInst);
289
290 delete memReq;
291 delete pkt;
292 }
293 }
294
295 if (fault == NoFault) {
296 TheISA::PCState pcState = thread->pcState();
297
298 if (isRomMicroPC(pcState.microPC())) {
299 fetchDone = true;
300 curStaticInst =
301 microcodeRom.fetchMicroop(pcState.microPC(), NULL);
302 } else if (!curMacroStaticInst) {
303 //We're not in the middle of a macro instruction
304 StaticInstPtr instPtr = NULL;
305
306 //Predecode, ie bundle up an ExtMachInst
307 predecoder.setTC(thread->getTC());
308 //If more fetch data is needed, pass it in.
309 Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
310 predecoder.moreBytes(pcState, fetchPC, machInst);
311
312 //If an instruction is ready, decode it.
313 //Otherwise, we'll have to fetch beyond the
314 //MachInst at the current pc.
315 if (predecoder.extMachInstReady()) {
316 fetchDone = true;
317 ExtMachInst newMachInst =
318 predecoder.getExtMachInst(pcState);
319 thread->pcState(pcState);
320 instPtr = thread->decoder.decode(newMachInst,
321 pcState.instAddr());
322 machInst = newMachInst;
323 } else {
324 fetchDone = false;
325 fetchOffset += sizeof(TheISA::MachInst);
326 }
327
328 //If we decoded an instruction and it's microcoded,
329 //start pulling out micro ops
330 if (instPtr && instPtr->isMacroop()) {
331 curMacroStaticInst = instPtr;
332 curStaticInst =
333 instPtr->fetchMicroop(pcState.microPC());
334 } else {
335 curStaticInst = instPtr;
336 }
337 } else {
338 // Read the next micro op from the macro-op
339 curStaticInst =
340 curMacroStaticInst->fetchMicroop(pcState.microPC());
341 fetchDone = true;
342 }
343 }
344 }
345 // reset predecoder on Checker
346 predecoder.reset();
347
348 // Check Checker and CPU get same instruction, and record
349 // any faults the CPU may have had.
350 Fault unverifiedFault;
351 if (fault == NoFault) {
352 unverifiedFault = unverifiedInst->getFault();
353
354 // Checks that the instruction matches what we expected it to be.
355 // Checks both the machine instruction and the PC.
356 validateInst(unverifiedInst);
357 }
358
359 // keep an instruction count
360 numInst++;
361
362
363 // Either the instruction was a fault and we should process the fault,
364 // or we should just go ahead execute the instruction. This assumes
365 // that the instruction is properly marked as a fault.
366 if (fault == NoFault) {
367 // Execute Checker instruction and trace
368 if (!unverifiedInst->isUnverifiable()) {
369 Trace::InstRecord *traceData = tracer->getInstRecord(curTick(),
370 tc,
371 curStaticInst,
372 pcState(),
373 curMacroStaticInst);
374 fault = curStaticInst->execute(this, traceData);
375 if (traceData) {
376 traceData->dump();
377 delete traceData;
378 }
379 }
380
381 if (fault == NoFault && unverifiedFault == NoFault) {
382 thread->funcExeInst++;
383 // Checks to make sure instrution results are correct.
384 validateExecution(unverifiedInst);
385
386 if (curStaticInst->isLoad()) {
387 ++numLoad;
388 }
389 } else if (fault != NoFault && unverifiedFault == NoFault) {
390 panic("%lli: sn: %lli at PC: %s took a fault in checker "
391 "but not in driver CPU\n", curTick(),
392 unverifiedInst->seqNum, unverifiedInst->pcState());
393 } else if (fault == NoFault && unverifiedFault != NoFault) {
394 panic("%lli: sn: %lli at PC: %s took a fault in driver "
395 "CPU but not in checker\n", curTick(),
396 unverifiedInst->seqNum, unverifiedInst->pcState());
397 }
398 }
399
400 // Take any faults here
401 if (fault != NoFault) {
248 fetch_PC, thread->contextId(),
249 unverifiedInst->threadNumber);
250 memReq->setVirt(0, fetch_PC, sizeof(MachInst),
251 Request::INST_FETCH, masterId, thread->instAddr());
252
253
254 fault = itb->translateFunctional(memReq, tc, BaseTLB::Execute);
255
256 if (fault != NoFault) {
257 if (unverifiedInst->getFault() == NoFault) {
258 // In this case the instruction was not a dummy
259 // instruction carrying an ITB fault. In the single
260 // threaded case the ITB should still be able to
261 // translate this instruction; in the SMT case it's
262 // possible that its ITB entry was kicked out.
263 warn("%lli: Instruction PC %s was not found in the "
264 "ITB!", curTick(), thread->pcState());
265 handleError(unverifiedInst);
266
267 // go to the next instruction
268 advancePC(NoFault);
269
270 // Give up on an ITB fault..
271 delete memReq;
272 unverifiedInst = NULL;
273 return;
274 } else {
275 // The instruction is carrying an ITB fault. Handle
276 // the fault and see if our results match the CPU on
277 // the next tick().
278 fault = unverifiedInst->getFault();
279 delete memReq;
280 break;
281 }
282 } else {
283 PacketPtr pkt = new Packet(memReq,
284 MemCmd::ReadReq,
285 Packet::Broadcast);
286
287 pkt->dataStatic(&machInst);
288 icachePort->sendFunctional(pkt);
289 machInst = gtoh(machInst);
290
291 delete memReq;
292 delete pkt;
293 }
294 }
295
296 if (fault == NoFault) {
297 TheISA::PCState pcState = thread->pcState();
298
299 if (isRomMicroPC(pcState.microPC())) {
300 fetchDone = true;
301 curStaticInst =
302 microcodeRom.fetchMicroop(pcState.microPC(), NULL);
303 } else if (!curMacroStaticInst) {
304 //We're not in the middle of a macro instruction
305 StaticInstPtr instPtr = NULL;
306
307 //Predecode, ie bundle up an ExtMachInst
308 predecoder.setTC(thread->getTC());
309 //If more fetch data is needed, pass it in.
310 Addr fetchPC = (pcState.instAddr() & PCMask) + fetchOffset;
311 predecoder.moreBytes(pcState, fetchPC, machInst);
312
313 //If an instruction is ready, decode it.
314 //Otherwise, we'll have to fetch beyond the
315 //MachInst at the current pc.
316 if (predecoder.extMachInstReady()) {
317 fetchDone = true;
318 ExtMachInst newMachInst =
319 predecoder.getExtMachInst(pcState);
320 thread->pcState(pcState);
321 instPtr = thread->decoder.decode(newMachInst,
322 pcState.instAddr());
323 machInst = newMachInst;
324 } else {
325 fetchDone = false;
326 fetchOffset += sizeof(TheISA::MachInst);
327 }
328
329 //If we decoded an instruction and it's microcoded,
330 //start pulling out micro ops
331 if (instPtr && instPtr->isMacroop()) {
332 curMacroStaticInst = instPtr;
333 curStaticInst =
334 instPtr->fetchMicroop(pcState.microPC());
335 } else {
336 curStaticInst = instPtr;
337 }
338 } else {
339 // Read the next micro op from the macro-op
340 curStaticInst =
341 curMacroStaticInst->fetchMicroop(pcState.microPC());
342 fetchDone = true;
343 }
344 }
345 }
346 // reset predecoder on Checker
347 predecoder.reset();
348
349 // Check Checker and CPU get same instruction, and record
350 // any faults the CPU may have had.
351 Fault unverifiedFault;
352 if (fault == NoFault) {
353 unverifiedFault = unverifiedInst->getFault();
354
355 // Checks that the instruction matches what we expected it to be.
356 // Checks both the machine instruction and the PC.
357 validateInst(unverifiedInst);
358 }
359
360 // keep an instruction count
361 numInst++;
362
363
364 // Either the instruction was a fault and we should process the fault,
365 // or we should just go ahead execute the instruction. This assumes
366 // that the instruction is properly marked as a fault.
367 if (fault == NoFault) {
368 // Execute Checker instruction and trace
369 if (!unverifiedInst->isUnverifiable()) {
370 Trace::InstRecord *traceData = tracer->getInstRecord(curTick(),
371 tc,
372 curStaticInst,
373 pcState(),
374 curMacroStaticInst);
375 fault = curStaticInst->execute(this, traceData);
376 if (traceData) {
377 traceData->dump();
378 delete traceData;
379 }
380 }
381
382 if (fault == NoFault && unverifiedFault == NoFault) {
383 thread->funcExeInst++;
384 // Checks to make sure instrution results are correct.
385 validateExecution(unverifiedInst);
386
387 if (curStaticInst->isLoad()) {
388 ++numLoad;
389 }
390 } else if (fault != NoFault && unverifiedFault == NoFault) {
391 panic("%lli: sn: %lli at PC: %s took a fault in checker "
392 "but not in driver CPU\n", curTick(),
393 unverifiedInst->seqNum, unverifiedInst->pcState());
394 } else if (fault == NoFault && unverifiedFault != NoFault) {
395 panic("%lli: sn: %lli at PC: %s took a fault in driver "
396 "CPU but not in checker\n", curTick(),
397 unverifiedInst->seqNum, unverifiedInst->pcState());
398 }
399 }
400
401 // Take any faults here
402 if (fault != NoFault) {
402 fault->invoke(tc, curStaticInst);
403 willChangePC = true;
404 newPCState = thread->pcState();
405 DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
406 curMacroStaticInst = StaticInst::nullStaticInstPtr;
403 if (FullSystem) {
404 fault->invoke(tc, curStaticInst);
405 willChangePC = true;
406 newPCState = thread->pcState();
407 DPRINTF(Checker, "Fault, PC is now %s\n", newPCState);
408 curMacroStaticInst = StaticInst::nullStaticInstPtr;
409 }
407 } else {
408 advancePC(fault);
409 }
410
411 if (FullSystem) {
412 // @todo: Determine if these should happen only if the
413 // instruction hasn't faulted. In the SimpleCPU case this may
414 // not be true, but in the O3 or Ozone case this may be true.
415 Addr oldpc;
416 int count = 0;
417 do {
418 oldpc = thread->instAddr();
419 system->pcEventQueue.service(tc);
420 count++;
421 } while (oldpc != thread->instAddr());
422 if (count > 1) {
423 willChangePC = true;
424 newPCState = thread->pcState();
425 DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState);
426 }
427 }
428
429 // @todo: Optionally can check all registers. (Or just those
430 // that have been modified).
431 validateState();
432
433 // Continue verifying instructions if there's another completed
434 // instruction waiting to be verified.
435 if (instList.empty()) {
436 break;
437 } else if (instList.front()->isCompleted()) {
438 unverifiedInst = NULL;
439 unverifiedInst = instList.front();
440 instList.pop_front();
441 } else {
442 break;
443 }
444 }
445 unverifiedInst = NULL;
446}
447
448template <class Impl>
449void
450Checker<Impl>::switchOut()
451{
452 instList.clear();
453}
454
455template <class Impl>
456void
457Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
458{
459}
460
461template <class Impl>
462void
463Checker<Impl>::validateInst(DynInstPtr &inst)
464{
465 if (inst->instAddr() != thread->instAddr()) {
466 warn("%lli: PCs do not match! Inst: %s, checker: %s",
467 curTick(), inst->pcState(), thread->pcState());
468 if (changedPC) {
469 warn("%lli: Changed PCs recently, may not be an error",
470 curTick());
471 } else {
472 handleError(inst);
473 }
474 }
475
476 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
477
478 if (mi != machInst) {
479 panic("%lli: Binary instructions do not match! Inst: %#x, "
480 "checker: %#x",
481 curTick(), mi, machInst);
482 handleError(inst);
483 }
484}
485
486template <class Impl>
487void
488Checker<Impl>::validateExecution(DynInstPtr &inst)
489{
490 uint64_t checker_val;
491 uint64_t inst_val;
492 int idx = -1;
493 bool result_mismatch = false;
494
495 if (inst->isUnverifiable()) {
496 // Unverifiable instructions assume they were executed
497 // properly by the CPU. Grab the result from the
498 // instruction and write it to the register.
499 copyResult(inst, 0, idx);
500 } else if (inst->numDestRegs() > 0 && !result.empty()) {
501 DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
502 inst->numDestRegs(), result.size());
503 for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) {
504 result.front().get(checker_val);
505 result.pop();
506 inst_val = 0;
507 inst->template popResult<uint64_t>(inst_val);
508 if (checker_val != inst_val) {
509 result_mismatch = true;
510 idx = i;
511 break;
512 }
513 }
514 } // Checker CPU checks all the saved results in the dyninst passed by
515 // the cpu model being checked against the saved results present in
516 // the static inst executed in the Checker. Sometimes the number
517 // of saved results differs between the dyninst and static inst, but
518 // this is ok and not a bug. May be worthwhile to try and correct this.
519
520 if (result_mismatch) {
521 warn("%lli: Instruction results do not match! (Values may not "
522 "actually be integers) Inst: %#x, checker: %#x",
523 curTick(), inst_val, checker_val);
524
525 // It's useful to verify load values from memory, but in MP
526 // systems the value obtained at execute may be different than
527 // the value obtained at completion. Similarly DMA can
528 // present the same problem on even UP systems. Thus there is
529 // the option to only warn on loads having a result error.
530 // The load/store queue in Detailed CPU can also cause problems
531 // if load/store forwarding is allowed.
532 if (inst->isLoad() && warnOnlyOnLoadError) {
533 copyResult(inst, inst_val, idx);
534 } else {
535 handleError(inst);
536 }
537 }
538
539 if (inst->nextInstAddr() != thread->nextInstAddr()) {
540 warn("%lli: Instruction next PCs do not match! Inst: %#x, "
541 "checker: %#x",
542 curTick(), inst->nextInstAddr(), thread->nextInstAddr());
543 handleError(inst);
544 }
545
546 // Checking side effect registers can be difficult if they are not
547 // checked simultaneously with the execution of the instruction.
548 // This is because other valid instructions may have modified
549 // these registers in the meantime, and their values are not
550 // stored within the DynInst.
551 while (!miscRegIdxs.empty()) {
552 int misc_reg_idx = miscRegIdxs.front();
553 miscRegIdxs.pop();
554
555 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) !=
556 thread->readMiscRegNoEffect(misc_reg_idx)) {
557 warn("%lli: Misc reg idx %i (side effect) does not match! "
558 "Inst: %#x, checker: %#x",
559 curTick(), misc_reg_idx,
560 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx),
561 thread->readMiscRegNoEffect(misc_reg_idx));
562 handleError(inst);
563 }
564 }
565}
566
567
568// This function is weird, if it is called it means the Checker and
569// O3 have diverged, so panic is called for now. It may be useful
570// to resynch states and continue if the divergence is a false positive
571template <class Impl>
572void
573Checker<Impl>::validateState()
574{
575 if (updateThisCycle) {
576 // Change this back to warn if divergences end up being false positives
577 panic("%lli: Instruction PC %#x results didn't match up, copying all "
578 "registers from main CPU", curTick(), unverifiedInst->instAddr());
579
580 // Terribly convoluted way to make sure O3 model does not implode
581 bool inSyscall = unverifiedInst->thread->inSyscall;
582 unverifiedInst->thread->inSyscall = true;
583
584 // Heavy-weight copying of all registers
585 thread->copyArchRegs(unverifiedInst->tcBase());
586 unverifiedInst->thread->inSyscall = inSyscall;
587
588 // Set curStaticInst to unverifiedInst->staticInst
589 curStaticInst = unverifiedInst->staticInst;
590 // Also advance the PC. Hopefully no PC-based events happened.
591 advancePC(NoFault);
592 updateThisCycle = false;
593 }
594}
595
596template <class Impl>
597void
598Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
599 int start_idx)
600{
601 // We've already popped one dest off the queue,
602 // so do the fix-up then start with the next dest reg;
603 if (start_idx >= 0) {
604 RegIndex idx = inst->destRegIdx(start_idx);
605 if (idx < TheISA::FP_Base_DepTag) {
606 thread->setIntReg(idx, mismatch_val);
607 } else if (idx < TheISA::Ctrl_Base_DepTag) {
608 thread->setFloatRegBits(idx, mismatch_val);
609 } else if (idx < TheISA::Max_DepTag) {
610 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag,
611 mismatch_val);
612 }
613 }
614 start_idx++;
615 uint64_t res = 0;
616 for (int i = start_idx; i < inst->numDestRegs(); i++) {
617 RegIndex idx = inst->destRegIdx(i);
618 inst->template popResult<uint64_t>(res);
619 if (idx < TheISA::FP_Base_DepTag) {
620 thread->setIntReg(idx, res);
621 } else if (idx < TheISA::Ctrl_Base_DepTag) {
622 thread->setFloatRegBits(idx, res);
623 } else if (idx < TheISA::Max_DepTag) {
624 // Try to get the proper misc register index for ARM here...
625 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res);
626 } // else Register is out of range...
627 }
628}
629
630template <class Impl>
631void
632Checker<Impl>::dumpAndExit(DynInstPtr &inst)
633{
634 cprintf("Error detected, instruction information:\n");
635 cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
636 "Completed:%i\n",
637 inst->pcState(),
638 inst->nextInstAddr(),
639 inst->seqNum,
640 inst->threadNumber,
641 inst->isCompleted());
642 inst->dump();
643 CheckerCPU::dumpAndExit();
644}
645
646template <class Impl>
647void
648Checker<Impl>::dumpInsts()
649{
650 int num = 0;
651
652 InstListIt inst_list_it = --(instList.end());
653
654 cprintf("Inst list size: %i\n", instList.size());
655
656 while (inst_list_it != instList.end())
657 {
658 cprintf("Instruction:%i\n",
659 num);
660
661 cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n"
662 "Completed:%i\n",
663 (*inst_list_it)->pcState(),
664 (*inst_list_it)->seqNum,
665 (*inst_list_it)->threadNumber,
666 (*inst_list_it)->isCompleted());
667
668 cprintf("\n");
669
670 inst_list_it--;
671 ++num;
672 }
673
674}
410 } else {
411 advancePC(fault);
412 }
413
414 if (FullSystem) {
415 // @todo: Determine if these should happen only if the
416 // instruction hasn't faulted. In the SimpleCPU case this may
417 // not be true, but in the O3 or Ozone case this may be true.
418 Addr oldpc;
419 int count = 0;
420 do {
421 oldpc = thread->instAddr();
422 system->pcEventQueue.service(tc);
423 count++;
424 } while (oldpc != thread->instAddr());
425 if (count > 1) {
426 willChangePC = true;
427 newPCState = thread->pcState();
428 DPRINTF(Checker, "PC Event, PC is now %s\n", newPCState);
429 }
430 }
431
432 // @todo: Optionally can check all registers. (Or just those
433 // that have been modified).
434 validateState();
435
436 // Continue verifying instructions if there's another completed
437 // instruction waiting to be verified.
438 if (instList.empty()) {
439 break;
440 } else if (instList.front()->isCompleted()) {
441 unverifiedInst = NULL;
442 unverifiedInst = instList.front();
443 instList.pop_front();
444 } else {
445 break;
446 }
447 }
448 unverifiedInst = NULL;
449}
450
451template <class Impl>
452void
453Checker<Impl>::switchOut()
454{
455 instList.clear();
456}
457
458template <class Impl>
459void
460Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
461{
462}
463
464template <class Impl>
465void
466Checker<Impl>::validateInst(DynInstPtr &inst)
467{
468 if (inst->instAddr() != thread->instAddr()) {
469 warn("%lli: PCs do not match! Inst: %s, checker: %s",
470 curTick(), inst->pcState(), thread->pcState());
471 if (changedPC) {
472 warn("%lli: Changed PCs recently, may not be an error",
473 curTick());
474 } else {
475 handleError(inst);
476 }
477 }
478
479 MachInst mi = static_cast<MachInst>(inst->staticInst->machInst);
480
481 if (mi != machInst) {
482 panic("%lli: Binary instructions do not match! Inst: %#x, "
483 "checker: %#x",
484 curTick(), mi, machInst);
485 handleError(inst);
486 }
487}
488
489template <class Impl>
490void
491Checker<Impl>::validateExecution(DynInstPtr &inst)
492{
493 uint64_t checker_val;
494 uint64_t inst_val;
495 int idx = -1;
496 bool result_mismatch = false;
497
498 if (inst->isUnverifiable()) {
499 // Unverifiable instructions assume they were executed
500 // properly by the CPU. Grab the result from the
501 // instruction and write it to the register.
502 copyResult(inst, 0, idx);
503 } else if (inst->numDestRegs() > 0 && !result.empty()) {
504 DPRINTF(Checker, "Dest regs %d, number of checker dest regs %d\n",
505 inst->numDestRegs(), result.size());
506 for (int i = 0; i < inst->numDestRegs() && !result.empty(); i++) {
507 result.front().get(checker_val);
508 result.pop();
509 inst_val = 0;
510 inst->template popResult<uint64_t>(inst_val);
511 if (checker_val != inst_val) {
512 result_mismatch = true;
513 idx = i;
514 break;
515 }
516 }
517 } // Checker CPU checks all the saved results in the dyninst passed by
518 // the cpu model being checked against the saved results present in
519 // the static inst executed in the Checker. Sometimes the number
520 // of saved results differs between the dyninst and static inst, but
521 // this is ok and not a bug. May be worthwhile to try and correct this.
522
523 if (result_mismatch) {
524 warn("%lli: Instruction results do not match! (Values may not "
525 "actually be integers) Inst: %#x, checker: %#x",
526 curTick(), inst_val, checker_val);
527
528 // It's useful to verify load values from memory, but in MP
529 // systems the value obtained at execute may be different than
530 // the value obtained at completion. Similarly DMA can
531 // present the same problem on even UP systems. Thus there is
532 // the option to only warn on loads having a result error.
533 // The load/store queue in Detailed CPU can also cause problems
534 // if load/store forwarding is allowed.
535 if (inst->isLoad() && warnOnlyOnLoadError) {
536 copyResult(inst, inst_val, idx);
537 } else {
538 handleError(inst);
539 }
540 }
541
542 if (inst->nextInstAddr() != thread->nextInstAddr()) {
543 warn("%lli: Instruction next PCs do not match! Inst: %#x, "
544 "checker: %#x",
545 curTick(), inst->nextInstAddr(), thread->nextInstAddr());
546 handleError(inst);
547 }
548
549 // Checking side effect registers can be difficult if they are not
550 // checked simultaneously with the execution of the instruction.
551 // This is because other valid instructions may have modified
552 // these registers in the meantime, and their values are not
553 // stored within the DynInst.
554 while (!miscRegIdxs.empty()) {
555 int misc_reg_idx = miscRegIdxs.front();
556 miscRegIdxs.pop();
557
558 if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) !=
559 thread->readMiscRegNoEffect(misc_reg_idx)) {
560 warn("%lli: Misc reg idx %i (side effect) does not match! "
561 "Inst: %#x, checker: %#x",
562 curTick(), misc_reg_idx,
563 inst->tcBase()->readMiscRegNoEffect(misc_reg_idx),
564 thread->readMiscRegNoEffect(misc_reg_idx));
565 handleError(inst);
566 }
567 }
568}
569
570
571// This function is weird, if it is called it means the Checker and
572// O3 have diverged, so panic is called for now. It may be useful
573// to resynch states and continue if the divergence is a false positive
574template <class Impl>
575void
576Checker<Impl>::validateState()
577{
578 if (updateThisCycle) {
579 // Change this back to warn if divergences end up being false positives
580 panic("%lli: Instruction PC %#x results didn't match up, copying all "
581 "registers from main CPU", curTick(), unverifiedInst->instAddr());
582
583 // Terribly convoluted way to make sure O3 model does not implode
584 bool inSyscall = unverifiedInst->thread->inSyscall;
585 unverifiedInst->thread->inSyscall = true;
586
587 // Heavy-weight copying of all registers
588 thread->copyArchRegs(unverifiedInst->tcBase());
589 unverifiedInst->thread->inSyscall = inSyscall;
590
591 // Set curStaticInst to unverifiedInst->staticInst
592 curStaticInst = unverifiedInst->staticInst;
593 // Also advance the PC. Hopefully no PC-based events happened.
594 advancePC(NoFault);
595 updateThisCycle = false;
596 }
597}
598
599template <class Impl>
600void
601Checker<Impl>::copyResult(DynInstPtr &inst, uint64_t mismatch_val,
602 int start_idx)
603{
604 // We've already popped one dest off the queue,
605 // so do the fix-up then start with the next dest reg;
606 if (start_idx >= 0) {
607 RegIndex idx = inst->destRegIdx(start_idx);
608 if (idx < TheISA::FP_Base_DepTag) {
609 thread->setIntReg(idx, mismatch_val);
610 } else if (idx < TheISA::Ctrl_Base_DepTag) {
611 thread->setFloatRegBits(idx, mismatch_val);
612 } else if (idx < TheISA::Max_DepTag) {
613 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag,
614 mismatch_val);
615 }
616 }
617 start_idx++;
618 uint64_t res = 0;
619 for (int i = start_idx; i < inst->numDestRegs(); i++) {
620 RegIndex idx = inst->destRegIdx(i);
621 inst->template popResult<uint64_t>(res);
622 if (idx < TheISA::FP_Base_DepTag) {
623 thread->setIntReg(idx, res);
624 } else if (idx < TheISA::Ctrl_Base_DepTag) {
625 thread->setFloatRegBits(idx, res);
626 } else if (idx < TheISA::Max_DepTag) {
627 // Try to get the proper misc register index for ARM here...
628 thread->setMiscReg(idx - TheISA::Ctrl_Base_DepTag, res);
629 } // else Register is out of range...
630 }
631}
632
633template <class Impl>
634void
635Checker<Impl>::dumpAndExit(DynInstPtr &inst)
636{
637 cprintf("Error detected, instruction information:\n");
638 cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
639 "Completed:%i\n",
640 inst->pcState(),
641 inst->nextInstAddr(),
642 inst->seqNum,
643 inst->threadNumber,
644 inst->isCompleted());
645 inst->dump();
646 CheckerCPU::dumpAndExit();
647}
648
649template <class Impl>
650void
651Checker<Impl>::dumpInsts()
652{
653 int num = 0;
654
655 InstListIt inst_list_it = --(instList.end());
656
657 cprintf("Inst list size: %i\n", instList.size());
658
659 while (inst_list_it != instList.end())
660 {
661 cprintf("Instruction:%i\n",
662 num);
663
664 cprintf("PC:%s\n[sn:%lli]\n[tid:%i]\n"
665 "Completed:%i\n",
666 (*inst_list_it)->pcState(),
667 (*inst_list_it)->seqNum,
668 (*inst_list_it)->threadNumber,
669 (*inst_list_it)->isCompleted());
670
671 cprintf("\n");
672
673 inst_list_it--;
674 ++num;
675 }
676
677}