375664be039da43603a22d7003cef73ac7066ebc
[gem5.git] / dev / tsunami_cchip.cc
1 /* $Id$ */
2
3 /* @file
4 * Emulation of the Tsunami CChip CSRs
5 */
6
7 #include <deque>
8 #include <string>
9 #include <vector>
10
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"
21
22 using namespace std;
23
24 TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
25 MemoryController *mmu)
26 : FunctionalMemory(name), addr(a), tsunami(t)
27 {
28 mmu->add_child(this, Range<Addr>(addr, addr + size));
29
30 for(int i=0; i < Tsunami::Max_CPUs; i++) {
31 dim[i] = 0;
32 dir[i] = 0;
33 dirInterrupting[i] = false;
34 }
35
36 drir = 0;
37 misc = 0;
38 RTCInterrupting = false;
39
40 //Put back pointer in tsunami
41 tsunami->cchip = this;
42 }
43
44 Fault
45 TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
46 {
47 DPRINTF(Tsunami, "read va=%#x size=%d\n",
48 req->vaddr, req->size);
49
50 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
51 ExecContext *xc = req->xc;
52
53 switch (req->size) {
54
55 case sizeof(uint64_t):
56 switch(daddr) {
57 case TSDEV_CC_CSR:
58 *(uint64_t*)data = 0x0;
59 return No_Fault;
60 case TSDEV_CC_MTR:
61 panic("TSDEV_CC_MTR not implemeted\n");
62 return No_Fault;
63 case TSDEV_CC_MISC:
64 *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
65 return No_Fault;
66 case TSDEV_CC_AAR0:
67 case TSDEV_CC_AAR1:
68 case TSDEV_CC_AAR2:
69 case TSDEV_CC_AAR3:
70 panic("TSDEV_CC_AARx not implemeted\n");
71 return No_Fault;
72 case TSDEV_CC_DIM0:
73 *(uint64_t*)data = dim[0];
74 return No_Fault;
75 case TSDEV_CC_DIM1:
76 *(uint64_t*)data = dim[1];
77 return No_Fault;
78 case TSDEV_CC_DIM2:
79 *(uint64_t*)data = dim[2];
80 return No_Fault;
81 case TSDEV_CC_DIM3:
82 *(uint64_t*)data = dim[3];
83 return No_Fault;
84 case TSDEV_CC_DIR0:
85 *(uint64_t*)data = dir[0];
86 return No_Fault;
87 case TSDEV_CC_DIR1:
88 *(uint64_t*)data = dir[1];
89 return No_Fault;
90 case TSDEV_CC_DIR2:
91 *(uint64_t*)data = dir[2];
92 return No_Fault;
93 case TSDEV_CC_DIR3:
94 *(uint64_t*)data = dir[3];
95 return No_Fault;
96 case TSDEV_CC_DRIR:
97 *(uint64_t*)data = drir;
98 return No_Fault;
99 case TSDEV_CC_PRBEN:
100 panic("TSDEV_CC_PRBEN not implemented\n");
101 return No_Fault;
102 case TSDEV_CC_IIC0:
103 case TSDEV_CC_IIC1:
104 case TSDEV_CC_IIC2:
105 case TSDEV_CC_IIC3:
106 panic("TSDEV_CC_IICx not implemented\n");
107 return No_Fault;
108 case TSDEV_CC_MPR0:
109 case TSDEV_CC_MPR1:
110 case TSDEV_CC_MPR2:
111 case TSDEV_CC_MPR3:
112 panic("TSDEV_CC_MPRx not implemented\n");
113 return No_Fault;
114 default:
115 panic("default in cchip read reached, accessing 0x%x\n");
116 } // uint64_t
117
118 break;
119 case sizeof(uint32_t):
120 case sizeof(uint16_t):
121 case sizeof(uint8_t):
122 default:
123 panic("invalid access size(?) for tsunami register!\n");
124 }
125 DPRINTFN("Tsunami CChip ERROR: read daddr=%#x size=%d\n", daddr, req->size);
126
127 return No_Fault;
128 }
129
130 Fault
131 TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
132 {
133 DPRINTF(Tsunami, "write - va=%#x size=%d \n",
134 req->vaddr, req->size);
135
136 Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
137 uint64_t olddim;
138
139 switch (req->size) {
140
141 case sizeof(uint64_t):
142 switch(daddr) {
143 case TSDEV_CC_CSR:
144 panic("TSDEV_CC_CSR write\n");
145 return No_Fault;
146 case TSDEV_CC_MTR:
147 panic("TSDEV_CC_MTR write not implemented\n");
148 return No_Fault;
149 case TSDEV_CC_MISC:
150 //If it is the seventh bit, clear the RTC interrupt
151 if ((*(uint64_t*) data) & (1<<4)) {
152 RTCInterrupting = false;
153 tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0);
154 DPRINTF(Tsunami, "clearing rtc interrupt\n");
155 misc &= ~(1<<4);
156 } else panic("TSDEV_CC_MISC write not implemented\n");
157 return No_Fault;
158 case TSDEV_CC_AAR0:
159 case TSDEV_CC_AAR1:
160 case TSDEV_CC_AAR2:
161 case TSDEV_CC_AAR3:
162 panic("TSDEV_CC_AARx write not implemeted\n");
163 return No_Fault;
164 case TSDEV_CC_DIM0:
165 case TSDEV_CC_DIM1:
166 case TSDEV_CC_DIM2:
167 case TSDEV_CC_DIM3:
168 int number;
169 if(daddr == TSDEV_CC_DIM0)
170 number = 0;
171 else if(daddr == TSDEV_CC_DIM1)
172 number = 1;
173 else if(daddr == TSDEV_CC_DIM2)
174 number = 2;
175 else
176 number = 3;
177
178 olddim = dim[number];
179 dim[number] = *(uint64_t*)data;
180 dir[number] = dim[number] & drir;
181 uint64_t bitvector;
182 for(int x = 0; x < 64; x++)
183 {
184 bitvector = 1 << x;
185 // Figure out which bits have changed
186 if ((dim[number] & bitvector) != (olddim & bitvector))
187 {
188 // The bit is now set and it wasn't before (set)
189 if((dim[number] & bitvector) && (dir[number] & bitvector))
190 {
191 tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
192 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
193 }
194 else if (!(dir[number] & bitvector))
195 {
196 // The bit was set and now its now clear and
197 // we were interrupting on that bit before
198 tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
199 DPRINTF(Tsunami, "dim write resulting in clear"
200 "dir interrupt to cpu 0\n");
201
202 }
203
204
205 }
206 }
207 return No_Fault;
208 case TSDEV_CC_DIR0:
209 case TSDEV_CC_DIR1:
210 case TSDEV_CC_DIR2:
211 case TSDEV_CC_DIR3:
212 panic("TSDEV_CC_DIR write not implemented\n");
213 case TSDEV_CC_DRIR:
214 panic("TSDEV_CC_DRIR write not implemented\n");
215 case TSDEV_CC_PRBEN:
216 panic("TSDEV_CC_PRBEN write not implemented\n");
217 case TSDEV_CC_IIC0:
218 case TSDEV_CC_IIC1:
219 case TSDEV_CC_IIC2:
220 case TSDEV_CC_IIC3:
221 panic("TSDEV_CC_IICx write not implemented\n");
222 case TSDEV_CC_MPR0:
223 case TSDEV_CC_MPR1:
224 case TSDEV_CC_MPR2:
225 case TSDEV_CC_MPR3:
226 panic("TSDEV_CC_MPRx write not implemented\n");
227 default:
228 panic("default in cchip read reached, accessing 0x%x\n");
229 }
230
231 break;
232 case sizeof(uint32_t):
233 case sizeof(uint16_t):
234 case sizeof(uint8_t):
235 default:
236 panic("invalid access size(?) for tsunami register!\n");
237 }
238
239 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
240
241 return No_Fault;
242 }
243
244 void
245 TsunamiCChip::postDRIR(uint32_t interrupt)
246 {
247 uint64_t bitvector = 0x1 << interrupt;
248 drir |= bitvector;
249 for(int i=0; i < Tsunami::Max_CPUs; i++) {
250 dir[i] = dim[i] & drir;
251 if (dim[i] & bitvector) {
252 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
253 DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
254 "interrupt %d\n",i, interrupt);
255 }
256 }
257 }
258
259 void
260 TsunamiCChip::clearDRIR(uint32_t interrupt)
261 {
262 uint64_t bitvector = 0x1 << interrupt;
263 if (drir & bitvector)
264 {
265 drir &= ~bitvector;
266 for(int i=0; i < Tsunami::Max_CPUs; i++) {
267 if (dir[i] & bitvector) {
268 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
269 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
270 "interrupt %d\n",i, interrupt);
271
272 }
273 dir[i] = dim[i] & drir;
274 }
275 }
276 else
277 DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
278 }
279
280 void
281 TsunamiCChip::serialize(std::ostream &os)
282 {
283 SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
284 SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
285 SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
286 SERIALIZE_SCALAR(drir);
287 SERIALIZE_SCALAR(misc);
288 SERIALIZE_SCALAR(RTCInterrupting);
289 }
290
291 void
292 TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
293 {
294 UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
295 UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
296 UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
297 UNSERIALIZE_SCALAR(drir);
298 UNSERIALIZE_SCALAR(misc);
299 UNSERIALIZE_SCALAR(RTCInterrupting);
300 }
301
302 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
303
304 SimObjectParam<Tsunami *> tsunami;
305 SimObjectParam<MemoryController *> mmu;
306 Param<Addr> addr;
307
308 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
309
310 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
311
312 INIT_PARAM(tsunami, "Tsunami"),
313 INIT_PARAM(mmu, "Memory Controller"),
314 INIT_PARAM(addr, "Device Address")
315
316 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
317
318 CREATE_SIM_OBJECT(TsunamiCChip)
319 {
320 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
321 }
322
323 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)