cpu.cc revision 8793:5f25086326ac
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 "arch/kernel_stats.hh" 35#include "arch/vtophys.hh" 36#include "cpu/checker/cpu.hh" 37#include "cpu/base.hh" 38#include "cpu/simple_thread.hh" 39#include "cpu/static_inst.hh" 40#include "cpu/thread_context.hh" 41 42using namespace std; 43//The CheckerCPU does alpha only 44using namespace AlphaISA; 45 46void 47CheckerCPU::init() 48{ 49} 50 51CheckerCPU::CheckerCPU(Params *p) 52 : BaseCPU(p), thread(NULL), tc(NULL) 53{ 54 memReq = NULL; 55 56 numInst = 0; 57 startNumInst = 0; 58 numLoad = 0; 59 startNumLoad = 0; 60 youngestSN = 0; 61 62 changedPC = willChangePC = changedNextPC = false; 63 64 exitOnError = p->exitOnError; 65 warnOnlyOnLoadError = p->warnOnlyOnLoadError; 66 itb = p->itb; 67 dtb = p->dtb; 68 systemPtr = NULL; 69 process = p->process; 70 thread = new SimpleThread(this, /* thread_num */ 0, process); 71 72 tc = thread->getTC(); 73 threadContexts.push_back(tc); 74 75 result.integer = 0; 76} 77 78CheckerCPU::~CheckerCPU() 79{ 80} 81 82void 83CheckerCPU::setSystem(System *system) 84{ 85 systemPtr = system; 86 87 thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false); 88 89 tc = thread->getTC(); 90 threadContexts.push_back(tc); 91 delete thread->kernelStats; 92 thread->kernelStats = NULL; 93} 94 95void 96CheckerCPU::setIcachePort(Port *icache_port) 97{ 98 icachePort = icache_port; 99} 100 101void 102CheckerCPU::setDcachePort(Port *dcache_port) 103{ 104 dcachePort = dcache_port; 105} 106 107void 108CheckerCPU::serialize(ostream &os) 109{ 110/* 111 BaseCPU::serialize(os); 112 SERIALIZE_SCALAR(inst); 113 nameOut(os, csprintf("%s.xc", name())); 114 thread->serialize(os); 115 cacheCompletionEvent.serialize(os); 116*/ 117} 118 119void 120CheckerCPU::unserialize(Checkpoint *cp, const string §ion) 121{ 122/* 123 BaseCPU::unserialize(cp, section); 124 UNSERIALIZE_SCALAR(inst); 125 thread->unserialize(cp, csprintf("%s.xc", section)); 126*/ 127} 128 129template <class T> 130Fault 131CheckerCPU::read(Addr addr, T &data, unsigned flags) 132{ 133 // need to fill in CPU & thread IDs here 134 memReq = new Request(); 135 136 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 137 138 // translate to physical address 139 dtb->translateAtomic(memReq, tc, false); 140 141 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 142 143 pkt->dataStatic(&data); 144 145 if (!(memReq->isUncacheable())) { 146 // Access memory to see if we have the same data 147 dcachePort->sendFunctional(pkt); 148 } else { 149 // Assume the data is correct if it's an uncached access 150 memcpy(&data, &unverifiedResult.integer, sizeof(T)); 151 } 152 153 delete pkt; 154 155 return NoFault; 156} 157 158#ifndef DOXYGEN_SHOULD_SKIP_THIS 159 160template 161Fault 162CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags); 163 164template 165Fault 166CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags); 167 168template 169Fault 170CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags); 171 172template 173Fault 174CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags); 175 176#endif //DOXYGEN_SHOULD_SKIP_THIS 177 178template<> 179Fault 180CheckerCPU::read(Addr addr, double &data, unsigned flags) 181{ 182 return read(addr, *(uint64_t*)&data, flags); 183} 184 185template<> 186Fault 187CheckerCPU::read(Addr addr, float &data, unsigned flags) 188{ 189 return read(addr, *(uint32_t*)&data, flags); 190} 191 192template<> 193Fault 194CheckerCPU::read(Addr addr, int32_t &data, unsigned flags) 195{ 196 return read(addr, (uint32_t&)data, flags); 197} 198 199template <class T> 200Fault 201CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) 202{ 203 // need to fill in CPU & thread IDs here 204 memReq = new Request(); 205 206 memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC()); 207 208 // translate to physical address 209 dtb->translateAtomic(memReq, tc, true); 210 211 // Can compare the write data and result only if it's cacheable, 212 // not a store conditional, or is a store conditional that 213 // succeeded. 214 // @todo: Verify that actual memory matches up with these values. 215 // Right now it only verifies that the instruction data is the 216 // same as what was in the request that got sent to memory; there 217 // is no verification that it is the same as what is in memory. 218 // This is because the LSQ would have to be snooped in the CPU to 219 // verify this data. 220 if (unverifiedReq && 221 !(unverifiedReq->isUncacheable()) && 222 (!(unverifiedReq->isLLSC()) || 223 ((unverifiedReq->isLLSC()) && 224 unverifiedReq->getExtraData() == 1))) { 225 T inst_data; 226/* 227 // This code would work if the LSQ allowed for snooping. 228 PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); 229 pkt.dataStatic(&inst_data); 230 231 dcachePort->sendFunctional(pkt); 232 233 delete pkt; 234*/ 235 memcpy(&inst_data, unverifiedMemData, sizeof(T)); 236 237 if (data != inst_data) { 238 warn("%lli: Store value does not match value in memory! " 239 "Instruction: %#x, memory: %#x", 240 curTick(), inst_data, data); 241 handleError(); 242 } 243 } 244 245 // Assume the result was the same as the one passed in. This checker 246 // doesn't check if the SC should succeed or fail, it just checks the 247 // value. 248 if (res && unverifiedReq->scResultValid()) 249 *res = unverifiedReq->getExtraData(); 250 251 return NoFault; 252} 253 254 255#ifndef DOXYGEN_SHOULD_SKIP_THIS 256template 257Fault 258CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res); 259 260template 261Fault 262CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res); 263 264template 265Fault 266CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res); 267 268template 269Fault 270CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res); 271 272#endif //DOXYGEN_SHOULD_SKIP_THIS 273 274template<> 275Fault 276CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res) 277{ 278 return write(*(uint64_t*)&data, addr, flags, res); 279} 280 281template<> 282Fault 283CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res) 284{ 285 return write(*(uint32_t*)&data, addr, flags, res); 286} 287 288template<> 289Fault 290CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res) 291{ 292 return write((uint32_t)data, addr, flags, res); 293} 294 295 296Addr 297CheckerCPU::dbg_vtophys(Addr addr) 298{ 299 return vtophys(tc, addr); 300} 301 302bool 303CheckerCPU::checkFlags(Request *req) 304{ 305 // Remove any dynamic flags that don't have to do with the request itself. 306 unsigned flags = unverifiedReq->getFlags(); 307 unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH; 308 flags = flags & (mask); 309 if (flags == req->getFlags()) { 310 return false; 311 } else { 312 return true; 313 } 314} 315 316void 317CheckerCPU::dumpAndExit() 318{ 319 warn("%lli: Checker PC:%#x, next PC:%#x", 320 curTick(), thread->readPC(), thread->readNextPC()); 321 panic("Checker found an error!"); 322} 323