tsunami_cchip.cc revision 831
12391SN/A/* $Id$ */
28931Sandreas.hansson@arm.com
38931Sandreas.hansson@arm.com/* @file
48931Sandreas.hansson@arm.com * Emulation of the Tsunami CChip CSRs
58931Sandreas.hansson@arm.com */
68931Sandreas.hansson@arm.com
78931Sandreas.hansson@arm.com#include <deque>
88931Sandreas.hansson@arm.com#include <string>
98931Sandreas.hansson@arm.com#include <vector>
108931Sandreas.hansson@arm.com
118931Sandreas.hansson@arm.com#include "base/trace.hh"
128931Sandreas.hansson@arm.com#include "cpu/exec_context.hh"
132391SN/A#include "dev/console.hh"
142391SN/A#include "dev/tsunami_cchip.hh"
152391SN/A#include "dev/tsunamireg.h"
162391SN/A#include "dev/tsunami.hh"
172391SN/A#include "cpu/intr_control.hh"
182391SN/A#include "mem/functional_mem/memory_control.hh"
192391SN/A#include "sim/builder.hh"
202391SN/A#include "sim/system.hh"
212391SN/A
222391SN/Ausing namespace std;
232391SN/A
242391SN/ATsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
252391SN/A                           MemoryController *mmu)
262391SN/A    : FunctionalMemory(name), addr(a), tsunami(t)
272391SN/A{
282391SN/A    mmu->add_child(this, Range<Addr>(addr, addr + size));
292391SN/A
302391SN/A    for(int i=0; i < Tsunami::Max_CPUs; i++) {
312391SN/A        dim[i] = 0;
322391SN/A        dir[i] = 0;
332391SN/A        dirInterrupting[i] = false;
342391SN/A        ipiInterrupting[i] = false;
352391SN/A        RTCInterrupting[i] = false;
362665Ssaidi@eecs.umich.edu    }
378931Sandreas.hansson@arm.com
382391SN/A    drir = 0;
392391SN/A    misc = 0;
4010482Sandreas.hansson@arm.com
4110482Sandreas.hansson@arm.com    //Put back pointer in tsunami
422391SN/A    tsunami->cchip = this;
439235Sandreas.hansson@arm.com}
4410482Sandreas.hansson@arm.com
459293Sandreas.hansson@arm.comFault
469293Sandreas.hansson@arm.comTsunamiCChip::read(MemReqPtr &req, uint8_t *data)
479293Sandreas.hansson@arm.com{
489293Sandreas.hansson@arm.com    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
499293Sandreas.hansson@arm.com            req->vaddr, req->size);
504762Snate@binkert.org
518931Sandreas.hansson@arm.com    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
528931Sandreas.hansson@arm.com    ExecContext *xc = req->xc;
538931Sandreas.hansson@arm.com
548931Sandreas.hansson@arm.com    switch (req->size) {
559293Sandreas.hansson@arm.com
569293Sandreas.hansson@arm.com      case sizeof(uint64_t):
579293Sandreas.hansson@arm.com          switch(daddr) {
589293Sandreas.hansson@arm.com              case TSDEV_CC_CSR:
599293Sandreas.hansson@arm.com                  *(uint64_t*)data = 0x0;
6010482Sandreas.hansson@arm.com                  return No_Fault;
619293Sandreas.hansson@arm.com              case TSDEV_CC_MTR:
629293Sandreas.hansson@arm.com                  panic("TSDEV_CC_MTR not implemeted\n");
639293Sandreas.hansson@arm.com                   return No_Fault;
649293Sandreas.hansson@arm.com              case TSDEV_CC_MISC:
659293Sandreas.hansson@arm.com                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
668931Sandreas.hansson@arm.com                  return No_Fault;
679293Sandreas.hansson@arm.com              case TSDEV_CC_AAR0:
682391SN/A              case TSDEV_CC_AAR1:
692413SN/A              case TSDEV_CC_AAR2:
702391SN/A              case TSDEV_CC_AAR3:
712391SN/A                  panic("TSDEV_CC_AARx not implemeted\n");
729293Sandreas.hansson@arm.com                  return No_Fault;
739293Sandreas.hansson@arm.com              case TSDEV_CC_DIM0:
749293Sandreas.hansson@arm.com                  *(uint64_t*)data = dim[0];
758931Sandreas.hansson@arm.com                  return No_Fault;
769235Sandreas.hansson@arm.com              case TSDEV_CC_DIM1:
773170Sstever@eecs.umich.edu                  *(uint64_t*)data = dim[1];
7810699Sandreas.hansson@arm.com                  return No_Fault;
7910699Sandreas.hansson@arm.com              case TSDEV_CC_DIM2:
8010699Sandreas.hansson@arm.com                  *(uint64_t*)data = dim[2];
813170Sstever@eecs.umich.edu                  return No_Fault;
828931Sandreas.hansson@arm.com              case TSDEV_CC_DIM3:
838931Sandreas.hansson@arm.com                  *(uint64_t*)data = dim[3];
843170Sstever@eecs.umich.edu                  return No_Fault;
858931Sandreas.hansson@arm.com              case TSDEV_CC_DIR0:
868931Sandreas.hansson@arm.com                  *(uint64_t*)data = dir[0];
873170Sstever@eecs.umich.edu                  return No_Fault;
8810700Sandreas.hansson@arm.com              case TSDEV_CC_DIR1:
8910700Sandreas.hansson@arm.com                  *(uint64_t*)data = dir[1];
9010700Sandreas.hansson@arm.com                  return No_Fault;
919293Sandreas.hansson@arm.com              case TSDEV_CC_DIR2:
929293Sandreas.hansson@arm.com                  *(uint64_t*)data = dir[2];
9310482Sandreas.hansson@arm.com                  return No_Fault;
949293Sandreas.hansson@arm.com              case TSDEV_CC_DIR3:
958931Sandreas.hansson@arm.com                  *(uint64_t*)data = dir[3];
968931Sandreas.hansson@arm.com                  return No_Fault;
973170Sstever@eecs.umich.edu              case TSDEV_CC_DRIR:
988931Sandreas.hansson@arm.com                  *(uint64_t*)data = drir;
998931Sandreas.hansson@arm.com                  return No_Fault;
1008719SAli.Saidi@ARM.com              case TSDEV_CC_PRBEN:
1019293Sandreas.hansson@arm.com                  panic("TSDEV_CC_PRBEN not implemented\n");
1029293Sandreas.hansson@arm.com                  return No_Fault;
1039293Sandreas.hansson@arm.com              case TSDEV_CC_IIC0:
1049293Sandreas.hansson@arm.com              case TSDEV_CC_IIC1:
1059293Sandreas.hansson@arm.com              case TSDEV_CC_IIC2:
1069293Sandreas.hansson@arm.com              case TSDEV_CC_IIC3:
1079293Sandreas.hansson@arm.com                  panic("TSDEV_CC_IICx not implemented\n");
1089293Sandreas.hansson@arm.com                  return No_Fault;
1099293Sandreas.hansson@arm.com              case TSDEV_CC_MPR0:
1109293Sandreas.hansson@arm.com              case TSDEV_CC_MPR1:
1119293Sandreas.hansson@arm.com              case TSDEV_CC_MPR2:
1122391SN/A              case TSDEV_CC_MPR3:
1132391SN/A                  panic("TSDEV_CC_MPRx not implemented\n");
1148931Sandreas.hansson@arm.com                  return No_Fault;
1158931Sandreas.hansson@arm.com              default:
1168931Sandreas.hansson@arm.com                  panic("default in cchip read reached, accessing 0x%x\n");
1179293Sandreas.hansson@arm.com           } // uint64_t
11810700Sandreas.hansson@arm.com
11910700Sandreas.hansson@arm.com      break;
1202391SN/A      case sizeof(uint32_t):
1218931Sandreas.hansson@arm.com      case sizeof(uint16_t):
1229293Sandreas.hansson@arm.com      case sizeof(uint8_t):
1238931Sandreas.hansson@arm.com      default:
1249293Sandreas.hansson@arm.com        panic("invalid access size(?) for tsunami register!\n");
1259293Sandreas.hansson@arm.com    }
1269293Sandreas.hansson@arm.com    DPRINTFN("Tsunami CChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
1279293Sandreas.hansson@arm.com
1289293Sandreas.hansson@arm.com    return No_Fault;
1299293Sandreas.hansson@arm.com}
1309293Sandreas.hansson@arm.com
1314762Snate@binkert.orgFault
1328931Sandreas.hansson@arm.comTsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
1338931Sandreas.hansson@arm.com{
1348931Sandreas.hansson@arm.com    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
1358931Sandreas.hansson@arm.com            req->vaddr, req->size);
1368931Sandreas.hansson@arm.com
1378931Sandreas.hansson@arm.com    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
1388931Sandreas.hansson@arm.com
1398931Sandreas.hansson@arm.com    bool supportedWrite = false;
1402391SN/A    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
1418931Sandreas.hansson@arm.com
1428931Sandreas.hansson@arm.com    switch (req->size) {
1439413Sandreas.hansson@arm.com
1449413Sandreas.hansson@arm.com      case sizeof(uint64_t):
1459413Sandreas.hansson@arm.com          switch(daddr) {
1468931Sandreas.hansson@arm.com            case TSDEV_CC_CSR:
1478931Sandreas.hansson@arm.com                  panic("TSDEV_CC_CSR write\n");
1488931Sandreas.hansson@arm.com                  return No_Fault;
1498931Sandreas.hansson@arm.com              case TSDEV_CC_MTR:
1508923Sandreas.hansson@arm.com                  panic("TSDEV_CC_MTR write not implemented\n");
1518931Sandreas.hansson@arm.com                   return No_Fault;
1528931Sandreas.hansson@arm.com              case TSDEV_CC_MISC:
1538931Sandreas.hansson@arm.com                //If it is the 4-7th bit, clear the RTC interrupt
1548931Sandreas.hansson@arm.com                uint64_t itintr;
1558931Sandreas.hansson@arm.com                if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
1568931Sandreas.hansson@arm.com                    //Clear the bits in ITINTR
1578923Sandreas.hansson@arm.com                    misc &= ~(itintr);
1589293Sandreas.hansson@arm.com                    for (int i=0; i < size; i++) {
1599293Sandreas.hansson@arm.com                        if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
1609293Sandreas.hansson@arm.com                            tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
1619293Sandreas.hansson@arm.com                            RTCInterrupting[i] = false;
1629293Sandreas.hansson@arm.com                            DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
1639293Sandreas.hansson@arm.com                        }
1649293Sandreas.hansson@arm.com                    }
1659293Sandreas.hansson@arm.com                    supportedWrite = true;
1669293Sandreas.hansson@arm.com                }
1679293Sandreas.hansson@arm.com                //If it is 12th-15th bit, IPI sent to Processor 1
1689293Sandreas.hansson@arm.com                uint64_t ipreq;
1699293Sandreas.hansson@arm.com                if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) {
17010482Sandreas.hansson@arm.com                    //Set the bits in IPINTR
1719293Sandreas.hansson@arm.com                    misc |= (ipreq >> 4);
1729293Sandreas.hansson@arm.com                    for (int i=0; i < size; i++) {
1738931Sandreas.hansson@arm.com                        if ((ipreq & (1 << (i + 12)))) {
1749293Sandreas.hansson@arm.com                            if (!ipiInterrupting[i])
1759293Sandreas.hansson@arm.com                                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0);
1769293Sandreas.hansson@arm.com                            ipiInterrupting[i]++;
1778931Sandreas.hansson@arm.com                            DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i,
1789293Sandreas.hansson@arm.com                                    ipiInterrupting[i], req->cpu_num);
1798719SAli.Saidi@ARM.com                        }
1808931Sandreas.hansson@arm.com                    }
1819293Sandreas.hansson@arm.com                    supportedWrite = true;
1829293Sandreas.hansson@arm.com                }
1839293Sandreas.hansson@arm.com                //If it is bits 8-11, then clearing IPI's
1849293Sandreas.hansson@arm.com                uint64_t ipintr;
1859293Sandreas.hansson@arm.com                if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
1869293Sandreas.hansson@arm.com                    //Clear the bits in IPINTR
1879293Sandreas.hansson@arm.com                    misc &= ~(ipintr);
1889293Sandreas.hansson@arm.com                    for (int i=0; i < size; i++) {
1899293Sandreas.hansson@arm.com                        if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) {
1908931Sandreas.hansson@arm.com                            if (!(--ipiInterrupting[i]))
1919293Sandreas.hansson@arm.com                                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0);
1929293Sandreas.hansson@arm.com                            DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i,
1939293Sandreas.hansson@arm.com                                    ipiInterrupting[i] + 1, req->cpu_num);
1949293Sandreas.hansson@arm.com                        }
1959293Sandreas.hansson@arm.com                    }
1969293Sandreas.hansson@arm.com                    supportedWrite = true;
1979293Sandreas.hansson@arm.com                }
1989293Sandreas.hansson@arm.com                if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
1999293Sandreas.hansson@arm.com                return No_Fault;
20010905Sandreas.sandberg@arm.com              case TSDEV_CC_AAR0:
2019293Sandreas.hansson@arm.com              case TSDEV_CC_AAR1:
2029293Sandreas.hansson@arm.com              case TSDEV_CC_AAR2:
2039293Sandreas.hansson@arm.com              case TSDEV_CC_AAR3:
2049293Sandreas.hansson@arm.com                  panic("TSDEV_CC_AARx write not implemeted\n");
2059293Sandreas.hansson@arm.com                  return No_Fault;
2069293Sandreas.hansson@arm.com              case TSDEV_CC_DIM0:
2079293Sandreas.hansson@arm.com              case TSDEV_CC_DIM1:
2089293Sandreas.hansson@arm.com              case TSDEV_CC_DIM2:
20910905Sandreas.sandberg@arm.com              case TSDEV_CC_DIM3:
21010905Sandreas.sandberg@arm.com                  int number;
2119293Sandreas.hansson@arm.com                  if(daddr == TSDEV_CC_DIM0)
2129293Sandreas.hansson@arm.com                      number = 0;
2139293Sandreas.hansson@arm.com                  else if(daddr == TSDEV_CC_DIM1)
2149293Sandreas.hansson@arm.com                      number = 1;
2159293Sandreas.hansson@arm.com                  else if(daddr == TSDEV_CC_DIM2)
2169293Sandreas.hansson@arm.com                      number = 2;
21710905Sandreas.sandberg@arm.com                  else
2189293Sandreas.hansson@arm.com                      number = 3;
2199293Sandreas.hansson@arm.com
2209293Sandreas.hansson@arm.com                  uint64_t bitvector;
2219293Sandreas.hansson@arm.com                  uint64_t olddim;
22210905Sandreas.sandberg@arm.com                  uint64_t olddir;
2239293Sandreas.hansson@arm.com
2242391SN/A                  olddim = dim[number];
2252391SN/A                  olddir = dir[number];
22610482Sandreas.hansson@arm.com                  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