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.
29 #ifndef __CPU_BASE_DYN_INST_CC__
30 #define __CPU_BASE_DYN_INST_CC__
36 #include "base/cprintf.hh"
37 #include "base/trace.hh"
39 #include "arch/alpha/faults.hh"
40 #include "cpu/exetrace.hh"
41 #include "mem/mem_req.hh"
43 #include "cpu/base_dyn_inst.hh"
44 #include "cpu/o3/alpha_impl.hh"
45 #include "cpu/o3/alpha_cpu.hh"
52 #include "base/hashmap.hh"
54 unsigned int MyHashFunc(const BaseDynInst
*addr
)
56 unsigned a
= (unsigned)addr
;
57 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
62 typedef m5::hash_map
<const BaseDynInst
*, const BaseDynInst
*, MyHashFunc
> my_hash_t
;
67 BaseDynInst
<Impl
>::BaseDynInst(MachInst machInst
, Addr inst_PC
,
68 Addr pred_PC
, InstSeqNum seq_num
,
70 : staticInst(machInst
), traceData(NULL
), cpu(cpu
), xc(cpu
->xcBase())
75 nextPC
= PC
+ sizeof(MachInst
);
82 BaseDynInst
<Impl
>::BaseDynInst(StaticInstPtr
&_staticInst
)
83 : staticInst(_staticInst
), traceData(NULL
)
90 BaseDynInst
<Impl
>::initVars()
92 effAddr
= MemReq::inval_addr
;
93 physEffAddr
= MemReq::inval_addr
;
103 squashedInIQ
= false;
106 blockingInst
= false;
109 // Eventually make this a parameter.
112 // Also make this a parameter, or perhaps get it from xc or cpu.
115 // Initialize the fault to be unimplemented opcode.
116 fault
= UnimplementedOpcodeFault
;
120 DPRINTF(FullCPU
, "DynInst: Instruction created. Instcount=%i\n",
124 template <class Impl
>
125 BaseDynInst
<Impl
>::~BaseDynInst()
128 DPRINTF(FullCPU
, "DynInst: Instruction destroyed. Instcount=%i\n",
132 template <class Impl
>
134 BaseDynInst
<Impl
>::prefetch(Addr addr
, unsigned flags
)
136 // This is the "functional" implementation of prefetch. Not much
137 // happens here since prefetches don't affect the architectural
140 // Generate a MemReq so we can translate the effective address.
141 MemReqPtr req
= new MemReq(addr
, xc
, 1, flags
);
144 // Prefetches never cause faults.
147 // note this is a local, not BaseDynInst::fault
148 Fault
* trans_fault
= xc
->translateDataReadReq(req
);
150 if (trans_fault
== NoFault
&& !(req
->flags
& UNCACHEABLE
)) {
151 // It's a valid address to cacheable space. Record key MemReq
152 // parameters so we can generate another one just like it for
153 // the timing access without calling translate() again (which
154 // might mess up the TLB).
155 effAddr
= req
->vaddr
;
156 physEffAddr
= req
->paddr
;
157 memReqFlags
= req
->flags
;
159 // Bogus address (invalid or uncacheable space). Mark it by
160 // setting the eff_addr to InvalidAddr.
161 effAddr
= physEffAddr
= MemReq::inval_addr
;
166 * Replace the disjoint functional memory with a unified one and remove
170 req
->paddr
= req
->vaddr
;
174 traceData
->setAddr(addr
);
178 template <class Impl
>
180 BaseDynInst
<Impl
>::writeHint(Addr addr
, int size
, unsigned flags
)
182 // Need to create a MemReq here so we can do a translation. This
183 // will casue a TLB miss trap if necessary... not sure whether
184 // that's the best thing to do or not. We don't really need the
185 // MemReq otherwise, since wh64 has no functional effect.
186 MemReqPtr req
= new MemReq(addr
, xc
, size
, flags
);
189 fault
= xc
->translateDataWriteReq(req
);
191 if (fault
== NoFault
&& !(req
->flags
& UNCACHEABLE
)) {
192 // Record key MemReq parameters so we can generate another one
193 // just like it for the timing access without calling translate()
194 // again (which might mess up the TLB).
195 effAddr
= req
->vaddr
;
196 physEffAddr
= req
->paddr
;
197 memReqFlags
= req
->flags
;
199 // ignore faults & accesses to uncacheable space... treat as no-op
200 effAddr
= physEffAddr
= MemReq::inval_addr
;
208 * @todo Need to find a way to get the cache block size here.
210 template <class Impl
>
212 BaseDynInst
<Impl
>::copySrcTranslate(Addr src
)
214 MemReqPtr req
= new MemReq(src
, xc
, 64);
217 // translate to physical address
218 Fault
* fault
= xc
->translateDataReadReq(req
);
220 if (fault
== NoFault
) {
221 xc
->copySrcAddr
= src
;
222 xc
->copySrcPhysAddr
= req
->paddr
;
225 xc
->copySrcPhysAddr
= 0;
231 * @todo Need to find a way to get the cache block size here.
233 template <class Impl
>
235 BaseDynInst
<Impl
>::copy(Addr dest
)
238 FunctionalMemory
*mem
= xc
->mem
;
239 assert(xc
->copySrcPhysAddr
|| xc
->misspeculating());
240 MemReqPtr req
= new MemReq(dest
, xc
, 64);
243 // translate to physical address
244 Fault
* fault
= xc
->translateDataWriteReq(req
);
246 if (fault
== NoFault
) {
247 Addr dest_addr
= req
->paddr
;
248 // Need to read straight from memory since we have more than 8 bytes.
249 req
->paddr
= xc
->copySrcPhysAddr
;
250 mem
->read(req
, data
);
251 req
->paddr
= dest_addr
;
252 mem
->write(req
, data
);
257 template <class Impl
>
259 BaseDynInst
<Impl
>::dump()
261 cprintf("T%d : %#08d `", threadNumber
, PC
);
262 cout
<< staticInst
->disassemble(PC
);
266 template <class Impl
>
268 BaseDynInst
<Impl
>::dump(std::string
&outstring
)
270 std::ostringstream s
;
271 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
272 << staticInst
->disassemble(PC
);
279 template <class Impl
>
281 BaseDynInst
<Impl
>::mem_access(mem_cmd cmd
, Addr addr
, void *p
, int nbytes
)
285 // check alignments, even speculative this test should always pass
286 if ((nbytes
& nbytes
- 1) != 0 || (addr
& nbytes
- 1) != 0) {
287 for (int i
= 0; i
< nbytes
; i
++)
290 // I added the following because according to the comment above,
291 // we should never get here. The comment lies
293 panic("unaligned access. Cycle = %n", curTick
);
298 MemReqPtr req
= new MemReq(addr
, thread
, nbytes
);
301 fault
= spec_mem
->read(req
, (uint8_t *)p
);
305 fault
= spec_mem
->write(req
, (uint8_t *)p
);
306 if (fault
!= NoFault
)
312 case sizeof(uint8_t):
313 *(uint8_t)&storeData
= (uint8_t *)p
;
315 case sizeof(uint16_t):
316 *(uint16_t)&storeData
= (uint16_t *)p
;
318 case sizeof(uint32_t):
319 *(uint32_t)&storeData
= (uint32_t *)p
;
321 case sizeof(uint64_t):
322 *(uint64_t)&storeData
= (uint64_t *)p
;
328 fault
= MachineCheckFault
;
332 trace_mem(fault
, cmd
, addr
, p
, nbytes
);
339 template <class Impl
>
341 BaseDynInst
<Impl
>::eaSrcsReady()
343 // For now I am assuming that src registers 1..n-1 are the ones that the
344 // EA calc depends on. (i.e. src reg 0 is the source of the data to be
347 for (int i
= 1; i
< numSrcRegs(); ++i
)
349 if (!_readySrcRegIdx
[i
])
356 // Forward declaration
357 template class BaseDynInst
<AlphaSimpleImpl
>;
361 BaseDynInst
<AlphaSimpleImpl
>::instcount
= 0;
363 #endif // __CPU_BASE_DYN_INST_CC__