cpu.cc revision 2723:4c47709f88ab
16019Shines@cs.fsu.edu/* 211496Sandreas.sandberg@arm.com * Copyright (c) 2006 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146019Shines@cs.fsu.edu * this software without specific prior written permission. 156019Shines@cs.fsu.edu * 166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * Authors: Kevin Lim 296019Shines@cs.fsu.edu */ 306019Shines@cs.fsu.edu 316019Shines@cs.fsu.edu#include <list> 326019Shines@cs.fsu.edu#include <string> 336019Shines@cs.fsu.edu 346019Shines@cs.fsu.edu#include "base/refcnt.hh" 356019Shines@cs.fsu.edu#include "cpu/base.hh" 366019Shines@cs.fsu.edu#include "cpu/base_dyn_inst.hh" 376019Shines@cs.fsu.edu#include "cpu/checker/cpu.hh" 386019Shines@cs.fsu.edu#include "cpu/simple_thread.hh" 396019Shines@cs.fsu.edu#include "cpu/thread_context.hh" 406019Shines@cs.fsu.edu#include "cpu/static_inst.hh" 416735Sgblack@eecs.umich.edu#include "mem/packet_impl.hh" 426735Sgblack@eecs.umich.edu#include "sim/byteswap.hh" 4310037SARM gem5 Developers#include "sim/sim_object.hh" 4410037SARM gem5 Developers#include "sim/stats.hh" 456019Shines@cs.fsu.edu 466019Shines@cs.fsu.edu#include "cpu/o3/alpha_dyn_inst.hh" 476019Shines@cs.fsu.edu#include "cpu/o3/alpha_impl.hh" 4810037SARM gem5 Developers 4910037SARM gem5 Developers//#include "cpu/ozone/dyn_inst.hh" 5010037SARM gem5 Developers//#include "cpu/ozone/ozone_impl.hh" 5110037SARM gem5 Developers//#include "cpu/ozone/simple_impl.hh" 528229Snate@binkert.org 538229Snate@binkert.org#if FULL_SYSTEM 546019Shines@cs.fsu.edu#include "sim/system.hh" 558232Snate@binkert.org#include "arch/vtophys.hh" 568782Sgblack@eecs.umich.edu#endif // FULL_SYSTEM 576019Shines@cs.fsu.edu 586019Shines@cs.fsu.eduusing namespace std; 596019Shines@cs.fsu.edu//The CheckerCPU does alpha only 606019Shines@cs.fsu.eduusing namespace AlphaISA; 6110037SARM gem5 Developers 6210037SARM gem5 Developersvoid 6310037SARM gem5 DevelopersCheckerCPU::init() 6410037SARM gem5 Developers{ 6510037SARM gem5 Developers} 6610037SARM gem5 Developers 6710037SARM gem5 DevelopersCheckerCPU::CheckerCPU(Params *p) 6810037SARM gem5 Developers : BaseCPU(p), thread(NULL), tc(NULL) 6910037SARM gem5 Developers{ 7010037SARM gem5 Developers memReq = NULL; 7110037SARM gem5 Developers 7210037SARM gem5 Developers numInst = 0; 7310037SARM gem5 Developers startNumInst = 0; 7410037SARM gem5 Developers numLoad = 0; 7510037SARM gem5 Developers startNumLoad = 0; 7610037SARM gem5 Developers youngestSN = 0; 7710037SARM gem5 Developers 7810037SARM gem5 Developers changedPC = willChangePC = changedNextPC = false; 7910037SARM gem5 Developers 8010037SARM gem5 Developers exitOnError = p->exitOnError; 8110037SARM gem5 Developers#if FULL_SYSTEM 8210037SARM gem5 Developers itb = p->itb; 8310037SARM gem5 Developers dtb = p->dtb; 8410037SARM gem5 Developers systemPtr = NULL; 8510037SARM gem5 Developers#else 8610037SARM gem5 Developers process = p->process; 8710037SARM gem5 Developers#endif 8810037SARM gem5 Developers 8910037SARM gem5 Developers result.integer = 0; 9010037SARM gem5 Developers} 9110037SARM gem5 Developers 9210037SARM gem5 DevelopersCheckerCPU::~CheckerCPU() 9310037SARM gem5 Developers{ 9410037SARM gem5 Developers} 9510037SARM gem5 Developers 9610037SARM gem5 Developersvoid 9710037SARM gem5 DevelopersCheckerCPU::setMemory(MemObject *mem) 9810037SARM gem5 Developers{ 9910037SARM gem5 Developers#if !FULL_SYSTEM 10010037SARM gem5 Developers memPtr = mem; 1016019Shines@cs.fsu.edu thread = new SimpleThread(this, /* thread_num */ 0, process, 10210037SARM gem5 Developers /* asid */ 0, mem); 10310037SARM gem5 Developers 10410037SARM gem5 Developers thread->setStatus(ThreadContext::Suspended); 1056019Shines@cs.fsu.edu tc = thread->getTC(); 10610037SARM gem5 Developers threadContexts.push_back(tc); 10710037SARM gem5 Developers#endif 10810037SARM gem5 Developers} 10910037SARM gem5 Developers 11010037SARM gem5 Developersvoid 11110037SARM gem5 DevelopersCheckerCPU::setSystem(System *system) 11210037SARM gem5 Developers{ 11310037SARM gem5 Developers#if FULL_SYSTEM 11410037SARM gem5 Developers systemPtr = system; 11510037SARM gem5 Developers 11610037SARM gem5 Developers thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 11710037SARM gem5 Developers 11810037SARM gem5 Developers thread->setStatus(ThreadContext::Suspended); 11910037SARM gem5 Developers tc = thread->getTC(); 12010037SARM gem5 Developers threadContexts.push_back(tc); 12110037SARM gem5 Developers delete thread->kernelStats; 12210037SARM gem5 Developers thread->kernelStats = NULL; 12310037SARM gem5 Developers#endif 12410037SARM gem5 Developers} 12510037SARM gem5 Developers 12610037SARM gem5 Developersvoid 12710037SARM gem5 DevelopersCheckerCPU::setIcachePort(Port *icache_port) 12810037SARM gem5 Developers{ 12910037SARM gem5 Developers icachePort = icache_port; 13010037SARM gem5 Developers} 13110037SARM gem5 Developers 13210037SARM gem5 Developersvoid 13310037SARM gem5 DevelopersCheckerCPU::setDcachePort(Port *dcache_port) 13410037SARM gem5 Developers{ 13510037SARM gem5 Developers dcachePort = dcache_port; 13610037SARM gem5 Developers} 13710037SARM gem5 Developers 13810037SARM gem5 Developersvoid 13910037SARM gem5 DevelopersCheckerCPU::serialize(ostream &os) 14010037SARM gem5 Developers{ 14110037SARM gem5 Developers/* 14210037SARM gem5 Developers BaseCPU::serialize(os); 14310037SARM gem5 Developers SERIALIZE_SCALAR(inst); 14410037SARM gem5 Developers nameOut(os, csprintf("%s.xc", name())); 14510037SARM gem5 Developers thread->serialize(os); 1466019Shines@cs.fsu.edu cacheCompletionEvent.serialize(os); 14710037SARM gem5 Developers*/ 14810037SARM gem5 Developers} 14910037SARM gem5 Developers 1506019Shines@cs.fsu.eduvoid 15110037SARM gem5 DevelopersCheckerCPU::unserialize(Checkpoint *cp, const string §ion) 15210037SARM gem5 Developers{ 15310037SARM gem5 Developers/* 15410037SARM gem5 Developers BaseCPU::unserialize(cp, section); 15510037SARM gem5 Developers UNSERIALIZE_SCALAR(inst); 15610037SARM gem5 Developers thread->unserialize(cp, csprintf("%s.xc", section)); 15710037SARM gem5 Developers*/ 15810037SARM gem5 Developers} 15910037SARM gem5 Developers 16010037SARM gem5 DevelopersFault 16110037SARM gem5 DevelopersCheckerCPU::copySrcTranslate(Addr src) 16210037SARM gem5 Developers{ 16310037SARM gem5 Developers panic("Unimplemented!"); 16410037SARM gem5 Developers} 16510037SARM gem5 Developers 16610037SARM gem5 DevelopersFault 16710037SARM gem5 DevelopersCheckerCPU::copy(Addr dest) 16810037SARM gem5 Developers{ 16910037SARM gem5 Developers panic("Unimplemented!"); 17010037SARM gem5 Developers} 17110037SARM gem5 Developers 17210037SARM gem5 Developerstemplate <class T> 17310037SARM gem5 DevelopersFault 17410037SARM gem5 DevelopersCheckerCPU::read(Addr addr, T &data, unsigned flags) 17510037SARM gem5 Developers{ 17610037SARM gem5 Developers // need to fill in CPU & thread IDs here 17710037SARM gem5 Developers memReq = new Request(); 17810037SARM gem5 Developers 17910037SARM gem5 Developers memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 18010037SARM gem5 Developers 18110037SARM gem5 Developers // translate to physical address 18210037SARM gem5 Developers translateDataReadReq(memReq); 18310037SARM gem5 Developers 18410037SARM gem5 Developers Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 18510037SARM gem5 Developers 18610037SARM gem5 Developers pkt->dataStatic(&data); 18710037SARM gem5 Developers 18810037SARM gem5 Developers if (!(memReq->getFlags() & UNCACHEABLE)) { 18910037SARM gem5 Developers // Access memory to see if we have the same data 19010037SARM gem5 Developers dcachePort->sendFunctional(pkt); 19110037SARM gem5 Developers } else { 1926019Shines@cs.fsu.edu // Assume the data is correct if it's an uncached access 19310037SARM gem5 Developers memcpy(&data, &unverifiedResult.integer, sizeof(T)); 19410037SARM gem5 Developers } 19510037SARM gem5 Developers 1966019Shines@cs.fsu.edu delete pkt; 19710037SARM gem5 Developers 19810037SARM gem5 Developers return NoFault; 19910037SARM gem5 Developers} 20010037SARM gem5 Developers 20110037SARM gem5 Developers#ifndef DOXYGEN_SHOULD_SKIP_THIS 20210037SARM gem5 Developers 20310037SARM gem5 Developerstemplate 20410037SARM gem5 DevelopersFault 20510037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 20610037SARM gem5 Developers 20710037SARM gem5 Developerstemplate 20810037SARM gem5 DevelopersFault 20910037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 21010037SARM gem5 Developers 21110037SARM gem5 Developerstemplate 21210037SARM gem5 DevelopersFault 21310037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 21410037SARM gem5 Developers 21510037SARM gem5 Developerstemplate 21610037SARM gem5 DevelopersFault 21710037SARM gem5 DevelopersCheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 21810037SARM gem5 Developers 21910037SARM gem5 Developers#endif //DOXYGEN_SHOULD_SKIP_THIS 22010037SARM gem5 Developers 22110037SARM gem5 Developerstemplate<> 22210037SARM gem5 DevelopersFault 22310037SARM gem5 DevelopersCheckerCPU::read(Addr addr, double &data, unsigned flags) 22410037SARM gem5 Developers{ 22510037SARM gem5 Developers return read(addr, *(uint64_t*)&data, flags); 22610037SARM gem5 Developers} 22710037SARM gem5 Developers 22810037SARM gem5 Developerstemplate<> 22910037SARM gem5 DevelopersFault 23010037SARM gem5 DevelopersCheckerCPU::read(Addr addr, float &data, unsigned flags) 23110037SARM gem5 Developers{ 23210037SARM gem5 Developers return read(addr, *(uint32_t*)&data, flags); 23310037SARM gem5 Developers} 23410037SARM gem5 Developers 23510037SARM gem5 Developerstemplate<> 23610037SARM gem5 DevelopersFault 23710037SARM gem5 DevelopersCheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 23810037SARM gem5 Developers{ 23910037SARM gem5 Developers return read(addr, (uint32_t&)data, flags); 24010037SARM gem5 Developers} 24110037SARM gem5 Developers 24210037SARM gem5 Developerstemplate <class T> 24310037SARM gem5 DevelopersFault 24410037SARM gem5 DevelopersCheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 24510037SARM gem5 Developers{ 24610037SARM gem5 Developers // need to fill in CPU & thread IDs here 24710037SARM gem5 Developers memReq = new Request(); 24810037SARM gem5 Developers 24910037SARM gem5 Developers memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 25010037SARM gem5 Developers 25110037SARM gem5 Developers // translate to physical address 25210037SARM gem5 Developers thread->translateDataWriteReq(memReq); 25310037SARM gem5 Developers 25410037SARM gem5 Developers // Can compare the write data and result only if it's cacheable, 25510037SARM gem5 Developers // not a store conditional, or is a store conditional that 25610037SARM gem5 Developers // succeeded. 25710037SARM gem5 Developers // @todo: Verify that actual memory matches up with these values. 25810037SARM gem5 Developers // Right now it only verifies that the instruction data is the 25910037SARM gem5 Developers // same as what was in the request that got sent to memory; there 26010037SARM gem5 Developers // is no verification that it is the same as what is in memory. 26110037SARM gem5 Developers // This is because the LSQ would have to be snooped in the CPU to 26210037SARM gem5 Developers // verify this data. 26310037SARM gem5 Developers if (unverifiedReq && 26410037SARM gem5 Developers !(unverifiedReq->getFlags() & UNCACHEABLE) && 26510037SARM gem5 Developers (!(unverifiedReq->getFlags() & LOCKED) || 26610037SARM gem5 Developers ((unverifiedReq->getFlags() & LOCKED) && 26710037SARM gem5 Developers unverifiedReq->getScResult() == 1))) { 26810037SARM gem5 Developers T inst_data; 26910037SARM gem5 Developers/* 27010037SARM gem5 Developers // This code would work if the LSQ allowed for snooping. 27110037SARM gem5 Developers Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 27210037SARM gem5 Developers pkt.dataStatic(&inst_data); 27310037SARM gem5 Developers 27410037SARM gem5 Developers dcachePort->sendFunctional(pkt); 27510037SARM gem5 Developers 27610037SARM gem5 Developers delete pkt; 27710037SARM gem5 Developers*/ 27810037SARM gem5 Developers memcpy(&inst_data, unverifiedMemData, sizeof(T)); 27910037SARM gem5 Developers 28010037SARM gem5 Developers if (data != inst_data) { 28110037SARM gem5 Developers warn("%lli: Store value does not match value in memory! " 28210037SARM gem5 Developers "Instruction: %#x, memory: %#x", 28310037SARM gem5 Developers curTick, inst_data, data); 28410037SARM gem5 Developers handleError(); 28510037SARM gem5 Developers } 28610037SARM gem5 Developers } 28710037SARM gem5 Developers 28810037SARM gem5 Developers // Assume the result was the same as the one passed in. This checker 28910037SARM gem5 Developers // doesn't check if the SC should succeed or fail, it just checks the 29010037SARM gem5 Developers // value. 29110037SARM gem5 Developers if (res && unverifiedReq->scResultValid()) 29210037SARM gem5 Developers *res = unverifiedReq->getScResult(); 29310037SARM gem5 Developers 29410037SARM gem5 Developers return NoFault; 2956019Shines@cs.fsu.edu} 29610037SARM gem5 Developers 2977362Sgblack@eecs.umich.edu 2986735Sgblack@eecs.umich.edu#ifndef DOXYGEN_SHOULD_SKIP_THIS 29910037SARM gem5 Developerstemplate 3006019Shines@cs.fsu.eduFault 30110037SARM gem5 DevelopersCheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 30210037SARM gem5 Developers 3037400SAli.Saidi@ARM.comtemplate 3046735Sgblack@eecs.umich.eduFault 3056735Sgblack@eecs.umich.eduCheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 30610037SARM gem5 Developers 3076735Sgblack@eecs.umich.edutemplate 30810037SARM gem5 DevelopersFault 30910037SARM gem5 DevelopersCheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 31010037SARM gem5 Developers 31110037SARM gem5 Developerstemplate 3127400SAli.Saidi@ARM.comFault 31310037SARM gem5 DevelopersCheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 31410037SARM gem5 Developers 31510037SARM gem5 Developers#endif //DOXYGEN_SHOULD_SKIP_THIS 31610037SARM gem5 Developers 31710037SARM gem5 Developerstemplate<> 31810037SARM gem5 DevelopersFault 31910037SARM gem5 DevelopersCheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 32010037SARM gem5 Developers{ 32110037SARM gem5 Developers return write(*(uint64_t*)&data, addr, flags, res); 32210037SARM gem5 Developers} 32310037SARM gem5 Developers 32410037SARM gem5 Developerstemplate<> 32510037SARM gem5 DevelopersFault 32610037SARM gem5 DevelopersCheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 32710037SARM gem5 Developers{ 32810037SARM gem5 Developers return write(*(uint32_t*)&data, addr, flags, res); 32910037SARM gem5 Developers} 3306019Shines@cs.fsu.edu 3316019Shines@cs.fsu.edutemplate<> 33210037SARM gem5 DevelopersFault 33310037SARM gem5 DevelopersCheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 33410037SARM gem5 Developers{ 33510037SARM gem5 Developers return write((uint32_t)data, addr, flags, res); 33610037SARM gem5 Developers} 33710037SARM gem5 Developers 33810037SARM gem5 Developers 33910037SARM gem5 Developers#if FULL_SYSTEM 34010037SARM gem5 DevelopersAddr 34110037SARM gem5 DevelopersCheckerCPU::dbg_vtophys(Addr addr) 34210037SARM gem5 Developers{ 34310037SARM gem5 Developers return vtophys(tc, addr); 34410037SARM gem5 Developers} 34510037SARM gem5 Developers#endif // FULL_SYSTEM 34610037SARM gem5 Developers 34710037SARM gem5 Developersbool 34810037SARM gem5 DevelopersCheckerCPU::translateInstReq(Request *req) 34910037SARM gem5 Developers{ 35010037SARM gem5 Developers#if FULL_SYSTEM 35110037SARM gem5 Developers return (thread->translateInstReq(req) == NoFault); 35210037SARM gem5 Developers#else 35310037SARM gem5 Developers thread->translateInstReq(req); 35410037SARM gem5 Developers return true; 35510037SARM gem5 Developers#endif 35610037SARM gem5 Developers} 35710037SARM gem5 Developers 35810037SARM gem5 Developersvoid 35910037SARM gem5 DevelopersCheckerCPU::translateDataReadReq(Request *req) 36010037SARM gem5 Developers{ 36110037SARM gem5 Developers thread->translateDataReadReq(req); 36210037SARM gem5 Developers 36310037SARM gem5 Developers if (req->getVaddr() != unverifiedReq->getVaddr()) { 36410037SARM gem5 Developers warn("%lli: Request virtual addresses do not match! Inst: %#x, " 36510037SARM gem5 Developers "checker: %#x", 36610037SARM gem5 Developers curTick, unverifiedReq->getVaddr(), req->getVaddr()); 36710037SARM gem5 Developers handleError(); 36810037SARM gem5 Developers } 36910037SARM gem5 Developers req->setPaddr(unverifiedReq->getPaddr()); 37010037SARM gem5 Developers 37110037SARM gem5 Developers if (checkFlags(req)) { 37210037SARM gem5 Developers warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 37310037SARM gem5 Developers curTick, unverifiedReq->getFlags(), req->getFlags()); 37410037SARM gem5 Developers handleError(); 37510037SARM gem5 Developers } 37610037SARM gem5 Developers} 37710037SARM gem5 Developers 37810037SARM gem5 Developersvoid 37910037SARM gem5 DevelopersCheckerCPU::translateDataWriteReq(Request *req) 38010037SARM gem5 Developers{ 38110037SARM gem5 Developers thread->translateDataWriteReq(req); 38210037SARM gem5 Developers 38310037SARM gem5 Developers if (req->getVaddr() != unverifiedReq->getVaddr()) { 38410037SARM gem5 Developers warn("%lli: Request virtual addresses do not match! Inst: %#x, " 38510037SARM gem5 Developers "checker: %#x", 38610037SARM gem5 Developers curTick, unverifiedReq->getVaddr(), req->getVaddr()); 38710037SARM gem5 Developers handleError(); 38810037SARM gem5 Developers } 38910037SARM gem5 Developers req->setPaddr(unverifiedReq->getPaddr()); 39010037SARM gem5 Developers 39110037SARM gem5 Developers if (checkFlags(req)) { 39210037SARM gem5 Developers warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 39310037SARM gem5 Developers curTick, unverifiedReq->getFlags(), req->getFlags()); 39410037SARM gem5 Developers handleError(); 39510037SARM gem5 Developers } 39610037SARM gem5 Developers} 39710037SARM gem5 Developers 39810037SARM gem5 Developersbool 39910037SARM gem5 DevelopersCheckerCPU::checkFlags(Request *req) 40010037SARM gem5 Developers{ 40110037SARM gem5 Developers // Remove any dynamic flags that don't have to do with the request itself. 40210037SARM gem5 Developers unsigned flags = unverifiedReq->getFlags(); 40310037SARM gem5 Developers unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 40410037SARM gem5 Developers flags = flags & (mask); 40510037SARM gem5 Developers if (flags == req->getFlags()) { 40610037SARM gem5 Developers return false; 40710037SARM gem5 Developers } else { 40810037SARM gem5 Developers return true; 40910037SARM gem5 Developers } 41010037SARM gem5 Developers} 41110037SARM gem5 Developers 41210037SARM gem5 Developerstemplate <class DynInstPtr> 41310037SARM gem5 Developersvoid 41410037SARM gem5 DevelopersChecker<DynInstPtr>::tick(DynInstPtr &completed_inst) 41510037SARM gem5 Developers{ 41610037SARM gem5 Developers DynInstPtr inst; 41710037SARM gem5 Developers 41810037SARM gem5 Developers // Either check this instruction, or add it to a list of 41910037SARM gem5 Developers // instructions waiting to be checked. Instructions must be 42010037SARM gem5 Developers // checked in program order, so if a store has committed yet not 42110037SARM gem5 Developers // completed, there may be some instructions that are waiting 42210037SARM gem5 Developers // behind it that have completed and must be checked. 42310037SARM gem5 Developers if (!instList.empty()) { 42410037SARM gem5 Developers if (youngestSN < completed_inst->seqNum) { 42510037SARM gem5 Developers DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 42610037SARM gem5 Developers completed_inst->seqNum, completed_inst->readPC()); 42710037SARM gem5 Developers instList.push_back(completed_inst); 42810037SARM gem5 Developers youngestSN = completed_inst->seqNum; 42910417Sandreas.hansson@arm.com } 4306019Shines@cs.fsu.edu 43110037SARM gem5 Developers if (!instList.front()->isCompleted()) { 43210037SARM gem5 Developers return; 43310037SARM gem5 Developers } else { 43410037SARM gem5 Developers inst = instList.front(); 43510037SARM gem5 Developers instList.pop_front(); 43610037SARM gem5 Developers } 43710037SARM gem5 Developers } else { 43810037SARM gem5 Developers if (!completed_inst->isCompleted()) { 43910037SARM gem5 Developers if (youngestSN < completed_inst->seqNum) { 44010037SARM gem5 Developers DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", 44110037SARM gem5 Developers completed_inst->seqNum, completed_inst->readPC()); 44210037SARM gem5 Developers instList.push_back(completed_inst); 44310037SARM gem5 Developers youngestSN = completed_inst->seqNum; 44410037SARM gem5 Developers } 44510037SARM gem5 Developers return; 44610037SARM gem5 Developers } else { 44710037SARM gem5 Developers if (youngestSN < completed_inst->seqNum) { 44810037SARM gem5 Developers inst = completed_inst; 44910037SARM gem5 Developers youngestSN = completed_inst->seqNum; 45010037SARM gem5 Developers } else { 45110037SARM gem5 Developers return; 45210037SARM gem5 Developers } 45310037SARM gem5 Developers } 45410037SARM gem5 Developers } 45510037SARM gem5 Developers 45610037SARM gem5 Developers // Try to check all instructions that are completed, ending if we 45710037SARM gem5 Developers // run out of instructions to check or if an instruction is not 45810037SARM gem5 Developers // yet completed. 45910037SARM gem5 Developers while (1) { 46010037SARM gem5 Developers DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", 4616735Sgblack@eecs.umich.edu inst->seqNum, inst->readPC()); 4628782Sgblack@eecs.umich.edu unverifiedResult.integer = inst->readIntResult(); 4638782Sgblack@eecs.umich.edu unverifiedReq = inst->req; 4646735Sgblack@eecs.umich.edu unverifiedMemData = inst->memData; 4656019Shines@cs.fsu.edu numCycles++; 4666735Sgblack@eecs.umich.edu 46710037SARM gem5 Developers Fault fault = NoFault; 4688303SAli.Saidi@ARM.com 46910338SCurtis.Dunham@arm.com // maintain $r0 semantics 47010338SCurtis.Dunham@arm.com thread->setIntReg(ZeroReg, 0); 47110338SCurtis.Dunham@arm.com#ifdef TARGET_ALPHA 47210338SCurtis.Dunham@arm.com thread->setFloatRegDouble(ZeroReg, 0.0); 4738303SAli.Saidi@ARM.com#endif // TARGET_ALPHA 4747720Sgblack@eecs.umich.edu 4758205SAli.Saidi@ARM.com // Check if any recent PC changes match up with anything we 4768205SAli.Saidi@ARM.com // expect to happen. This is mostly to check if traps or 4778205SAli.Saidi@ARM.com // PC-based events have occurred in both the checker and CPU. 4786735Sgblack@eecs.umich.edu if (changedPC) { 47910037SARM gem5 Developers DPRINTF(Checker, "Changed PC recently to %#x\n", 48010037SARM gem5 Developers thread->readPC()); 48110037SARM gem5 Developers if (willChangePC) { 48210037SARM gem5 Developers if (newPC == thread->readPC()) { 48310037SARM gem5 Developers DPRINTF(Checker, "Changed PC matches expected PC\n"); 48410037SARM gem5 Developers } else { 48510037SARM gem5 Developers warn("%lli: Changed PC does not match expected PC, " 48610037SARM gem5 Developers "changed: %#x, expected: %#x", 48710037SARM gem5 Developers curTick, thread->readPC(), newPC); 48810037SARM gem5 Developers handleError(); 48910037SARM gem5 Developers } 49010037SARM gem5 Developers willChangePC = false; 49110037SARM gem5 Developers } 49210037SARM gem5 Developers changedPC = false; 49310037SARM gem5 Developers } 49410037SARM gem5 Developers if (changedNextPC) { 49510037SARM gem5 Developers DPRINTF(Checker, "Changed NextPC recently to %#x\n", 49610037SARM gem5 Developers thread->readNextPC()); 49710037SARM gem5 Developers changedNextPC = false; 49810037SARM gem5 Developers } 49910037SARM gem5 Developers 50010037SARM gem5 Developers // Try to fetch the instruction 50110037SARM gem5 Developers 50210037SARM gem5 Developers#if FULL_SYSTEM 50310037SARM gem5 Developers#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0 50410037SARM gem5 Developers#else 50510037SARM gem5 Developers#define IFETCH_FLAGS(pc) 0 50610037SARM gem5 Developers#endif 50710037SARM gem5 Developers 50810037SARM gem5 Developers uint64_t fetch_PC = thread->readPC() & ~3; 50910037SARM gem5 Developers 51010037SARM gem5 Developers // set up memory request for instruction fetch 51110037SARM gem5 Developers memReq = new Request(inst->threadNumber, fetch_PC, 51210037SARM gem5 Developers sizeof(uint32_t), 51310037SARM gem5 Developers IFETCH_FLAGS(thread->readPC()), 51410037SARM gem5 Developers fetch_PC, thread->readCpuId(), inst->threadNumber); 51510037SARM gem5 Developers 51610037SARM gem5 Developers bool succeeded = translateInstReq(memReq); 51710037SARM gem5 Developers 51810037SARM gem5 Developers if (!succeeded) { 51910037SARM gem5 Developers if (inst->getFault() == NoFault) { 52010037SARM gem5 Developers // In this case the instruction was not a dummy 52110037SARM gem5 Developers // instruction carrying an ITB fault. In the single 52210037SARM gem5 Developers // threaded case the ITB should still be able to 52310037SARM gem5 Developers // translate this instruction; in the SMT case it's 52410037SARM gem5 Developers // possible that its ITB entry was kicked out. 52510037SARM gem5 Developers warn("%lli: Instruction PC %#x was not found in the ITB!", 52610037SARM gem5 Developers curTick, thread->readPC()); 5276735Sgblack@eecs.umich.edu handleError(); 5286735Sgblack@eecs.umich.edu 5296735Sgblack@eecs.umich.edu // go to the next instruction 53010037SARM gem5 Developers thread->setPC(thread->readNextPC()); 5318518Sgeoffrey.blake@arm.com thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 5328518Sgeoffrey.blake@arm.com 5336735Sgblack@eecs.umich.edu return; 53410037SARM gem5 Developers } else { 53510037SARM gem5 Developers // The instruction is carrying an ITB fault. Handle 53610037SARM gem5 Developers // the fault and see if our results match the CPU on 53710037SARM gem5 Developers // the next tick(). 53810037SARM gem5 Developers fault = inst->getFault(); 53910037SARM gem5 Developers } 54010037SARM gem5 Developers } 54110037SARM gem5 Developers 54210037SARM gem5 Developers if (fault == NoFault) { 54310037SARM gem5 Developers Packet *pkt = new Packet(memReq, Packet::ReadReq, 54410037SARM gem5 Developers Packet::Broadcast); 54510037SARM gem5 Developers 5466735Sgblack@eecs.umich.edu pkt->dataStatic(&machInst); 5476735Sgblack@eecs.umich.edu 5486735Sgblack@eecs.umich.edu icachePort->sendFunctional(pkt); 5496735Sgblack@eecs.umich.edu 5506735Sgblack@eecs.umich.edu delete pkt; 5516735Sgblack@eecs.umich.edu 5526735Sgblack@eecs.umich.edu // keep an instruction count 5536735Sgblack@eecs.umich.edu numInst++; 5546735Sgblack@eecs.umich.edu 55510037SARM gem5 Developers // decode the instruction 55610037SARM gem5 Developers machInst = gtoh(machInst); 55710037SARM gem5 Developers // Checks that the instruction matches what we expected it to be. 5586735Sgblack@eecs.umich.edu // Checks both the machine instruction and the PC. 5596735Sgblack@eecs.umich.edu validateInst(inst); 5606735Sgblack@eecs.umich.edu 5616735Sgblack@eecs.umich.edu curStaticInst = StaticInst::decode(makeExtMI(machInst, 56210037SARM gem5 Developers thread->readPC())); 56310037SARM gem5 Developers 56410037SARM gem5 Developers#if FULL_SYSTEM 56510037SARM gem5 Developers thread->setInst(machInst); 56610037SARM gem5 Developers#endif // FULL_SYSTEM 56710037SARM gem5 Developers 56810037SARM gem5 Developers fault = inst->getFault(); 56910037SARM gem5 Developers } 57010037SARM gem5 Developers 57110037SARM gem5 Developers // Discard fetch's memReq. 5726735Sgblack@eecs.umich.edu delete memReq; 5736735Sgblack@eecs.umich.edu memReq = NULL; 5747093Sgblack@eecs.umich.edu 5757093Sgblack@eecs.umich.edu // Either the instruction was a fault and we should process the fault, 5767720Sgblack@eecs.umich.edu // or we should just go ahead execute the instruction. This assumes 5777585SAli.Saidi@arm.com // that the instruction is properly marked as a fault. 5787720Sgblack@eecs.umich.edu if (fault == NoFault) { 5797720Sgblack@eecs.umich.edu 5807720Sgblack@eecs.umich.edu thread->funcExeInst++; 5817720Sgblack@eecs.umich.edu 5827720Sgblack@eecs.umich.edu fault = curStaticInst->execute(this, NULL); 5837720Sgblack@eecs.umich.edu 58410037SARM gem5 Developers // Checks to make sure instrution results are correct. 58510037SARM gem5 Developers validateExecution(inst); 5867720Sgblack@eecs.umich.edu 5876019Shines@cs.fsu.edu if (curStaticInst->isLoad()) { 5887189Sgblack@eecs.umich.edu ++numLoad; 5897400SAli.Saidi@ARM.com } 59010417Sandreas.hansson@arm.com } 59110037SARM gem5 Developers 59210037SARM gem5 Developers if (fault != NoFault) { 59310037SARM gem5 Developers#if FULL_SYSTEM 59410037SARM gem5 Developers fault->invoke(tc); 59510037SARM gem5 Developers willChangePC = true; 59610037SARM gem5 Developers newPC = thread->readPC(); 59710037SARM gem5 Developers DPRINTF(Checker, "Fault, PC is now %#x\n", newPC); 59810037SARM gem5 Developers#else // !FULL_SYSTEM 59910037SARM gem5 Developers fatal("fault (%d) detected @ PC 0x%08p", fault, thread->readPC()); 60010037SARM gem5 Developers#endif // FULL_SYSTEM 60110037SARM gem5 Developers } else { 60210037SARM gem5 Developers#if THE_ISA != MIPS_ISA 60310037SARM gem5 Developers // go to the next instruction 60410037SARM gem5 Developers thread->setPC(thread->readNextPC()); 60510037SARM gem5 Developers thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); 60610037SARM gem5 Developers#else 60710037SARM gem5 Developers // go to the next instruction 60810037SARM gem5 Developers thread->setPC(thread->readNextPC()); 60910037SARM gem5 Developers thread->setNextPC(thread->readNextNPC()); 61010037SARM gem5 Developers thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst)); 61110037SARM gem5 Developers#endif 61210037SARM gem5 Developers 61310037SARM gem5 Developers } 61410037SARM gem5 Developers 61510037SARM gem5 Developers#if FULL_SYSTEM 61610037SARM gem5 Developers // @todo: Determine if these should happen only if the 61710037SARM gem5 Developers // instruction hasn't faulted. In the SimpleCPU case this may 61810338SCurtis.Dunham@arm.com // not be true, but in the O3 or Ozone case this may be true. 61910338SCurtis.Dunham@arm.com Addr oldpc; 62010338SCurtis.Dunham@arm.com int count = 0; 62110037SARM gem5 Developers do { 62210037SARM gem5 Developers oldpc = thread->readPC(); 62310037SARM gem5 Developers system->pcEventQueue.service(tc); 62410037SARM gem5 Developers count++; 62510037SARM gem5 Developers } while (oldpc != thread->readPC()); 62610037SARM gem5 Developers if (count > 1) { 62710037SARM gem5 Developers willChangePC = true; 62810037SARM gem5 Developers newPC = thread->readPC(); 62910037SARM gem5 Developers DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); 63010037SARM gem5 Developers } 63110338SCurtis.Dunham@arm.com#endif 63210037SARM gem5 Developers 63310037SARM gem5 Developers // @todo: Optionally can check all registers. (Or just those 63410037SARM gem5 Developers // that have been modified). 63510037SARM gem5 Developers validateState(); 63610037SARM gem5 Developers 63710037SARM gem5 Developers if (memReq) { 63810037SARM gem5 Developers delete memReq; 63910037SARM gem5 Developers memReq = NULL; 64010037SARM gem5 Developers } 64110037SARM gem5 Developers 64210037SARM gem5 Developers // Continue verifying instructions if there's another completed 64310037SARM gem5 Developers // instruction waiting to be verified. 64410037SARM gem5 Developers if (instList.empty()) { 64510037SARM gem5 Developers break; 64610037SARM gem5 Developers } else if (instList.front()->isCompleted()) { 64710037SARM gem5 Developers inst = instList.front(); 64810037SARM gem5 Developers instList.pop_front(); 64910037SARM gem5 Developers } else { 65010037SARM gem5 Developers break; 65110037SARM gem5 Developers } 65210037SARM gem5 Developers } 65310037SARM gem5 Developers} 65410037SARM gem5 Developers 65510037SARM gem5 Developerstemplate <class DynInstPtr> 65610037SARM gem5 Developersvoid 65710037SARM gem5 DevelopersChecker<DynInstPtr>::switchOut(Sampler *s) 65810037SARM gem5 Developers{ 65910037SARM gem5 Developers instList.clear(); 66010037SARM gem5 Developers} 66110037SARM gem5 Developers 66210037SARM gem5 Developerstemplate <class DynInstPtr> 66310037SARM gem5 Developersvoid 66410037SARM gem5 DevelopersChecker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU) 66510037SARM gem5 Developers{ 66610037SARM gem5 Developers} 66710037SARM gem5 Developers 66810037SARM gem5 Developerstemplate <class DynInstPtr> 66910037SARM gem5 Developersvoid 67010037SARM gem5 DevelopersChecker<DynInstPtr>::validateInst(DynInstPtr &inst) 67110037SARM gem5 Developers{ 67210037SARM gem5 Developers if (inst->readPC() != thread->readPC()) { 67310037SARM gem5 Developers warn("%lli: PCs do not match! Inst: %#x, checker: %#x", 67410037SARM gem5 Developers curTick, inst->readPC(), thread->readPC()); 67510037SARM gem5 Developers if (changedPC) { 67610037SARM gem5 Developers warn("%lli: Changed PCs recently, may not be an error", 67710037SARM gem5 Developers curTick); 67810037SARM gem5 Developers } else { 67910037SARM gem5 Developers handleError(); 68010037SARM gem5 Developers } 68110417Sandreas.hansson@arm.com } 6827400SAli.Saidi@ARM.com 6838782Sgblack@eecs.umich.edu MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); 68411150Smitch.hayenga@arm.com 6858782Sgblack@eecs.umich.edu if (mi != machInst) { 6868782Sgblack@eecs.umich.edu warn("%lli: Binary instructions do not match! Inst: %#x, " 68710037SARM gem5 Developers "checker: %#x", 68810037SARM gem5 Developers curTick, mi, machInst); 68910037SARM gem5 Developers handleError(); 69010037SARM gem5 Developers } 69110037SARM gem5 Developers} 69210037SARM gem5 Developers 69310037SARM gem5 Developerstemplate <class DynInstPtr> 69410037SARM gem5 Developersvoid 69510037SARM gem5 DevelopersChecker<DynInstPtr>::validateExecution(DynInstPtr &inst) 69610037SARM gem5 Developers{ 69710037SARM gem5 Developers if (inst->numDestRegs()) { 69810037SARM gem5 Developers // @todo: Support more destination registers. 69910037SARM gem5 Developers if (inst->isUnverifiable()) { 70010037SARM gem5 Developers // Unverifiable instructions assume they were executed 70110037SARM gem5 Developers // properly by the CPU. Grab the result from the 70210037SARM gem5 Developers // instruction and write it to the register. 70310037SARM gem5 Developers RegIndex idx = inst->destRegIdx(0); 70410037SARM gem5 Developers if (idx < TheISA::FP_Base_DepTag) { 70510037SARM gem5 Developers thread->setIntReg(idx, inst->readIntResult()); 7067400SAli.Saidi@ARM.com } else if (idx < TheISA::Fpcr_DepTag) { 7077400SAli.Saidi@ARM.com thread->setFloatRegBits(idx, inst->readIntResult()); 7087189Sgblack@eecs.umich.edu } else { 70910417Sandreas.hansson@arm.com thread->setMiscReg(idx, inst->readIntResult()); 7107189Sgblack@eecs.umich.edu } 7118782Sgblack@eecs.umich.edu } else if (result.integer != inst->readIntResult()) { 7128782Sgblack@eecs.umich.edu warn("%lli: Instruction results do not match! (Values may not " 7138806Sgblack@eecs.umich.edu "actually be integers) Inst: %#x, checker: %#x", 7148806Sgblack@eecs.umich.edu curTick, inst->readIntResult(), result.integer); 7158806Sgblack@eecs.umich.edu handleError(); 7168806Sgblack@eecs.umich.edu } 7178806Sgblack@eecs.umich.edu } 7188806Sgblack@eecs.umich.edu 7198806Sgblack@eecs.umich.edu if (inst->readNextPC() != thread->readNextPC()) { 7208806Sgblack@eecs.umich.edu warn("%lli: Instruction next PCs do not match! Inst: %#x, " 7218806Sgblack@eecs.umich.edu "checker: %#x", 7228806Sgblack@eecs.umich.edu curTick, inst->readNextPC(), thread->readNextPC()); 7238806Sgblack@eecs.umich.edu handleError(); 7247189Sgblack@eecs.umich.edu } 7258806Sgblack@eecs.umich.edu 7268806Sgblack@eecs.umich.edu // Checking side effect registers can be difficult if they are not 7277189Sgblack@eecs.umich.edu // checked simultaneously with the execution of the instruction. 7287189Sgblack@eecs.umich.edu // This is because other valid instructions may have modified 7297189Sgblack@eecs.umich.edu // these registers in the meantime, and their values are not 73010037SARM gem5 Developers // stored within the DynInst. 73110037SARM gem5 Developers while (!miscRegIdxs.empty()) { 73210037SARM gem5 Developers int misc_reg_idx = miscRegIdxs.front(); 73310037SARM gem5 Developers miscRegIdxs.pop(); 73410037SARM gem5 Developers 73510037SARM gem5 Developers if (inst->tcBase()->readMiscReg(misc_reg_idx) != 73610037SARM gem5 Developers thread->readMiscReg(misc_reg_idx)) { 73710037SARM gem5 Developers warn("%lli: Misc reg idx %i (side effect) does not match! " 73810037SARM gem5 Developers "Inst: %#x, checker: %#x", 73910037SARM gem5 Developers curTick, misc_reg_idx, 74010037SARM gem5 Developers inst->tcBase()->readMiscReg(misc_reg_idx), 74110037SARM gem5 Developers thread->readMiscReg(misc_reg_idx)); 74210037SARM gem5 Developers handleError(); 74310037SARM gem5 Developers } 74410037SARM gem5 Developers } 74510037SARM gem5 Developers} 74610037SARM gem5 Developers 74710037SARM gem5 Developerstemplate <class DynInstPtr> 74810037SARM gem5 Developersvoid 74910037SARM gem5 DevelopersChecker<DynInstPtr>::validateState() 75010037SARM gem5 Developers{ 75110037SARM gem5 Developers} 75210037SARM gem5 Developers 75310037SARM gem5 Developerstemplate <class DynInstPtr> 75410037SARM gem5 Developersvoid 75510037SARM gem5 DevelopersChecker<DynInstPtr>::dumpInsts() 75610037SARM gem5 Developers{ 75710037SARM gem5 Developers int num = 0; 75810037SARM gem5 Developers 75910037SARM gem5 Developers InstListIt inst_list_it = --(instList.end()); 76010037SARM gem5 Developers 76110037SARM gem5 Developers cprintf("Inst list size: %i\n", instList.size()); 76210037SARM gem5 Developers 76310037SARM gem5 Developers while (inst_list_it != instList.end()) 76410037SARM gem5 Developers { 76510037SARM gem5 Developers cprintf("Instruction:%i\n", 76610037SARM gem5 Developers num); 76710037SARM gem5 Developers 76810037SARM gem5 Developers cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 7697197Sgblack@eecs.umich.edu "Completed:%i\n", 77010417Sandreas.hansson@arm.com (*inst_list_it)->readPC(), 7717197Sgblack@eecs.umich.edu (*inst_list_it)->seqNum, 7728782Sgblack@eecs.umich.edu (*inst_list_it)->threadNumber, 7738782Sgblack@eecs.umich.edu (*inst_list_it)->isCompleted()); 7748806Sgblack@eecs.umich.edu 7758806Sgblack@eecs.umich.edu cprintf("\n"); 7767197Sgblack@eecs.umich.edu 7778806Sgblack@eecs.umich.edu inst_list_it--; 7788806Sgblack@eecs.umich.edu ++num; 7798806Sgblack@eecs.umich.edu } 78010037SARM gem5 Developers 78110037SARM gem5 Developers} 78210037SARM gem5 Developers 78310037SARM gem5 Developers//template 78410037SARM gem5 Developers//class Checker<RefCountingPtr<OzoneDynInst<OzoneImpl> > >; 78510037SARM gem5 Developers 7868806Sgblack@eecs.umich.edutemplate 7878806Sgblack@eecs.umich.educlass Checker<RefCountingPtr<AlphaDynInst<AlphaSimpleImpl> > >; 7888806Sgblack@eecs.umich.edu