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