tsunami_cchip.cc revision 811
112855Sgabeblack@google.com/* $Id$ */
212855Sgabeblack@google.com
312855Sgabeblack@google.com/* @file
412855Sgabeblack@google.com * Emulation of the Tsunami CChip CSRs
512855Sgabeblack@google.com */
612855Sgabeblack@google.com
712855Sgabeblack@google.com#include <deque>
812855Sgabeblack@google.com#include <string>
912855Sgabeblack@google.com#include <vector>
1012855Sgabeblack@google.com
1112855Sgabeblack@google.com#include "base/trace.hh"
1212855Sgabeblack@google.com#include "cpu/exec_context.hh"
1312855Sgabeblack@google.com#include "dev/console.hh"
1412855Sgabeblack@google.com#include "dev/tsunami_cchip.hh"
1512855Sgabeblack@google.com#include "dev/tsunamireg.h"
1612855Sgabeblack@google.com#include "dev/tsunami.hh"
1712855Sgabeblack@google.com#include "cpu/intr_control.hh"
1812855Sgabeblack@google.com#include "mem/functional_mem/memory_control.hh"
1912855Sgabeblack@google.com#include "sim/builder.hh"
2012855Sgabeblack@google.com#include "sim/system.hh"
2112855Sgabeblack@google.com
2212855Sgabeblack@google.comusing namespace std;
2312855Sgabeblack@google.com
2412855Sgabeblack@google.comTsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
2512855Sgabeblack@google.com                           MemoryController *mmu)
2612855Sgabeblack@google.com    : FunctionalMemory(name), addr(a), tsunami(t)
2712855Sgabeblack@google.com{
2812855Sgabeblack@google.com    mmu->add_child(this, Range<Addr>(addr, addr + size));
2912855Sgabeblack@google.com
3012855Sgabeblack@google.com    for(int i=0; i < Tsunami::Max_CPUs; i++) {
3112855Sgabeblack@google.com        dim[i] = 0;
3212855Sgabeblack@google.com        dir[i] = 0;
3312855Sgabeblack@google.com        dirInterrupting[i] = false;
3412855Sgabeblack@google.com    }
3512855Sgabeblack@google.com
3612855Sgabeblack@google.com    drir = 0;
3712855Sgabeblack@google.com    misc = 0;
3812855Sgabeblack@google.com    RTCInterrupting = false;
3912855Sgabeblack@google.com
4012855Sgabeblack@google.com    //Put back pointer in tsunami
4112855Sgabeblack@google.com    tsunami->cchip = this;
4212855Sgabeblack@google.com}
4312855Sgabeblack@google.com
4412855Sgabeblack@google.comFault
4512855Sgabeblack@google.comTsunamiCChip::read(MemReqPtr &req, uint8_t *data)
4612855Sgabeblack@google.com{
4712855Sgabeblack@google.com    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
4812855Sgabeblack@google.com            req->vaddr, req->size);
4912855Sgabeblack@google.com
5012855Sgabeblack@google.com    Addr daddr = (req->paddr & size) >> 6;
5112855Sgabeblack@google.com    ExecContext *xc = req->xc;
5212855Sgabeblack@google.com
5312855Sgabeblack@google.com    switch (req->size) {
5412855Sgabeblack@google.com
5512855Sgabeblack@google.com      case sizeof(uint64_t):
5612855Sgabeblack@google.com          switch(daddr) {
5712855Sgabeblack@google.com              case TSDEV_CC_CSR:
5812855Sgabeblack@google.com                  *(uint64_t*)data = 0x0;
5912855Sgabeblack@google.com                  return No_Fault;
6012855Sgabeblack@google.com              case TSDEV_CC_MTR:
6112855Sgabeblack@google.com                  panic("TSDEV_CC_MTR not implemeted\n");
6212855Sgabeblack@google.com                   return No_Fault;
6312855Sgabeblack@google.com              case TSDEV_CC_MISC:
6412855Sgabeblack@google.com                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
6512855Sgabeblack@google.com                  return No_Fault;
6612855Sgabeblack@google.com              case TSDEV_CC_AAR0:
6712855Sgabeblack@google.com              case TSDEV_CC_AAR1:
6812855Sgabeblack@google.com              case TSDEV_CC_AAR2:
6912855Sgabeblack@google.com              case TSDEV_CC_AAR3:
7012855Sgabeblack@google.com                  panic("TSDEV_CC_AARx not implemeted\n");
7112855Sgabeblack@google.com                  return No_Fault;
7212855Sgabeblack@google.com              case TSDEV_CC_DIM0:
7312855Sgabeblack@google.com                  *(uint64_t*)data = dim[0];
7412855Sgabeblack@google.com                  return No_Fault;
7512855Sgabeblack@google.com              case TSDEV_CC_DIM1:
7612855Sgabeblack@google.com                  *(uint64_t*)data = dim[1];
7712855Sgabeblack@google.com                  return No_Fault;
7812855Sgabeblack@google.com              case TSDEV_CC_DIM2:
7912855Sgabeblack@google.com                  *(uint64_t*)data = dim[2];
8012855Sgabeblack@google.com                  return No_Fault;
8112855Sgabeblack@google.com              case TSDEV_CC_DIM3:
8212855Sgabeblack@google.com                  *(uint64_t*)data = dim[3];
8312855Sgabeblack@google.com                  return No_Fault;
8412855Sgabeblack@google.com              case TSDEV_CC_DIR0:
8512855Sgabeblack@google.com                  *(uint64_t*)data = dir[0];
8612855Sgabeblack@google.com                  return No_Fault;
8712855Sgabeblack@google.com              case TSDEV_CC_DIR1:
8812855Sgabeblack@google.com                  *(uint64_t*)data = dir[1];
8912855Sgabeblack@google.com                  return No_Fault;
9012855Sgabeblack@google.com              case TSDEV_CC_DIR2:
9112855Sgabeblack@google.com                  *(uint64_t*)data = dir[2];
9212855Sgabeblack@google.com                  return No_Fault;
9312855Sgabeblack@google.com              case TSDEV_CC_DIR3:
9412855Sgabeblack@google.com                  *(uint64_t*)data = dir[3];
9512855Sgabeblack@google.com                  return No_Fault;
9612855Sgabeblack@google.com              case TSDEV_CC_DRIR:
9712855Sgabeblack@google.com                  *(uint64_t*)data = drir;
9812855Sgabeblack@google.com                  return No_Fault;
9912855Sgabeblack@google.com              case TSDEV_CC_PRBEN:
10012855Sgabeblack@google.com                  panic("TSDEV_CC_PRBEN not implemented\n");
10112855Sgabeblack@google.com                  return No_Fault;
10212855Sgabeblack@google.com              case TSDEV_CC_IIC0:
10312855Sgabeblack@google.com              case TSDEV_CC_IIC1:
10412855Sgabeblack@google.com              case TSDEV_CC_IIC2:
10512855Sgabeblack@google.com              case TSDEV_CC_IIC3:
10612855Sgabeblack@google.com                  panic("TSDEV_CC_IICx not implemented\n");
10712855Sgabeblack@google.com                  return No_Fault;
10812855Sgabeblack@google.com              case TSDEV_CC_MPR0:
10912855Sgabeblack@google.com              case TSDEV_CC_MPR1:
11012855Sgabeblack@google.com              case TSDEV_CC_MPR2:
11112855Sgabeblack@google.com              case TSDEV_CC_MPR3:
11212855Sgabeblack@google.com                  panic("TSDEV_CC_MPRx not implemented\n");
11312855Sgabeblack@google.com                  return No_Fault;
11412855Sgabeblack@google.com              default:
11512855Sgabeblack@google.com                  panic("default in cchip read reached, accessing 0x%x\n");
11612855Sgabeblack@google.com           } // uint64_t
11712855Sgabeblack@google.com
11812855Sgabeblack@google.com      break;
11912855Sgabeblack@google.com      case sizeof(uint32_t):
12012855Sgabeblack@google.com      case sizeof(uint16_t):
12112855Sgabeblack@google.com      case sizeof(uint8_t):
12212855Sgabeblack@google.com      default:
12312855Sgabeblack@google.com        panic("invalid access size(?) for tsunami register!\n");
12412855Sgabeblack@google.com    }
12512855Sgabeblack@google.com    DPRINTFN("Tsunami CChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
12612855Sgabeblack@google.com
12712855Sgabeblack@google.com    return No_Fault;
12812855Sgabeblack@google.com}
12912855Sgabeblack@google.com
13012855Sgabeblack@google.comFault
13112855Sgabeblack@google.comTsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
13212855Sgabeblack@google.com{
13312855Sgabeblack@google.com    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
13412855Sgabeblack@google.com            req->vaddr, req->size);
13512855Sgabeblack@google.com
13612855Sgabeblack@google.com    Addr daddr = (req->paddr & size) >> 6;
13712855Sgabeblack@google.com
13812855Sgabeblack@google.com    switch (req->size) {
13912855Sgabeblack@google.com
14012855Sgabeblack@google.com      case sizeof(uint64_t):
14112855Sgabeblack@google.com          switch(daddr) {
14212855Sgabeblack@google.com              case TSDEV_CC_CSR:
14312855Sgabeblack@google.com                  panic("TSDEV_CC_CSR write\n");
14412855Sgabeblack@google.com                  return No_Fault;
14512855Sgabeblack@google.com              case TSDEV_CC_MTR:
14612855Sgabeblack@google.com                  panic("TSDEV_CC_MTR write not implemented\n");
14712855Sgabeblack@google.com                   return No_Fault;
14812855Sgabeblack@google.com              case TSDEV_CC_MISC:
14912855Sgabeblack@google.com                //If it is the seventh bit, clear the RTC interrupt
15012855Sgabeblack@google.com                if ((*(uint64_t*) data) & (1<<4)) {
15112855Sgabeblack@google.com                    RTCInterrupting = false;
15212855Sgabeblack@google.com                    tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0);
15312855Sgabeblack@google.com                    DPRINTF(Tsunami, "clearing rtc interrupt\n");
15412855Sgabeblack@google.com                    misc &= ~(1<<4);
15512855Sgabeblack@google.com                } else panic("TSDEV_CC_MISC write not implemented\n");
15612855Sgabeblack@google.com                  return No_Fault;
15712855Sgabeblack@google.com              case TSDEV_CC_AAR0:
15812855Sgabeblack@google.com              case TSDEV_CC_AAR1:
15912855Sgabeblack@google.com              case TSDEV_CC_AAR2:
16012855Sgabeblack@google.com              case TSDEV_CC_AAR3:
16112855Sgabeblack@google.com                  panic("TSDEV_CC_AARx write not implemeted\n");
16212855Sgabeblack@google.com                  return No_Fault;
16312855Sgabeblack@google.com              case TSDEV_CC_DIM0:
16412855Sgabeblack@google.com                   dim[0] = *(uint64_t*)data;
16512855Sgabeblack@google.com                   if (dim[0] & drir) {
16612855Sgabeblack@google.com                       dir[0] = dim[0] & drir;
16712855Sgabeblack@google.com                       if (!dirInterrupting[0]) {
16812855Sgabeblack@google.com                           dirInterrupting[0] = true;
16912855Sgabeblack@google.com                           tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0);
17012855Sgabeblack@google.com                           DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
17112855Sgabeblack@google.com                       }
17212855Sgabeblack@google.com                   }
17312855Sgabeblack@google.com                  return No_Fault;
17412855Sgabeblack@google.com              case TSDEV_CC_DIM1:
17512855Sgabeblack@google.com                  dim[1] = *(uint64_t*)data;
17612855Sgabeblack@google.com                  if (dim[1] & drir) {
17712855Sgabeblack@google.com                       dir[1] = dim[1] & drir;
17812855Sgabeblack@google.com                       if (!dirInterrupting[1]) {
17912855Sgabeblack@google.com                           dirInterrupting[1] = true;
18012855Sgabeblack@google.com                           tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0);
181                           DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n");
182                       }
183                  }
184                  return No_Fault;
185              case TSDEV_CC_DIM2:
186                  dim[2] = *(uint64_t*)data;
187                  if (dim[2] & drir) {
188                       dir[2] = dim[2] & drir;
189                       if (!dirInterrupting[2]) {
190                           dirInterrupting[2] = true;
191                           tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0);
192                           DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n");
193                       }
194                  }
195                  return No_Fault;
196              case TSDEV_CC_DIM3:
197                  dim[3] = *(uint64_t*)data;
198                  if ((dim[3] & drir) /*And Not Already Int*/) {
199                       dir[3] = dim[3] & drir;
200                       if (!dirInterrupting[3]) {
201                           dirInterrupting[3] = true;
202                           tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0);
203                           DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n");
204                       }
205                  }
206                  return No_Fault;
207              case TSDEV_CC_DIR0:
208              case TSDEV_CC_DIR1:
209              case TSDEV_CC_DIR2:
210              case TSDEV_CC_DIR3:
211                  panic("TSDEV_CC_DIR write not implemented\n");
212                  return No_Fault;
213              case TSDEV_CC_DRIR:
214                  panic("TSDEV_CC_DRIR write not implemented\n");
215                  return No_Fault;
216              case TSDEV_CC_PRBEN:
217                  panic("TSDEV_CC_PRBEN write not implemented\n");
218                  return No_Fault;
219              case TSDEV_CC_IIC0:
220              case TSDEV_CC_IIC1:
221              case TSDEV_CC_IIC2:
222              case TSDEV_CC_IIC3:
223                  panic("TSDEV_CC_IICx write not implemented\n");
224                  return No_Fault;
225              case TSDEV_CC_MPR0:
226              case TSDEV_CC_MPR1:
227              case TSDEV_CC_MPR2:
228              case TSDEV_CC_MPR3:
229                  panic("TSDEV_CC_MPRx write not implemented\n");
230                  return No_Fault;
231              default:
232                  panic("default in cchip read reached, accessing 0x%x\n");
233          }
234
235      break;
236      case sizeof(uint32_t):
237      case sizeof(uint16_t):
238      case sizeof(uint8_t):
239      default:
240        panic("invalid access size(?) for tsunami register!\n");
241    }
242
243    DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
244
245    return No_Fault;
246}
247
248void
249TsunamiCChip::postDRIR(uint64_t bitvector)
250{
251    drir |= bitvector;
252    for(int i=0; i < Tsunami::Max_CPUs; i++) {
253        if (bitvector & dim[i]) {
254            dir[i] |= bitvector;
255            if (!dirInterrupting[i]) {
256                dirInterrupting[i] = true;
257                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0);
258                DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i);
259            }
260        }
261    }
262}
263
264void
265TsunamiCChip::clearDRIR(uint64_t bitvector)
266{
267    drir &= ~bitvector;
268    for(int i=0; i < Tsunami::Max_CPUs; i++) {
269        dir[i] &= ~bitvector;
270        if (!dir[i]) {
271            dirInterrupting[i] = false;
272            tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0);
273            DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i);
274
275        }
276    }
277}
278
279void
280TsunamiCChip::serialize(std::ostream &os)
281{
282    SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
283    SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
284    SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
285    SERIALIZE_SCALAR(drir);
286    SERIALIZE_SCALAR(misc);
287    SERIALIZE_SCALAR(RTCInterrupting);
288}
289
290void
291TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
292{
293    UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
294    UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
295    UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
296    UNSERIALIZE_SCALAR(drir);
297    UNSERIALIZE_SCALAR(misc);
298    UNSERIALIZE_SCALAR(RTCInterrupting);
299}
300
301BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
302
303    SimObjectParam<Tsunami *> tsunami;
304    SimObjectParam<MemoryController *> mmu;
305    Param<Addr> addr;
306
307END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
308
309BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
310
311    INIT_PARAM(tsunami, "Tsunami"),
312    INIT_PARAM(mmu, "Memory Controller"),
313    INIT_PARAM(addr, "Device Address")
314
315END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
316
317CREATE_SIM_OBJECT(TsunamiCChip)
318{
319    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
320}
321
322REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
323