2 * Copyright (c) 2004 The Regents of The University of Michigan
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.
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.
30 * Emulation of the Tsunami CChip CSRs
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"
52 TsunamiCChip::TsunamiCChip(const string
&name
, Tsunami
*t
, Addr a
,
53 MemoryController
*mmu
, HierParams
*hier
, Bus
* bus
)
54 : PioDevice(name
), addr(a
), tsunami(t
)
56 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
58 for(int i
=0; i
< Tsunami::Max_CPUs
; i
++) {
61 dirInterrupting
[i
] = false;
62 ipiInterrupting
[i
] = false;
63 RTCInterrupting
[i
] = false;
67 pioInterface
= newPioInterface(name
, hier
, bus
, this,
68 &TsunamiCChip::cacheAccess
);
69 pioInterface
->addAddrRange(addr
, addr
+ size
- 1);
75 //Put back pointer in tsunami
76 tsunami
->cchip
= this;
80 TsunamiCChip::read(MemReqPtr
&req
, uint8_t *data
)
82 DPRINTF(Tsunami
, "read va=%#x size=%d\n",
83 req
->vaddr
, req
->size
);
85 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
86 ExecContext
*xc
= req
->xc
;
90 case sizeof(uint64_t):
93 *(uint64_t*)data
= 0x0;
96 panic("TSDEV_CC_MTR not implemeted\n");
99 *(uint64_t*)data
= misc
| (xc
->cpu_id
& 0x3);
105 *(uint64_t*)data
= 0;
108 *(uint64_t*)data
= dim
[0];
111 *(uint64_t*)data
= dim
[1];
114 *(uint64_t*)data
= dim
[2];
117 *(uint64_t*)data
= dim
[3];
120 *(uint64_t*)data
= dir
[0];
123 *(uint64_t*)data
= dir
[1];
126 *(uint64_t*)data
= dir
[2];
129 *(uint64_t*)data
= dir
[3];
132 *(uint64_t*)data
= drir
;
135 panic("TSDEV_CC_PRBEN not implemented\n");
141 panic("TSDEV_CC_IICx not implemented\n");
147 panic("TSDEV_CC_MPRx not implemented\n");
150 panic("default in cchip read reached, accessing 0x%x\n");
154 case sizeof(uint32_t):
155 case sizeof(uint16_t):
156 case sizeof(uint8_t):
158 panic("invalid access size(?) for tsunami register!\n");
160 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr
, req
->size
);
166 TsunamiCChip::write(MemReqPtr
&req
, const uint8_t *data
)
168 DPRINTF(Tsunami
, "write - va=%#x value=%#x size=%d \n",
169 req
->vaddr
, *(uint64_t*)data
, req
->size
);
171 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
173 bool supportedWrite
= false;
174 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
178 case sizeof(uint64_t):
181 panic("TSDEV_CC_CSR write\n");
184 panic("TSDEV_CC_MTR write not implemented\n");
187 //If it is the 4-7th bit, clear the RTC interrupt
189 if ((itintr
= (*(uint64_t*) data
) & (0xf<<4))) {
190 //Clear the bits in 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
);
199 supportedWrite
= true;
201 //If it is 12th-15th bit, IPI sent to Processor 1
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
);
215 supportedWrite
= true;
217 //If it is bits 8-11, then clearing IPI's
219 if ((ipintr
= (*(uint64_t*) data
) & (0xf << 8))) {
220 //Clear the bits in 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
);
230 supportedWrite
= true;
234 if (*(uint64_t*)data
& 0x10000000)
235 supportedWrite
= true;
237 if(!supportedWrite
) panic("TSDEV_CC_MISC write not implemented\n");
243 panic("TSDEV_CC_AARx write not implemeted\n");
250 if(daddr
== TSDEV_CC_DIM0
)
252 else if(daddr
== TSDEV_CC_DIM1
)
254 else if(daddr
== TSDEV_CC_DIM2
)
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
++)
269 bitvector
= (uint64_t)1 << x
;
270 // Figure out which bits have changed
271 if ((dim
[number
] & bitvector
) != (olddim
& bitvector
))
273 // The bit is now set and it wasn't before (set)
274 if((dim
[number
] & bitvector
) && (dir
[number
] & bitvector
))
276 tsunami
->intrctrl
->post(number
, TheISA::INTLEVEL_IRQ1
, x
);
277 DPRINTF(Tsunami
, "posting dir interrupt to cpu 0\n");
279 else if ((olddir
& bitvector
) &&
280 !(dir
[number
] & bitvector
))
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");
298 panic("TSDEV_CC_DIR write not implemented\n");
300 panic("TSDEV_CC_DRIR write not implemented\n");
302 panic("TSDEV_CC_PRBEN write not implemented\n");
307 panic("TSDEV_CC_IICx write not implemented\n");
312 panic("TSDEV_CC_MPRx write not implemented\n");
314 panic("default in cchip read reached, accessing 0x%x\n");
318 case sizeof(uint32_t):
319 case sizeof(uint16_t):
320 case sizeof(uint8_t):
322 panic("invalid access size(?) for tsunami register!\n");
325 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr
, req
->size
);
331 TsunamiCChip::postRTC()
333 int size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
335 for (int i
= 0; i
< size
; i
++) {
336 if (!RTCInterrupting
[i
]) {
338 RTCInterrupting
[i
] = true;
339 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ2
, 0);
340 DPRINTF(Tsunami
, "Posting RTC interrupt to cpu=%d", i
);
347 TsunamiCChip::postDRIR(uint32_t interrupt
)
349 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
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
);
363 TsunamiCChip::clearDRIR(uint32_t interrupt
)
365 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
366 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
367 if (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
);
377 dir
[i
] = dim
[i
] & drir
;
381 DPRINTF(Tsunami
, "Spurrious clear? interrupt %d\n", interrupt
);
385 TsunamiCChip::cacheAccess(MemReqPtr
&req
)
387 return curTick
+ 1000;
392 TsunamiCChip::serialize(std::ostream
&os
)
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
);
404 TsunamiCChip::unserialize(Checkpoint
*cp
, const std::string
§ion
)
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
);
415 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
417 SimObjectParam
<Tsunami
*> tsunami
;
418 SimObjectParam
<MemoryController
*> mmu
;
420 SimObjectParam
<Bus
*> io_bus
;
421 SimObjectParam
<HierParams
*> hier
;
423 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
425 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
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
)
433 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
435 CREATE_SIM_OBJECT(TsunamiCChip
)
437 return new TsunamiCChip(getInstanceName(), tsunami
, addr
, mmu
, hier
, io_bus
);
440 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip
)