Merge zizzer.eecs.umich.edu:/z/m5/Bitkeeper/m5
[gem5.git] / cpu / o3 / alpha_cpu.hh
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 // Todo: Find all the stuff in ExecContext and ev5 that needs to be
30 // specifically designed for this CPU.
31
32 #ifndef __CPU_O3_CPU_ALPHA_FULL_CPU_HH__
33 #define __CPU_O3_CPU_ALPHA_FULL_CPU_HH__
34
35 #include "cpu/o3/cpu.hh"
36 #include "arch/isa_traits.hh"
37 #include "sim/byteswap.hh"
38
39 template <class Impl>
40 class AlphaFullCPU : public FullO3CPU<Impl>
41 {
42 protected:
43 typedef TheISA::IntReg IntReg;
44 public:
45 typedef typename Impl::Params Params;
46
47 public:
48 AlphaFullCPU(Params &params);
49
50 #if FULL_SYSTEM
51 AlphaITB *itb;
52 AlphaDTB *dtb;
53 #endif
54
55 public:
56 void regStats();
57
58 #if FULL_SYSTEM
59 //Note that the interrupt stuff from the base CPU might be somewhat
60 //ISA specific (ie NumInterruptLevels). These functions might not
61 //be needed in FullCPU though.
62 // void post_interrupt(int int_num, int index);
63 // void clear_interrupt(int int_num, int index);
64 // void clear_interrupts();
65
66 Fault translateInstReq(MemReqPtr &req)
67 {
68 return itb->translate(req);
69 }
70
71 Fault translateDataReadReq(MemReqPtr &req)
72 {
73 return dtb->translate(req, false);
74 }
75
76 Fault translateDataWriteReq(MemReqPtr &req)
77 {
78 return dtb->translate(req, true);
79 }
80
81 #else
82 Fault dummyTranslation(MemReqPtr &req)
83 {
84 #if 0
85 assert((req->vaddr >> 48 & 0xffff) == 0);
86 #endif
87
88 // put the asid in the upper 16 bits of the paddr
89 req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
90 req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
91 return NoFault;
92 }
93
94 Fault translateInstReq(MemReqPtr &req)
95 {
96 return dummyTranslation(req);
97 }
98
99 Fault translateDataReadReq(MemReqPtr &req)
100 {
101 return dummyTranslation(req);
102 }
103
104 Fault translateDataWriteReq(MemReqPtr &req)
105 {
106 return dummyTranslation(req);
107 }
108
109 #endif
110
111 // Later on may want to remove this misc stuff from the regfile and
112 // have it handled at this level. Might prove to be an issue when
113 // trying to rename source/destination registers...
114 uint64_t readUniq()
115 {
116 return this->regFile.readUniq();
117 }
118
119 void setUniq(uint64_t val)
120 {
121 this->regFile.setUniq(val);
122 }
123
124 uint64_t readFpcr()
125 {
126 return this->regFile.readFpcr();
127 }
128
129 void setFpcr(uint64_t val)
130 {
131 this->regFile.setFpcr(val);
132 }
133
134 // Most of the full system code and syscall emulation is not yet
135 // implemented. These functions do show what the final interface will
136 // look like.
137 #if FULL_SYSTEM
138 uint64_t *getIpr();
139 uint64_t readIpr(int idx, Fault &fault);
140 Fault setIpr(int idx, uint64_t val);
141 int readIntrFlag();
142 void setIntrFlag(int val);
143 Fault hwrei();
144 bool inPalMode() { return AlphaISA::PcPAL(this->regFile.readPC()); }
145 bool inPalMode(uint64_t PC)
146 { return AlphaISA::PcPAL(PC); }
147
148 void trap(Fault fault);
149 bool simPalCheck(int palFunc);
150
151 void processInterrupts();
152 #endif
153
154
155 #if !FULL_SYSTEM
156 // Need to change these into regfile calls that directly set a certain
157 // register. Actually, these functions should handle most of this
158 // functionality by themselves; should look up the rename and then
159 // set the register.
160 IntReg getSyscallArg(int i)
161 {
162 return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
163 }
164
165 // used to shift args for indirect syscall
166 void setSyscallArg(int i, IntReg val)
167 {
168 this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
169 }
170
171 void setSyscallReturn(int64_t return_value)
172 {
173 // check for error condition. Alpha syscall convention is to
174 // indicate success/failure in reg a3 (r19) and put the
175 // return value itself in the standard return value reg (v0).
176 const int RegA3 = 19; // only place this is used
177 if (return_value >= 0) {
178 // no error
179 this->xc->regs.intRegFile[RegA3] = 0;
180 this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
181 } else {
182 // got an error, return details
183 this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
184 this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
185 }
186 }
187
188 void syscall(short thread_num);
189 void squashStages();
190
191 #endif
192
193 void copyToXC();
194 void copyFromXC();
195
196 public:
197 #if FULL_SYSTEM
198 bool palShadowEnabled;
199
200 // Not sure this is used anywhere.
201 void intr_post(RegFile *regs, Fault fault, Addr pc);
202 // Actually used within exec files. Implement properly.
203 void swapPALShadow(bool use_shadow);
204 // Called by CPU constructor. Can implement as I please.
205 void initCPU(RegFile *regs);
206 // Called by initCPU. Implement as I please.
207 void initIPRs(RegFile *regs);
208
209 void halt() { panic("Halt not implemented!\n"); }
210 #endif
211
212
213 template <class T>
214 Fault read(MemReqPtr &req, T &data)
215 {
216 #if FULL_SYSTEM && defined(TARGET_ALPHA)
217 if (req->flags & LOCKED) {
218 MiscRegFile *cregs = &req->xc->regs.miscRegs;
219 cregs->lock_addr = req->paddr;
220 cregs->lock_flag = true;
221 }
222 #endif
223
224 Fault error;
225 error = this->mem->read(req, data);
226 data = gtoh(data);
227 return error;
228 }
229
230 template <class T>
231 Fault read(MemReqPtr &req, T &data, int load_idx)
232 {
233 return this->iew.ldstQueue.read(req, data, load_idx);
234 }
235
236 template <class T>
237 Fault write(MemReqPtr &req, T &data)
238 {
239 #if FULL_SYSTEM && defined(TARGET_ALPHA)
240
241 MiscRegFile *cregs;
242
243 // If this is a store conditional, act appropriately
244 if (req->flags & LOCKED) {
245 cregs = &this->xc->regs.miscRegs;
246
247 if (req->flags & UNCACHEABLE) {
248 // Don't update result register (see stq_c in isa_desc)
249 req->result = 2;
250 req->xc->storeCondFailures = 0;//Needed? [RGD]
251 } else {
252 req->result = cregs->lock_flag;
253 if (!cregs->lock_flag ||
254 ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) {
255 cregs->lock_flag = false;
256 if (((++req->xc->storeCondFailures) % 100000) == 0) {
257 std::cerr << "Warning: "
258 << req->xc->storeCondFailures
259 << " consecutive store conditional failures "
260 << "on cpu " << this->cpu_id
261 << std::endl;
262 }
263 return NoFault;
264 }
265 else req->xc->storeCondFailures = 0;
266 }
267 }
268
269 // Need to clear any locked flags on other proccessors for
270 // this address. Only do this for succsful Store Conditionals
271 // and all other stores (WH64?). Unsuccessful Store
272 // Conditionals would have returned above, and wouldn't fall
273 // through.
274 for (int i = 0; i < this->system->execContexts.size(); i++){
275 cregs = &this->system->execContexts[i]->regs.miscRegs;
276 if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) {
277 cregs->lock_flag = false;
278 }
279 }
280
281 #endif
282
283 return this->mem->write(req, (T)::htog(data));
284 }
285
286 template <class T>
287 Fault write(MemReqPtr &req, T &data, int store_idx)
288 {
289 return this->iew.ldstQueue.write(req, data, store_idx);
290 }
291
292 };
293
294 #endif // __CPU_O3_CPU_ALPHA_FULL_CPU_HH__