tsunami_cchip.cc revision 830
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
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 < 4; 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\n");
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 < 4; 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 < 4; 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::postDRIR(uint32_t interrupt)
293{
294    uint64_t bitvector = (uint64_t)0x1 << interrupt;
295    drir |= bitvector;
296    for(int i=0; i < Tsunami::Max_CPUs; i++) {
297        dir[i] = dim[i] & drir;
298        if (dim[i] & bitvector) {
299                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
300                DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
301                        "interrupt %d\n",i, interrupt);
302        }
303    }
304}
305
306void
307TsunamiCChip::clearDRIR(uint32_t interrupt)
308{
309    uint64_t bitvector = (uint64_t)0x1 << interrupt;
310    if (drir & bitvector)
311    {
312        drir &= ~bitvector;
313        for(int i=0; i < Tsunami::Max_CPUs; i++) {
314            if (dir[i] & bitvector) {
315                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
316                DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
317                    "interrupt %d\n",i, interrupt);
318
319            }
320            dir[i] = dim[i] & drir;
321        }
322    }
323    else
324        DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
325}
326
327void
328TsunamiCChip::serialize(std::ostream &os)
329{
330    SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
331    SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
332    SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
333    SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
334    SERIALIZE_SCALAR(drir);
335    SERIALIZE_SCALAR(misc);
336    SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
337}
338
339void
340TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
341{
342    UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
343    UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
344    UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
345    UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
346    UNSERIALIZE_SCALAR(drir);
347    UNSERIALIZE_SCALAR(misc);
348    UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
349}
350
351BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
352
353    SimObjectParam<Tsunami *> tsunami;
354    SimObjectParam<MemoryController *> mmu;
355    Param<Addr> addr;
356
357END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
358
359BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
360
361    INIT_PARAM(tsunami, "Tsunami"),
362    INIT_PARAM(mmu, "Memory Controller"),
363    INIT_PARAM(addr, "Device Address")
364
365END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
366
367CREATE_SIM_OBJECT(TsunamiCChip)
368{
369    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
370}
371
372REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
373