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