base_dyn_inst_impl.hh revision 1060
1/* 2 * Copyright (c) 2001-2004 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 29#ifndef __BASE_DYN_INST_CC__ 30#define __BASE_DYN_INST_CC__ 31 32#include <iostream> 33#include <string> 34#include <sstream> 35 36#include "base/cprintf.hh" 37 38#include "arch/alpha/faults.hh" 39#include "cpu/exetrace.hh" 40#include "mem/mem_req.hh" 41 42#include "cpu/base_dyn_inst.hh" 43#include "cpu/beta_cpu/alpha_impl.hh" 44#include "cpu/beta_cpu/alpha_full_cpu.hh" 45 46using namespace std; 47 48#define NOHASH 49#ifndef NOHASH 50 51#include "base/hashmap.hh" 52 53unsigned int MyHashFunc(const BaseDynInst *addr) 54{ 55 unsigned a = (unsigned)addr; 56 unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF; 57 58 return hash; 59} 60 61typedef m5::hash_map<const BaseDynInst *, const BaseDynInst *, MyHashFunc> my_hash_t; 62my_hash_t thishash; 63#endif 64 65/** This may need to be specific to an implementation. */ 66//int BaseDynInst<Impl>::instcount = 0; 67 68//int break_inst = -1; 69 70template<class Impl> 71BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC, 72 Addr pred_PC, InstSeqNum seq_num, 73 FullCPU *cpu) 74 : staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase()) 75{ 76 effAddr = MemReq::inval_addr; 77 physEffAddr = MemReq::inval_addr; 78 79 readyRegs = 0; 80 81 seqNum = seq_num; 82 83 specMemWrite = false; 84 85 canIssue = false; 86 issued = false; 87 executed = false; 88 canCommit = false; 89 squashed = false; 90 squashedInIQ = false; 91 92 blockingInst = false; 93 recoverInst = false; 94 specMode = false; 95 btbMissed = false; 96 // Eventually make this a parameter. 97 threadNumber = 0; 98 // Also make this a parameter. 99 specMode = true; 100 // Also make this a parameter, or perhaps get it from xc or cpu. 101 asid = 0; 102 103 // Initialize the fault to be unimplemented opcode. 104 fault = Unimplemented_Opcode_Fault; 105 106 PC = inst_PC; 107 nextPC = PC + sizeof(MachInst); 108 predPC = pred_PC; 109 110 // Make sure to have the renamed register entries set to the same 111 // as the normal register entries. It will allow the IQ to work 112 // without any modifications. 113 for (int i = 0; i < staticInst->numDestRegs(); i++) 114 { 115 _destRegIdx[i] = staticInst->destRegIdx(i); 116 } 117 118 for (int i = 0; i < staticInst->numSrcRegs(); i++) 119 { 120 _srcRegIdx[i] = staticInst->srcRegIdx(i); 121 _readySrcRegIdx[i] = 0; 122 } 123 124 ++instcount; 125 126 DPRINTF(FullCPU, "DynInst: Instruction created. Instcount=%i\n", 127 instcount); 128} 129 130template<class Impl> 131BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst) 132 : staticInst(_staticInst), traceData(NULL) 133{ 134 effAddr = MemReq::inval_addr; 135 physEffAddr = MemReq::inval_addr; 136 137 specMemWrite = false; 138 139 blockingInst = false; 140 recoverInst = false; 141 specMode = false; 142 btbMissed = false; 143 144 // Make sure to have the renamed register entries set to the same 145 // as the normal register entries. It will allow the IQ to work 146 // without any modifications. 147 for (int i = 0; i < staticInst->numDestRegs(); i++) 148 { 149 _destRegIdx[i] = staticInst->destRegIdx(i); 150 } 151 152 for (int i = 0; i < staticInst->numSrcRegs(); i++) 153 { 154 _srcRegIdx[i] = staticInst->srcRegIdx(i); 155 } 156} 157 158template<class Impl> 159BaseDynInst<Impl>::~BaseDynInst() 160{ 161/* 162 if (specMemWrite) { 163 // Remove effects of this instruction from speculative memory 164 xc->spec_mem->erase(effAddr); 165 } 166*/ 167 --instcount; 168 DPRINTF(FullCPU, "DynInst: Instruction destroyed. Instcount=%i\n", 169 instcount); 170} 171 172template<class Impl> 173FunctionalMemory * 174BaseDynInst<Impl>::getMemory(void) 175{ 176 return xc->mem; 177} 178/* 179template<class Impl> 180IntReg * 181BaseDynInst<Impl>::getIntegerRegs(void) 182{ 183 return (spec_mode ? xc->specIntRegFile : xc->regs.intRegFile); 184} 185*/ 186template<class Impl> 187void 188BaseDynInst<Impl>::prefetch(Addr addr, unsigned flags) 189{ 190 // This is the "functional" implementation of prefetch. Not much 191 // happens here since prefetches don't affect the architectural 192 // state. 193 194 // Generate a MemReq so we can translate the effective address. 195 MemReqPtr req = new MemReq(addr, xc, 1, flags); 196 req->asid = asid; 197 198 // Prefetches never cause faults. 199 fault = No_Fault; 200 201 // note this is a local, not BaseDynInst::fault 202 Fault trans_fault = xc->translateDataReadReq(req); 203 204 if (trans_fault == No_Fault && !(req->flags & UNCACHEABLE)) { 205 // It's a valid address to cacheable space. Record key MemReq 206 // parameters so we can generate another one just like it for 207 // the timing access without calling translate() again (which 208 // might mess up the TLB). 209 effAddr = req->vaddr; 210 physEffAddr = req->paddr; 211 memReqFlags = req->flags; 212 } else { 213 // Bogus address (invalid or uncacheable space). Mark it by 214 // setting the eff_addr to InvalidAddr. 215 effAddr = physEffAddr = MemReq::inval_addr; 216 } 217 218 /** 219 * @todo 220 * Replace the disjoint functional memory with a unified one and remove 221 * this hack. 222 */ 223#ifndef FULL_SYSTEM 224 req->paddr = req->vaddr; 225#endif 226 227 if (traceData) { 228 traceData->setAddr(addr); 229 } 230} 231 232template<class Impl> 233void 234BaseDynInst<Impl>::writeHint(Addr addr, int size, unsigned flags) 235{ 236 // Need to create a MemReq here so we can do a translation. This 237 // will casue a TLB miss trap if necessary... not sure whether 238 // that's the best thing to do or not. We don't really need the 239 // MemReq otherwise, since wh64 has no functional effect. 240 MemReqPtr req = new MemReq(addr, xc, size, flags); 241 req->asid = asid; 242 243 fault = xc->translateDataWriteReq(req); 244 245 if (fault == No_Fault && !(req->flags & UNCACHEABLE)) { 246 // Record key MemReq parameters so we can generate another one 247 // just like it for the timing access without calling translate() 248 // again (which might mess up the TLB). 249 effAddr = req->vaddr; 250 physEffAddr = req->paddr; 251 memReqFlags = req->flags; 252 } else { 253 // ignore faults & accesses to uncacheable space... treat as no-op 254 effAddr = physEffAddr = MemReq::inval_addr; 255 } 256 257 storeSize = size; 258 storeData = 0; 259} 260 261/** 262 * @todo Need to find a way to get the cache block size here. 263 */ 264template<class Impl> 265Fault 266BaseDynInst<Impl>::copySrcTranslate(Addr src) 267{ 268 MemReqPtr req = new MemReq(src, xc, 64); 269 req->asid = asid; 270 271 // translate to physical address 272 Fault fault = xc->translateDataReadReq(req); 273 274 if (fault == No_Fault) { 275 xc->copySrcAddr = src; 276 xc->copySrcPhysAddr = req->paddr; 277 } else { 278 xc->copySrcAddr = 0; 279 xc->copySrcPhysAddr = 0; 280 } 281 return fault; 282} 283 284/** 285 * @todo Need to find a way to get the cache block size here. 286 */ 287template<class Impl> 288Fault 289BaseDynInst<Impl>::copy(Addr dest) 290{ 291 uint8_t data[64]; 292 FunctionalMemory *mem = xc->mem; 293 assert(xc->copySrcPhysAddr || xc->misspeculating()); 294 MemReqPtr req = new MemReq(dest, xc, 64); 295 req->asid = asid; 296 297 // translate to physical address 298 Fault fault = xc->translateDataWriteReq(req); 299 300 if (fault == No_Fault) { 301 Addr dest_addr = req->paddr; 302 // Need to read straight from memory since we have more than 8 bytes. 303 req->paddr = xc->copySrcPhysAddr; 304 mem->read(req, data); 305 req->paddr = dest_addr; 306 mem->write(req, data); 307 } 308 return fault; 309} 310 311template<class Impl> 312void 313BaseDynInst<Impl>::dump() 314{ 315 cprintf("T%d : %#08d `", threadNumber, PC); 316 cout << staticInst->disassemble(PC); 317 cprintf("'\n"); 318} 319 320template<class Impl> 321void 322BaseDynInst<Impl>::dump(std::string &outstring) 323{ 324 std::ostringstream s; 325 s << "T" << threadNumber << " : 0x" << PC << " " 326 << staticInst->disassemble(PC); 327 328 outstring = s.str(); 329} 330 331 332#if 0 333template<class Impl> 334Fault 335BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes) 336{ 337 Fault fault; 338 339 // check alignments, even speculative this test should always pass 340 if ((nbytes & nbytes - 1) != 0 || (addr & nbytes - 1) != 0) { 341 for (int i = 0; i < nbytes; i++) 342 ((char *) p)[i] = 0; 343 344 // I added the following because according to the comment above, 345 // we should never get here. The comment lies 346#if 0 347 panic("unaligned access. Cycle = %n", curTick); 348#endif 349 return No_Fault; 350 } 351 352 MemReqPtr req = new MemReq(addr, thread, nbytes); 353 switch(cmd) { 354 case Read: 355 fault = spec_mem->read(req, (uint8_t *)p); 356 break; 357 358 case Write: 359 fault = spec_mem->write(req, (uint8_t *)p); 360 if (fault != No_Fault) 361 break; 362 363 specMemWrite = true; 364 storeSize = nbytes; 365 switch(nbytes) { 366 case sizeof(uint8_t): 367 *(uint8_t)&storeData = (uint8_t *)p; 368 break; 369 case sizeof(uint16_t): 370 *(uint16_t)&storeData = (uint16_t *)p; 371 break; 372 case sizeof(uint32_t): 373 *(uint32_t)&storeData = (uint32_t *)p; 374 break; 375 case sizeof(uint64_t): 376 *(uint64_t)&storeData = (uint64_t *)p; 377 break; 378 } 379 break; 380 381 default: 382 fault = Machine_Check_Fault; 383 break; 384 } 385 386 trace_mem(fault, cmd, addr, p, nbytes); 387 388 return fault; 389} 390 391#endif 392 393int 394BaseDynInst<AlphaSimpleImpl>::instcount = 0; 395 396// Forward declaration... 397template BaseDynInst<AlphaSimpleImpl>; 398 399#endif // __BASE_DYN_INST_CC__ 400