cpu.cc revision 7823
1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Kevin Lim 29 */ 30 31#include <list> 32#include <string> 33 34#include "cpu/base.hh" 35#include "cpu/checker/cpu.hh" 36#include "cpu/simple_thread.hh" 37#include "cpu/static_inst.hh" 38#include "cpu/thread_context.hh" 39 40#if FULL_SYSTEM 41#include "arch/kernel_stats.hh" 42#include "arch/vtophys.hh" 43#endif // FULL_SYSTEM 44 45using namespace std; 46//The CheckerCPU does alpha only 47using namespace AlphaISA; 48 49void 50CheckerCPU::init() 51{ 52} 53 54CheckerCPU::CheckerCPU(Params *p) 55 : BaseCPU(p), thread(NULL), tc(NULL) 56{ 57 memReq = NULL; 58 59 numInst = 0; 60 startNumInst = 0; 61 numLoad = 0; 62 startNumLoad = 0; 63 youngestSN = 0; 64 65 changedPC = willChangePC = changedNextPC = false; 66 67 exitOnError = p->exitOnError; 68 warnOnlyOnLoadError = p->warnOnlyOnLoadError; 69#if FULL_SYSTEM 70 itb = p->itb; 71 dtb = p->dtb; 72 systemPtr = NULL; 73#else 74 process = p->process; 75 thread = new SimpleThread(this, /* thread_num */ 0, process); 76 77 tc = thread->getTC(); 78 threadContexts.push_back(tc); 79#endif 80 81 result.integer = 0; 82} 83 84CheckerCPU::~CheckerCPU() 85{ 86} 87 88void 89CheckerCPU::setSystem(System *system) 90{ 91#if FULL_SYSTEM 92 systemPtr = system; 93 94 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 95 96 tc = thread->getTC(); 97 threadContexts.push_back(tc); 98 delete thread->kernelStats; 99 thread->kernelStats = NULL; 100#endif 101} 102 103void 104CheckerCPU::setIcachePort(Port *icache_port) 105{ 106 icachePort = icache_port; 107} 108 109void 110CheckerCPU::setDcachePort(Port *dcache_port) 111{ 112 dcachePort = dcache_port; 113} 114 115void 116CheckerCPU::serialize(ostream &os) 117{ 118/* 119 BaseCPU::serialize(os); 120 SERIALIZE_SCALAR(inst); 121 nameOut(os, csprintf("%s.xc", name())); 122 thread->serialize(os); 123 cacheCompletionEvent.serialize(os); 124*/ 125} 126 127void 128CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 129{ 130/* 131 BaseCPU::unserialize(cp, section); 132 UNSERIALIZE_SCALAR(inst); 133 thread->unserialize(cp, csprintf("%s.xc", section)); 134*/ 135} 136 137template <class T> 138Fault 139CheckerCPU::read(Addr addr, T &data, unsigned flags) 140{ 141 // need to fill in CPU & thread IDs here 142 memReq = new Request(); 143 144 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 145 146 // translate to physical address 147 dtb->translateAtomic(memReq, tc, false); 148 149 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 150 151 pkt->dataStatic(&data); 152 153 if (!(memReq->isUncacheable())) { 154 // Access memory to see if we have the same data 155 dcachePort->sendFunctional(pkt); 156 } else { 157 // Assume the data is correct if it's an uncached access 158 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 159 } 160 161 delete pkt; 162 163 return NoFault; 164} 165 166#ifndef DOXYGEN_SHOULD_SKIP_THIS 167 168template 169Fault 170CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 171 172template 173Fault 174CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 175 176template 177Fault 178CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 179 180template 181Fault 182CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 183 184#endif //DOXYGEN_SHOULD_SKIP_THIS 185 186template<> 187Fault 188CheckerCPU::read(Addr addr, double &data, unsigned flags) 189{ 190 return read(addr, *(uint64_t*)&data, flags); 191} 192 193template<> 194Fault 195CheckerCPU::read(Addr addr, float &data, unsigned flags) 196{ 197 return read(addr, *(uint32_t*)&data, flags); 198} 199 200template<> 201Fault 202CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 203{ 204 return read(addr, (uint32_t&)data, flags); 205} 206 207template <class T> 208Fault 209CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 210{ 211 // need to fill in CPU & thread IDs here 212 memReq = new Request(); 213 214 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 215 216 // translate to physical address 217 dtb->translateAtomic(memReq, tc, true); 218 219 // Can compare the write data and result only if it's cacheable, 220 // not a store conditional, or is a store conditional that 221 // succeeded. 222 // @todo: Verify that actual memory matches up with these values. 223 // Right now it only verifies that the instruction data is the 224 // same as what was in the request that got sent to memory; there 225 // is no verification that it is the same as what is in memory. 226 // This is because the LSQ would have to be snooped in the CPU to 227 // verify this data. 228 if (unverifiedReq && 229 !(unverifiedReq->isUncacheable()) && 230 (!(unverifiedReq->isLLSC()) || 231 ((unverifiedReq->isLLSC()) && 232 unverifiedReq->getExtraData() == 1))) { 233 T inst_data; 234/* 235 // This code would work if the LSQ allowed for snooping. 236 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 237 pkt.dataStatic(&inst_data); 238 239 dcachePort->sendFunctional(pkt); 240 241 delete pkt; 242*/ 243 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 244 245 if (data != inst_data) { 246 warn("%lli: Store value does not match value in memory! " 247 "Instruction: %#x, memory: %#x", 248 curTick(), inst_data, data); 249 handleError(); 250 } 251 } 252 253 // Assume the result was the same as the one passed in. This checker 254 // doesn't check if the SC should succeed or fail, it just checks the 255 // value. 256 if (res && unverifiedReq->scResultValid()) 257 *res = unverifiedReq->getExtraData(); 258 259 return NoFault; 260} 261 262 263#ifndef DOXYGEN_SHOULD_SKIP_THIS 264template 265Fault 266CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 267 268template 269Fault 270CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 271 272template 273Fault 274CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 275 276template 277Fault 278CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 279 280#endif //DOXYGEN_SHOULD_SKIP_THIS 281 282template<> 283Fault 284CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 285{ 286 return write(*(uint64_t*)&data, addr, flags, res); 287} 288 289template<> 290Fault 291CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 292{ 293 return write(*(uint32_t*)&data, addr, flags, res); 294} 295 296template<> 297Fault 298CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 299{ 300 return write((uint32_t)data, addr, flags, res); 301} 302 303 304#if FULL_SYSTEM 305Addr 306CheckerCPU::dbg_vtophys(Addr addr) 307{ 308 return vtophys(tc, addr); 309} 310#endif // FULL_SYSTEM 311 312bool 313CheckerCPU::checkFlags(Request *req) 314{ 315 // Remove any dynamic flags that don't have to do with the request itself. 316 unsigned flags = unverifiedReq->getFlags(); 317 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH; 318 flags = flags & (mask); 319 if (flags == req->getFlags()) { 320 return false; 321 } else { 322 return true; 323 } 324} 325 326void 327CheckerCPU::dumpAndExit() 328{ 329 warn("%lli: Checker PC:%#x, next PC:%#x", 330 curTick(), thread->readPC(), thread->readNextPC()); 331 panic("Checker found an error!"); 332} 333