cpu.cc revision 6331:d947798df4a1
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 137Fault 138CheckerCPU::copySrcTranslate(Addr src) 139{ 140 panic("Unimplemented!"); 141} 142 143Fault 144CheckerCPU::copy(Addr dest) 145{ 146 panic("Unimplemented!"); 147} 148 149template <class T> 150Fault 151CheckerCPU::read(Addr addr, T &data, unsigned flags) 152{ 153 // need to fill in CPU & thread IDs here 154 memReq = new Request(); 155 156 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 157 158 // translate to physical address 159 dtb->translateAtomic(memReq, tc, false); 160 161 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 162 163 pkt->dataStatic(&data); 164 165 if (!(memReq->isUncacheable())) { 166 // Access memory to see if we have the same data 167 dcachePort->sendFunctional(pkt); 168 } else { 169 // Assume the data is correct if it's an uncached access 170 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 171 } 172 173 delete pkt; 174 175 return NoFault; 176} 177 178#ifndef DOXYGEN_SHOULD_SKIP_THIS 179 180template 181Fault 182CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 183 184template 185Fault 186CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 187 188template 189Fault 190CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 191 192template 193Fault 194CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 195 196#endif //DOXYGEN_SHOULD_SKIP_THIS 197 198template<> 199Fault 200CheckerCPU::read(Addr addr, double &data, unsigned flags) 201{ 202 return read(addr, *(uint64_t*)&data, flags); 203} 204 205template<> 206Fault 207CheckerCPU::read(Addr addr, float &data, unsigned flags) 208{ 209 return read(addr, *(uint32_t*)&data, flags); 210} 211 212template<> 213Fault 214CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 215{ 216 return read(addr, (uint32_t&)data, flags); 217} 218 219template <class T> 220Fault 221CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 222{ 223 // need to fill in CPU & thread IDs here 224 memReq = new Request(); 225 226 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 227 228 // translate to physical address 229 dtb->translateAtomic(memReq, tc, true); 230 231 // Can compare the write data and result only if it's cacheable, 232 // not a store conditional, or is a store conditional that 233 // succeeded. 234 // @todo: Verify that actual memory matches up with these values. 235 // Right now it only verifies that the instruction data is the 236 // same as what was in the request that got sent to memory; there 237 // is no verification that it is the same as what is in memory. 238 // This is because the LSQ would have to be snooped in the CPU to 239 // verify this data. 240 if (unverifiedReq && 241 !(unverifiedReq->isUncacheable()) && 242 (!(unverifiedReq->isLLSC()) || 243 ((unverifiedReq->isLLSC()) && 244 unverifiedReq->getExtraData() == 1))) { 245 T inst_data; 246/* 247 // This code would work if the LSQ allowed for snooping. 248 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 249 pkt.dataStatic(&inst_data); 250 251 dcachePort->sendFunctional(pkt); 252 253 delete pkt; 254*/ 255 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 256 257 if (data != inst_data) { 258 warn("%lli: Store value does not match value in memory! " 259 "Instruction: %#x, memory: %#x", 260 curTick, inst_data, data); 261 handleError(); 262 } 263 } 264 265 // Assume the result was the same as the one passed in. This checker 266 // doesn't check if the SC should succeed or fail, it just checks the 267 // value. 268 if (res && unverifiedReq->scResultValid()) 269 *res = unverifiedReq->getExtraData(); 270 271 return NoFault; 272} 273 274 275#ifndef DOXYGEN_SHOULD_SKIP_THIS 276template 277Fault 278CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 279 280template 281Fault 282CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 283 284template 285Fault 286CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 287 288template 289Fault 290CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 291 292#endif //DOXYGEN_SHOULD_SKIP_THIS 293 294template<> 295Fault 296CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 297{ 298 return write(*(uint64_t*)&data, addr, flags, res); 299} 300 301template<> 302Fault 303CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 304{ 305 return write(*(uint32_t*)&data, addr, flags, res); 306} 307 308template<> 309Fault 310CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 311{ 312 return write((uint32_t)data, addr, flags, res); 313} 314 315 316#if FULL_SYSTEM 317Addr 318CheckerCPU::dbg_vtophys(Addr addr) 319{ 320 return vtophys(tc, addr); 321} 322#endif // FULL_SYSTEM 323 324bool 325CheckerCPU::checkFlags(Request *req) 326{ 327 // Remove any dynamic flags that don't have to do with the request itself. 328 unsigned flags = unverifiedReq->getFlags(); 329 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | NO_FAULT; 330 flags = flags & (mask); 331 if (flags == req->getFlags()) { 332 return false; 333 } else { 334 return true; 335 } 336} 337 338void 339CheckerCPU::dumpAndExit() 340{ 341 warn("%lli: Checker PC:%#x, next PC:%#x", 342 curTick, thread->readPC(), thread->readNextPC()); 343 panic("Checker found an error!"); 344} 345