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