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