Deleted Added
sdiff udiff text old ( 12748:ae5ce8e42de7 ) new ( 12749:223c83ed9979 )
full compact
1/*
2 * Copyright (c) 2011, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_CHECKER_CPU_HH__
45#define __CPU_CHECKER_CPU_HH__
46
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/types.hh"
52#include "base/statistics.hh"
53#include "cpu/base.hh"
54#include "cpu/base_dyn_inst.hh"
55#include "cpu/exec_context.hh"
56#include "cpu/inst_res.hh"
57#include "cpu/pc_event.hh"
58#include "cpu/simple_thread.hh"
59#include "cpu/static_inst.hh"
60#include "debug/Checker.hh"
61#include "mem/request.hh"
62#include "params/CheckerCPU.hh"
63#include "sim/eventq.hh"
64
65class BaseTLB;
66template <class>
67class BaseDynInst;
68class ThreadContext;
69class Request;
70
71/**
72 * CheckerCPU class. Dynamically verifies instructions as they are
73 * completed by making sure that the instruction and its results match
74 * the independent execution of the benchmark inside the checker. The
75 * checker verifies instructions in order, regardless of the order in
76 * which instructions complete. There are certain results that can
77 * not be verified, specifically the result of a store conditional or
78 * the values of uncached accesses. In these cases, and with
79 * instructions marked as "IsUnverifiable", the checker assumes that
80 * the value from the main CPU's execution is correct and simply
81 * copies that value. It provides a CheckerThreadContext (see
82 * checker/thread_context.hh) that provides hooks for updating the
83 * Checker's state through any ThreadContext accesses. This allows the
84 * checker to be able to correctly verify instructions, even with
85 * external accesses to the ThreadContext that change state.
86 */
87class CheckerCPU : public BaseCPU, public ExecContext
88{
89 protected:
90 typedef TheISA::MachInst MachInst;
91 typedef TheISA::FloatReg FloatReg;
92 typedef TheISA::FloatRegBits FloatRegBits;
93 typedef TheISA::MiscReg MiscReg;
94 using VecRegContainer = TheISA::VecRegContainer;
95
96 /** id attached to all issued requests */
97 MasterID masterId;
98 public:
99 void init() override;
100
101 typedef CheckerCPUParams Params;
102 CheckerCPU(Params *p);
103 virtual ~CheckerCPU();
104
105 void setSystem(System *system);
106
107 void setIcachePort(MasterPort *icache_port);
108
109 void setDcachePort(MasterPort *dcache_port);
110
111 MasterPort &getDataPort() override
112 {
113 // the checker does not have ports on its own so return the
114 // data port of the actual CPU core
115 assert(dcachePort);
116 return *dcachePort;
117 }
118
119 MasterPort &getInstPort() override
120 {
121 // the checker does not have ports on its own so return the
122 // data port of the actual CPU core
123 assert(icachePort);
124 return *icachePort;
125 }
126
127 protected:
128
129 std::vector<Process*> workload;
130
131 System *systemPtr;
132
133 MasterPort *icachePort;
134 MasterPort *dcachePort;
135
136 ThreadContext *tc;
137
138 BaseTLB *itb;
139 BaseTLB *dtb;
140
141 Addr dbg_vtophys(Addr addr);
142
143 // ISAs like ARM can have multiple destination registers to check,
144 // keep them all in a std::queue
145 std::queue<InstResult> result;
146
147 // Pointer to the one memory request.
148 RequestPtr memReq;
149
150 StaticInstPtr curStaticInst;
151 StaticInstPtr curMacroStaticInst;
152
153 // number of simulated instructions
154 Counter numInst;
155 Counter startNumInst;
156
157 std::queue<int> miscRegIdxs;
158
159 public:
160
161 // Primary thread being run.
162 SimpleThread *thread;
163
164 BaseTLB* getITBPtr() { return itb; }
165 BaseTLB* getDTBPtr() { return dtb; }
166
167 virtual Counter totalInsts() const override
168 {
169 return 0;
170 }
171
172 virtual Counter totalOps() const override
173 {
174 return 0;
175 }
176
177 // number of simulated loads
178 Counter numLoad;
179 Counter startNumLoad;
180
181 void serialize(CheckpointOut &cp) const override;
182 void unserialize(CheckpointIn &cp) override;
183
184 // The register accessor methods provide the index of the
185 // instruction's operand (e.g., 0 or 1), not the architectural
186 // register index, to simplify the implementation of register
187 // renaming. We find the architectural register index by indexing
188 // into the instruction's own operand index table. Note that a
189 // raw pointer to the StaticInst is provided instead of a
190 // ref-counted StaticInstPtr to redice overhead. This is fine as
191 // long as these methods don't copy the pointer into any long-term
192 // storage (which is pretty hard to imagine they would have reason
193 // to do).
194
195 IntReg readIntRegOperand(const StaticInst *si, int idx) override
196 {
197 const RegId& reg = si->srcRegIdx(idx);
198 assert(reg.isIntReg());
199 return thread->readIntReg(reg.index());
200 }
201
202 FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
203 {
204 const RegId& reg = si->srcRegIdx(idx);
205 assert(reg.isFloatReg());
206 return thread->readFloatReg(reg.index());
207 }
208
209 FloatRegBits readFloatRegOperandBits(const StaticInst *si,
210 int idx) override
211 {
212 const RegId& reg = si->srcRegIdx(idx);
213 assert(reg.isFloatReg());
214 return thread->readFloatRegBits(reg.index());
215 }
216
217 /**
218 * Read source vector register operand.
219 */
220 const VecRegContainer& readVecRegOperand(const StaticInst *si,
221 int idx) const override
222 {
223 const RegId& reg = si->srcRegIdx(idx);
224 assert(reg.isVecReg());
225 return thread->readVecReg(reg);
226 }
227
228 /**
229 * Read destination vector register operand for modification.
230 */
231 VecRegContainer& getWritableVecRegOperand(const StaticInst *si,
232 int idx) override
233 {
234 const RegId& reg = si->destRegIdx(idx);
235 assert(reg.isVecReg());
236 return thread->getWritableVecReg(reg);
237 }
238
239 /** Vector Register Lane Interfaces. */
240 /** @{ */
241 /** Reads source vector 8bit operand. */
242 virtual ConstVecLane8
243 readVec8BitLaneOperand(const StaticInst *si, int idx) const
244 override
245 {
246 const RegId& reg = si->destRegIdx(idx);
247 assert(reg.isVecReg());
248 return thread->readVec8BitLaneReg(reg);
249 }
250
251 /** Reads source vector 16bit operand. */
252 virtual ConstVecLane16
253 readVec16BitLaneOperand(const StaticInst *si, int idx) const
254 override
255 {
256 const RegId& reg = si->destRegIdx(idx);
257 assert(reg.isVecReg());
258 return thread->readVec16BitLaneReg(reg);
259 }
260
261 /** Reads source vector 32bit operand. */
262 virtual ConstVecLane32
263 readVec32BitLaneOperand(const StaticInst *si, int idx) const
264 override
265 {
266 const RegId& reg = si->destRegIdx(idx);
267 assert(reg.isVecReg());
268 return thread->readVec32BitLaneReg(reg);
269 }
270
271 /** Reads source vector 64bit operand. */
272 virtual ConstVecLane64
273 readVec64BitLaneOperand(const StaticInst *si, int idx) const
274 override
275 {
276 const RegId& reg = si->destRegIdx(idx);
277 assert(reg.isVecReg());
278 return thread->readVec64BitLaneReg(reg);
279 }
280
281 /** Write a lane of the destination vector operand. */
282 template <typename LD>
283 void
284 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
285 {
286 const RegId& reg = si->destRegIdx(idx);
287 assert(reg.isVecReg());
288 return thread->setVecLane(reg, val);
289 }
290 virtual void
291 setVecLaneOperand(const StaticInst *si, int idx,
292 const LaneData<LaneSize::Byte>& val) override
293 {
294 setVecLaneOperandT(si, idx, val);
295 }
296 virtual void
297 setVecLaneOperand(const StaticInst *si, int idx,
298 const LaneData<LaneSize::TwoByte>& val) override
299 {
300 setVecLaneOperandT(si, idx, val);
301 }
302 virtual void
303 setVecLaneOperand(const StaticInst *si, int idx,
304 const LaneData<LaneSize::FourByte>& val) override
305 {
306 setVecLaneOperandT(si, idx, val);
307 }
308 virtual void
309 setVecLaneOperand(const StaticInst *si, int idx,
310 const LaneData<LaneSize::EightByte>& val) override
311 {
312 setVecLaneOperandT(si, idx, val);
313 }
314 /** @} */
315
316 VecElem readVecElemOperand(const StaticInst *si, int idx) const override
317 {
318 const RegId& reg = si->srcRegIdx(idx);
319 return thread->readVecElem(reg);
320 }
321
322 CCReg readCCRegOperand(const StaticInst *si, int idx) override
323 {
324 const RegId& reg = si->srcRegIdx(idx);
325 assert(reg.isCCReg());
326 return thread->readCCReg(reg.index());
327 }
328
329 template<typename T>
330 void setScalarResult(T&& t)
331 {
332 result.push(InstResult(std::forward<T>(t),
333 InstResult::ResultType::Scalar));
334 }
335
336 template<typename T>
337 void setVecResult(T&& t)
338 {
339 result.push(InstResult(std::forward<T>(t),
340 InstResult::ResultType::VecReg));
341 }
342
343 template<typename T>
344 void setVecElemResult(T&& t)
345 {
346 result.push(InstResult(std::forward<T>(t),
347 InstResult::ResultType::VecElem));
348 }
349
350 void setIntRegOperand(const StaticInst *si, int idx,
351 IntReg val) override
352 {
353 const RegId& reg = si->destRegIdx(idx);
354 assert(reg.isIntReg());
355 thread->setIntReg(reg.index(), val);
356 setScalarResult(val);
357 }
358
359 void setFloatRegOperand(const StaticInst *si, int idx,
360 FloatReg val) override
361 {
362 const RegId& reg = si->destRegIdx(idx);
363 assert(reg.isFloatReg());
364 thread->setFloatReg(reg.index(), val);
365 setScalarResult(val);
366 }
367
368 void setFloatRegOperandBits(const StaticInst *si, int idx,
369 FloatRegBits val) override
370 {
371 const RegId& reg = si->destRegIdx(idx);
372 assert(reg.isFloatReg());
373 thread->setFloatRegBits(reg.index(), val);
374 setScalarResult(val);
375 }
376
377 void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
378 {
379 const RegId& reg = si->destRegIdx(idx);
380 assert(reg.isCCReg());
381 thread->setCCReg(reg.index(), val);
382 setScalarResult((uint64_t)val);
383 }
384
385 void setVecRegOperand(const StaticInst *si, int idx,
386 const VecRegContainer& val) override
387 {
388 const RegId& reg = si->destRegIdx(idx);
389 assert(reg.isVecReg());
390 thread->setVecReg(reg, val);
391 setVecResult(val);
392 }
393
394 void setVecElemOperand(const StaticInst *si, int idx,
395 const VecElem val) override
396 {
397 const RegId& reg = si->destRegIdx(idx);
398 assert(reg.isVecElem());
399 thread->setVecElem(reg, val);
400 setVecElemResult(val);
401 }
402
403 bool readPredicate() override { return thread->readPredicate(); }
404 void setPredicate(bool val) override
405 {
406 thread->setPredicate(val);
407 }
408
409 TheISA::PCState pcState() const override { return thread->pcState(); }
410 void pcState(const TheISA::PCState &val) override
411 {
412 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
413 val, thread->pcState());
414 thread->pcState(val);
415 }
416 Addr instAddr() { return thread->instAddr(); }
417 Addr nextInstAddr() { return thread->nextInstAddr(); }
418 MicroPC microPC() { return thread->microPC(); }
419 //////////////////////////////////////////
420
421 MiscReg readMiscRegNoEffect(int misc_reg) const
422 {
423 return thread->readMiscRegNoEffect(misc_reg);
424 }
425
426 MiscReg readMiscReg(int misc_reg) override
427 {
428 return thread->readMiscReg(misc_reg);
429 }
430
431 void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
432 {
433 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
434 miscRegIdxs.push(misc_reg);
435 return thread->setMiscRegNoEffect(misc_reg, val);
436 }
437
438 void setMiscReg(int misc_reg, const MiscReg &val) override
439 {
440 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
441 miscRegIdxs.push(misc_reg);
442 return thread->setMiscReg(misc_reg, val);
443 }
444
445 MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
446 {
447 const RegId& reg = si->srcRegIdx(idx);
448 assert(reg.isMiscReg());
449 return thread->readMiscReg(reg.index());
450 }
451
452 void setMiscRegOperand(const StaticInst *si, int idx,
453 const MiscReg &val) override
454 {
455 const RegId& reg = si->destRegIdx(idx);
456 assert(reg.isMiscReg());
457 return this->setMiscReg(reg.index(), val);
458 }
459
460#if THE_ISA == MIPS_ISA
461 MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
462 {
463 panic("MIPS MT not defined for CheckerCPU.\n");
464 return 0;
465 }
466
467 void setRegOtherThread(const RegId& misc_reg, MiscReg val,
468 ThreadID tid) override
469 {
470 panic("MIPS MT not defined for CheckerCPU.\n");
471 }
472#endif
473
474 /////////////////////////////////////////
475
476 void recordPCChange(const TheISA::PCState &val)
477 {
478 changedPC = true;
479 newPCState = val;
480 }
481
482 void demapPage(Addr vaddr, uint64_t asn) override
483 {
484 this->itb->demapPage(vaddr, asn);
485 this->dtb->demapPage(vaddr, asn);
486 }
487
488 // monitor/mwait funtions
489 void armMonitor(Addr address) override
490 { BaseCPU::armMonitor(0, address); }
491 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
492 void mwaitAtomic(ThreadContext *tc) override
493 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
494 AddressMonitor *getAddrMonitor() override
495 { return BaseCPU::getCpuAddrMonitor(0); }
496
497 void demapInstPage(Addr vaddr, uint64_t asn)
498 {
499 this->itb->demapPage(vaddr, asn);
500 }
501
502 void demapDataPage(Addr vaddr, uint64_t asn)
503 {
504 this->dtb->demapPage(vaddr, asn);
505 }
506
507 Fault readMem(Addr addr, uint8_t *data, unsigned size,
508 Request::Flags flags) override;
509 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
510 Request::Flags flags, uint64_t *res) override;
511
512 unsigned int readStCondFailures() const override {
513 return thread->readStCondFailures();
514 }
515
516 void setStCondFailures(unsigned int sc_failures) override
517 {}
518 /////////////////////////////////////////////////////
519
520 Fault hwrei() override { return thread->hwrei(); }
521 bool simPalCheck(int palFunc) override
522 { return thread->simPalCheck(palFunc); }
523 void wakeup(ThreadID tid) override { }
524 // Assume that the normal CPU's call to syscall was successful.
525 // The checker's state would have already been updated by the syscall.
526 void syscall(int64_t callnum, Fault *fault) override { }
527
528 void handleError()
529 {
530 if (exitOnError)
531 dumpAndExit();
532 }
533
534 bool checkFlags(RequestPtr unverified_req, Addr vAddr,
535 Addr pAddr, int flags);
536
537 void dumpAndExit();
538
539 ThreadContext *tcBase() override { return tc; }
540 SimpleThread *threadBase() { return thread; }
541
542 InstResult unverifiedResult;
543 RequestPtr unverifiedReq;
544 uint8_t *unverifiedMemData;
545
546 bool changedPC;
547 bool willChangePC;
548 TheISA::PCState newPCState;
549 bool exitOnError;
550 bool updateOnError;
551 bool warnOnlyOnLoadError;
552
553 InstSeqNum youngestSN;
554};
555
556/**
557 * Templated Checker class. This Checker class is templated on the
558 * DynInstPtr of the instruction type that will be verified. Proper
559 * template instantiations of the Checker must be placed at the bottom
560 * of checker/cpu.cc.
561 */
562template <class Impl>
563class Checker : public CheckerCPU
564{
565 private:
566 typedef typename Impl::DynInstPtr DynInstPtr;
567
568 public:
569 Checker(Params *p)
570 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
571 { }
572
573 void switchOut();
574 void takeOverFrom(BaseCPU *oldCPU);
575
576 void advancePC(const Fault &fault);
577
578 void verify(DynInstPtr &inst);
579
580 void validateInst(DynInstPtr &inst);
581 void validateExecution(DynInstPtr &inst);
582 void validateState();
583
584 void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
585 int start_idx);
586 void handlePendingInt();
587
588 private:
589 void handleError(DynInstPtr &inst)
590 {
591 if (exitOnError) {
592 dumpAndExit(inst);
593 } else if (updateOnError) {
594 updateThisCycle = true;
595 }
596 }
597
598 void dumpAndExit(DynInstPtr &inst);
599
600 bool updateThisCycle;
601
602 DynInstPtr unverifiedInst;
603
604 std::list<DynInstPtr> instList;
605 typedef typename std::list<DynInstPtr>::iterator InstListIt;
606 void dumpInsts();
607};
608
609#endif // __CPU_CHECKER_CPU_HH__