tsunami_cchip.cc revision 892
17584SAli.Saidi@arm.com/*
27584SAli.Saidi@arm.com * Copyright (c) 2004 The Regents of The University of Michigan
37584SAli.Saidi@arm.com * All rights reserved.
47584SAli.Saidi@arm.com *
57584SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without
67584SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are
77584SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright
87584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer;
97584SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright
107584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the
117584SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution;
127584SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its
137584SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from
147584SAli.Saidi@arm.com * this software without specific prior written permission.
157584SAli.Saidi@arm.com *
167584SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177584SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187584SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197584SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207584SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217584SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227584SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237584SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247584SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257584SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267584SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277584SAli.Saidi@arm.com */
287584SAli.Saidi@arm.com
297584SAli.Saidi@arm.com/* @file
307584SAli.Saidi@arm.com * Emulation of the Tsunami CChip CSRs
317584SAli.Saidi@arm.com */
327584SAli.Saidi@arm.com
337584SAli.Saidi@arm.com#include <deque>
347584SAli.Saidi@arm.com#include <string>
357584SAli.Saidi@arm.com#include <vector>
367584SAli.Saidi@arm.com
377584SAli.Saidi@arm.com#include "base/trace.hh"
387584SAli.Saidi@arm.com#include "cpu/exec_context.hh"
397584SAli.Saidi@arm.com#include "dev/console.hh"
407584SAli.Saidi@arm.com#include "dev/tsunami_cchip.hh"
417584SAli.Saidi@arm.com#include "dev/tsunamireg.h"
427584SAli.Saidi@arm.com#include "dev/tsunami.hh"
437584SAli.Saidi@arm.com#include "cpu/intr_control.hh"
447584SAli.Saidi@arm.com#include "mem/functional_mem/memory_control.hh"
457584SAli.Saidi@arm.com#include "sim/builder.hh"
467584SAli.Saidi@arm.com#include "sim/system.hh"
477584SAli.Saidi@arm.com
487584SAli.Saidi@arm.comusing namespace std;
497584SAli.Saidi@arm.com
507584SAli.Saidi@arm.comTsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
517584SAli.Saidi@arm.com                           MemoryController *mmu)
527584SAli.Saidi@arm.com    : FunctionalMemory(name), addr(a), tsunami(t)
537584SAli.Saidi@arm.com{
547584SAli.Saidi@arm.com    mmu->add_child(this, Range<Addr>(addr, addr + size));
557584SAli.Saidi@arm.com
567584SAli.Saidi@arm.com    for(int i=0; i < Tsunami::Max_CPUs; i++) {
579806Sstever@gmail.com        dim[i] = 0;
587584SAli.Saidi@arm.com        dir[i] = 0;
597584SAli.Saidi@arm.com        dirInterrupting[i] = false;
607584SAli.Saidi@arm.com        ipiInterrupting[i] = false;
617584SAli.Saidi@arm.com        RTCInterrupting[i] = false;
627584SAli.Saidi@arm.com    }
637584SAli.Saidi@arm.com
647584SAli.Saidi@arm.com    drir = 0;
657584SAli.Saidi@arm.com    misc = 0;
667584SAli.Saidi@arm.com
677584SAli.Saidi@arm.com    //Put back pointer in tsunami
687584SAli.Saidi@arm.com    tsunami->cchip = this;
697584SAli.Saidi@arm.com}
707584SAli.Saidi@arm.com
717584SAli.Saidi@arm.comFault
727584SAli.Saidi@arm.comTsunamiCChip::read(MemReqPtr &req, uint8_t *data)
737584SAli.Saidi@arm.com{
74    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
75            req->vaddr, req->size);
76
77    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
78    ExecContext *xc = req->xc;
79
80    switch (req->size) {
81
82      case sizeof(uint64_t):
83          switch(daddr) {
84              case TSDEV_CC_CSR:
85                  *(uint64_t*)data = 0x0;
86                  return No_Fault;
87              case TSDEV_CC_MTR:
88                  panic("TSDEV_CC_MTR not implemeted\n");
89                   return No_Fault;
90              case TSDEV_CC_MISC:
91                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
92                  return No_Fault;
93              case TSDEV_CC_AAR0:
94              case TSDEV_CC_AAR1:
95              case TSDEV_CC_AAR2:
96              case TSDEV_CC_AAR3:
97                  *(uint64_t*)data = 0;
98                  return No_Fault;
99              case TSDEV_CC_DIM0:
100                  *(uint64_t*)data = dim[0];
101                  return No_Fault;
102              case TSDEV_CC_DIM1:
103                  *(uint64_t*)data = dim[1];
104                  return No_Fault;
105              case TSDEV_CC_DIM2:
106                  *(uint64_t*)data = dim[2];
107                  return No_Fault;
108              case TSDEV_CC_DIM3:
109                  *(uint64_t*)data = dim[3];
110                  return No_Fault;
111              case TSDEV_CC_DIR0:
112                  *(uint64_t*)data = dir[0];
113                  return No_Fault;
114              case TSDEV_CC_DIR1:
115                  *(uint64_t*)data = dir[1];
116                  return No_Fault;
117              case TSDEV_CC_DIR2:
118                  *(uint64_t*)data = dir[2];
119                  return No_Fault;
120              case TSDEV_CC_DIR3:
121                  *(uint64_t*)data = dir[3];
122                  return No_Fault;
123              case TSDEV_CC_DRIR:
124                  *(uint64_t*)data = drir;
125                  return No_Fault;
126              case TSDEV_CC_PRBEN:
127                  panic("TSDEV_CC_PRBEN not implemented\n");
128                  return No_Fault;
129              case TSDEV_CC_IIC0:
130              case TSDEV_CC_IIC1:
131              case TSDEV_CC_IIC2:
132              case TSDEV_CC_IIC3:
133                  panic("TSDEV_CC_IICx not implemented\n");
134                  return No_Fault;
135              case TSDEV_CC_MPR0:
136              case TSDEV_CC_MPR1:
137              case TSDEV_CC_MPR2:
138              case TSDEV_CC_MPR3:
139                  panic("TSDEV_CC_MPRx not implemented\n");
140                  return No_Fault;
141              default:
142                  panic("default in cchip read reached, accessing 0x%x\n");
143           } // uint64_t
144
145      break;
146      case sizeof(uint32_t):
147      case sizeof(uint16_t):
148      case sizeof(uint8_t):
149      default:
150        panic("invalid access size(?) for tsunami register!\n");
151    }
152    DPRINTFN("Tsunami CChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
153
154    return No_Fault;
155}
156
157Fault
158TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
159{
160    DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
161            req->vaddr, *(uint64_t*)data, req->size);
162
163    Addr daddr = (req->paddr - (addr & PA_IMPL_MASK)) >> 6;
164
165    bool supportedWrite = false;
166    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
167
168    switch (req->size) {
169
170      case sizeof(uint64_t):
171          switch(daddr) {
172            case TSDEV_CC_CSR:
173                  panic("TSDEV_CC_CSR write\n");
174                  return No_Fault;
175              case TSDEV_CC_MTR:
176                  panic("TSDEV_CC_MTR write not implemented\n");
177                   return No_Fault;
178              case TSDEV_CC_MISC:
179                //If it is the 4-7th bit, clear the RTC interrupt
180                uint64_t itintr;
181                if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
182                    //Clear the bits in ITINTR
183                    misc &= ~(itintr);
184                    for (int i=0; i < size; i++) {
185                        if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
186                            tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
187                            RTCInterrupting[i] = false;
188                            DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
189                        }
190                    }
191                    supportedWrite = true;
192                }
193                //If it is 12th-15th bit, IPI sent to Processor 1
194                uint64_t ipreq;
195                if ((ipreq = (*(uint64_t*) data) & (0xf << 12))) {
196                    //Set the bits in IPINTR
197                    misc |= (ipreq >> 4);
198                    for (int i=0; i < size; i++) {
199                        if ((ipreq & (1 << (i + 12)))) {
200                            if (!ipiInterrupting[i])
201                                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ3, 0);
202                            ipiInterrupting[i]++;
203                            DPRINTF(IPI, "send cpu=%d pending=%d from=%d\n", i,
204                                    ipiInterrupting[i], req->cpu_num);
205                        }
206                    }
207                    supportedWrite = true;
208                }
209                //If it is bits 8-11, then clearing IPI's
210                uint64_t ipintr;
211                if ((ipintr = (*(uint64_t*) data) & (0xf << 8))) {
212                    //Clear the bits in IPINTR
213                    misc &= ~(ipintr);
214                    for (int i=0; i < size; i++) {
215                        if ((ipintr & (1 << (i + 8))) && ipiInterrupting[i]) {
216                            if (!(--ipiInterrupting[i]))
217                                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ3, 0);
218                            DPRINTF(IPI, "clearing cpu=%d pending=%d from=%d\n", i,
219                                    ipiInterrupting[i] + 1, req->cpu_num);
220                        }
221                    }
222                    supportedWrite = true;
223                }
224
225        // ignore NXMs
226        if (*(uint64_t*)data & 0x10000000)
227            supportedWrite = true;
228
229                if(!supportedWrite) panic("TSDEV_CC_MISC write not implemented\n");
230                return No_Fault;
231              case TSDEV_CC_AAR0:
232              case TSDEV_CC_AAR1:
233              case TSDEV_CC_AAR2:
234              case TSDEV_CC_AAR3:
235                  panic("TSDEV_CC_AARx write not implemeted\n");
236                  return No_Fault;
237              case TSDEV_CC_DIM0:
238              case TSDEV_CC_DIM1:
239              case TSDEV_CC_DIM2:
240              case TSDEV_CC_DIM3:
241                  int number;
242                  if(daddr == TSDEV_CC_DIM0)
243                      number = 0;
244                  else if(daddr == TSDEV_CC_DIM1)
245                      number = 1;
246                  else if(daddr == TSDEV_CC_DIM2)
247                      number = 2;
248                  else
249                      number = 3;
250
251                  uint64_t bitvector;
252                  uint64_t olddim;
253                  uint64_t olddir;
254
255                  olddim = dim[number];
256                  olddir = dir[number];
257                  dim[number] = *(uint64_t*)data;
258                  dir[number] = dim[number] & drir;
259                  for(int x = 0; x < 64; x++)
260                  {
261                      bitvector = (uint64_t)1 << x;
262                      // Figure out which bits have changed
263                      if ((dim[number] & bitvector) != (olddim & bitvector))
264                      {
265                          // The bit is now set and it wasn't before (set)
266                          if((dim[number] & bitvector) && (dir[number] & bitvector))
267                          {
268                              tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
269                              DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
270                          }
271                          else if ((olddir & bitvector) &&
272                                  !(dir[number] & bitvector))
273                          {
274                              // The bit was set and now its now clear and
275                              // we were interrupting on that bit before
276                              tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
277                              DPRINTF(Tsunami, "dim write resulting in clear"
278                                      "dir interrupt to cpu 0\n");
279
280                          }
281
282
283                      }
284                  }
285                  return No_Fault;
286              case TSDEV_CC_DIR0:
287              case TSDEV_CC_DIR1:
288              case TSDEV_CC_DIR2:
289              case TSDEV_CC_DIR3:
290                  panic("TSDEV_CC_DIR write not implemented\n");
291              case TSDEV_CC_DRIR:
292                  panic("TSDEV_CC_DRIR write not implemented\n");
293              case TSDEV_CC_PRBEN:
294                  panic("TSDEV_CC_PRBEN write not implemented\n");
295              case TSDEV_CC_IIC0:
296              case TSDEV_CC_IIC1:
297              case TSDEV_CC_IIC2:
298              case TSDEV_CC_IIC3:
299                  panic("TSDEV_CC_IICx write not implemented\n");
300              case TSDEV_CC_MPR0:
301              case TSDEV_CC_MPR1:
302              case TSDEV_CC_MPR2:
303              case TSDEV_CC_MPR3:
304                  panic("TSDEV_CC_MPRx write not implemented\n");
305              default:
306                  panic("default in cchip read reached, accessing 0x%x\n");
307          }
308
309      break;
310      case sizeof(uint32_t):
311      case sizeof(uint16_t):
312      case sizeof(uint8_t):
313      default:
314        panic("invalid access size(?) for tsunami register!\n");
315    }
316
317    DPRINTFN("Tsunami ERROR: write daddr=%#x size=%d\n", daddr, req->size);
318
319    return No_Fault;
320}
321
322void
323TsunamiCChip::postRTC()
324{
325    int size = tsunami->intrctrl->cpu->system->execContexts.size();
326
327    for (int i = 0; i < size; i++) {
328        if (!RTCInterrupting[i]) {
329            misc |= 16 << i;
330            RTCInterrupting[i] = true;
331            tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
332            DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
333        }
334    }
335
336}
337
338void
339TsunamiCChip::postDRIR(uint32_t interrupt)
340{
341    uint64_t bitvector = (uint64_t)0x1 << interrupt;
342    drir |= bitvector;
343    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
344    for(int i=0; i < size; i++) {
345        dir[i] = dim[i] & drir;
346        if (dim[i] & bitvector) {
347                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
348                DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
349                        "interrupt %d\n",i, interrupt);
350        }
351    }
352}
353
354void
355TsunamiCChip::clearDRIR(uint32_t interrupt)
356{
357    uint64_t bitvector = (uint64_t)0x1 << interrupt;
358    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
359    if (drir & bitvector)
360    {
361        drir &= ~bitvector;
362        for(int i=0; i < size; i++) {
363            if (dir[i] & bitvector) {
364                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
365                DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
366                    "interrupt %d\n",i, interrupt);
367
368            }
369            dir[i] = dim[i] & drir;
370        }
371    }
372    else
373        DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
374}
375
376void
377TsunamiCChip::serialize(std::ostream &os)
378{
379    SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
380    SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
381    SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
382    SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
383    SERIALIZE_SCALAR(drir);
384    SERIALIZE_SCALAR(misc);
385    SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
386}
387
388void
389TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
390{
391    UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
392    UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
393    UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
394    UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
395    UNSERIALIZE_SCALAR(drir);
396    UNSERIALIZE_SCALAR(misc);
397    UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
398}
399
400BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
401
402    SimObjectParam<Tsunami *> tsunami;
403    SimObjectParam<MemoryController *> mmu;
404    Param<Addr> addr;
405
406END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
407
408BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
409
410    INIT_PARAM(tsunami, "Tsunami"),
411    INIT_PARAM(mmu, "Memory Controller"),
412    INIT_PARAM(addr, "Device Address")
413
414END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
415
416CREATE_SIM_OBJECT(TsunamiCChip)
417{
418    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu);
419}
420
421REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)
422