cpu.hh revision 12749
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() override { return thread->readPredicate(); }
401    void setPredicate(bool val) override
402    {
403        thread->setPredicate(val);
404    }
405
406    TheISA::PCState pcState() const override { return thread->pcState(); }
407    void pcState(const TheISA::PCState &val) override
408    {
409        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
410                         val, thread->pcState());
411        thread->pcState(val);
412    }
413    Addr instAddr() { return thread->instAddr(); }
414    Addr nextInstAddr() { return thread->nextInstAddr(); }
415    MicroPC microPC() { return thread->microPC(); }
416    //////////////////////////////////////////
417
418    MiscReg readMiscRegNoEffect(int misc_reg) const
419    {
420        return thread->readMiscRegNoEffect(misc_reg);
421    }
422
423    MiscReg readMiscReg(int misc_reg) override
424    {
425        return thread->readMiscReg(misc_reg);
426    }
427
428    void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
429    {
430        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
431        miscRegIdxs.push(misc_reg);
432        return thread->setMiscRegNoEffect(misc_reg, val);
433    }
434
435    void setMiscReg(int misc_reg, const MiscReg &val) override
436    {
437        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
438        miscRegIdxs.push(misc_reg);
439        return thread->setMiscReg(misc_reg, val);
440    }
441
442    MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
443    {
444        const RegId& reg = si->srcRegIdx(idx);
445        assert(reg.isMiscReg());
446        return thread->readMiscReg(reg.index());
447    }
448
449    void setMiscRegOperand(const StaticInst *si, int idx,
450                           const MiscReg &val) override
451    {
452        const RegId& reg = si->destRegIdx(idx);
453        assert(reg.isMiscReg());
454        return this->setMiscReg(reg.index(), val);
455    }
456
457#if THE_ISA == MIPS_ISA
458    MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
459    {
460        panic("MIPS MT not defined for CheckerCPU.\n");
461        return 0;
462    }
463
464    void setRegOtherThread(const RegId& misc_reg, MiscReg val,
465                               ThreadID tid) override
466    {
467        panic("MIPS MT not defined for CheckerCPU.\n");
468    }
469#endif
470
471    /////////////////////////////////////////
472
473    void recordPCChange(const TheISA::PCState &val)
474    {
475       changedPC = true;
476       newPCState = val;
477    }
478
479    void demapPage(Addr vaddr, uint64_t asn) override
480    {
481        this->itb->demapPage(vaddr, asn);
482        this->dtb->demapPage(vaddr, asn);
483    }
484
485    // monitor/mwait funtions
486    void armMonitor(Addr address) override
487    { BaseCPU::armMonitor(0, address); }
488    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
489    void mwaitAtomic(ThreadContext *tc) override
490    { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
491    AddressMonitor *getAddrMonitor() override
492    { return BaseCPU::getCpuAddrMonitor(0); }
493
494    void demapInstPage(Addr vaddr, uint64_t asn)
495    {
496        this->itb->demapPage(vaddr, asn);
497    }
498
499    void demapDataPage(Addr vaddr, uint64_t asn)
500    {
501        this->dtb->demapPage(vaddr, asn);
502    }
503
504    Fault readMem(Addr addr, uint8_t *data, unsigned size,
505                  Request::Flags flags) override;
506    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
507                   Request::Flags flags, uint64_t *res) override;
508
509    unsigned int readStCondFailures() const override {
510        return thread->readStCondFailures();
511    }
512
513    void setStCondFailures(unsigned int sc_failures) override
514    {}
515    /////////////////////////////////////////////////////
516
517    Fault hwrei() override { return thread->hwrei(); }
518    bool simPalCheck(int palFunc) override
519    { return thread->simPalCheck(palFunc); }
520    void wakeup(ThreadID tid) override { }
521    // Assume that the normal CPU's call to syscall was successful.
522    // The checker's state would have already been updated by the syscall.
523    void syscall(int64_t callnum, Fault *fault) override { }
524
525    void handleError()
526    {
527        if (exitOnError)
528            dumpAndExit();
529    }
530
531    bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
532                    Addr pAddr, int flags);
533
534    void dumpAndExit();
535
536    ThreadContext *tcBase() override { return tc; }
537    SimpleThread *threadBase() { return thread; }
538
539    InstResult unverifiedResult;
540    RequestPtr unverifiedReq;
541    uint8_t *unverifiedMemData;
542
543    bool changedPC;
544    bool willChangePC;
545    TheISA::PCState newPCState;
546    bool exitOnError;
547    bool updateOnError;
548    bool warnOnlyOnLoadError;
549
550    InstSeqNum youngestSN;
551};
552
553/**
554 * Templated Checker class.  This Checker class is templated on the
555 * DynInstPtr of the instruction type that will be verified.  Proper
556 * template instantiations of the Checker must be placed at the bottom
557 * of checker/cpu.cc.
558 */
559template <class Impl>
560class Checker : public CheckerCPU
561{
562  private:
563    typedef typename Impl::DynInstPtr DynInstPtr;
564
565  public:
566    Checker(Params *p)
567        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
568    { }
569
570    void switchOut();
571    void takeOverFrom(BaseCPU *oldCPU);
572
573    void advancePC(const Fault &fault);
574
575    void verify(DynInstPtr &inst);
576
577    void validateInst(DynInstPtr &inst);
578    void validateExecution(DynInstPtr &inst);
579    void validateState();
580
581    void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
582                    int start_idx);
583    void handlePendingInt();
584
585  private:
586    void handleError(DynInstPtr &inst)
587    {
588        if (exitOnError) {
589            dumpAndExit(inst);
590        } else if (updateOnError) {
591            updateThisCycle = true;
592        }
593    }
594
595    void dumpAndExit(DynInstPtr &inst);
596
597    bool updateThisCycle;
598
599    DynInstPtr unverifiedInst;
600
601    std::list<DynInstPtr> instList;
602    typedef typename std::list<DynInstPtr>::iterator InstListIt;
603    void dumpInsts();
604};
605
606#endif // __CPU_CHECKER_CPU_HH__
607