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