b825a91bc68efa1d72b508caac57b54312cab581
[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
138 switch (req->size) {
139
140 case sizeof(uint64_t):
141 switch(daddr) {
142 case TSDEV_CC_CSR:
143 panic("TSDEV_CC_CSR write\n");
144 return No_Fault;
145 case TSDEV_CC_MTR:
146 panic("TSDEV_CC_MTR write not implemented\n");
147 return No_Fault;
148 case TSDEV_CC_MISC:
149 //If it is the seventh bit, clear the RTC interrupt
150 if ((*(uint64_t*) data) & (1<<4)) {
151 RTCInterrupting = false;
152 tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0);
153 DPRINTF(Tsunami, "clearing rtc interrupt\n");
154 misc &= ~(1<<4);
155 } else panic("TSDEV_CC_MISC write not implemented\n");
156 return No_Fault;
157 case TSDEV_CC_AAR0:
158 case TSDEV_CC_AAR1:
159 case TSDEV_CC_AAR2:
160 case TSDEV_CC_AAR3:
161 panic("TSDEV_CC_AARx write not implemeted\n");
162 return No_Fault;
163 case TSDEV_CC_DIM0:
164 dim[0] = *(uint64_t*)data;
165 if (dim[0] & drir) {
166 dir[0] = dim[0] & drir;
167 if (!dirInterrupting[0]) {
168 dirInterrupting[0] = true;
169 tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0);
170 DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
171 }
172 }
173 return No_Fault;
174 case TSDEV_CC_DIM1:
175 dim[1] = *(uint64_t*)data;
176 if (dim[1] & drir) {
177 dir[1] = dim[1] & drir;
178 if (!dirInterrupting[1]) {
179 dirInterrupting[1] = true;
180 tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0);
181 DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n");
182 }
183 }
184 return No_Fault;
185 case TSDEV_CC_DIM2:
186 dim[2] = *(uint64_t*)data;
187 if (dim[2] & drir) {
188 dir[2] = dim[2] & drir;
189 if (!dirInterrupting[2]) {
190 dirInterrupting[2] = true;
191 tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0);
192 DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n");
193 }
194 }
195 return No_Fault;
196 case TSDEV_CC_DIM3:
197 dim[3] = *(uint64_t*)data;
198 if ((dim[3] & drir) /*And Not Already Int*/) {
199 dir[3] = dim[3] & drir;
200 if (!dirInterrupting[3]) {
201 dirInterrupting[3] = true;
202 tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0);
203 DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n");
204 }
205 }
206 return No_Fault;
207 case TSDEV_CC_DIR0:
208 case TSDEV_CC_DIR1:
209 case TSDEV_CC_DIR2:
210 case TSDEV_CC_DIR3:
211 panic("TSDEV_CC_DIR write not implemented\n");
212 return No_Fault;
213 case TSDEV_CC_DRIR:
214 panic("TSDEV_CC_DRIR write not implemented\n");
215 return No_Fault;
216 case TSDEV_CC_PRBEN:
217 panic("TSDEV_CC_PRBEN write not implemented\n");
218 return No_Fault;
219 case TSDEV_CC_IIC0:
220 case TSDEV_CC_IIC1:
221 case TSDEV_CC_IIC2:
222 case TSDEV_CC_IIC3:
223 panic("TSDEV_CC_IICx write not implemented\n");
224 return No_Fault;
225 case TSDEV_CC_MPR0:
226 case TSDEV_CC_MPR1:
227 case TSDEV_CC_MPR2:
228 case TSDEV_CC_MPR3:
229 panic("TSDEV_CC_MPRx write not implemented\n");
230 return No_Fault;
231 default:
232 panic("default in cchip read reached, accessing 0x%x\n");
233 }
234
235 break;
236 case sizeof(uint32_t):
237 case sizeof(uint16_t):
238 case sizeof(uint8_t):
239 default:
240 panic("invalid access size(?) for tsunami register!\n");
241 }
242
243 DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
244
245 return No_Fault;
246 }
247
248 void
249 TsunamiCChip::postDRIR(uint64_t bitvector)
250 {
251 drir |= bitvector;
252 for(int i=0; i < Tsunami::Max_CPUs; i++) {
253 if (bitvector & dim[i]) {
254 dir[i] |= bitvector;
255 if (!dirInterrupting[i]) {
256 dirInterrupting[i] = true;
257 tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0);
258 DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i);
259 }
260 }
261 }
262 }
263
264 void
265 TsunamiCChip::clearDRIR(uint64_t bitvector)
266 {
267 drir &= ~bitvector;
268 for(int i=0; i < Tsunami::Max_CPUs; i++) {
269 dir[i] &= ~bitvector;
270 if (!dir[i]) {
271 dirInterrupting[i] = false;
272 tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0);
273 DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i);
274
275 }
276 }
277 }
278
279 void
280 TsunamiCChip::serialize(std::ostream &os)
281 {
282 // code should be written
283 }
284
285 void
286 TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
287 {
288 //code should be written
289 }
290
291 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
292
293 SimObjectParam<Tsunami *> tsunami;
294 SimObjectParam<MemoryController *> mmu;
295 Param<Addr> addr;
296
297 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
298
299 BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
300
301 INIT_PARAM(tsunami, "Tsunami"),
302 INIT_PARAM(mmu, "Memory Controller"),
303 INIT_PARAM(addr, "Device Address")
304
305 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
306
307 CREATE_SIM_OBJECT(TsunamiCChip)
308 {
309 return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
310 }
311
312 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)