2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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.
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.
36 #include "base/cprintf.hh"
37 #include "base/trace.hh"
39 #include "arch/faults.hh"
40 #include "cpu/exetrace.hh"
41 #include "mem/request.hh"
43 #include "cpu/base_dyn_inst.hh"
44 #include "cpu/o3/alpha_impl.hh"
45 #include "cpu/o3/alpha_cpu.hh"
46 //#include "cpu/ozone/simple_impl.hh"
47 //#include "cpu/ozone/ozone_impl.hh"
50 using namespace TheISA
;
55 #include "base/hashmap.hh"
57 unsigned int MyHashFunc(const BaseDynInst
*addr
)
59 unsigned a
= (unsigned)addr
;
60 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
65 typedef m5::hash_map
<const BaseDynInst
*, const BaseDynInst
*, MyHashFunc
>
72 BaseDynInst
<Impl
>::BaseDynInst(ExtMachInst machInst
, Addr inst_PC
,
73 Addr pred_PC
, InstSeqNum seq_num
,
75 : staticInst(machInst
), traceData(NULL
), cpu(cpu
)/*, xc(cpu->xcBase())*/
80 nextPC
= PC
+ sizeof(MachInst
);
87 BaseDynInst
<Impl
>::BaseDynInst(StaticInstPtr
&_staticInst
)
88 : staticInst(_staticInst
), traceData(NULL
)
96 BaseDynInst
<Impl
>::initVars()
113 squashedInIQ
= false;
114 squashedInLSQ
= false;
115 squashedInROB
= false;
120 reachedCommit
= false;
122 blockingInst
= false;
128 serializeBefore
= false;
129 serializeAfter
= false;
130 serializeHandled
= false;
132 // Eventually make this a parameter.
135 // Also make this a parameter, or perhaps get it from xc or cpu.
138 // Initialize the fault to be unimplemented opcode.
139 // fault = new UnimplementedOpcodeFault;
144 if (instcount
> 1500) {
149 assert(instcount
<= 1500);
152 DPRINTF(DynInst
, "DynInst: [sn:%lli] Instruction created. Instcount=%i\n",
156 cpu
->snList
.insert(seqNum
);
160 template <class Impl
>
161 BaseDynInst
<Impl
>::~BaseDynInst()
175 DPRINTF(DynInst
, "DynInst: [sn:%lli] Instruction destroyed. Instcount=%i\n",
178 cpu
->snList
.erase(seqNum
);
183 template <class Impl
>
185 BaseDynInst
<Impl
>::dumpSNList()
187 std::set
<InstSeqNum
>::iterator sn_it
= cpu
->snList
.begin();
190 while (sn_it
!= cpu
->snList
.end()) {
191 cprintf("%i: [sn:%lli] not destroyed\n", count
, (*sn_it
));
198 template <class Impl
>
200 BaseDynInst
<Impl
>::prefetch(Addr addr
, unsigned flags
)
202 // This is the "functional" implementation of prefetch. Not much
203 // happens here since prefetches don't affect the architectural
206 // Generate a MemReq so we can translate the effective address.
207 MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags);
210 // Prefetches never cause faults.
213 // note this is a local, not BaseDynInst::fault
214 Fault trans_fault = cpu->translateDataReadReq(req);
216 if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
217 // It's a valid address to cacheable space. Record key MemReq
218 // parameters so we can generate another one just like it for
219 // the timing access without calling translate() again (which
220 // might mess up the TLB).
221 effAddr = req->vaddr;
222 physEffAddr = req->paddr;
223 memReqFlags = req->flags;
225 // Bogus address (invalid or uncacheable space). Mark it by
226 // setting the eff_addr to InvalidAddr.
227 effAddr = physEffAddr = MemReq::inval_addr;
231 traceData->setAddr(addr);
236 template <class Impl
>
238 BaseDynInst
<Impl
>::writeHint(Addr addr
, int size
, unsigned flags
)
240 // Need to create a MemReq here so we can do a translation. This
241 // will casue a TLB miss trap if necessary... not sure whether
242 // that's the best thing to do or not. We don't really need the
243 // MemReq otherwise, since wh64 has no functional effect.
245 MemReqPtr req = new MemReq(addr, thread->getXCProxy(), size, flags);
248 fault = cpu->translateDataWriteReq(req);
250 if (fault == NoFault && !(req->flags & UNCACHEABLE)) {
251 // Record key MemReq parameters so we can generate another one
252 // just like it for the timing access without calling translate()
253 // again (which might mess up the TLB).
254 effAddr = req->vaddr;
255 physEffAddr = req->paddr;
256 memReqFlags = req->flags;
258 // ignore faults & accesses to uncacheable space... treat as no-op
259 effAddr = physEffAddr = MemReq::inval_addr;
268 * @todo Need to find a way to get the cache block size here.
270 template <class Impl
>
272 BaseDynInst
<Impl
>::copySrcTranslate(Addr src
)
275 MemReqPtr req = new MemReq(src, thread->getXCProxy(), 64);
278 // translate to physical address
279 Fault fault = cpu->translateDataReadReq(req);
281 if (fault == NoFault) {
282 thread->copySrcAddr = src;
283 thread->copySrcPhysAddr = req->paddr;
285 thread->copySrcAddr = 0;
286 thread->copySrcPhysAddr = 0;
294 * @todo Need to find a way to get the cache block size here.
296 template <class Impl
>
298 BaseDynInst
<Impl
>::copy(Addr dest
)
302 FunctionalMemory *mem = thread->mem;
303 assert(thread->copySrcPhysAddr);
304 MemReqPtr req = new MemReq(dest, thread->getXCProxy(), 64);
307 // translate to physical address
308 Fault fault = cpu->translateDataWriteReq(req);
310 if (fault == NoFault) {
311 Addr dest_addr = req->paddr;
312 // Need to read straight from memory since we have more than 8 bytes.
313 req->paddr = thread->copySrcPhysAddr;
314 mem->read(req, data);
315 req->paddr = dest_addr;
316 mem->write(req, data);
323 template <class Impl
>
325 BaseDynInst
<Impl
>::dump()
327 cprintf("T%d : %#08d `", threadNumber
, PC
);
328 cout
<< staticInst
->disassemble(PC
);
332 template <class Impl
>
334 BaseDynInst
<Impl
>::dump(std::string
&outstring
)
336 std::ostringstream s
;
337 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
338 << staticInst
->disassemble(PC
);
344 template <class Impl
>
346 BaseDynInst
<Impl
>::mem_access(mem_cmd cmd
, Addr addr
, void *p
, int nbytes
)
350 // check alignments, even speculative this test should always pass
351 if ((nbytes
& nbytes
- 1) != 0 || (addr
& nbytes
- 1) != 0) {
352 for (int i
= 0; i
< nbytes
; i
++)
355 // I added the following because according to the comment above,
356 // we should never get here. The comment lies
358 panic("unaligned access. Cycle = %n", curTick
);
363 MemReqPtr req
= new MemReq(addr
, thread
, nbytes
);
366 fault
= spec_mem
->read(req
, (uint8_t *)p
);
370 fault
= spec_mem
->write(req
, (uint8_t *)p
);
371 if (fault
!= NoFault
)
377 case sizeof(uint8_t):
378 *(uint8_t)&storeData
= (uint8_t *)p
;
380 case sizeof(uint16_t):
381 *(uint16_t)&storeData
= (uint16_t *)p
;
383 case sizeof(uint32_t):
384 *(uint32_t)&storeData
= (uint32_t *)p
;
386 case sizeof(uint64_t):
387 *(uint64_t)&storeData
= (uint64_t *)p
;
393 fault
= genMachineCheckFault();
397 trace_mem(fault
, cmd
, addr
, p
, nbytes
);
404 template <class Impl
>
406 BaseDynInst
<Impl
>::markSrcRegReady()
408 if (++readyRegs
== numSrcRegs()) {
413 template <class Impl
>
415 BaseDynInst
<Impl
>::markSrcRegReady(RegIndex src_idx
)
419 _readySrcRegIdx
[src_idx
] = true;
421 if (readyRegs
== numSrcRegs()) {
426 template <class Impl
>
428 BaseDynInst
<Impl
>::eaSrcsReady()
430 // For now I am assuming that src registers 1..n-1 are the ones that the
431 // EA calc depends on. (i.e. src reg 0 is the source of the data to be
434 for (int i
= 1; i
< numSrcRegs(); ++i
) {
435 if (!_readySrcRegIdx
[i
])
442 // Forward declaration
443 template class BaseDynInst
<AlphaSimpleImpl
>;
447 BaseDynInst
<AlphaSimpleImpl
>::instcount
= 0;
449 // Forward declaration
450 template class BaseDynInst<SimpleImpl>;
454 BaseDynInst<SimpleImpl>::instcount = 0;
456 // Forward declaration
457 template class BaseDynInst<OzoneImpl>;
461 BaseDynInst<OzoneImpl>::instcount = 0;