make some changes to bonnie - now that the simulator uses more memory the old config...
[gem5.git] / dev / tsunami_cchip.cc
index 9bb9be13f3f33eec3e27056acb2d4e6e8bf86825..2fb293fbf70feccec4c84c89ea543447ea38b8a1 100644 (file)
@@ -1,7 +1,33 @@
-/* $Id$ */
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /* @file
- * Tsunami CChip (processor, memory, or IO)
+ * Emulation of the Tsunami CChip CSRs
  */
 
 #include <deque>
 #include <vector>
 
 #include "base/trace.hh"
-#include "cpu/exec_context.hh"
-#include "dev/console.hh"
 #include "dev/tsunami_cchip.hh"
 #include "dev/tsunamireg.h"
 #include "dev/tsunami.hh"
-#include "cpu/intr_control.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
 #include "mem/functional_mem/memory_control.hh"
+#include "cpu/intr_control.hh"
 #include "sim/builder.hh"
 #include "sim/system.hh"
 
 using namespace std;
 
-TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t,
-                       Addr addr, Addr mask, MemoryController *mmu)
-    : MmapDevice(name, addr, mask, mmu), tsunami(t)
+TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
+                           MemoryController *mmu, HierParams *hier, Bus* bus,
+                           Tick pio_latency)
+    : PioDevice(name, t), addr(a), tsunami(t)
 {
-    for(int i=0; i < Tsunami::Max_CPUs; i++) {
-        dim[i] = 0;
-        dir[i] = 0;
-        dirInterrupting[i] = false;
+    mmu->add_child(this, RangeSize(addr, size));
+
+    if (bus) {
+        pioInterface = newPioInterface(name, hier, bus, this,
+                                      &TsunamiCChip::cacheAccess);
+        pioInterface->addAddrRange(RangeSize(addr, size));
+        pioLatency = pio_latency * bus->clockRatio;
     }
 
     drir = 0;
-    misc = 0;
-    RTCInterrupting = false;
+    ipint = 0;
+    itint = 0;
+
+    for (int x = 0; x < Tsunami::Max_CPUs; x++)
+    {
+        dim[x] = 0;
+        dir[x] = 0;
+    }
 
     //Put back pointer in tsunami
     tsunami->cchip = this;
 }
 
 Fault
-TsunamiCChip::read(MemReqPtr req, uint8_t *data)
+TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
 {
-    DPRINTF(Tsunami, "read  va=%#x size=%d\n",
-            req->vaddr, req->size);
+    DPRINTF(Tsunami, "read  va=%#x size=%d\n", req->vaddr, req->size);
+
+    Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
 
-    Addr daddr = (req->paddr & addr_mask) >> 6;
     ExecContext *xc = req->xc;
 
     switch (req->size) {
 
       case sizeof(uint64_t):
-          switch(daddr) {
+          if (daddr & TSDEV_CC_BDIMS)
+          {
+              *(uint64_t*)data = dim[(daddr >> 4) & 0x3F];
+              return No_Fault;
+          }
+
+          if (daddr & TSDEV_CC_BDIRS)
+          {
+              *(uint64_t*)data = dir[(daddr >> 4) & 0x3F];
+              return No_Fault;
+          }
+
+          switch(regnum) {
               case TSDEV_CC_CSR:
                   *(uint64_t*)data = 0x0;
                   return No_Fault;
@@ -59,13 +109,15 @@ TsunamiCChip::read(MemReqPtr req, uint8_t *data)
                   panic("TSDEV_CC_MTR not implemeted\n");
                    return No_Fault;
               case TSDEV_CC_MISC:
-                *(uint64_t*)data = misc | (xc->cpu_id & 0x3);
+                  *(uint64_t*)data = (ipint << 8) & 0xF |
+                                     (itint << 4) & 0xF |
+                                     (xc->cpu_id & 0x3);
                   return No_Fault;
               case TSDEV_CC_AAR0:
               case TSDEV_CC_AAR1:
               case TSDEV_CC_AAR2:
               case TSDEV_CC_AAR3:
-                  panic("TSDEV_CC_AARx not implemeted\n");
+                  *(uint64_t*)data = 0;
                   return No_Fault;
               case TSDEV_CC_DIM0:
                   *(uint64_t*)data = dim[0];
@@ -109,34 +161,92 @@ TsunamiCChip::read(MemReqPtr req, uint8_t *data)
               case TSDEV_CC_MPR3:
                   panic("TSDEV_CC_MPRx not implemented\n");
                   return No_Fault;
+              case TSDEV_CC_IPIR:
+                  *(uint64_t*)data = ipint;
+                  return No_Fault;
+              case TSDEV_CC_ITIR:
+                  *(uint64_t*)data = itint;
+                  return No_Fault;
               default:
                   panic("default in cchip read reached, accessing 0x%x\n");
            } // uint64_t
 
       break;
       case sizeof(uint32_t):
+          if (regnum == TSDEV_CC_DRIR) {
+              warn("accessing DRIR with 32 bit read, "
+                   "hopefully your just reading this for timing");
+              *(uint32_t*)data = drir;
+          } else
+              panic("invalid access size(?) for tsunami register!\n");
+          return No_Fault;
       case sizeof(uint16_t):
       case sizeof(uint8_t):
       default:
         panic("invalid access size(?) for tsunami register!\n");
     }
-    DPRINTFN("Tsunami CChip ERROR: read  daddr=%#x size=%d\n", daddr, req->size);
+    DPRINTFN("Tsunami CChip ERROR: read  regnum=%#x size=%d\n", regnum, req->size);
 
     return No_Fault;
 }
 
 Fault
-TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
+TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
 {
-    DPRINTF(Tsunami, "write - va=%#x size=%d \n",
-            req->vaddr, req->size);
+    DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
+            req->vaddr, *(uint64_t*)data, req->size);
 
-    Addr daddr = (req->paddr & addr_mask) >> 6;
+    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+    Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+
+    bool supportedWrite = false;
 
     switch (req->size) {
 
       case sizeof(uint64_t):
-          switch(daddr) {
+          if (daddr & TSDEV_CC_BDIMS)
+          {
+              int number = (daddr >> 4) & 0x3F;
+
+              uint64_t bitvector;
+              uint64_t olddim;
+              uint64_t olddir;
+
+              olddim = dim[number];
+              olddir = dir[number];
+              dim[number] = *(uint64_t*)data;
+              dir[number] = dim[number] & drir;
+              for(int x = 0; x < Tsunami::Max_CPUs; x++)
+              {
+                  bitvector = ULL(1) << x;
+                  // Figure out which bits have changed
+                  if ((dim[number] & bitvector) != (olddim & bitvector))
+                  {
+                      // The bit is now set and it wasn't before (set)
+                      if((dim[number] & bitvector) && (dir[number] & bitvector))
+                      {
+                          tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
+                          DPRINTF(Tsunami, "dim write resulting in posting dir"
+                                  " interrupt to cpu %d\n", number);
+                      }
+                      else if ((olddir & bitvector) &&
+                              !(dir[number] & bitvector))
+                      {
+                          // The bit was set and now its now clear and
+                          // we were interrupting on that bit before
+                          tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
+                          DPRINTF(Tsunami, "dim write resulting in clear"
+                                  " dir interrupt to cpu %d\n", number);
+
+                      }
+
+
+                  }
+              }
+              return No_Fault;
+          }
+
+          switch(regnum) {
               case TSDEV_CC_CSR:
                   panic("TSDEV_CC_CSR write\n");
                   return No_Fault;
@@ -144,14 +254,38 @@ TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
                   panic("TSDEV_CC_MTR write not implemented\n");
                    return No_Fault;
               case TSDEV_CC_MISC:
-                //If it is the seventh bit, clear the RTC interrupt
-                if ((*(uint64_t*) data) & (1<<4)) {
-                    RTCInterrupting = false;
-                    tsunami->intrctrl->clear(0, TheISA::INTLEVEL_IRQ2, 0);
-                    DPRINTF(Tsunami, "clearing rtc interrupt\n");
-                    misc &= ~(1<<4);
-                } else panic("TSDEV_CC_MISC write not implemented\n");
-                  return No_Fault;
+                uint64_t ipreq;
+                ipreq = (*(uint64_t*)data >> 12) & 0xF;
+                //If it is bit 12-15, this is an IPI post
+                if (ipreq) {
+                    reqIPI(ipreq);
+                    supportedWrite = true;
+                }
+
+                //If it is bit 8-11, this is an IPI clear
+                uint64_t ipintr;
+                ipintr = (*(uint64_t*)data >> 8) & 0xF;
+                if (ipintr) {
+                    clearIPI(ipintr);
+                    supportedWrite = true;
+                }
+
+                //If it is the 4-7th bit, clear the RTC interrupt
+                uint64_t itintr;
+                itintr = (*(uint64_t*)data >> 4) & 0xF;
+                if (itintr) {
+                    clearITI(itintr);
+                    supportedWrite = true;
+                }
+
+                // ignore NXMs
+                if (*(uint64_t*)data & 0x10000000)
+                    supportedWrite = true;
+
+                if(!supportedWrite)
+                    panic("TSDEV_CC_MISC write not implemented\n");
+
+                return No_Fault;
               case TSDEV_CC_AAR0:
               case TSDEV_CC_AAR1:
               case TSDEV_CC_AAR2:
@@ -159,47 +293,53 @@ TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
                   panic("TSDEV_CC_AARx write not implemeted\n");
                   return No_Fault;
               case TSDEV_CC_DIM0:
-                   dim[0] = *(uint64_t*)data;
-                   if (dim[0] & drir) {
-                       dir[0] = dim[0] & drir;
-                       if (!dirInterrupting[0]) {
-                           dirInterrupting[0] = true;
-                           tsunami->intrctrl->post(0, TheISA::INTLEVEL_IRQ1, 0);
-                           DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
-                       }
-                   }
-                  return No_Fault;
               case TSDEV_CC_DIM1:
-                  dim[1] = *(uint64_t*)data;
-                  if (dim[1] & drir) {
-                       dir[1] = dim[1] & drir;
-                       if (!dirInterrupting[1]) {
-                           dirInterrupting[1] = true;
-                           tsunami->intrctrl->post(1, TheISA::INTLEVEL_IRQ1, 0);
-                           DPRINTF(Tsunami, "posting dir interrupt to cpu 1\n");
-                       }
-                  }
-                  return No_Fault;
               case TSDEV_CC_DIM2:
-                  dim[2] = *(uint64_t*)data;
-                  if (dim[2] & drir) {
-                       dir[2] = dim[2] & drir;
-                       if (!dirInterrupting[2]) {
-                           dirInterrupting[2] = true;
-                           tsunami->intrctrl->post(2, TheISA::INTLEVEL_IRQ1, 0);
-                           DPRINTF(Tsunami, "posting dir interrupt to cpu 2\n");
-                       }
-                  }
-                  return No_Fault;
               case TSDEV_CC_DIM3:
-                  dim[3] = *(uint64_t*)data;
-                  if ((dim[3] & drir) /*And Not Already Int*/) {
-                       dir[3] = dim[3] & drir;
-                       if (!dirInterrupting[3]) {
-                           dirInterrupting[3] = true;
-                           tsunami->intrctrl->post(3, TheISA::INTLEVEL_IRQ1, 0);
-                           DPRINTF(Tsunami, "posting dir interrupt to cpu 3\n");
-                       }
+                  int number;
+                  if(regnum == TSDEV_CC_DIM0)
+                      number = 0;
+                  else if(regnum == TSDEV_CC_DIM1)
+                      number = 1;
+                  else if(regnum == TSDEV_CC_DIM2)
+                      number = 2;
+                  else
+                      number = 3;
+
+                  uint64_t bitvector;
+                  uint64_t olddim;
+                  uint64_t olddir;
+
+                  olddim = dim[number];
+                  olddir = dir[number];
+                  dim[number] = *(uint64_t*)data;
+                  dir[number] = dim[number] & drir;
+                  for(int x = 0; x < 64; x++)
+                  {
+                      bitvector = ULL(1) << x;
+                      // Figure out which bits have changed
+                      if ((dim[number] & bitvector) != (olddim & bitvector))
+                      {
+                          // The bit is now set and it wasn't before (set)
+                          if((dim[number] & bitvector) && (dir[number] & bitvector))
+                          {
+                              tsunami->intrctrl->post(number, TheISA::INTLEVEL_IRQ1, x);
+                              DPRINTF(Tsunami, "posting dir interrupt to cpu 0\n");
+                          }
+                          else if ((olddir & bitvector) &&
+                                  !(dir[number] & bitvector))
+                          {
+                              // The bit was set and now its now clear and
+                              // we were interrupting on that bit before
+                              tsunami->intrctrl->clear(number, TheISA::INTLEVEL_IRQ1, x);
+                              DPRINTF(Tsunami, "dim write resulting in clear"
+                                      " dir interrupt to cpu %d\n",
+                                      x);
+
+                          }
+
+
+                      }
                   }
                   return No_Fault;
               case TSDEV_CC_DIR0:
@@ -207,24 +347,28 @@ TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
               case TSDEV_CC_DIR2:
               case TSDEV_CC_DIR3:
                   panic("TSDEV_CC_DIR write not implemented\n");
-                  return No_Fault;
               case TSDEV_CC_DRIR:
                   panic("TSDEV_CC_DRIR write not implemented\n");
-                  return No_Fault;
               case TSDEV_CC_PRBEN:
                   panic("TSDEV_CC_PRBEN write not implemented\n");
-                  return No_Fault;
               case TSDEV_CC_IIC0:
               case TSDEV_CC_IIC1:
               case TSDEV_CC_IIC2:
               case TSDEV_CC_IIC3:
                   panic("TSDEV_CC_IICx write not implemented\n");
-                  return No_Fault;
               case TSDEV_CC_MPR0:
               case TSDEV_CC_MPR1:
               case TSDEV_CC_MPR2:
               case TSDEV_CC_MPR3:
                   panic("TSDEV_CC_MPRx write not implemented\n");
+              case TSDEV_CC_IPIR:
+                  clearIPI(*(uint64_t*)data);
+                  return No_Fault;
+              case TSDEV_CC_ITIR:
+                  clearITI(*(uint64_t*)data);
+                  return No_Fault;
+              case TSDEV_CC_IPIQ:
+                  reqIPI(*(uint64_t*)data);
                   return No_Fault;
               default:
                   panic("default in cchip read reached, accessing 0x%x\n");
@@ -244,46 +388,162 @@ TsunamiCChip::write(MemReqPtr req, const uint8_t *data)
 }
 
 void
-TsunamiCChip::postDRIR(uint64_t bitvector)
+TsunamiCChip::clearIPI(uint64_t ipintr)
 {
-    drir |= bitvector;
-    for(int i=0; i < Tsunami::Max_CPUs; i++) {
-        if (bitvector & dim[i]) {
-            dir[i] |= bitvector;
-            if (!dirInterrupting[i]) {
-                dirInterrupting[i] = true;
-                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, 0);
-                DPRINTF(Tsunami, "posting dir interrupt to cpu %d\n",i);
+    int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(numcpus <= Tsunami::Max_CPUs);
+
+    if (ipintr) {
+        for (int cpunum=0; cpunum < numcpus; cpunum++) {
+            // Check each cpu bit
+            uint64_t cpumask = ULL(1) << cpunum;
+            if (ipintr & cpumask) {
+                // Check if there is a pending ipi
+                if (ipint & cpumask) {
+                    ipint &= ~cpumask;
+                    tsunami->intrctrl->clear(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+                    DPRINTF(IPI, "clear IPI IPI cpu=%d\n", cpunum);
+                }
+                else
+                    warn("clear IPI for CPU=%d, but NO IPI\n", cpunum);
             }
         }
     }
+    else
+        panic("Big IPI Clear, but not processors indicated\n");
 }
 
 void
-TsunamiCChip::clearDRIR(uint64_t bitvector)
+TsunamiCChip::clearITI(uint64_t itintr)
 {
-    drir &= ~bitvector;
-    for(int i=0; i < Tsunami::Max_CPUs; i++) {
-        dir[i] &= ~bitvector;
-        if (!dir[i]) {
-            dirInterrupting[i] = false;
-            tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, 0);
-            DPRINTF(Tsunami, "clearing dir interrupt to cpu %d\n", i);
+    int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(numcpus <= Tsunami::Max_CPUs);
+
+    if (itintr) {
+        for (int i=0; i < numcpus; i++) {
+            uint64_t cpumask = ULL(1) << i;
+            if (itintr & cpumask & itint) {
+                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
+                itint &= ~cpumask;
+                DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
+            }
+        }
+    }
+    else
+        panic("Big ITI Clear, but not processors indicated\n");
+}
 
+void
+TsunamiCChip::reqIPI(uint64_t ipreq)
+{
+    int numcpus = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(numcpus <= Tsunami::Max_CPUs);
+
+    if (ipreq) {
+        for (int cpunum=0; cpunum < numcpus; cpunum++) {
+            // Check each cpu bit
+            uint64_t cpumask = ULL(1) << cpunum;
+            if (ipreq & cpumask) {
+                // Check if there is already an ipi (bits 8:11)
+                if (!(ipint & cpumask)) {
+                    ipint  |= cpumask;
+                    tsunami->intrctrl->post(cpunum, TheISA::INTLEVEL_IRQ3, 0);
+                    DPRINTF(IPI, "send IPI cpu=%d\n", cpunum);
+                }
+                else
+                    warn("post IPI for CPU=%d, but IPI already\n", cpunum);
+            }
         }
     }
+    else
+        panic("Big IPI Request, but not processors indicated\n");
 }
 
+
+void
+TsunamiCChip::postRTC()
+{
+    int size = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(size <= Tsunami::Max_CPUs);
+
+    for (int i = 0; i < size; i++) {
+        uint64_t cpumask = ULL(1) << i;
+        if (!(cpumask & itint)) {
+            itint |= cpumask;
+            tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ2, 0);
+            DPRINTF(Tsunami, "Posting RTC interrupt to cpu=%d", i);
+        }
+    }
+
+}
+
+void
+TsunamiCChip::postDRIR(uint32_t interrupt)
+{
+    uint64_t bitvector = ULL(1) << interrupt;
+    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(size <= Tsunami::Max_CPUs);
+    drir |= bitvector;
+
+    for(int i=0; i < size; i++) {
+        dir[i] = dim[i] & drir;
+        if (dim[i] & bitvector) {
+                tsunami->intrctrl->post(i, TheISA::INTLEVEL_IRQ1, interrupt);
+                DPRINTF(Tsunami, "posting dir interrupt to cpu %d,"
+                        "interrupt %d\n",i, interrupt);
+        }
+    }
+}
+
+void
+TsunamiCChip::clearDRIR(uint32_t interrupt)
+{
+    uint64_t bitvector = ULL(1) << interrupt;
+    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
+    assert(size <= Tsunami::Max_CPUs);
+
+    if (drir & bitvector)
+    {
+        drir &= ~bitvector;
+        for(int i=0; i < size; i++) {
+            if (dir[i] & bitvector) {
+                tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ1, interrupt);
+                DPRINTF(Tsunami, "clearing dir interrupt to cpu %d,"
+                    "interrupt %d\n",i, interrupt);
+
+            }
+            dir[i] = dim[i] & drir;
+        }
+    }
+    else
+        DPRINTF(Tsunami, "Spurrious clear? interrupt %d\n", interrupt);
+}
+
+Tick
+TsunamiCChip::cacheAccess(MemReqPtr &req)
+{
+    return curTick + pioLatency;
+}
+
+
 void
 TsunamiCChip::serialize(std::ostream &os)
 {
-    // code should be written
+    SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
+    SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
+    SERIALIZE_SCALAR(ipint);
+    SERIALIZE_SCALAR(itint);
+    SERIALIZE_SCALAR(drir);
 }
 
 void
 TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
 {
-    //code should be written
+    UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
+    UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
+    UNSERIALIZE_SCALAR(ipint);
+    UNSERIALIZE_SCALAR(itint);
+    UNSERIALIZE_SCALAR(drir);
 }
 
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
@@ -291,7 +551,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
     SimObjectParam<Tsunami *> tsunami;
     SimObjectParam<MemoryController *> mmu;
     Param<Addr> addr;
-    Param<Addr> mask;
+    SimObjectParam<Bus*> io_bus;
+    Param<Tick> pio_latency;
+    SimObjectParam<HierParams *> hier;
 
 END_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
 
@@ -300,13 +562,16 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
     INIT_PARAM(tsunami, "Tsunami"),
     INIT_PARAM(mmu, "Memory Controller"),
     INIT_PARAM(addr, "Device Address"),
-    INIT_PARAM(mask, "Address Mask")
+    INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+    INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+    INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
 
 END_INIT_SIM_OBJECT_PARAMS(TsunamiCChip)
 
 CREATE_SIM_OBJECT(TsunamiCChip)
 {
-    return new TsunamiCChip(getInstanceName(), tsunami, addr, mask, mmu);
+    return new TsunamiCChip(getInstanceName(), tsunami, addr, mmu, hier,
+                            io_bus, pio_latency);
 }
 
 REGISTER_SIM_OBJECT("TsunamiCChip", TsunamiCChip)