fix some broken .ini's
[gem5.git] / dev / tsunami_cchip.cc
1 /*
2 * Copyright (c) 2004 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 /* @file
30 * Emulation of the Tsunami CChip CSRs
31 */
32
33 #include <deque>
34 #include <string>
35 #include <vector>
36
37 #include "base/trace.hh"
38 #include "dev/tsunami_cchip.hh"
39 #include "dev/tsunamireg.h"
40 #include "dev/tsunami.hh"
41 #include "mem/bus/bus.hh"
42 #include "mem/bus/pio_interface.hh"
43 #include "mem/bus/pio_interface_impl.hh"
44 #include "mem/functional_mem/memory_control.hh"
45 #include "cpu/intr_control.hh"
46 #include "sim/builder.hh"
47 #include "sim/system.hh"
48
49 using namespace std;
50
51 TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
52 MemoryController *mmu, HierParams *hier, Bus* bus)
53 : PioDevice(name), addr(a), tsunami(t)
54 {
55 mmu->add_child(this, Range<Addr>(addr, addr + size));
56
57 for(int i=0; i < Tsunami::Max_CPUs; i++) {
58 dim[i] = 0;
59 dir[i] = 0;
60 dirInterrupting[i] = false;
61 ipiInterrupting[i] = false;
62 RTCInterrupting[i] = false;
63 }
64
65 if (bus) {
66 pioInterface = newPioInterface(name, hier, bus, this,
67 &TsunamiCChip::cacheAccess);
68 pioInterface->addAddrRange(addr, addr + size - 1);
69 }
70
71 drir = 0;
72 misc = 0;
73
74 //Put back pointer in tsunami
75 tsunami->cchip = this;
76 }
77
78 Fault
79 TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
80 {
81 DPRINTF(Tsunami, "read va=%#x size=%d\n",
82 req->vaddr, req->size);
83
84 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
85 ExecContext *xc = req->xc;
86
87 switch (req->size) {
88
89 case sizeof(uint64_t):
90 switch(daddr) {
91 case TSDEV_CC_CSR:
92 *(uint64_t*)data = 0x0;
93 return No_Fault;
94 case TSDEV_CC_MTR:
95 panic("TSDEV_CC_MTR not implemeted\n");
96 return No_Fault;
97 case TSDEV_CC_MISC:
98 *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
99 return No_Fault;
100 case TSDEV_CC_AAR0:
101 case TSDEV_CC_AAR1:
102 case TSDEV_CC_AAR2:
103 case TSDEV_CC_AAR3:
104 *(uint64_t*)data = 0;
105 return No_Fault;
106 case TSDEV_CC_DIM0:
107 *(uint64_t*)data = dim[0];
108 return No_Fault;
109 case TSDEV_CC_DIM1:
110 *(uint64_t*)data = dim[1];
111 return No_Fault;
112 case TSDEV_CC_DIM2:
113 *(uint64_t*)data = dim[2];
114 return No_Fault;
115 case TSDEV_CC_DIM3:
116 *(uint64_t*)data = dim[3];
117 return No_Fault;
118 case TSDEV_CC_DIR0:
119 *(uint64_t*)data = dir[0];
120 return No_Fault;
121 case TSDEV_CC_DIR1:
122 *(uint64_t*)data = dir[1];
123 return No_Fault;
124 case TSDEV_CC_DIR2:
125 *(uint64_t*)data = dir[2];
126 return No_Fault;
127 case TSDEV_CC_DIR3:
128 *(uint64_t*)data = dir[3];
129 return No_Fault;
130 case TSDEV_CC_DRIR:
131 *(uint64_t*)data = drir;
132 return No_Fault;
133 case TSDEV_CC_PRBEN:
134 panic("TSDEV_CC_PRBEN not implemented\n");
135 return No_Fault;
136 case TSDEV_CC_IIC0:
137 case TSDEV_CC_IIC1:
138 case TSDEV_CC_IIC2:
139 case TSDEV_CC_IIC3:
140 panic("TSDEV_CC_IICx not implemented\n");
141 return No_Fault;
142 case TSDEV_CC_MPR0:
143 case TSDEV_CC_MPR1:
144 case TSDEV_CC_MPR2:
145 case TSDEV_CC_MPR3:
146 panic("TSDEV_CC_MPRx not implemented\n");
147 return No_Fault;
148 default:
149 panic("default in cchip read reached, accessing 0x%x\n");
150 } // uint64_t
151
152 break;
153 case sizeof(uint32_t):
154 case sizeof(uint16_t):
155 case sizeof(uint8_t):
156 default:
157 panic("invalid access size(?) for tsunami register!\n");
158 }
159 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
160
161 return No_Fault;
162 }
163
164 Fault
165 TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
166 {
167 DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
168 req->vaddr, *(uint64_t*)data, req->size);
169
170 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
171
172 bool supportedWrite = false;
173 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
174
175 switch (req->size) {
176
177 case sizeof(uint64_t):
178 switch(daddr) {
179 case TSDEV_CC_CSR:
180 panic("TSDEV_CC_CSR write\n");
181 return No_Fault;
182 case TSDEV_CC_MTR:
183 panic("TSDEV_CC_MTR write not implemented\n");
184 return No_Fault;
185 case TSDEV_CC_MISC:
186 //If it is the 4-7th bit, clear the RTC interrupt
187 uint64_t itintr;
188 if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
189 //Clear the bits in ITINTR
190 misc &= ~(itintr);
191 for (int i=0; i < size; i++) {
192 if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
193 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
194 RTCInterrupting[i] = false;
195 DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
196 }
197 }
198 supportedWrite = true;
199 }
200 //If it is 12th-15th bit, IPI sent to Processor 1
201 uint64_t ipreq;
202 if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) {
203 //Set the bits in IPINTR
204 misc |= (ipreq >> 4);
205 for (int i=0; i < size; i++) {
206 if ((ipreq & (1 << (i + 12)))) {
207 if (!ipiInterrupting[i])
208 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0);
209 ipiInterrupting[i]++;
210 DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i,
211 ipiInterrupting[i], req->cpu_num);
212 }
213 }
214 supportedWrite = true;
215 }
216 //If it is bits 8-11, then clearing IPI's
217 uint64_t ipintr;
218 if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
219 //Clear the bits in IPINTR
220 misc &= ~(ipintr);
221 for (int i=0; i < size; i++) {
222 if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) {
223 if (!(--ipiInterrupting[i]))
224 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0);
225 DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i,
226 ipiInterrupting[i] + 1, req->cpu_num);
227 }
228 }
229 supportedWrite = true;
230 }
231
232 // ignore NXMs
233 if (*(uint64_t*)data & 0x10000000)
234 supportedWrite = true;
235
236 if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
237 return No_Fault;
238 case TSDEV_CC_AAR0:
239 case TSDEV_CC_AAR1:
240 case TSDEV_CC_AAR2:
241 case TSDEV_CC_AAR3:
242 panic("TSDEV_CC_AARx write not implemeted\n");
243 return No_Fault;
244 case TSDEV_CC_DIM0:
245 case TSDEV_CC_DIM1:
246 case TSDEV_CC_DIM2:
247 case TSDEV_CC_DIM3:
248 int number;
249 if(daddr == TSDEV_CC_DIM0)
250 number = 0;
251 else if(daddr == TSDEV_CC_DIM1)
252 number = 1;
253 else if(daddr == TSDEV_CC_DIM2)
254 number = 2;
255 else
256 number = 3;
257
258 uint64_t bitvector;
259 uint64_t olddim;
260 uint64_t olddir;
261
262 olddim = dim[number];
263 olddir = dir[number];
264 dim[number] = *(uint64_t*)data;
265 dir[number] = dim[number] & drir;
266 for(int x = 0; x < 64; x++)
267 {
268 bitvector = (uint64_t)1 << x;
269 // Figure out which bits have changed
270 if ((dim[number] & bitvector) != (olddim & bitvector))
271 {
272 // The bit is now set and it wasn't before (set)
273 if((dim[number] & bitvector) && (dir[number] & bitvector))
274 {
275 tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
276 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
277 }
278 else if ((olddir & bitvector) &&
279 !(dir[number] & bitvector))
280 {
281 // The bit was set and now its now clear and
282 // we were interrupting on that bit before
283 tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
284 DPRINTF(Tsunami, "dim write resulting in clear"
285 "dir interrupt to cpu 0\n");
286
287 }
288
289
290 }
291 }
292 return No_Fault;
293 case TSDEV_CC_DIR0:
294 case TSDEV_CC_DIR1:
295 case TSDEV_CC_DIR2:
296 case TSDEV_CC_DIR3:
297 panic("TSDEV_CC_DIR write not implemented\n");
298 case TSDEV_CC_DRIR:
299 panic("TSDEV_CC_DRIR write not implemented\n");
300 case TSDEV_CC_PRBEN:
301 panic("TSDEV_CC_PRBEN write not implemented\n");
302 case TSDEV_CC_IIC0:
303 case TSDEV_CC_IIC1:
304 case TSDEV_CC_IIC2:
305 case TSDEV_CC_IIC3:
306 panic("TSDEV_CC_IICx write not implemented\n");
307 case TSDEV_CC_MPR0:
308 case TSDEV_CC_MPR1:
309 case TSDEV_CC_MPR2:
310 case TSDEV_CC_MPR3:
311 panic("TSDEV_CC_MPRx write not implemented\n");
312 default:
313 panic("default in cchip read reached, accessing 0x%x\n");
314 }
315
316 break;
317 case sizeof(uint32_t):
318 case sizeof(uint16_t):
319 case sizeof(uint8_t):
320 default:
321 panic("invalid access size(?) for tsunami register!\n");
322 }
323
324 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
325
326 return No_Fault;
327 }
328
329 void
330 TsunamiCChip::postRTC()
331 {
332 int size = tsunami->intrctrl->cpu->system->execContexts.size();
333
334 for (int i = 0; i < size; i++) {
335 if (!RTCInterrupting[i]) {
336 misc |= 16 << i;
337 RTCInterrupting[i] = true;
338 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
339 DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
340 }
341 }
342
343 }
344
345 void
346 TsunamiCChip::postDRIR(uint32_t interrupt)
347 {
348 uint64_t bitvector = (uint64_t)0x1 << interrupt;
349 drir |= bitvector;
350 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
351 for(int i=0; i < size; i++) {
352 dir[i] = dim[i] & drir;
353 if (dim[i] & bitvector) {
354 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
355 DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
356 "interrupt %d\n",i, interrupt);
357 }
358 }
359 }
360
361 void
362 TsunamiCChip::clearDRIR(uint32_t interrupt)
363 {
364 uint64_t bitvector = (uint64_t)0x1 << interrupt;
365 uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
366 if (drir & bitvector)
367 {
368 drir &= ~bitvector;
369 for(int i=0; i < size; i++) {
370 if (dir[i] & bitvector) {
371 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
372 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
373 "interrupt %d\n",i, interrupt);
374
375 }
376 dir[i] = dim[i] & drir;
377 }
378 }
379 else
380 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
381 }
382
383 Tick
384 TsunamiCChip::cacheAccess(MemReqPtr &req)
385 {
386 return curTick + 1000;
387 }
388
389
390 void
391 TsunamiCChip::serialize(std::ostream &os)
392 {
393 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
394 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
395 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
396 SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
397 SERIALIZE_SCALAR(drir);
398 SERIALIZE_SCALAR(misc);
399 SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
400 }
401
402 void
403 TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
404 {
405 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
406 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
407 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
408 UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
409 UNSERIALIZE_SCALAR(drir);
410 UNSERIALIZE_SCALAR(misc);
411 UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
412 }
413
414 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
415
416 SimObjectParam<Tsunami *> tsunami;
417 SimObjectParam<MemoryController *> mmu;
418 Param<Addr> addr;
419 SimObjectParam<Bus*> io_bus;
420 SimObjectParam<HierParams *> hier;
421
422 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
423
424 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
425
426 INIT_PARAM(tsunami, "Tsunami"),
427 INIT_PARAM(mmu, "Memory Controller"),
428 INIT_PARAM(addr, "Device Address"),
429 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
430 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
431
432 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
433
434 CREATE_SIM_OBJECT(TsunamiCChip)
435 {
436 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier, io_bus);
437 }
438
439 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)