cpu.cc revision 3348:11f6ef023158
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/vtophys.hh" 42#include "kern/kernel_stats.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#endif 76 77 result.integer = 0; 78} 79 80CheckerCPU::~CheckerCPU() 81{ 82} 83 84void 85CheckerCPU::setMemory(MemObject *mem) 86{ 87#if !FULL_SYSTEM 88 memPtr = mem; 89 thread = new SimpleThread(this, /* thread_num */ 0, process, 90 /* asid */ 0, mem); 91 92 thread->setStatus(ThreadContext::Suspended); 93 tc = thread->getTC(); 94 threadContexts.push_back(tc); 95#endif 96} 97 98void 99CheckerCPU::setSystem(System *system) 100{ 101#if FULL_SYSTEM 102 systemPtr = system; 103 104 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 105 106 thread->setStatus(ThreadContext::Suspended); 107 tc = thread->getTC(); 108 threadContexts.push_back(tc); 109 delete thread->kernelStats; 110 thread->kernelStats = NULL; 111#endif 112} 113 114void 115CheckerCPU::setIcachePort(Port *icache_port) 116{ 117 icachePort = icache_port; 118} 119 120void 121CheckerCPU::setDcachePort(Port *dcache_port) 122{ 123 dcachePort = dcache_port; 124} 125 126void 127CheckerCPU::serialize(ostream &os) 128{ 129/* 130 BaseCPU::serialize(os); 131 SERIALIZE_SCALAR(inst); 132 nameOut(os, csprintf("%s.xc", name())); 133 thread->serialize(os); 134 cacheCompletionEvent.serialize(os); 135*/ 136} 137 138void 139CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 140{ 141/* 142 BaseCPU::unserialize(cp, section); 143 UNSERIALIZE_SCALAR(inst); 144 thread->unserialize(cp, csprintf("%s.xc", section)); 145*/ 146} 147 148Fault 149CheckerCPU::copySrcTranslate(Addr src) 150{ 151 panic("Unimplemented!"); 152} 153 154Fault 155CheckerCPU::copy(Addr dest) 156{ 157 panic("Unimplemented!"); 158} 159 160template <class T> 161Fault 162CheckerCPU::read(Addr addr, T &data, unsigned flags) 163{ 164 // need to fill in CPU & thread IDs here 165 memReq = new Request(); 166 167 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 168 169 // translate to physical address 170 translateDataReadReq(memReq); 171 172 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 173 174 pkt->dataStatic(&data); 175 176 if (!(memReq->isUncacheable())) { 177 // Access memory to see if we have the same data 178 dcachePort->sendFunctional(pkt); 179 } else { 180 // Assume the data is correct if it's an uncached access 181 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 182 } 183 184 delete pkt; 185 186 return NoFault; 187} 188 189#ifndef DOXYGEN_SHOULD_SKIP_THIS 190 191template 192Fault 193CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 194 195template 196Fault 197CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 198 199template 200Fault 201CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 202 203template 204Fault 205CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 206 207#endif //DOXYGEN_SHOULD_SKIP_THIS 208 209template<> 210Fault 211CheckerCPU::read(Addr addr, double &data, unsigned flags) 212{ 213 return read(addr, *(uint64_t*)&data, flags); 214} 215 216template<> 217Fault 218CheckerCPU::read(Addr addr, float &data, unsigned flags) 219{ 220 return read(addr, *(uint32_t*)&data, flags); 221} 222 223template<> 224Fault 225CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 226{ 227 return read(addr, (uint32_t&)data, flags); 228} 229 230template <class T> 231Fault 232CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 233{ 234 // need to fill in CPU & thread IDs here 235 memReq = new Request(); 236 237 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 238 239 // translate to physical address 240 thread->translateDataWriteReq(memReq); 241 242 // Can compare the write data and result only if it's cacheable, 243 // not a store conditional, or is a store conditional that 244 // succeeded. 245 // @todo: Verify that actual memory matches up with these values. 246 // Right now it only verifies that the instruction data is the 247 // same as what was in the request that got sent to memory; there 248 // is no verification that it is the same as what is in memory. 249 // This is because the LSQ would have to be snooped in the CPU to 250 // verify this data. 251 if (unverifiedReq && 252 !(unverifiedReq->isUncacheable()) && 253 (!(unverifiedReq->isLocked()) || 254 ((unverifiedReq->isLocked()) && 255 unverifiedReq->getScResult() == 1))) { 256 T inst_data; 257/* 258 // This code would work if the LSQ allowed for snooping. 259 Packet *pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 260 pkt.dataStatic(&inst_data); 261 262 dcachePort->sendFunctional(pkt); 263 264 delete pkt; 265*/ 266 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 267 268 if (data != inst_data) { 269 warn("%lli: Store value does not match value in memory! " 270 "Instruction: %#x, memory: %#x", 271 curTick, inst_data, data); 272 handleError(); 273 } 274 } 275 276 // Assume the result was the same as the one passed in. This checker 277 // doesn't check if the SC should succeed or fail, it just checks the 278 // value. 279 if (res && unverifiedReq->scResultValid()) 280 *res = unverifiedReq->getScResult(); 281 282 return NoFault; 283} 284 285 286#ifndef DOXYGEN_SHOULD_SKIP_THIS 287template 288Fault 289CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 290 291template 292Fault 293CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 294 295template 296Fault 297CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 298 299template 300Fault 301CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 302 303#endif //DOXYGEN_SHOULD_SKIP_THIS 304 305template<> 306Fault 307CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 308{ 309 return write(*(uint64_t*)&data, addr, flags, res); 310} 311 312template<> 313Fault 314CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 315{ 316 return write(*(uint32_t*)&data, addr, flags, res); 317} 318 319template<> 320Fault 321CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 322{ 323 return write((uint32_t)data, addr, flags, res); 324} 325 326 327#if FULL_SYSTEM 328Addr 329CheckerCPU::dbg_vtophys(Addr addr) 330{ 331 return vtophys(tc, addr); 332} 333#endif // FULL_SYSTEM 334 335bool 336CheckerCPU::translateInstReq(Request *req) 337{ 338#if FULL_SYSTEM 339 return (thread->translateInstReq(req) == NoFault); 340#else 341 thread->translateInstReq(req); 342 return true; 343#endif 344} 345 346void 347CheckerCPU::translateDataReadReq(Request *req) 348{ 349 thread->translateDataReadReq(req); 350 351 if (req->getVaddr() != unverifiedReq->getVaddr()) { 352 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 353 "checker: %#x", 354 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 355 handleError(); 356 } 357 req->setPaddr(unverifiedReq->getPaddr()); 358 359 if (checkFlags(req)) { 360 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 361 curTick, unverifiedReq->getFlags(), req->getFlags()); 362 handleError(); 363 } 364} 365 366void 367CheckerCPU::translateDataWriteReq(Request *req) 368{ 369 thread->translateDataWriteReq(req); 370 371 if (req->getVaddr() != unverifiedReq->getVaddr()) { 372 warn("%lli: Request virtual addresses do not match! Inst: %#x, " 373 "checker: %#x", 374 curTick, unverifiedReq->getVaddr(), req->getVaddr()); 375 handleError(); 376 } 377 req->setPaddr(unverifiedReq->getPaddr()); 378 379 if (checkFlags(req)) { 380 warn("%lli: Request flags do not match! Inst: %#x, checker: %#x", 381 curTick, unverifiedReq->getFlags(), req->getFlags()); 382 handleError(); 383 } 384} 385 386bool 387CheckerCPU::checkFlags(Request *req) 388{ 389 // Remove any dynamic flags that don't have to do with the request itself. 390 unsigned flags = unverifiedReq->getFlags(); 391 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 392 flags = flags & (mask); 393 if (flags == req->getFlags()) { 394 return false; 395 } else { 396 return true; 397 } 398} 399 400void 401CheckerCPU::dumpAndExit() 402{ 403 warn("%lli: Checker PC:%#x, next PC:%#x", 404 curTick, thread->readPC(), thread->readNextPC()); 405 panic("Checker found an error!"); 406} 407