2 * Copyright (c) 2001-2004 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 __BASE_DYN_INST_CC__
30 #define __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/beta_cpu/alpha_impl.hh"
45 #include "cpu/beta_cpu/alpha_full_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
;
66 /** This may need to be specific to an implementation. */
67 //int BaseDynInst<Impl>::instcount = 0;
69 //int break_inst = -1;
72 BaseDynInst
<Impl
>::BaseDynInst(MachInst machInst
, Addr inst_PC
,
73 Addr pred_PC
, InstSeqNum seq_num
,
75 : staticInst(machInst
), traceData(NULL
), cpu(cpu
), xc(cpu
->xcBase())
77 DPRINTF(FullCPU
, "DynInst: Creating new DynInst.\n");
79 effAddr
= MemReq::inval_addr
;
80 physEffAddr
= MemReq::inval_addr
;
86 // specMemWrite = false;
99 // Eventually make this a parameter.
101 // Also make this a parameter.
103 // Also make this a parameter, or perhaps get it from xc or cpu.
106 // Initialize the fault to be unimplemented opcode.
107 fault
= Unimplemented_Opcode_Fault
;
110 nextPC
= PC
+ sizeof(MachInst
);
113 // Make sure to have the renamed register entries set to the same
114 // as the normal register entries. It will allow the IQ to work
115 // without any modifications.
116 for (int i
= 0; i
< staticInst
->numDestRegs(); i
++)
118 _destRegIdx
[i
] = staticInst
->destRegIdx(i
);
121 for (int i
= 0; i
< staticInst
->numSrcRegs(); i
++)
123 _srcRegIdx
[i
] = staticInst
->srcRegIdx(i
);
124 _readySrcRegIdx
[i
] = 0;
129 // assert(instcount < 50);
131 DPRINTF(FullCPU
, "DynInst: Instruction created. Instcount=%i\n",
135 template <class Impl
>
136 BaseDynInst
<Impl
>::BaseDynInst(StaticInstPtr
<ISA
> &_staticInst
)
137 : staticInst(_staticInst
), traceData(NULL
)
139 effAddr
= MemReq::inval_addr
;
140 physEffAddr
= MemReq::inval_addr
;
142 // specMemWrite = false;
144 blockingInst
= false;
147 // btbMissed = false;
149 // Make sure to have the renamed register entries set to the same
150 // as the normal register entries. It will allow the IQ to work
151 // without any modifications.
152 for (int i
= 0; i
< staticInst
->numDestRegs(); i
++)
154 _destRegIdx
[i
] = staticInst
->destRegIdx(i
);
157 for (int i
= 0; i
< staticInst
->numSrcRegs(); i
++)
159 _srcRegIdx
[i
] = staticInst
->srcRegIdx(i
);
163 template <class Impl
>
164 BaseDynInst
<Impl
>::~BaseDynInst()
168 // Remove effects of this instruction from speculative memory
169 xc->spec_mem->erase(effAddr);
173 DPRINTF(FullCPU
, "DynInst: Instruction destroyed. Instcount=%i\n",
177 template <class Impl
>
179 BaseDynInst
<Impl
>::getMemory(void)
184 template <class Impl>
186 BaseDynInst<Impl>::getIntegerRegs(void)
188 return (spec_mode ? xc->specIntRegFile : xc->regs.intRegFile);
191 template <class Impl
>
193 BaseDynInst
<Impl
>::prefetch(Addr addr
, unsigned flags
)
195 // This is the "functional" implementation of prefetch. Not much
196 // happens here since prefetches don't affect the architectural
199 // Generate a MemReq so we can translate the effective address.
200 MemReqPtr req
= new MemReq(addr
, xc
, 1, flags
);
203 // Prefetches never cause faults.
206 // note this is a local, not BaseDynInst::fault
207 Fault trans_fault
= xc
->translateDataReadReq(req
);
209 if (trans_fault
== No_Fault
&& !(req
->flags
& UNCACHEABLE
)) {
210 // It's a valid address to cacheable space. Record key MemReq
211 // parameters so we can generate another one just like it for
212 // the timing access without calling translate() again (which
213 // might mess up the TLB).
214 effAddr
= req
->vaddr
;
215 physEffAddr
= req
->paddr
;
216 memReqFlags
= req
->flags
;
218 // Bogus address (invalid or uncacheable space). Mark it by
219 // setting the eff_addr to InvalidAddr.
220 effAddr
= physEffAddr
= MemReq::inval_addr
;
225 * Replace the disjoint functional memory with a unified one and remove
229 req
->paddr
= req
->vaddr
;
233 traceData
->setAddr(addr
);
237 template <class Impl
>
239 BaseDynInst
<Impl
>::writeHint(Addr addr
, int size
, unsigned flags
)
241 // Need to create a MemReq here so we can do a translation. This
242 // will casue a TLB miss trap if necessary... not sure whether
243 // that's the best thing to do or not. We don't really need the
244 // MemReq otherwise, since wh64 has no functional effect.
245 MemReqPtr req
= new MemReq(addr
, xc
, size
, flags
);
248 fault
= xc
->translateDataWriteReq(req
);
250 if (fault
== No_Fault
&& !(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
;
267 * @todo Need to find a way to get the cache block size here.
269 template <class Impl
>
271 BaseDynInst
<Impl
>::copySrcTranslate(Addr src
)
273 MemReqPtr req
= new MemReq(src
, xc
, 64);
276 // translate to physical address
277 Fault fault
= xc
->translateDataReadReq(req
);
279 if (fault
== No_Fault
) {
280 xc
->copySrcAddr
= src
;
281 xc
->copySrcPhysAddr
= req
->paddr
;
284 xc
->copySrcPhysAddr
= 0;
290 * @todo Need to find a way to get the cache block size here.
292 template <class Impl
>
294 BaseDynInst
<Impl
>::copy(Addr dest
)
297 FunctionalMemory
*mem
= xc
->mem
;
298 assert(xc
->copySrcPhysAddr
|| xc
->misspeculating());
299 MemReqPtr req
= new MemReq(dest
, xc
, 64);
302 // translate to physical address
303 Fault fault
= xc
->translateDataWriteReq(req
);
305 if (fault
== No_Fault
) {
306 Addr dest_addr
= req
->paddr
;
307 // Need to read straight from memory since we have more than 8 bytes.
308 req
->paddr
= xc
->copySrcPhysAddr
;
309 mem
->read(req
, data
);
310 req
->paddr
= dest_addr
;
311 mem
->write(req
, data
);
316 template <class Impl
>
318 BaseDynInst
<Impl
>::dump()
320 cprintf("T%d : %#08d `", threadNumber
, PC
);
321 cout
<< staticInst
->disassemble(PC
);
325 template <class Impl
>
327 BaseDynInst
<Impl
>::dump(std::string
&outstring
)
329 std::ostringstream s
;
330 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
331 << staticInst
->disassemble(PC
);
338 template <class Impl
>
340 BaseDynInst
<Impl
>::mem_access(mem_cmd cmd
, Addr addr
, void *p
, int nbytes
)
344 // check alignments, even speculative this test should always pass
345 if ((nbytes
& nbytes
- 1) != 0 || (addr
& nbytes
- 1) != 0) {
346 for (int i
= 0; i
< nbytes
; i
++)
349 // I added the following because according to the comment above,
350 // we should never get here. The comment lies
352 panic("unaligned access. Cycle = %n", curTick
);
357 MemReqPtr req
= new MemReq(addr
, thread
, nbytes
);
360 fault
= spec_mem
->read(req
, (uint8_t *)p
);
364 fault
= spec_mem
->write(req
, (uint8_t *)p
);
365 if (fault
!= No_Fault
)
371 case sizeof(uint8_t):
372 *(uint8_t)&storeData
= (uint8_t *)p
;
374 case sizeof(uint16_t):
375 *(uint16_t)&storeData
= (uint16_t *)p
;
377 case sizeof(uint32_t):
378 *(uint32_t)&storeData
= (uint32_t *)p
;
380 case sizeof(uint64_t):
381 *(uint64_t)&storeData
= (uint64_t *)p
;
387 fault
= Machine_Check_Fault
;
391 trace_mem(fault
, cmd
, addr
, p
, nbytes
);
399 BaseDynInst
<AlphaSimpleImpl
>::instcount
= 0;
401 // Forward declaration...
402 template BaseDynInst
<AlphaSimpleImpl
>;
404 #endif // __BASE_DYN_INST_CC__