cpu.hh revision 13429
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    StaticInstPtr curStaticInst;
148    StaticInstPtr curMacroStaticInst;
149
150    // number of simulated instructions
151    Counter numInst;
152    Counter startNumInst;
153
154    std::queue<int> miscRegIdxs;
155
156  public:
157
158    // Primary thread being run.
159    SimpleThread *thread;
160
161    BaseTLB* getITBPtr() { return itb; }
162    BaseTLB* getDTBPtr() { return dtb; }
163
164    virtual Counter totalInsts() const override
165    {
166        return 0;
167    }
168
169    virtual Counter totalOps() const override
170    {
171        return 0;
172    }
173
174    // number of simulated loads
175    Counter numLoad;
176    Counter startNumLoad;
177
178    void serialize(CheckpointOut &cp) const override;
179    void unserialize(CheckpointIn &cp) override;
180
181    // The register accessor methods provide the index of the
182    // instruction's operand (e.g., 0 or 1), not the architectural
183    // register index, to simplify the implementation of register
184    // renaming.  We find the architectural register index by indexing
185    // into the instruction's own operand index table.  Note that a
186    // raw pointer to the StaticInst is provided instead of a
187    // ref-counted StaticInstPtr to redice overhead.  This is fine as
188    // long as these methods don't copy the pointer into any long-term
189    // storage (which is pretty hard to imagine they would have reason
190    // to do).
191
192    IntReg readIntRegOperand(const StaticInst *si, int idx) override
193    {
194        const RegId& reg = si->srcRegIdx(idx);
195        assert(reg.isIntReg());
196        return thread->readIntReg(reg.index());
197    }
198
199    FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
200    {
201        const RegId& reg = si->srcRegIdx(idx);
202        assert(reg.isFloatReg());
203        return thread->readFloatReg(reg.index());
204    }
205
206    FloatRegBits readFloatRegOperandBits(const StaticInst *si,
207                                         int idx) override
208    {
209        const RegId& reg = si->srcRegIdx(idx);
210        assert(reg.isFloatReg());
211        return thread->readFloatRegBits(reg.index());
212    }
213
214    /**
215     * Read source vector register operand.
216     */
217    const VecRegContainer& readVecRegOperand(const StaticInst *si,
218                                             int idx) const override
219    {
220        const RegId& reg = si->srcRegIdx(idx);
221        assert(reg.isVecReg());
222        return thread->readVecReg(reg);
223    }
224
225    /**
226     * Read destination vector register operand for modification.
227     */
228    VecRegContainer& getWritableVecRegOperand(const StaticInst *si,
229                                             int idx) override
230    {
231        const RegId& reg = si->destRegIdx(idx);
232        assert(reg.isVecReg());
233        return thread->getWritableVecReg(reg);
234    }
235
236    /** Vector Register Lane Interfaces. */
237    /** @{ */
238    /** Reads source vector 8bit operand. */
239    virtual ConstVecLane8
240    readVec8BitLaneOperand(const StaticInst *si, int idx) const
241                            override
242    {
243        const RegId& reg = si->destRegIdx(idx);
244        assert(reg.isVecReg());
245        return thread->readVec8BitLaneReg(reg);
246    }
247
248    /** Reads source vector 16bit operand. */
249    virtual ConstVecLane16
250    readVec16BitLaneOperand(const StaticInst *si, int idx) const
251                            override
252    {
253        const RegId& reg = si->destRegIdx(idx);
254        assert(reg.isVecReg());
255        return thread->readVec16BitLaneReg(reg);
256    }
257
258    /** Reads source vector 32bit operand. */
259    virtual ConstVecLane32
260    readVec32BitLaneOperand(const StaticInst *si, int idx) const
261                            override
262    {
263        const RegId& reg = si->destRegIdx(idx);
264        assert(reg.isVecReg());
265        return thread->readVec32BitLaneReg(reg);
266    }
267
268    /** Reads source vector 64bit operand. */
269    virtual ConstVecLane64
270    readVec64BitLaneOperand(const StaticInst *si, int idx) const
271                            override
272    {
273        const RegId& reg = si->destRegIdx(idx);
274        assert(reg.isVecReg());
275        return thread->readVec64BitLaneReg(reg);
276    }
277
278    /** Write a lane of the destination vector operand. */
279    template <typename LD>
280    void
281    setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
282    {
283        const RegId& reg = si->destRegIdx(idx);
284        assert(reg.isVecReg());
285        return thread->setVecLane(reg, val);
286    }
287    virtual void
288    setVecLaneOperand(const StaticInst *si, int idx,
289            const LaneData<LaneSize::Byte>& val) override
290    {
291        setVecLaneOperandT(si, idx, val);
292    }
293    virtual void
294    setVecLaneOperand(const StaticInst *si, int idx,
295            const LaneData<LaneSize::TwoByte>& val) override
296    {
297        setVecLaneOperandT(si, idx, val);
298    }
299    virtual void
300    setVecLaneOperand(const StaticInst *si, int idx,
301            const LaneData<LaneSize::FourByte>& val) override
302    {
303        setVecLaneOperandT(si, idx, val);
304    }
305    virtual void
306    setVecLaneOperand(const StaticInst *si, int idx,
307            const LaneData<LaneSize::EightByte>& val) override
308    {
309        setVecLaneOperandT(si, idx, val);
310    }
311    /** @} */
312
313    VecElem readVecElemOperand(const StaticInst *si, int idx) const override
314    {
315        const RegId& reg = si->srcRegIdx(idx);
316        return thread->readVecElem(reg);
317    }
318
319    CCReg readCCRegOperand(const StaticInst *si, int idx) override
320    {
321        const RegId& reg = si->srcRegIdx(idx);
322        assert(reg.isCCReg());
323        return thread->readCCReg(reg.index());
324    }
325
326    template<typename T>
327    void setScalarResult(T&& t)
328    {
329        result.push(InstResult(std::forward<T>(t),
330                        InstResult::ResultType::Scalar));
331    }
332
333    template<typename T>
334    void setVecResult(T&& t)
335    {
336        result.push(InstResult(std::forward<T>(t),
337                        InstResult::ResultType::VecReg));
338    }
339
340    template<typename T>
341    void setVecElemResult(T&& t)
342    {
343        result.push(InstResult(std::forward<T>(t),
344                        InstResult::ResultType::VecElem));
345    }
346
347    void setIntRegOperand(const StaticInst *si, int idx,
348                          IntReg val) override
349    {
350        const RegId& reg = si->destRegIdx(idx);
351        assert(reg.isIntReg());
352        thread->setIntReg(reg.index(), val);
353        setScalarResult(val);
354    }
355
356    void setFloatRegOperand(const StaticInst *si, int idx,
357                            FloatReg val) override
358    {
359        const RegId& reg = si->destRegIdx(idx);
360        assert(reg.isFloatReg());
361        thread->setFloatReg(reg.index(), val);
362        setScalarResult(val);
363    }
364
365    void setFloatRegOperandBits(const StaticInst *si, int idx,
366                                FloatRegBits val) override
367    {
368        const RegId& reg = si->destRegIdx(idx);
369        assert(reg.isFloatReg());
370        thread->setFloatRegBits(reg.index(), val);
371        setScalarResult(val);
372    }
373
374    void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
375    {
376        const RegId& reg = si->destRegIdx(idx);
377        assert(reg.isCCReg());
378        thread->setCCReg(reg.index(), val);
379        setScalarResult((uint64_t)val);
380    }
381
382    void setVecRegOperand(const StaticInst *si, int idx,
383                                const VecRegContainer& val) override
384    {
385        const RegId& reg = si->destRegIdx(idx);
386        assert(reg.isVecReg());
387        thread->setVecReg(reg, val);
388        setVecResult(val);
389    }
390
391    void setVecElemOperand(const StaticInst *si, int idx,
392                           const VecElem val) override
393    {
394        const RegId& reg = si->destRegIdx(idx);
395        assert(reg.isVecElem());
396        thread->setVecElem(reg, val);
397        setVecElemResult(val);
398    }
399
400    bool readPredicate() const override { return thread->readPredicate(); }
401
402    void setPredicate(bool val) override
403    {
404        thread->setPredicate(val);
405    }
406
407    TheISA::PCState pcState() const override { return thread->pcState(); }
408    void pcState(const TheISA::PCState &val) override
409    {
410        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
411                         val, thread->pcState());
412        thread->pcState(val);
413    }
414    Addr instAddr() { return thread->instAddr(); }
415    Addr nextInstAddr() { return thread->nextInstAddr(); }
416    MicroPC microPC() { return thread->microPC(); }
417    //////////////////////////////////////////
418
419    MiscReg readMiscRegNoEffect(int misc_reg) const
420    {
421        return thread->readMiscRegNoEffect(misc_reg);
422    }
423
424    MiscReg readMiscReg(int misc_reg) override
425    {
426        return thread->readMiscReg(misc_reg);
427    }
428
429    void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
430    {
431        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
432        miscRegIdxs.push(misc_reg);
433        return thread->setMiscRegNoEffect(misc_reg, val);
434    }
435
436    void setMiscReg(int misc_reg, const MiscReg &val) override
437    {
438        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
439        miscRegIdxs.push(misc_reg);
440        return thread->setMiscReg(misc_reg, val);
441    }
442
443    MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
444    {
445        const RegId& reg = si->srcRegIdx(idx);
446        assert(reg.isMiscReg());
447        return thread->readMiscReg(reg.index());
448    }
449
450    void setMiscRegOperand(const StaticInst *si, int idx,
451                           const MiscReg &val) override
452    {
453        const RegId& reg = si->destRegIdx(idx);
454        assert(reg.isMiscReg());
455        return this->setMiscReg(reg.index(), val);
456    }
457
458#if THE_ISA == MIPS_ISA
459    MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
460    {
461        panic("MIPS MT not defined for CheckerCPU.\n");
462        return 0;
463    }
464
465    void setRegOtherThread(const RegId& misc_reg, MiscReg val,
466                               ThreadID tid) override
467    {
468        panic("MIPS MT not defined for CheckerCPU.\n");
469    }
470#endif
471
472    /////////////////////////////////////////
473
474    void recordPCChange(const TheISA::PCState &val)
475    {
476       changedPC = true;
477       newPCState = val;
478    }
479
480    void demapPage(Addr vaddr, uint64_t asn) override
481    {
482        this->itb->demapPage(vaddr, asn);
483        this->dtb->demapPage(vaddr, asn);
484    }
485
486    // monitor/mwait funtions
487    void armMonitor(Addr address) override
488    { BaseCPU::armMonitor(0, address); }
489    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
490    void mwaitAtomic(ThreadContext *tc) override
491    { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
492    AddressMonitor *getAddrMonitor() override
493    { return BaseCPU::getCpuAddrMonitor(0); }
494
495    void demapInstPage(Addr vaddr, uint64_t asn)
496    {
497        this->itb->demapPage(vaddr, asn);
498    }
499
500    void demapDataPage(Addr vaddr, uint64_t asn)
501    {
502        this->dtb->demapPage(vaddr, asn);
503    }
504
505    Fault readMem(Addr addr, uint8_t *data, unsigned size,
506                  Request::Flags flags) override;
507    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
508                   Request::Flags flags, uint64_t *res) override;
509
510    unsigned int readStCondFailures() const override {
511        return thread->readStCondFailures();
512    }
513
514    void setStCondFailures(unsigned int sc_failures) override
515    {}
516    /////////////////////////////////////////////////////
517
518    Fault hwrei() override { return thread->hwrei(); }
519    bool simPalCheck(int palFunc) override
520    { return thread->simPalCheck(palFunc); }
521    void wakeup(ThreadID tid) override { }
522    // Assume that the normal CPU's call to syscall was successful.
523    // The checker's state would have already been updated by the syscall.
524    void syscall(int64_t callnum, Fault *fault) override { }
525
526    void handleError()
527    {
528        if (exitOnError)
529            dumpAndExit();
530    }
531
532    bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
533                    Addr pAddr, int flags);
534
535    void dumpAndExit();
536
537    ThreadContext *tcBase() override { return tc; }
538    SimpleThread *threadBase() { return thread; }
539
540    InstResult unverifiedResult;
541    RequestPtr unverifiedReq;
542    uint8_t *unverifiedMemData;
543
544    bool changedPC;
545    bool willChangePC;
546    TheISA::PCState newPCState;
547    bool exitOnError;
548    bool updateOnError;
549    bool warnOnlyOnLoadError;
550
551    InstSeqNum youngestSN;
552};
553
554/**
555 * Templated Checker class.  This Checker class is templated on the
556 * DynInstPtr of the instruction type that will be verified.  Proper
557 * template instantiations of the Checker must be placed at the bottom
558 * of checker/cpu.cc.
559 */
560template <class Impl>
561class Checker : public CheckerCPU
562{
563  private:
564    typedef typename Impl::DynInstPtr DynInstPtr;
565
566  public:
567    Checker(Params *p)
568        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
569    { }
570
571    void switchOut();
572    void takeOverFrom(BaseCPU *oldCPU);
573
574    void advancePC(const Fault &fault);
575
576    void verify(const DynInstPtr &inst);
577
578    void validateInst(const DynInstPtr &inst);
579    void validateExecution(const DynInstPtr &inst);
580    void validateState();
581
582    void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
583                    int start_idx);
584    void handlePendingInt();
585
586  private:
587    void handleError(const DynInstPtr &inst)
588    {
589        if (exitOnError) {
590            dumpAndExit(inst);
591        } else if (updateOnError) {
592            updateThisCycle = true;
593        }
594    }
595
596    void dumpAndExit(const DynInstPtr &inst);
597
598    bool updateThisCycle;
599
600    DynInstPtr unverifiedInst;
601
602    std::list<DynInstPtr> instList;
603    typedef typename std::list<DynInstPtr>::iterator InstListIt;
604    void dumpInsts();
605};
606
607#endif // __CPU_CHECKER_CPU_HH__
608