tsunami_cchip.cc revision 817
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    }
35
36    drir = 0;
37    misc = 0;
38    RTCInterrupting = false;
39
40    //Put back pointer in tsunami
41    tsunami->cchip = this;
42}
43
44Fault
45TsunamiCChip::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
130Fault
131TsunamiCChip::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
244void
245TsunamiCChip::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
259void
260TsunamiCChip::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
280void
281TsunamiCChip::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
291void
292TsunamiCChip::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
302BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
303
304    SimObjectParam<Tsunami *> tsunami;
305    SimObjectParam<MemoryController *> mmu;
306    Param<Addr> addr;
307
308END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
309
310BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
311
312    INIT_PARAM(tsunami, "Tsunami"),
313    INIT_PARAM(mmu, "Memory Controller"),
314    INIT_PARAM(addr, "Device Address")
315
316END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
317
318CREATE_SIM_OBJECT(TsunamiCChip)
319{
320    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
321}
322
323REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
324