tsunami_cchip.cc revision 831
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
22using namespace std;
23
24TsunamiCChip::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        ipiInterrupting[i] = false;
35        RTCInterrupting[i] = false;
36    }
37
38    drir = 0;
39    misc = 0;
40
41    //Put back pointer in tsunami
42    tsunami->cchip = this;
43}
44
45Fault
46TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
47{
48    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
49            req->vaddr, req->size);
50
51    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
52    ExecContext *xc = req->xc;
53
54    switch (req->size) {
55
56      case sizeof(uint64_t):
57          switch(daddr) {
58              case TSDEV_CC_CSR:
59                  *(uint64_t*)data = 0x0;
60                  return No_Fault;
61              case TSDEV_CC_MTR:
62                  panic("TSDEV_CC_MTR not implemeted\n");
63                   return No_Fault;
64              case TSDEV_CC_MISC:
65                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
66                  return No_Fault;
67              case TSDEV_CC_AAR0:
68              case TSDEV_CC_AAR1:
69              case TSDEV_CC_AAR2:
70              case TSDEV_CC_AAR3:
71                  panic("TSDEV_CC_AARx not implemeted\n");
72                  return No_Fault;
73              case TSDEV_CC_DIM0:
74                  *(uint64_t*)data = dim[0];
75                  return No_Fault;
76              case TSDEV_CC_DIM1:
77                  *(uint64_t*)data = dim[1];
78                  return No_Fault;
79              case TSDEV_CC_DIM2:
80                  *(uint64_t*)data = dim[2];
81                  return No_Fault;
82              case TSDEV_CC_DIM3:
83                  *(uint64_t*)data = dim[3];
84                  return No_Fault;
85              case TSDEV_CC_DIR0:
86                  *(uint64_t*)data = dir[0];
87                  return No_Fault;
88              case TSDEV_CC_DIR1:
89                  *(uint64_t*)data = dir[1];
90                  return No_Fault;
91              case TSDEV_CC_DIR2:
92                  *(uint64_t*)data = dir[2];
93                  return No_Fault;
94              case TSDEV_CC_DIR3:
95                  *(uint64_t*)data = dir[3];
96                  return No_Fault;
97              case TSDEV_CC_DRIR:
98                  *(uint64_t*)data = drir;
99                  return No_Fault;
100              case TSDEV_CC_PRBEN:
101                  panic("TSDEV_CC_PRBEN not implemented\n");
102                  return No_Fault;
103              case TSDEV_CC_IIC0:
104              case TSDEV_CC_IIC1:
105              case TSDEV_CC_IIC2:
106              case TSDEV_CC_IIC3:
107                  panic("TSDEV_CC_IICx not implemented\n");
108                  return No_Fault;
109              case TSDEV_CC_MPR0:
110              case TSDEV_CC_MPR1:
111              case TSDEV_CC_MPR2:
112              case TSDEV_CC_MPR3:
113                  panic("TSDEV_CC_MPRx not implemented\n");
114                  return No_Fault;
115              default:
116                  panic("default in cchip read reached, accessing 0x%x\n");
117           } // uint64_t
118
119      break;
120      case sizeof(uint32_t):
121      case sizeof(uint16_t):
122      case sizeof(uint8_t):
123      default:
124        panic("invalid access size(?) for tsunami register!\n");
125    }
126    DPRINTFN("Tsunami CChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
127
128    return No_Fault;
129}
130
131Fault
132TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
133{
134    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
135            req->vaddr, req->size);
136
137    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
138
139    bool supportedWrite = false;
140    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
141
142    switch (req->size) {
143
144      case sizeof(uint64_t):
145          switch(daddr) {
146            case TSDEV_CC_CSR:
147                  panic("TSDEV_CC_CSR write\n");
148                  return No_Fault;
149              case TSDEV_CC_MTR:
150                  panic("TSDEV_CC_MTR write not implemented\n");
151                   return No_Fault;
152              case TSDEV_CC_MISC:
153                //If it is the 4-7th bit, clear the RTC interrupt
154                uint64_t itintr;
155                if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
156                    //Clear the bits in ITINTR
157                    misc &= ~(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);
163                        }
164                    }
165                    supportedWrite = true;
166                }
167                //If it is 12th-15th bit, IPI sent to Processor 1
168                uint64_t ipreq;
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);
179                        }
180                    }
181                    supportedWrite = true;
182                }
183                //If it is bits 8-11, then clearing IPI's
184                uint64_t ipintr;
185                if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
186                    //Clear the bits in IPINTR
187                    misc &= ~(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);
194                        }
195                    }
196                    supportedWrite = true;
197                }
198                if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
199                return No_Fault;
200              case TSDEV_CC_AAR0:
201              case TSDEV_CC_AAR1:
202              case TSDEV_CC_AAR2:
203              case TSDEV_CC_AAR3:
204                  panic("TSDEV_CC_AARx write not implemeted\n");
205                  return No_Fault;
206              case TSDEV_CC_DIM0:
207              case TSDEV_CC_DIM1:
208              case TSDEV_CC_DIM2:
209              case TSDEV_CC_DIM3:
210                  int number;
211                  if(daddr == TSDEV_CC_DIM0)
212                      number = 0;
213                  else if(daddr == TSDEV_CC_DIM1)
214                      number = 1;
215                  else if(daddr == TSDEV_CC_DIM2)
216                      number = 2;
217                  else
218                      number = 3;
219
220                  uint64_t bitvector;
221                  uint64_t olddim;
222                  uint64_t olddir;
223
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++)
229                  {
230                      bitvector = (uint64_t)1 << x;
231                      // Figure out which bits have changed
232                      if ((dim[number] & bitvector) != (olddim & bitvector))
233                      {
234                          // The bit is now set and it wasn't before (set)
235                          if((dim[number] & bitvector) && (dir[number] & bitvector))
236                          {
237                              tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
238                              DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
239                          }
240                          else if ((olddir & bitvector) &&
241                                  !(dir[number] & bitvector))
242                          {
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");
248
249                          }
250
251
252                      }
253                  }
254                  return No_Fault;
255              case TSDEV_CC_DIR0:
256              case TSDEV_CC_DIR1:
257              case TSDEV_CC_DIR2:
258              case TSDEV_CC_DIR3:
259                  panic("TSDEV_CC_DIR write not implemented\n");
260              case TSDEV_CC_DRIR:
261                  panic("TSDEV_CC_DRIR write not implemented\n");
262              case TSDEV_CC_PRBEN:
263                  panic("TSDEV_CC_PRBEN write not implemented\n");
264              case TSDEV_CC_IIC0:
265              case TSDEV_CC_IIC1:
266              case TSDEV_CC_IIC2:
267              case TSDEV_CC_IIC3:
268                  panic("TSDEV_CC_IICx write not implemented\n");
269              case TSDEV_CC_MPR0:
270              case TSDEV_CC_MPR1:
271              case TSDEV_CC_MPR2:
272              case TSDEV_CC_MPR3:
273                  panic("TSDEV_CC_MPRx write not implemented\n");
274              default:
275                  panic("default in cchip read reached, accessing 0x%x\n");
276          }
277
278      break;
279      case sizeof(uint32_t):
280      case sizeof(uint16_t):
281      case sizeof(uint8_t):
282      default:
283        panic("invalid access size(?) for tsunami register!\n");
284    }
285
286    DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
287
288    return No_Fault;
289}
290
291void
292TsunamiCChip::postRTC()
293{
294    int size = tsunami->intrctrl->cpu->system->execContexts.size();
295
296    for (int i = 0; i < size; i++) {
297        if (!RTCInterrupting[i]) {
298            misc |= 16 << i;
299            RTCInterrupting[i] = true;
300            tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
301            DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
302        }
303    }
304
305}
306
307void
308TsunamiCChip::postDRIR(uint32_t interrupt)
309{
310    uint64_t bitvector = (uint64_t)0x1 << interrupt;
311    drir |= bitvector;
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);
319        }
320    }
321}
322
323void
324TsunamiCChip::clearDRIR(uint32_t interrupt)
325{
326    uint64_t bitvector = (uint64_t)0x1 << interrupt;
327    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
328    if (drir & bitvector)
329    {
330        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);
336
337            }
338            dir[i] = dim[i] & drir;
339        }
340    }
341    else
342        DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
343}
344
345void
346TsunamiCChip::serialize(std::ostream &os)
347{
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);
355}
356
357void
358TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
359{
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);
367}
368
369BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
370
371    SimObjectParam<Tsunami *> tsunami;
372    SimObjectParam<MemoryController *> mmu;
373    Param<Addr> addr;
374
375END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
376
377BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
378
379    INIT_PARAM(tsunami, "Tsunami"),
380    INIT_PARAM(mmu, "Memory Controller"),
381    INIT_PARAM(addr, "Device Address")
382
383END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
384
385CREATE_SIM_OBJECT(TsunamiCChip)
386{
387    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
388}
389
390REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
391