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.
34 #include "base/cprintf.hh"
35 #include "base/trace.hh"
37 #include "arch/faults.hh"
38 #include "cpu/exetrace.hh"
39 #include "mem/mem_req.hh"
41 #include "cpu/base_dyn_inst.hh"
42 #include "cpu/o3/alpha_impl.hh"
43 #include "cpu/o3/alpha_cpu.hh"
44 #include "cpu/ozone/simple_impl.hh"
45 #include "cpu/ozone/ozone_impl.hh"
48 using namespace TheISA
;
53 #include "base/hashmap.hh"
55 unsigned int MyHashFunc(const BaseDynInst
*addr
)
57 unsigned a
= (unsigned)addr
;
58 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
63 typedef m5::hash_map
<const BaseDynInst
*, const BaseDynInst
*, MyHashFunc
>
70 BaseDynInst
<Impl
>::BaseDynInst(ExtMachInst machInst
, Addr inst_PC
,
71 Addr pred_PC
, InstSeqNum seq_num
,
73 : staticInst(machInst
), traceData(NULL
), cpu(cpu
)/*, xc(cpu->xcBase())*/
78 nextPC
= PC
+ sizeof(MachInst
);
85 BaseDynInst
<Impl
>::BaseDynInst(StaticInstPtr
&_staticInst
)
86 : staticInst(_staticInst
), traceData(NULL
)
94 BaseDynInst
<Impl
>::initVars()
97 effAddr
= MemReq::inval_addr
;
98 physEffAddr
= MemReq::inval_addr
;
111 squashedInIQ
= false;
112 squashedInLSQ
= false;
113 squashedInROB
= false;
118 reachedCommit
= false;
120 blockingInst
= false;
126 serializeBefore
= false;
127 serializeAfter
= false;
128 serializeHandled
= false;
130 // Eventually make this a parameter.
133 // Also make this a parameter, or perhaps get it from xc or cpu.
136 // Initialize the fault to be unimplemented opcode.
137 // fault = new UnimplementedOpcodeFault;
142 if (instcount
> 1500) {
147 assert(instcount
<= 1500);
150 DPRINTF(DynInst
, "DynInst: [sn:%lli] Instruction created. Instcount=%i\n",
154 cpu
->snList
.insert(seqNum
);
158 template <class Impl
>
159 BaseDynInst
<Impl
>::~BaseDynInst()
171 DPRINTF(DynInst
, "DynInst: [sn:%lli] Instruction destroyed. Instcount=%i\n",
174 cpu
->snList
.erase(seqNum
);
179 template <class Impl
>
181 BaseDynInst
<Impl
>::dumpSNList()
183 std::set
<InstSeqNum
>::iterator sn_it
= cpu
->snList
.begin();
186 while (sn_it
!= cpu
->snList
.end()) {
187 cprintf("%i: [sn:%lli] not destroyed\n", count
, (*sn_it
));
194 template <class Impl
>
196 BaseDynInst
<Impl
>::prefetch(Addr addr
, unsigned flags
)
198 // This is the "functional" implementation of prefetch. Not much
199 // happens here since prefetches don't affect the architectural
202 // Generate a MemReq so we can translate the effective address.
203 MemReqPtr req
= new MemReq(addr
, thread
->getXCProxy(), 1, flags
);
206 // Prefetches never cause faults.
209 // note this is a local, not BaseDynInst::fault
210 Fault trans_fault
= cpu
->translateDataReadReq(req
);
212 if (trans_fault
== NoFault
&& !(req
->flags
& UNCACHEABLE
)) {
213 // It's a valid address to cacheable space. Record key MemReq
214 // parameters so we can generate another one just like it for
215 // the timing access without calling translate() again (which
216 // might mess up the TLB).
217 effAddr
= req
->vaddr
;
218 physEffAddr
= req
->paddr
;
219 memReqFlags
= req
->flags
;
221 // Bogus address (invalid or uncacheable space). Mark it by
222 // setting the eff_addr to InvalidAddr.
223 effAddr
= physEffAddr
= MemReq::inval_addr
;
227 traceData
->setAddr(addr
);
231 template <class Impl
>
233 BaseDynInst
<Impl
>::writeHint(Addr addr
, int size
, unsigned flags
)
235 // Need to create a MemReq here so we can do a translation. This
236 // will casue a TLB miss trap if necessary... not sure whether
237 // that's the best thing to do or not. We don't really need the
238 // MemReq otherwise, since wh64 has no functional effect.
239 MemReqPtr req
= new MemReq(addr
, thread
->getXCProxy(), size
, flags
);
242 fault
= cpu
->translateDataWriteReq(req
);
244 if (fault
== NoFault
&& !(req
->flags
& UNCACHEABLE
)) {
245 // Record key MemReq parameters so we can generate another one
246 // just like it for the timing access without calling translate()
247 // again (which might mess up the TLB).
248 effAddr
= req
->vaddr
;
249 physEffAddr
= req
->paddr
;
250 memReqFlags
= req
->flags
;
252 // ignore faults & accesses to uncacheable space... treat as no-op
253 effAddr
= physEffAddr
= MemReq::inval_addr
;
261 * @todo Need to find a way to get the cache block size here.
263 template <class Impl
>
265 BaseDynInst
<Impl
>::copySrcTranslate(Addr src
)
267 MemReqPtr req
= new MemReq(src
, thread
->getXCProxy(), 64);
270 // translate to physical address
271 Fault fault
= cpu
->translateDataReadReq(req
);
273 if (fault
== NoFault
) {
274 thread
->copySrcAddr
= src
;
275 thread
->copySrcPhysAddr
= req
->paddr
;
277 thread
->copySrcAddr
= 0;
278 thread
->copySrcPhysAddr
= 0;
284 * @todo Need to find a way to get the cache block size here.
286 template <class Impl
>
288 BaseDynInst
<Impl
>::copy(Addr dest
)
291 FunctionalMemory
*mem
= thread
->mem
;
292 assert(thread
->copySrcPhysAddr
|| thread
->misspeculating());
293 MemReqPtr req
= new MemReq(dest
, thread
->getXCProxy(), 64);
296 // translate to physical address
297 Fault fault
= cpu
->translateDataWriteReq(req
);
299 if (fault
== NoFault
) {
300 Addr dest_addr
= req
->paddr
;
301 // Need to read straight from memory since we have more than 8 bytes.
302 req
->paddr
= thread
->copySrcPhysAddr
;
303 mem
->read(req
, data
);
304 req
->paddr
= dest_addr
;
305 mem
->write(req
, data
);
310 template <class Impl
>
312 BaseDynInst
<Impl
>::dump()
314 cprintf("T%d : %#08d `", threadNumber
, PC
);
315 cout
<< staticInst
->disassemble(PC
);
319 template <class Impl
>
321 BaseDynInst
<Impl
>::dump(std::string
&outstring
)
323 std::ostringstream s
;
324 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
325 << staticInst
->disassemble(PC
);
331 template <class Impl
>
333 BaseDynInst
<Impl
>::mem_access(mem_cmd cmd
, Addr addr
, void *p
, int nbytes
)
337 // check alignments, even speculative this test should always pass
338 if ((nbytes
& nbytes
- 1) != 0 || (addr
& nbytes
- 1) != 0) {
339 for (int i
= 0; i
< nbytes
; i
++)
342 // I added the following because according to the comment above,
343 // we should never get here. The comment lies
345 panic("unaligned access. Cycle = %n", curTick
);
350 MemReqPtr req
= new MemReq(addr
, thread
, nbytes
);
353 fault
= spec_mem
->read(req
, (uint8_t *)p
);
357 fault
= spec_mem
->write(req
, (uint8_t *)p
);
358 if (fault
!= NoFault
)
364 case sizeof(uint8_t):
365 *(uint8_t)&storeData
= (uint8_t *)p
;
367 case sizeof(uint16_t):
368 *(uint16_t)&storeData
= (uint16_t *)p
;
370 case sizeof(uint32_t):
371 *(uint32_t)&storeData
= (uint32_t *)p
;
373 case sizeof(uint64_t):
374 *(uint64_t)&storeData
= (uint64_t *)p
;
380 fault
= genMachineCheckFault();
384 trace_mem(fault
, cmd
, addr
, p
, nbytes
);
391 template <class Impl
>
393 BaseDynInst
<Impl
>::markSrcRegReady()
395 if (++readyRegs
== numSrcRegs()) {
400 template <class Impl
>
402 BaseDynInst
<Impl
>::markSrcRegReady(RegIndex src_idx
)
406 _readySrcRegIdx
[src_idx
] = true;
408 if (readyRegs
== numSrcRegs()) {
413 template <class Impl
>
415 BaseDynInst
<Impl
>::eaSrcsReady()
417 // For now I am assuming that src registers 1..n-1 are the ones that the
418 // EA calc depends on. (i.e. src reg 0 is the source of the data to be
421 for (int i
= 1; i
< numSrcRegs(); ++i
) {
422 if (!_readySrcRegIdx
[i
])
429 // Forward declaration
430 template class BaseDynInst
<AlphaSimpleImpl
>;
434 BaseDynInst
<AlphaSimpleImpl
>::instcount
= 0;
436 // Forward declaration
437 template class BaseDynInst
<SimpleImpl
>;
441 BaseDynInst
<SimpleImpl
>::instcount
= 0;
443 // Forward declaration
444 template class BaseDynInst
<OzoneImpl
>;
448 BaseDynInst
<OzoneImpl
>::instcount
= 0;