tsunami_cchip.cc revision 830
15651Sgblack@eecs.umich.edu/* $Id$ */
25651Sgblack@eecs.umich.edu
35651Sgblack@eecs.umich.edu/* @file
45651Sgblack@eecs.umich.edu * Emulation of the Tsunami CChip CSRs
55651Sgblack@eecs.umich.edu */
65651Sgblack@eecs.umich.edu
75651Sgblack@eecs.umich.edu#include <deque>
85651Sgblack@eecs.umich.edu#include <string>
95651Sgblack@eecs.umich.edu#include <vector>
105651Sgblack@eecs.umich.edu
115651Sgblack@eecs.umich.edu#include "base/trace.hh"
125651Sgblack@eecs.umich.edu#include "cpu/exec_context.hh"
135651Sgblack@eecs.umich.edu#include "dev/console.hh"
145651Sgblack@eecs.umich.edu#include "dev/tsunami_cchip.hh"
155651Sgblack@eecs.umich.edu#include "dev/tsunamireg.h"
165651Sgblack@eecs.umich.edu#include "dev/tsunami.hh"
175651Sgblack@eecs.umich.edu#include "cpu/intr_control.hh"
185651Sgblack@eecs.umich.edu#include "mem/functional_mem/memory_control.hh"
195651Sgblack@eecs.umich.edu#include "sim/builder.hh"
205651Sgblack@eecs.umich.edu#include "sim/system.hh"
215651Sgblack@eecs.umich.edu
225651Sgblack@eecs.umich.eduusing namespace std;
235651Sgblack@eecs.umich.edu
245651Sgblack@eecs.umich.eduTsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
255651Sgblack@eecs.umich.edu                           MemoryController *mmu)
265651Sgblack@eecs.umich.edu    : FunctionalMemory(name), addr(a), tsunami(t)
275651Sgblack@eecs.umich.edu{
285651Sgblack@eecs.umich.edu    mmu->add_child(this, Range<Addr>(addr, addr + size));
295651Sgblack@eecs.umich.edu
305651Sgblack@eecs.umich.edu    for(int i=0; i < Tsunami::Max_CPUs; i++) {
315651Sgblack@eecs.umich.edu        dim[i] = 0;
325651Sgblack@eecs.umich.edu        dir[i] = 0;
335651Sgblack@eecs.umich.edu        dirInterrupting[i] = false;
345651Sgblack@eecs.umich.edu        ipiInterrupting[i] = false;
355651Sgblack@eecs.umich.edu        RTCInterrupting[i] = false;
365651Sgblack@eecs.umich.edu    }
376046Sgblack@eecs.umich.edu
385651Sgblack@eecs.umich.edu    drir = 0;
395651Sgblack@eecs.umich.edu    misc = 0;
405651Sgblack@eecs.umich.edu
415651Sgblack@eecs.umich.edu    //Put back pointer in tsunami
425651Sgblack@eecs.umich.edu    tsunami->cchip = this;
435651Sgblack@eecs.umich.edu}
445651Sgblack@eecs.umich.edu
455651Sgblack@eecs.umich.eduFault
465651Sgblack@eecs.umich.eduTsunamiCChip::read(MemReqPtr &req, uint8_t *data)
475651Sgblack@eecs.umich.edu{
485654Sgblack@eecs.umich.edu    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
495654Sgblack@eecs.umich.edu            req->vaddr, req->size);
505651Sgblack@eecs.umich.edu
515651Sgblack@eecs.umich.edu    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
525654Sgblack@eecs.umich.edu    ExecContext *xc = req->xc;
535654Sgblack@eecs.umich.edu
545654Sgblack@eecs.umich.edu    switch (req->size) {
555654Sgblack@eecs.umich.edu
565654Sgblack@eecs.umich.edu      case sizeof(uint64_t):
575654Sgblack@eecs.umich.edu          switch(daddr) {
585654Sgblack@eecs.umich.edu              case TSDEV_CC_CSR:
595654Sgblack@eecs.umich.edu                  *(uint64_t*)data = 0x0;
605654Sgblack@eecs.umich.edu                  return No_Fault;
615654Sgblack@eecs.umich.edu              case TSDEV_CC_MTR:
625654Sgblack@eecs.umich.edu                  panic("TSDEV_CC_MTR not implemeted\n");
635654Sgblack@eecs.umich.edu                   return No_Fault;
645654Sgblack@eecs.umich.edu              case TSDEV_CC_MISC:
655654Sgblack@eecs.umich.edu                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
665654Sgblack@eecs.umich.edu                  return No_Fault;
675654Sgblack@eecs.umich.edu              case TSDEV_CC_AAR0:
685654Sgblack@eecs.umich.edu              case TSDEV_CC_AAR1:
695654Sgblack@eecs.umich.edu              case TSDEV_CC_AAR2:
705654Sgblack@eecs.umich.edu              case TSDEV_CC_AAR3:
715654Sgblack@eecs.umich.edu                  panic("TSDEV_CC_AARx not implemeted\n");
725655Sgblack@eecs.umich.edu                  return No_Fault;
735654Sgblack@eecs.umich.edu              case TSDEV_CC_DIM0:
745654Sgblack@eecs.umich.edu                  *(uint64_t*)data = dim[0];
755654Sgblack@eecs.umich.edu                  return No_Fault;
765651Sgblack@eecs.umich.edu              case TSDEV_CC_DIM1:
775651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dim[1];
785651Sgblack@eecs.umich.edu                  return No_Fault;
795651Sgblack@eecs.umich.edu              case TSDEV_CC_DIM2:
805651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dim[2];
815651Sgblack@eecs.umich.edu                  return No_Fault;
825736Snate@binkert.org              case TSDEV_CC_DIM3:
835651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dim[3];
845651Sgblack@eecs.umich.edu                  return No_Fault;
855651Sgblack@eecs.umich.edu              case TSDEV_CC_DIR0:
865651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dir[0];
875651Sgblack@eecs.umich.edu                  return No_Fault;
885651Sgblack@eecs.umich.edu              case TSDEV_CC_DIR1:
895651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dir[1];
905651Sgblack@eecs.umich.edu                  return No_Fault;
915651Sgblack@eecs.umich.edu              case TSDEV_CC_DIR2:
925651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dir[2];
935651Sgblack@eecs.umich.edu                  return No_Fault;
945651Sgblack@eecs.umich.edu              case TSDEV_CC_DIR3:
955651Sgblack@eecs.umich.edu                  *(uint64_t*)data = dir[3];
965651Sgblack@eecs.umich.edu                  return No_Fault;
975651Sgblack@eecs.umich.edu              case TSDEV_CC_DRIR:
985651Sgblack@eecs.umich.edu                  *(uint64_t*)data = drir;
995651Sgblack@eecs.umich.edu                  return No_Fault;
1005651Sgblack@eecs.umich.edu              case TSDEV_CC_PRBEN:
1015651Sgblack@eecs.umich.edu                  panic("TSDEV_CC_PRBEN not implemented\n");
1025651Sgblack@eecs.umich.edu                  return No_Fault;
1035651Sgblack@eecs.umich.edu              case TSDEV_CC_IIC0:
1045651Sgblack@eecs.umich.edu              case TSDEV_CC_IIC1:
1055651Sgblack@eecs.umich.edu              case TSDEV_CC_IIC2:
1065651Sgblack@eecs.umich.edu              case TSDEV_CC_IIC3:
1075651Sgblack@eecs.umich.edu                  panic("TSDEV_CC_IICx not implemented\n");
1085651Sgblack@eecs.umich.edu                  return No_Fault;
1095651Sgblack@eecs.umich.edu              case TSDEV_CC_MPR0:
1105651Sgblack@eecs.umich.edu              case TSDEV_CC_MPR1:
1115651Sgblack@eecs.umich.edu              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