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 "cpu/exec_context.hh"
39 #include "dev/console.hh"
40 #include "dev/tsunami_cchip.hh"
41 #include "dev/tsunamireg.h"
42 #include "dev/tsunami.hh"
43 #include "cpu/intr_control.hh"
44 #include "mem/functional_mem/memory_control.hh"
45 #include "sim/builder.hh"
46 #include "sim/system.hh"
50 TsunamiCChip::TsunamiCChip(const string
&name
, Tsunami
*t
, Addr a
,
51 MemoryController
*mmu
)
52 : FunctionalMemory(name
), addr(a
), tsunami(t
)
54 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
56 for(int i
=0; i
< Tsunami::Max_CPUs
; i
++) {
59 dirInterrupting
[i
] = false;
60 ipiInterrupting
[i
] = false;
61 RTCInterrupting
[i
] = false;
67 //Put back pointer in tsunami
68 tsunami
->cchip
= this;
72 TsunamiCChip::read(MemReqPtr
&req
, uint8_t *data
)
74 DPRINTF(Tsunami
, "read va=%#x size=%d\n",
75 req
->vaddr
, req
->size
);
77 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
78 ExecContext
*xc
= req
->xc
;
82 case sizeof(uint64_t):
85 *(uint64_t*)data
= 0x0;
88 panic("TSDEV_CC_MTR not implemeted\n");
91 *(uint64_t*)data
= misc
| (xc
->cpu_id
& 0x3);
100 *(uint64_t*)data
= dim
[0];
103 *(uint64_t*)data
= dim
[1];
106 *(uint64_t*)data
= dim
[2];
109 *(uint64_t*)data
= dim
[3];
112 *(uint64_t*)data
= dir
[0];
115 *(uint64_t*)data
= dir
[1];
118 *(uint64_t*)data
= dir
[2];
121 *(uint64_t*)data
= dir
[3];
124 *(uint64_t*)data
= drir
;
127 panic("TSDEV_CC_PRBEN not implemented\n");
133 panic("TSDEV_CC_IICx not implemented\n");
139 panic("TSDEV_CC_MPRx not implemented\n");
142 panic("default in cchip read reached, accessing 0x%x\n");
146 case sizeof(uint32_t):
147 case sizeof(uint16_t):
148 case sizeof(uint8_t):
150 panic("invalid access size(?) for tsunami register!\n");
152 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr
, req
->size
);
158 TsunamiCChip::write(MemReqPtr
&req
, const uint8_t *data
)
160 DPRINTF(Tsunami
, "write - va=%#x value=%#x size=%d \n",
161 req
->vaddr
, *(uint64_t*)data
, req
->size
);
163 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
165 bool supportedWrite
= false;
166 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
170 case sizeof(uint64_t):
173 panic("TSDEV_CC_CSR write\n");
176 panic("TSDEV_CC_MTR write not implemented\n");
179 //If it is the 4-7th bit, clear the RTC interrupt
181 if ((itintr
= (*(uint64_t*) data
) & (0xf<<4))) {
182 //Clear the bits in ITINTR
184 for (int i
=0; i
< size
; i
++) {
185 if ((itintr
& (1 << (i
+4))) && RTCInterrupting
[i
]) {
186 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ2
, 0);
187 RTCInterrupting
[i
] = false;
188 DPRINTF(Tsunami
, "clearing rtc interrupt to cpu=%d\n", i
);
191 supportedWrite
= true;
193 //If it is 12th-15th bit, IPI sent to Processor 1
195 if ((ipreq
= (*(uint64_t*) data
) & (0xf << 12))) {
196 //Set the bits in IPINTR
197 misc
|= (ipreq
>> 4);
198 for (int i
=0; i
< size
; i
++) {
199 if ((ipreq
& (1 << (i
+ 12)))) {
200 if (!ipiInterrupting
[i
])
201 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ3
, 0);
202 ipiInterrupting
[i
]++;
203 DPRINTF(IPI
, "send cpu=%d pending=%d from=%d\n", i
,
204 ipiInterrupting
[i
], req
->cpu_num
);
207 supportedWrite
= true;
209 //If it is bits 8-11, then clearing IPI's
211 if ((ipintr
= (*(uint64_t*) data
) & (0xf << 8))) {
212 //Clear the bits in IPINTR
214 for (int i
=0; i
< size
; i
++) {
215 if ((ipintr
& (1 << (i
+ 8))) && ipiInterrupting
[i
]) {
216 if (!(--ipiInterrupting
[i
]))
217 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ3
, 0);
218 DPRINTF(IPI
, "clearing cpu=%d pending=%d from=%d\n", i
,
219 ipiInterrupting
[i
] + 1, req
->cpu_num
);
222 supportedWrite
= true;
226 if (*(uint64_t*)data
& 0x10000000)
227 supportedWrite
= true;
229 if(!supportedWrite
) panic("TSDEV_CC_MISC write not implemented\n");
235 panic("TSDEV_CC_AARx write not implemeted\n");
242 if(daddr
== TSDEV_CC_DIM0
)
244 else if(daddr
== TSDEV_CC_DIM1
)
246 else if(daddr
== TSDEV_CC_DIM2
)
255 olddim
= dim
[number
];
256 olddir
= dir
[number
];
257 dim
[number
] = *(uint64_t*)data
;
258 dir
[number
] = dim
[number
] & drir
;
259 for(int x
= 0; x
< 64; x
++)
261 bitvector
= (uint64_t)1 << x
;
262 // Figure out which bits have changed
263 if ((dim
[number
] & bitvector
) != (olddim
& bitvector
))
265 // The bit is now set and it wasn't before (set)
266 if((dim
[number
] & bitvector
) && (dir
[number
] & bitvector
))
268 tsunami
->intrctrl
->post(number
, TheISA::INTLEVEL_IRQ1
, x
);
269 DPRINTF(Tsunami
, "posting dir interrupt to cpu 0\n");
271 else if ((olddir
& bitvector
) &&
272 !(dir
[number
] & bitvector
))
274 // The bit was set and now its now clear and
275 // we were interrupting on that bit before
276 tsunami
->intrctrl
->clear(number
, TheISA::INTLEVEL_IRQ1
, x
);
277 DPRINTF(Tsunami
, "dim write resulting in clear"
278 "dir interrupt to cpu 0\n");
290 panic("TSDEV_CC_DIR write not implemented\n");
292 panic("TSDEV_CC_DRIR write not implemented\n");
294 panic("TSDEV_CC_PRBEN write not implemented\n");
299 panic("TSDEV_CC_IICx write not implemented\n");
304 panic("TSDEV_CC_MPRx write not implemented\n");
306 panic("default in cchip read reached, accessing 0x%x\n");
310 case sizeof(uint32_t):
311 case sizeof(uint16_t):
312 case sizeof(uint8_t):
314 panic("invalid access size(?) for tsunami register!\n");
317 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr
, req
->size
);
323 TsunamiCChip::postRTC()
325 int size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
327 for (int i
= 0; i
< size
; i
++) {
328 if (!RTCInterrupting
[i
]) {
330 RTCInterrupting
[i
] = true;
331 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ2
, 0);
332 DPRINTF(Tsunami
, "Posting RTC interrupt to cpu=%d", i
);
339 TsunamiCChip::postDRIR(uint32_t interrupt
)
341 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
343 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
344 for(int i
=0; i
< size
; i
++) {
345 dir
[i
] = dim
[i
] & drir
;
346 if (dim
[i
] & bitvector
) {
347 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ1
, interrupt
);
348 DPRINTF(Tsunami
, "posting dir interrupt to cpu %d,"
349 "interrupt %d\n",i
, interrupt
);
355 TsunamiCChip::clearDRIR(uint32_t interrupt
)
357 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
358 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
359 if (drir
& bitvector
)
362 for(int i
=0; i
< size
; i
++) {
363 if (dir
[i
] & bitvector
) {
364 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ1
, interrupt
);
365 DPRINTF(Tsunami
, "clearing dir interrupt to cpu %d,"
366 "interrupt %d\n",i
, interrupt
);
369 dir
[i
] = dim
[i
] & drir
;
373 DPRINTF(Tsunami
, "Spurrious clear? interrupt %d\n", interrupt
);
377 TsunamiCChip::serialize(std::ostream
&os
)
379 SERIALIZE_ARRAY(dim
, Tsunami::Max_CPUs
);
380 SERIALIZE_ARRAY(dir
, Tsunami::Max_CPUs
);
381 SERIALIZE_ARRAY(dirInterrupting
, Tsunami::Max_CPUs
);
382 SERIALIZE_ARRAY(ipiInterrupting
, Tsunami::Max_CPUs
);
383 SERIALIZE_SCALAR(drir
);
384 SERIALIZE_SCALAR(misc
);
385 SERIALIZE_ARRAY(RTCInterrupting
, Tsunami::Max_CPUs
);
389 TsunamiCChip::unserialize(Checkpoint
*cp
, const std::string
§ion
)
391 UNSERIALIZE_ARRAY(dim
, Tsunami::Max_CPUs
);
392 UNSERIALIZE_ARRAY(dir
, Tsunami::Max_CPUs
);
393 UNSERIALIZE_ARRAY(dirInterrupting
, Tsunami::Max_CPUs
);
394 UNSERIALIZE_ARRAY(ipiInterrupting
, Tsunami::Max_CPUs
);
395 UNSERIALIZE_SCALAR(drir
);
396 UNSERIALIZE_SCALAR(misc
);
397 UNSERIALIZE_ARRAY(RTCInterrupting
, Tsunami::Max_CPUs
);
400 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
402 SimObjectParam
<Tsunami
*> tsunami
;
403 SimObjectParam
<MemoryController
*> mmu
;
406 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
408 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
410 INIT_PARAM(tsunami
, "Tsunami"),
411 INIT_PARAM(mmu
, "Memory Controller"),
412 INIT_PARAM(addr
, "Device Address")
414 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
416 CREATE_SIM_OBJECT(TsunamiCChip
)
418 return new TsunamiCChip(getInstanceName(), tsunami
, addr
, mmu
);
421 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip
)