4 * Emulation of the Tsunami CChip CSRs
11 #include "base/trace.hh"
12 #include "cpu/exec_context.hh"
13 #include "dev/console.hh"
14 #include "dev/tsunami_cchip.hh"
15 #include "dev/tsunamireg.h"
16 #include "dev/tsunami.hh"
17 #include "cpu/intr_control.hh"
18 #include "mem/functional_mem/memory_control.hh"
19 #include "sim/builder.hh"
20 #include "sim/system.hh"
24 TsunamiCChip::TsunamiCChip(const string
&name
, Tsunami
*t
, Addr a
,
25 MemoryController
*mmu
)
26 : FunctionalMemory(name
), addr(a
), tsunami(t
)
28 mmu
->add_child(this, Range
<Addr
>(addr
, addr
+ size
));
30 for(int i
=0; i
< Tsunami::Max_CPUs
; i
++) {
33 dirInterrupting
[i
] = false;
34 ipiInterrupting
[i
] = false;
35 RTCInterrupting
[i
] = false;
41 //Put back pointer in tsunami
42 tsunami
->cchip
= this;
46 TsunamiCChip::read(MemReqPtr
&req
, uint8_t *data
)
48 DPRINTF(Tsunami
, "read va=%#x size=%d\n",
49 req
->vaddr
, req
->size
);
51 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
52 ExecContext
*xc
= req
->xc
;
56 case sizeof(uint64_t):
59 *(uint64_t*)data
= 0x0;
62 panic("TSDEV_CC_MTR not implemeted\n");
65 *(uint64_t*)data
= misc
| (xc
->cpu_id
& 0x3);
71 panic("TSDEV_CC_AARx not implemeted\n");
74 *(uint64_t*)data
= dim
[0];
77 *(uint64_t*)data
= dim
[1];
80 *(uint64_t*)data
= dim
[2];
83 *(uint64_t*)data
= dim
[3];
86 *(uint64_t*)data
= dir
[0];
89 *(uint64_t*)data
= dir
[1];
92 *(uint64_t*)data
= dir
[2];
95 *(uint64_t*)data
= dir
[3];
98 *(uint64_t*)data
= drir
;
101 panic("TSDEV_CC_PRBEN not implemented\n");
107 panic("TSDEV_CC_IICx not implemented\n");
113 panic("TSDEV_CC_MPRx not implemented\n");
116 panic("default in cchip read reached, accessing 0x%x\n");
120 case sizeof(uint32_t):
121 case sizeof(uint16_t):
122 case sizeof(uint8_t):
124 panic("invalid access size(?) for tsunami register!\n");
126 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr
, req
->size
);
132 TsunamiCChip::write(MemReqPtr
&req
, const uint8_t *data
)
134 DPRINTF(Tsunami
, "write - va=%#x size=%d \n",
135 req
->vaddr
, req
->size
);
137 Addr daddr
= (req
->paddr
- (addr
& PA_IMPL_MASK
)) >> 6;
139 bool supportedWrite
= false;
140 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
144 case sizeof(uint64_t):
147 panic("TSDEV_CC_CSR write\n");
150 panic("TSDEV_CC_MTR write not implemented\n");
153 //If it is the 4-7th bit, clear the RTC interrupt
155 if ((itintr
= (*(uint64_t*) data
) & (0xf<<4))) {
156 //Clear the bits in ITINTR
158 for (int i
=0; i
< size
; i
++) {
159 if ((itintr
& (1 << (i
+4))) && RTCInterrupting
[i
]) {
160 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ2
, 0);
161 RTCInterrupting
[i
] = false;
162 DPRINTF(Tsunami
, "clearing rtc interrupt to cpu=%d\n", i
);
165 supportedWrite
= true;
167 //If it is 12th-15th bit, IPI sent to Processor 1
169 if ((ipreq
= (*(uint64_t*) data
) & (0xf << 12))) {
170 //Set the bits in IPINTR
171 misc
|= (ipreq
>> 4);
172 for (int i
=0; i
< size
; i
++) {
173 if ((ipreq
& (1 << (i
+ 12)))) {
174 if (!ipiInterrupting
[i
])
175 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ3
, 0);
176 ipiInterrupting
[i
]++;
177 DPRINTF(IPI
, "send cpu=%d pending=%d from=%d\n", i
,
178 ipiInterrupting
[i
], req
->cpu_num
);
181 supportedWrite
= true;
183 //If it is bits 8-11, then clearing IPI's
185 if ((ipintr
= (*(uint64_t*) data
) & (0xf << 8))) {
186 //Clear the bits in IPINTR
188 for (int i
=0; i
< size
; i
++) {
189 if ((ipintr
& (1 << (i
+ 8))) && ipiInterrupting
[i
]) {
190 if (!(--ipiInterrupting
[i
]))
191 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ3
, 0);
192 DPRINTF(IPI
, "clearing cpu=%d pending=%d from=%d\n", i
,
193 ipiInterrupting
[i
] + 1, req
->cpu_num
);
196 supportedWrite
= true;
198 if(!supportedWrite
) panic("TSDEV_CC_MISC write not implemented\n");
204 panic("TSDEV_CC_AARx write not implemeted\n");
211 if(daddr
== TSDEV_CC_DIM0
)
213 else if(daddr
== TSDEV_CC_DIM1
)
215 else if(daddr
== TSDEV_CC_DIM2
)
224 olddim
= dim
[number
];
225 olddir
= dir
[number
];
226 dim
[number
] = *(uint64_t*)data
;
227 dir
[number
] = dim
[number
] & drir
;
228 for(int x
= 0; x
< 64; x
++)
230 bitvector
= (uint64_t)1 << x
;
231 // Figure out which bits have changed
232 if ((dim
[number
] & bitvector
) != (olddim
& bitvector
))
234 // The bit is now set and it wasn't before (set)
235 if((dim
[number
] & bitvector
) && (dir
[number
] & bitvector
))
237 tsunami
->intrctrl
->post(number
, TheISA::INTLEVEL_IRQ1
, x
);
238 DPRINTF(Tsunami
, "posting dir interrupt to cpu 0\n");
240 else if ((olddir
& bitvector
) &&
241 !(dir
[number
] & bitvector
))
243 // The bit was set and now its now clear and
244 // we were interrupting on that bit before
245 tsunami
->intrctrl
->clear(number
, TheISA::INTLEVEL_IRQ1
, x
);
246 DPRINTF(Tsunami
, "dim write resulting in clear"
247 "dir interrupt to cpu 0\n");
259 panic("TSDEV_CC_DIR write not implemented\n");
261 panic("TSDEV_CC_DRIR write not implemented\n");
263 panic("TSDEV_CC_PRBEN write not implemented\n");
268 panic("TSDEV_CC_IICx write not implemented\n");
273 panic("TSDEV_CC_MPRx write not implemented\n");
275 panic("default in cchip read reached, accessing 0x%x\n");
279 case sizeof(uint32_t):
280 case sizeof(uint16_t):
281 case sizeof(uint8_t):
283 panic("invalid access size(?) for tsunami register!\n");
286 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr
, req
->size
);
292 TsunamiCChip::postRTC()
294 int size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
296 for (int i
= 0; i
< size
; i
++) {
297 if (!RTCInterrupting
[i
]) {
299 RTCInterrupting
[i
] = true;
300 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ2
, 0);
301 DPRINTF(Tsunami
, "Posting RTC interrupt to cpu=%d", i
);
308 TsunamiCChip::postDRIR(uint32_t interrupt
)
310 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
312 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
313 for(int i
=0; i
< size
; i
++) {
314 dir
[i
] = dim
[i
] & drir
;
315 if (dim
[i
] & bitvector
) {
316 tsunami
->intrctrl
->post(i
, TheISA::INTLEVEL_IRQ1
, interrupt
);
317 DPRINTF(Tsunami
, "posting dir interrupt to cpu %d,"
318 "interrupt %d\n",i
, interrupt
);
324 TsunamiCChip::clearDRIR(uint32_t interrupt
)
326 uint64_t bitvector
= (uint64_t)0x1 << interrupt
;
327 uint64_t size
= tsunami
->intrctrl
->cpu
->system
->execContexts
.size();
328 if (drir
& bitvector
)
331 for(int i
=0; i
< size
; i
++) {
332 if (dir
[i
] & bitvector
) {
333 tsunami
->intrctrl
->clear(i
, TheISA::INTLEVEL_IRQ1
, interrupt
);
334 DPRINTF(Tsunami
, "clearing dir interrupt to cpu %d,"
335 "interrupt %d\n",i
, interrupt
);
338 dir
[i
] = dim
[i
] & drir
;
342 DPRINTF(Tsunami
, "Spurrious clear? interrupt %d\n", interrupt
);
346 TsunamiCChip::serialize(std::ostream
&os
)
348 SERIALIZE_ARRAY(dim
, Tsunami::Max_CPUs
);
349 SERIALIZE_ARRAY(dir
, Tsunami::Max_CPUs
);
350 SERIALIZE_ARRAY(dirInterrupting
, Tsunami::Max_CPUs
);
351 SERIALIZE_ARRAY(ipiInterrupting
, Tsunami::Max_CPUs
);
352 SERIALIZE_SCALAR(drir
);
353 SERIALIZE_SCALAR(misc
);
354 SERIALIZE_ARRAY(RTCInterrupting
, Tsunami::Max_CPUs
);
358 TsunamiCChip::unserialize(Checkpoint
*cp
, const std::string
§ion
)
360 UNSERIALIZE_ARRAY(dim
, Tsunami::Max_CPUs
);
361 UNSERIALIZE_ARRAY(dir
, Tsunami::Max_CPUs
);
362 UNSERIALIZE_ARRAY(dirInterrupting
, Tsunami::Max_CPUs
);
363 UNSERIALIZE_ARRAY(ipiInterrupting
, Tsunami::Max_CPUs
);
364 UNSERIALIZE_SCALAR(drir
);
365 UNSERIALIZE_SCALAR(misc
);
366 UNSERIALIZE_ARRAY(RTCInterrupting
, Tsunami::Max_CPUs
);
369 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
371 SimObjectParam
<Tsunami
*> tsunami
;
372 SimObjectParam
<MemoryController
*> mmu
;
375 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip
)
377 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
379 INIT_PARAM(tsunami
, "Tsunami"),
380 INIT_PARAM(mmu
, "Memory Controller"),
381 INIT_PARAM(addr
, "Device Address")
383 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip
)
385 CREATE_SIM_OBJECT(TsunamiCChip
)
387 return new TsunamiCChip(getInstanceName(), tsunami
, addr
, mmu
);
390 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip
)