cpu.hh revision 12107
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
65// forward declarations
66namespace TheISA
67{
68    class TLB;
69}
70
71template <class>
72class BaseDynInst;
73class ThreadContext;
74class Request;
75
76/**
77 * CheckerCPU class.  Dynamically verifies instructions as they are
78 * completed by making sure that the instruction and its results match
79 * the independent execution of the benchmark inside the checker.  The
80 * checker verifies instructions in order, regardless of the order in
81 * which instructions complete.  There are certain results that can
82 * not be verified, specifically the result of a store conditional or
83 * the values of uncached accesses.  In these cases, and with
84 * instructions marked as "IsUnverifiable", the checker assumes that
85 * the value from the main CPU's execution is correct and simply
86 * copies that value.  It provides a CheckerThreadContext (see
87 * checker/thread_context.hh) that provides hooks for updating the
88 * Checker's state through any ThreadContext accesses.  This allows the
89 * checker to be able to correctly verify instructions, even with
90 * external accesses to the ThreadContext that change state.
91 */
92class CheckerCPU : public BaseCPU, public ExecContext
93{
94  protected:
95    typedef TheISA::MachInst MachInst;
96    typedef TheISA::FloatReg FloatReg;
97    typedef TheISA::FloatRegBits FloatRegBits;
98    typedef TheISA::MiscReg MiscReg;
99
100    /** id attached to all issued requests */
101    MasterID masterId;
102  public:
103    void init() override;
104
105    typedef CheckerCPUParams Params;
106    CheckerCPU(Params *p);
107    virtual ~CheckerCPU();
108
109    void setSystem(System *system);
110
111    void setIcachePort(MasterPort *icache_port);
112
113    void setDcachePort(MasterPort *dcache_port);
114
115    MasterPort &getDataPort() override
116    {
117        // the checker does not have ports on its own so return the
118        // data port of the actual CPU core
119        assert(dcachePort);
120        return *dcachePort;
121    }
122
123    MasterPort &getInstPort() override
124    {
125        // the checker does not have ports on its own so return the
126        // data port of the actual CPU core
127        assert(icachePort);
128        return *icachePort;
129    }
130
131  protected:
132
133    std::vector<Process*> workload;
134
135    System *systemPtr;
136
137    MasterPort *icachePort;
138    MasterPort *dcachePort;
139
140    ThreadContext *tc;
141
142    TheISA::TLB *itb;
143    TheISA::TLB *dtb;
144
145    Addr dbg_vtophys(Addr addr);
146
147    // ISAs like ARM can have multiple destination registers to check,
148    // keep them all in a std::queue
149    std::queue<InstResult> result;
150
151    // Pointer to the one memory request.
152    RequestPtr memReq;
153
154    StaticInstPtr curStaticInst;
155    StaticInstPtr curMacroStaticInst;
156
157    // number of simulated instructions
158    Counter numInst;
159    Counter startNumInst;
160
161    std::queue<int> miscRegIdxs;
162
163  public:
164
165    // Primary thread being run.
166    SimpleThread *thread;
167
168    TheISA::TLB* getITBPtr() { return itb; }
169    TheISA::TLB* getDTBPtr() { return dtb; }
170
171    virtual Counter totalInsts() const override
172    {
173        return 0;
174    }
175
176    virtual Counter totalOps() const override
177    {
178        return 0;
179    }
180
181    // number of simulated loads
182    Counter numLoad;
183    Counter startNumLoad;
184
185    void serialize(CheckpointOut &cp) const override;
186    void unserialize(CheckpointIn &cp) override;
187
188    // These functions are only used in CPU models that split
189    // effective address computation from the actual memory access.
190    void setEA(Addr EA) override
191    { panic("CheckerCPU::setEA() not implemented\n"); }
192    Addr getEA() const  override
193    { panic("CheckerCPU::getEA() not implemented\n"); }
194
195    // The register accessor methods provide the index of the
196    // instruction's operand (e.g., 0 or 1), not the architectural
197    // register index, to simplify the implementation of register
198    // renaming.  We find the architectural register index by indexing
199    // into the instruction's own operand index table.  Note that a
200    // raw pointer to the StaticInst is provided instead of a
201    // ref-counted StaticInstPtr to redice overhead.  This is fine as
202    // long as these methods don't copy the pointer into any long-term
203    // storage (which is pretty hard to imagine they would have reason
204    // to do).
205
206    IntReg readIntRegOperand(const StaticInst *si, int idx) override
207    {
208        const RegId& reg = si->srcRegIdx(idx);
209        assert(reg.isIntReg());
210        return thread->readIntReg(reg.index());
211    }
212
213    FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
214    {
215        const RegId& reg = si->srcRegIdx(idx);
216        assert(reg.isFloatReg());
217        return thread->readFloatReg(reg.index());
218    }
219
220    FloatRegBits readFloatRegOperandBits(const StaticInst *si,
221                                         int idx) override
222    {
223        const RegId& reg = si->srcRegIdx(idx);
224        assert(reg.isFloatReg());
225        return thread->readFloatRegBits(reg.index());
226    }
227
228    CCReg readCCRegOperand(const StaticInst *si, int idx) override
229    {
230        const RegId& reg = si->srcRegIdx(idx);
231        assert(reg.isCCReg());
232        return thread->readCCReg(reg.index());
233    }
234
235    template<typename T>
236    void setScalarResult(T&& t)
237    {
238        result.push(InstResult(std::forward<T>(t),
239                        InstResult::ResultType::Scalar));
240    }
241
242    void setIntRegOperand(const StaticInst *si, int idx,
243                          IntReg val) override
244    {
245        const RegId& reg = si->destRegIdx(idx);
246        assert(reg.isIntReg());
247        thread->setIntReg(reg.index(), val);
248        setScalarResult(val);
249    }
250
251    void setFloatRegOperand(const StaticInst *si, int idx,
252                            FloatReg val) override
253    {
254        const RegId& reg = si->destRegIdx(idx);
255        assert(reg.isFloatReg());
256        thread->setFloatReg(reg.index(), val);
257        setScalarResult(val);
258    }
259
260    void setFloatRegOperandBits(const StaticInst *si, int idx,
261                                FloatRegBits val) override
262    {
263        const RegId& reg = si->destRegIdx(idx);
264        assert(reg.isFloatReg());
265        thread->setFloatRegBits(reg.index(), val);
266        setScalarResult(val);
267    }
268
269    void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
270    {
271        const RegId& reg = si->destRegIdx(idx);
272        assert(reg.isCCReg());
273        thread->setCCReg(reg.index(), val);
274        setScalarResult((uint64_t)val);
275    }
276
277    bool readPredicate() override { return thread->readPredicate(); }
278    void setPredicate(bool val) override
279    {
280        thread->setPredicate(val);
281    }
282
283    TheISA::PCState pcState() const override { return thread->pcState(); }
284    void pcState(const TheISA::PCState &val) override
285    {
286        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
287                         val, thread->pcState());
288        thread->pcState(val);
289    }
290    Addr instAddr() { return thread->instAddr(); }
291    Addr nextInstAddr() { return thread->nextInstAddr(); }
292    MicroPC microPC() { return thread->microPC(); }
293    //////////////////////////////////////////
294
295    MiscReg readMiscRegNoEffect(int misc_reg) const
296    {
297        return thread->readMiscRegNoEffect(misc_reg);
298    }
299
300    MiscReg readMiscReg(int misc_reg) override
301    {
302        return thread->readMiscReg(misc_reg);
303    }
304
305    void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
306    {
307        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
308        miscRegIdxs.push(misc_reg);
309        return thread->setMiscRegNoEffect(misc_reg, val);
310    }
311
312    void setMiscReg(int misc_reg, const MiscReg &val) override
313    {
314        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
315        miscRegIdxs.push(misc_reg);
316        return thread->setMiscReg(misc_reg, val);
317    }
318
319    MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
320    {
321        const RegId& reg = si->srcRegIdx(idx);
322        assert(reg.isMiscReg());
323        return thread->readMiscReg(reg.index());
324    }
325
326    void setMiscRegOperand(const StaticInst *si, int idx,
327                           const MiscReg &val) override
328    {
329        const RegId& reg = si->destRegIdx(idx);
330        assert(reg.isMiscReg());
331        return this->setMiscReg(reg.index(), val);
332    }
333
334#if THE_ISA == MIPS_ISA
335    MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
336    {
337        panic("MIPS MT not defined for CheckerCPU.\n");
338        return 0;
339    }
340
341    void setRegOtherThread(const RegId& misc_reg, MiscReg val,
342                               ThreadID tid) override
343    {
344        panic("MIPS MT not defined for CheckerCPU.\n");
345    }
346#endif
347
348    /////////////////////////////////////////
349
350    void recordPCChange(const TheISA::PCState &val)
351    {
352       changedPC = true;
353       newPCState = val;
354    }
355
356    void demapPage(Addr vaddr, uint64_t asn) override
357    {
358        this->itb->demapPage(vaddr, asn);
359        this->dtb->demapPage(vaddr, asn);
360    }
361
362    // monitor/mwait funtions
363    void armMonitor(Addr address) override
364    { BaseCPU::armMonitor(0, address); }
365    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
366    void mwaitAtomic(ThreadContext *tc) override
367    { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
368    AddressMonitor *getAddrMonitor() override
369    { return BaseCPU::getCpuAddrMonitor(0); }
370
371    void demapInstPage(Addr vaddr, uint64_t asn)
372    {
373        this->itb->demapPage(vaddr, asn);
374    }
375
376    void demapDataPage(Addr vaddr, uint64_t asn)
377    {
378        this->dtb->demapPage(vaddr, asn);
379    }
380
381    Fault readMem(Addr addr, uint8_t *data, unsigned size,
382                  Request::Flags flags) override;
383    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
384                   Request::Flags flags, uint64_t *res) override;
385
386    unsigned int readStCondFailures() const override {
387        return thread->readStCondFailures();
388    }
389
390    void setStCondFailures(unsigned int sc_failures) override
391    {}
392    /////////////////////////////////////////////////////
393
394    Fault hwrei() override { return thread->hwrei(); }
395    bool simPalCheck(int palFunc) override
396    { return thread->simPalCheck(palFunc); }
397    void wakeup(ThreadID tid) override { }
398    // Assume that the normal CPU's call to syscall was successful.
399    // The checker's state would have already been updated by the syscall.
400    void syscall(int64_t callnum, Fault *fault) override { }
401
402    void handleError()
403    {
404        if (exitOnError)
405            dumpAndExit();
406    }
407
408    bool checkFlags(Request *unverified_req, Addr vAddr,
409                    Addr pAddr, int flags);
410
411    void dumpAndExit();
412
413    ThreadContext *tcBase() override { return tc; }
414    SimpleThread *threadBase() { return thread; }
415
416    InstResult unverifiedResult;
417    Request *unverifiedReq;
418    uint8_t *unverifiedMemData;
419
420    bool changedPC;
421    bool willChangePC;
422    TheISA::PCState newPCState;
423    bool exitOnError;
424    bool updateOnError;
425    bool warnOnlyOnLoadError;
426
427    InstSeqNum youngestSN;
428};
429
430/**
431 * Templated Checker class.  This Checker class is templated on the
432 * DynInstPtr of the instruction type that will be verified.  Proper
433 * template instantiations of the Checker must be placed at the bottom
434 * of checker/cpu.cc.
435 */
436template <class Impl>
437class Checker : public CheckerCPU
438{
439  private:
440    typedef typename Impl::DynInstPtr DynInstPtr;
441
442  public:
443    Checker(Params *p)
444        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
445    { }
446
447    void switchOut();
448    void takeOverFrom(BaseCPU *oldCPU);
449
450    void advancePC(const Fault &fault);
451
452    void verify(DynInstPtr &inst);
453
454    void validateInst(DynInstPtr &inst);
455    void validateExecution(DynInstPtr &inst);
456    void validateState();
457
458    void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
459                    int start_idx);
460    void handlePendingInt();
461
462  private:
463    void handleError(DynInstPtr &inst)
464    {
465        if (exitOnError) {
466            dumpAndExit(inst);
467        } else if (updateOnError) {
468            updateThisCycle = true;
469        }
470    }
471
472    void dumpAndExit(DynInstPtr &inst);
473
474    bool updateThisCycle;
475
476    DynInstPtr unverifiedInst;
477
478    std::list<DynInstPtr> instList;
479    typedef typename std::list<DynInstPtr>::iterator InstListIt;
480    void dumpInsts();
481};
482
483#endif // __CPU_CHECKER_CPU_HH__
484