cpu.hh revision 7725:00ea9430643b
1955SN/A/* 2955SN/A * Copyright (c) 2006 The Regents of The University of Michigan 37816Ssteve.reinhardt@amd.com * All rights reserved. 45871Snate@binkert.org * 51762SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A * 28955SN/A * Authors: Kevin Lim 29955SN/A */ 302665Ssaidi@eecs.umich.edu 312665Ssaidi@eecs.umich.edu#ifndef __CPU_CHECKER_CPU_HH__ 325863Snate@binkert.org#define __CPU_CHECKER_CPU_HH__ 33955SN/A 34955SN/A#include <list> 35955SN/A#include <queue> 36955SN/A#include <map> 37955SN/A 382632Sstever@eecs.umich.edu#include "arch/types.hh" 392632Sstever@eecs.umich.edu#include "base/statistics.hh" 402632Sstever@eecs.umich.edu#include "config/full_system.hh" 412632Sstever@eecs.umich.edu#include "cpu/base.hh" 42955SN/A#include "cpu/base_dyn_inst.hh" 432632Sstever@eecs.umich.edu#include "cpu/simple_thread.hh" 442632Sstever@eecs.umich.edu#include "cpu/pc_event.hh" 452761Sstever@eecs.umich.edu#include "cpu/static_inst.hh" 462632Sstever@eecs.umich.edu#include "sim/eventq.hh" 472632Sstever@eecs.umich.edu 482632Sstever@eecs.umich.edu// forward declarations 492761Sstever@eecs.umich.edu#if FULL_SYSTEM 502761Sstever@eecs.umich.edunamespace TheISA 512761Sstever@eecs.umich.edu{ 522632Sstever@eecs.umich.edu class TLB; 532632Sstever@eecs.umich.edu} 542761Sstever@eecs.umich.educlass Processor; 552761Sstever@eecs.umich.educlass PhysicalMemory; 562761Sstever@eecs.umich.edu 572761Sstever@eecs.umich.edu#else 582761Sstever@eecs.umich.edu 592632Sstever@eecs.umich.educlass Process; 602632Sstever@eecs.umich.edu 612632Sstever@eecs.umich.edu#endif // FULL_SYSTEM 622632Sstever@eecs.umich.edutemplate <class> 632632Sstever@eecs.umich.educlass BaseDynInst; 642632Sstever@eecs.umich.educlass CheckerCPUParams; 652632Sstever@eecs.umich.educlass ThreadContext; 66955SN/Aclass MemInterface; 67955SN/Aclass Checkpoint; 68955SN/Aclass Request; 695863Snate@binkert.org 705863Snate@binkert.org/** 715863Snate@binkert.org * CheckerCPU class. Dynamically verifies instructions as they are 725863Snate@binkert.org * completed by making sure that the instruction and its results match 735863Snate@binkert.org * the independent execution of the benchmark inside the checker. The 745863Snate@binkert.org * checker verifies instructions in order, regardless of the order in 755863Snate@binkert.org * which instructions complete. There are certain results that can 765863Snate@binkert.org * not be verified, specifically the result of a store conditional or 775863Snate@binkert.org * the values of uncached accesses. In these cases, and with 785863Snate@binkert.org * instructions marked as "IsUnverifiable", the checker assumes that 795863Snate@binkert.org * the value from the main CPU's execution is correct and simply 805863Snate@binkert.org * copies that value. It provides a CheckerThreadContext (see 815863Snate@binkert.org * checker/thread_context.hh) that provides hooks for updating the 825863Snate@binkert.org * Checker's state through any ThreadContext accesses. This allows the 835863Snate@binkert.org * checker to be able to correctly verify instructions, even with 845863Snate@binkert.org * external accesses to the ThreadContext that change state. 855863Snate@binkert.org */ 865863Snate@binkert.orgclass CheckerCPU : public BaseCPU 875863Snate@binkert.org{ 885863Snate@binkert.org protected: 895863Snate@binkert.org typedef TheISA::MachInst MachInst; 905863Snate@binkert.org typedef TheISA::FloatReg FloatReg; 915863Snate@binkert.org typedef TheISA::FloatRegBits FloatRegBits; 925863Snate@binkert.org typedef TheISA::MiscReg MiscReg; 935863Snate@binkert.org public: 945863Snate@binkert.org virtual void init(); 955863Snate@binkert.org 965863Snate@binkert.org public: 975863Snate@binkert.org typedef CheckerCPUParams Params; 985863Snate@binkert.org const Params *params() const 995863Snate@binkert.org { return reinterpret_cast<const Params *>(_params); } 1006654Snate@binkert.org CheckerCPU(Params *p); 101955SN/A virtual ~CheckerCPU(); 1025396Ssaidi@eecs.umich.edu 1035863Snate@binkert.org Process *process; 1045863Snate@binkert.org 1054202Sbinkertn@umich.edu void setSystem(System *system); 1065863Snate@binkert.org 1075863Snate@binkert.org System *systemPtr; 1085863Snate@binkert.org 1095863Snate@binkert.org void setIcachePort(Port *icache_port); 110955SN/A 1116654Snate@binkert.org Port *icachePort; 1125273Sstever@gmail.com 1135871Snate@binkert.org void setDcachePort(Port *dcache_port); 1145273Sstever@gmail.com 1156655Snate@binkert.org Port *dcachePort; 1166655Snate@binkert.org 1176655Snate@binkert.org virtual Port *getPort(const std::string &name, int idx) 1186655Snate@binkert.org { 1196655Snate@binkert.org panic("Not supported on checker!"); 1206655Snate@binkert.org return NULL; 1215871Snate@binkert.org } 1226654Snate@binkert.org 1235396Ssaidi@eecs.umich.edu public: 1248120Sgblack@eecs.umich.edu // Primary thread being run. 1258120Sgblack@eecs.umich.edu SimpleThread *thread; 1268120Sgblack@eecs.umich.edu 1278120Sgblack@eecs.umich.edu ThreadContext *tc; 1288120Sgblack@eecs.umich.edu 1298120Sgblack@eecs.umich.edu TheISA::TLB *itb; 1308120Sgblack@eecs.umich.edu TheISA::TLB *dtb; 1318120Sgblack@eecs.umich.edu 1328120Sgblack@eecs.umich.edu#if FULL_SYSTEM 1338120Sgblack@eecs.umich.edu Addr dbg_vtophys(Addr addr); 1348120Sgblack@eecs.umich.edu#endif 1358120Sgblack@eecs.umich.edu 1368120Sgblack@eecs.umich.edu union Result { 1378120Sgblack@eecs.umich.edu uint64_t integer; 1388120Sgblack@eecs.umich.edu// float fp; 1398120Sgblack@eecs.umich.edu double dbl; 1408120Sgblack@eecs.umich.edu }; 1418120Sgblack@eecs.umich.edu 1428120Sgblack@eecs.umich.edu Result result; 1438120Sgblack@eecs.umich.edu 1448120Sgblack@eecs.umich.edu // current instruction 1458120Sgblack@eecs.umich.edu MachInst machInst; 1468120Sgblack@eecs.umich.edu 1478120Sgblack@eecs.umich.edu // Pointer to the one memory request. 1488120Sgblack@eecs.umich.edu RequestPtr memReq; 1498120Sgblack@eecs.umich.edu 1508120Sgblack@eecs.umich.edu StaticInstPtr curStaticInst; 1518120Sgblack@eecs.umich.edu 1528120Sgblack@eecs.umich.edu // number of simulated instructions 1538120Sgblack@eecs.umich.edu Counter numInst; 1548120Sgblack@eecs.umich.edu Counter startNumInst; 1558120Sgblack@eecs.umich.edu 1568120Sgblack@eecs.umich.edu std::queue<int> miscRegIdxs; 1578120Sgblack@eecs.umich.edu 1588120Sgblack@eecs.umich.edu virtual Counter totalInstructions() const 1598120Sgblack@eecs.umich.edu { 1607816Ssteve.reinhardt@amd.com return 0; 1617816Ssteve.reinhardt@amd.com } 1627816Ssteve.reinhardt@amd.com 1637816Ssteve.reinhardt@amd.com // number of simulated loads 1647816Ssteve.reinhardt@amd.com Counter numLoad; 1657816Ssteve.reinhardt@amd.com Counter startNumLoad; 1667816Ssteve.reinhardt@amd.com 1677816Ssteve.reinhardt@amd.com virtual void serialize(std::ostream &os); 1687816Ssteve.reinhardt@amd.com virtual void unserialize(Checkpoint *cp, const std::string §ion); 1695871Snate@binkert.org 1705871Snate@binkert.org template <class T> 1716121Snate@binkert.org Fault read(Addr addr, T &data, unsigned flags); 1725871Snate@binkert.org 1735871Snate@binkert.org template <class T> 1746003Snate@binkert.org Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 1756655Snate@binkert.org 176955SN/A // These functions are only used in CPU models that split 1775871Snate@binkert.org // effective address computation from the actual memory access. 1785871Snate@binkert.org void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 1795871Snate@binkert.org Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 1805871Snate@binkert.org 181955SN/A // The register accessor methods provide the index of the 1826121Snate@binkert.org // instruction's operand (e.g., 0 or 1), not the architectural 1836121Snate@binkert.org // register index, to simplify the implementation of register 1846121Snate@binkert.org // renaming. We find the architectural register index by indexing 1851533SN/A // into the instruction's own operand index table. Note that a 1866655Snate@binkert.org // raw pointer to the StaticInst is provided instead of a 1876655Snate@binkert.org // ref-counted StaticInstPtr to redice overhead. This is fine as 1886655Snate@binkert.org // long as these methods don't copy the pointer into any long-term 1896655Snate@binkert.org // storage (which is pretty hard to imagine they would have reason 1905871Snate@binkert.org // to do). 1915871Snate@binkert.org 1925863Snate@binkert.org uint64_t readIntRegOperand(const StaticInst *si, int idx) 1935871Snate@binkert.org { 1945871Snate@binkert.org return thread->readIntReg(si->srcRegIdx(idx)); 1955871Snate@binkert.org } 1965871Snate@binkert.org 1975871Snate@binkert.org FloatReg readFloatRegOperand(const StaticInst *si, int idx) 1985863Snate@binkert.org { 1996121Snate@binkert.org int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 2005863Snate@binkert.org return thread->readFloatReg(reg_idx); 2015871Snate@binkert.org } 2024678Snate@binkert.org 2034678Snate@binkert.org FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) 2044678Snate@binkert.org { 2054678Snate@binkert.org int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 2064678Snate@binkert.org return thread->readFloatRegBits(reg_idx); 2074678Snate@binkert.org } 2084678Snate@binkert.org 2094678Snate@binkert.org void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) 2104678Snate@binkert.org { 2114678Snate@binkert.org thread->setIntReg(si->destRegIdx(idx), val); 2124678Snate@binkert.org result.integer = val; 2137827Snate@binkert.org } 2147827Snate@binkert.org 2156121Snate@binkert.org void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) 2164678Snate@binkert.org { 2175871Snate@binkert.org int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 2185871Snate@binkert.org thread->setFloatReg(reg_idx, val); 2195871Snate@binkert.org result.dbl = (double)val; 2205871Snate@binkert.org } 2215871Snate@binkert.org 2225871Snate@binkert.org void setFloatRegOperandBits(const StaticInst *si, int idx, 2235871Snate@binkert.org FloatRegBits val) 2245871Snate@binkert.org { 2255871Snate@binkert.org int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 2265871Snate@binkert.org thread->setFloatRegBits(reg_idx, val); 2275871Snate@binkert.org result.integer = val; 2285871Snate@binkert.org } 2295871Snate@binkert.org 2305871Snate@binkert.org uint64_t instAddr() { return thread->instAddr(); } 2318126Sgblack@eecs.umich.edu 2325871Snate@binkert.org uint64_t nextInstAddr() { return thread->nextInstAddr(); } 2335871Snate@binkert.org 2348122Sgblack@eecs.umich.edu MiscReg readMiscRegNoEffect(int misc_reg) 2355871Snate@binkert.org { 2365871Snate@binkert.org return thread->readMiscRegNoEffect(misc_reg); 2374678Snate@binkert.org } 2385871Snate@binkert.org 2394678Snate@binkert.org MiscReg readMiscReg(int misc_reg) 2405871Snate@binkert.org { 2415871Snate@binkert.org return thread->readMiscReg(misc_reg); 2425871Snate@binkert.org } 2435871Snate@binkert.org 2445871Snate@binkert.org void setMiscRegNoEffect(int misc_reg, const MiscReg &val) 2455871Snate@binkert.org { 2465871Snate@binkert.org result.integer = val; 2475871Snate@binkert.org miscRegIdxs.push(misc_reg); 2485871Snate@binkert.org return thread->setMiscRegNoEffect(misc_reg, val); 2496121Snate@binkert.org } 250955SN/A 251955SN/A void setMiscReg(int misc_reg, const MiscReg &val) 2522632Sstever@eecs.umich.edu { 2532632Sstever@eecs.umich.edu miscRegIdxs.push(misc_reg); 254955SN/A return thread->setMiscReg(misc_reg, val); 255955SN/A } 256955SN/A 257955SN/A void recordPCChange(uint64_t val) { changedPC = true; newPC = val; } 2585863Snate@binkert.org void recordNextPCChange(uint64_t val) { changedNextPC = true; } 259955SN/A 2602632Sstever@eecs.umich.edu void demapPage(Addr vaddr, uint64_t asn) 2612632Sstever@eecs.umich.edu { 2622632Sstever@eecs.umich.edu this->itb->demapPage(vaddr, asn); 2632632Sstever@eecs.umich.edu this->dtb->demapPage(vaddr, asn); 2642632Sstever@eecs.umich.edu } 2652632Sstever@eecs.umich.edu 2662632Sstever@eecs.umich.edu void demapInstPage(Addr vaddr, uint64_t asn) 2672632Sstever@eecs.umich.edu { 2682632Sstever@eecs.umich.edu this->itb->demapPage(vaddr, asn); 2692632Sstever@eecs.umich.edu } 2702632Sstever@eecs.umich.edu 2712632Sstever@eecs.umich.edu void demapDataPage(Addr vaddr, uint64_t asn) 2722632Sstever@eecs.umich.edu { 2733718Sstever@eecs.umich.edu this->dtb->demapPage(vaddr, asn); 2743718Sstever@eecs.umich.edu } 2753718Sstever@eecs.umich.edu 2763718Sstever@eecs.umich.edu#if FULL_SYSTEM 2773718Sstever@eecs.umich.edu Fault hwrei() { return thread->hwrei(); } 2785863Snate@binkert.org bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } 2795863Snate@binkert.org#else 2803718Sstever@eecs.umich.edu // Assume that the normal CPU's call to syscall was successful. 2813718Sstever@eecs.umich.edu // The checker's state would have already been updated by the syscall. 2826121Snate@binkert.org void syscall(uint64_t callnum) { } 2835863Snate@binkert.org#endif 2843718Sstever@eecs.umich.edu 2853718Sstever@eecs.umich.edu void handleError() 2862634Sstever@eecs.umich.edu { 2872634Sstever@eecs.umich.edu if (exitOnError) 2885863Snate@binkert.org dumpAndExit(); 2892638Sstever@eecs.umich.edu } 2902632Sstever@eecs.umich.edu 2912632Sstever@eecs.umich.edu bool checkFlags(Request *req); 2922632Sstever@eecs.umich.edu 2932632Sstever@eecs.umich.edu void dumpAndExit(); 2942632Sstever@eecs.umich.edu 2952632Sstever@eecs.umich.edu ThreadContext *tcBase() { return tc; } 2961858SN/A SimpleThread *threadBase() { return thread; } 2973716Sstever@eecs.umich.edu 2982638Sstever@eecs.umich.edu Result unverifiedResult; 2992638Sstever@eecs.umich.edu Request *unverifiedReq; 3002638Sstever@eecs.umich.edu uint8_t *unverifiedMemData; 3012638Sstever@eecs.umich.edu 3022638Sstever@eecs.umich.edu bool changedPC; 3032638Sstever@eecs.umich.edu bool willChangePC; 3042638Sstever@eecs.umich.edu uint64_t newPC; 3055863Snate@binkert.org bool changedNextPC; 3065863Snate@binkert.org bool exitOnError; 3075863Snate@binkert.org bool updateOnError; 308955SN/A bool warnOnlyOnLoadError; 3095341Sstever@gmail.com 3105341Sstever@gmail.com InstSeqNum youngestSN; 3115863Snate@binkert.org}; 3127756SAli.Saidi@ARM.com 3135341Sstever@gmail.com/** 3146121Snate@binkert.org * Templated Checker class. This Checker class is templated on the 3154494Ssaidi@eecs.umich.edu * DynInstPtr of the instruction type that will be verified. Proper 3166121Snate@binkert.org * template instantiations of the Checker must be placed at the bottom 3171105SN/A * of checker/cpu.cc. 3182667Sstever@eecs.umich.edu */ 3192667Sstever@eecs.umich.edutemplate <class DynInstPtr> 3202667Sstever@eecs.umich.educlass Checker : public CheckerCPU 3212667Sstever@eecs.umich.edu{ 3226121Snate@binkert.org public: 3232667Sstever@eecs.umich.edu Checker(Params *p) 3245341Sstever@gmail.com : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL) 3255863Snate@binkert.org { } 3265341Sstever@gmail.com 3275341Sstever@gmail.com void switchOut(); 3285341Sstever@gmail.com void takeOverFrom(BaseCPU *oldCPU); 3295863Snate@binkert.org 3305341Sstever@gmail.com void verify(DynInstPtr &inst); 3315341Sstever@gmail.com 3325341Sstever@gmail.com void validateInst(DynInstPtr &inst); 3335863Snate@binkert.org void validateExecution(DynInstPtr &inst); 3345341Sstever@gmail.com void validateState(); 3355341Sstever@gmail.com 3365341Sstever@gmail.com void copyResult(DynInstPtr &inst); 3375341Sstever@gmail.com 3385341Sstever@gmail.com private: 3395341Sstever@gmail.com void handleError(DynInstPtr &inst) 3405341Sstever@gmail.com { 3415341Sstever@gmail.com if (exitOnError) { 3425341Sstever@gmail.com dumpAndExit(inst); 3435341Sstever@gmail.com } else if (updateOnError) { 3448120Sgblack@eecs.umich.edu updateThisCycle = true; 3455341Sstever@gmail.com } 3468120Sgblack@eecs.umich.edu } 3475341Sstever@gmail.com 3488120Sgblack@eecs.umich.edu void dumpAndExit(DynInstPtr &inst); 3496121Snate@binkert.org 3506121Snate@binkert.org bool updateThisCycle; 3515397Ssaidi@eecs.umich.edu 3525397Ssaidi@eecs.umich.edu DynInstPtr unverifiedInst; 3537727SAli.Saidi@ARM.com 3548121Sgblack@eecs.umich.edu std::list<DynInstPtr> instList; 3556168Snate@binkert.org typedef typename std::list<DynInstPtr>::iterator InstListIt; 3566168Snate@binkert.org void dumpInsts(); 3575341Sstever@gmail.com}; 3588120Sgblack@eecs.umich.edu 3598120Sgblack@eecs.umich.edu#endif // __CPU_CHECKER_CPU_HH__ 3608120Sgblack@eecs.umich.edu