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