Add support for Tsunami with 64 processors
authorAli Saidi <saidi@eecs.umich.edu>
Mon, 6 Dec 2004 17:06:16 +0000 (12:06 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Mon, 6 Dec 2004 17:06:16 +0000 (12:06 -0500)
base/socket.cc:
    Make panic print a more worthwhile message
dev/tsunami.hh:
    Change max number of tsunami cpus to be 64
dev/tsunamireg.h:
    Add new registers and register blocks for 64 cpu tsunami

--HG--
extra : convert_revision : 3ceaaa998518ded8613bc64edc04cb9120fd3d15

base/socket.cc
dev/tsunami.hh
dev/tsunami_cchip.cc
dev/tsunami_cchip.hh
dev/tsunamireg.h

index aa6a183a9c21751770ec742d74971591f6ab486f..ee87dc057f8498b27b871558e92f483a493144e0 100644 (file)
@@ -64,7 +64,7 @@ ListenSocket::listen(int port, bool reuse)
 
     fd = ::socket(PF_INET, SOCK_STREAM, 0);
     if (fd < 0)
-        panic("Can't create socket!");
+        panic("Can't create socket:%s !", strerror(errno));
 
     if (reuse) {
         int i = 1;
index 05563f80b14091388c5b3a0106b49e16bad68c10..d7c549e902c7197602dcfd6e4512417283bdef94 100644 (file)
@@ -58,7 +58,7 @@ class Tsunami : public Platform
   public:
 
     /** Max number of CPUs in a Tsunami */
-    static const int Max_CPUs = 4;
+    static const int Max_CPUs = 64;
 
     /** Pointer to the system */
     System *system;
index c389063d01baa04410571f5ad3872c274a1697da..a1f90015374ebd266ee512dd72891a1f8f8a802e 100644 (file)
@@ -55,14 +55,6 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
 {
     mmu->add_child(this, RangeSize(addr, size));
 
-    for(int i=0; i < Tsunami::Max_CPUs; i++) {
-        dim[i] = 0;
-        dir[i] = 0;
-        dirInterrupting[i] = false;
-        ipiInterrupting[i] = false;
-        RTCInterrupting[i] = false;
-    }
-
     if (bus) {
         pioInterface = newPioInterface(name, hier, bus, this,
                                       &TsunamiCChip::cacheAccess);
@@ -71,7 +63,14 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
     }
 
     drir = 0;
-    misc = 0;
+    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;
@@ -80,16 +79,29 @@ TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
 Fault
 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 & EV5::PAddrImplMask)) >> 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;
@@ -97,7 +109,9 @@ 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:
@@ -147,6 +161,12 @@ 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
@@ -158,7 +178,7 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
       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;
 }
@@ -169,16 +189,58 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
     DPRINTF(Tsunami, "write - va=%#x value=%#x size=%d \n",
             req->vaddr, *(uint64_t*)data, req->size);
 
-    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
+    Addr daddr = (req->paddr - (addr & EV5::PAddrImplMask));
+    Addr regnum = (req->paddr - (addr & EV5::PAddrImplMask)) >> 6;
 
     bool supportedWrite = false;
-    uint64_t size = tsunami->intrctrl->cpu->system->execContexts.size();
 
     switch (req->size) {
 
       case sizeof(uint64_t):
-          switch(daddr) {
-            case TSDEV_CC_CSR:
+          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;
               case TSDEV_CC_MTR:
@@ -189,19 +251,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
                 ipreq = (*(uint64_t*)data >> 12) & 0xF;
                 //If it is bit 12-15, this is an IPI post
                 if (ipreq) {
-                    for (int cpunum=0; cpunum < Tsunami::Max_CPUs; cpunum++) {
-                        // Check each cpu bit
-                        if (ipreq & (1 << cpunum)) {
-                            // Check if there is already an ipi (bits 8:11)
-                            if (!(misc & (0x100 << cpunum))) {
-                                misc |= (0x100 << cpunum);
-                                tsunami->intrctrl->post(cpunum,
-                                        TheISA::INTLEVEL_IRQ3, 0);
-                                DPRINTF(IPI, "send IPI cpu=%d from=%d\n",
-                                        cpunum, req->cpu_num);
-                            }
-                        }
-                    }
+                    reqIPI(ipreq);
                     supportedWrite = true;
                 }
 
@@ -209,36 +259,15 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
                 uint64_t ipintr;
                 ipintr = (*(uint64_t*)data >> 8) & 0xF;
                 if (ipintr) {
-                    for (int cpunum=0; cpunum < Tsunami::Max_CPUs; cpunum++) {
-                        // Check each cpu bit
-                        if (ipintr & (1 << cpunum)) {
-                            // Check if there is a pending ipi (bits 8:11)
-                            if (misc & (0x100 << cpunum)) {
-                                misc &= ~(0x100 << cpunum);
-                                tsunami->intrctrl->clear(cpunum,
-                                        TheISA::INTLEVEL_IRQ3, 0);
-                                DPRINTF(IPI, "clear IPI IPI cpu=%d from=%d\n",
-                                        cpunum, req->cpu_num);
-                            }
-                        }
-                    }
+                    clearIPI(ipintr);
                     supportedWrite = true;
                 }
 
-
-
                 //If it is the 4-7th bit, clear the RTC interrupt
                 uint64_t itintr;
-                if ((itintr = (*(uint64_t*) data) & (0xf<<4))) {
-                    //Clear the bits in ITINTR
-                    misc &= ~(itintr);
-                    for (int i=0; i < size; i++) {
-                        if ((itintr & (1 << (i+4))) && RTCInterrupting[i]) {
-                            tsunami->intrctrl->clear(i, TheISA::INTLEVEL_IRQ2, 0);
-                            RTCInterrupting[i] = false;
-                            DPRINTF(Tsunami, "clearing rtc interrupt to cpu=%d\n", i);
-                        }
-                    }
+                itintr = (*(uint64_t*)data >> 4) & 0xF;
+                if (itintr) {
+                    clearITI(itintr);
                     supportedWrite = true;
                 }
 
@@ -261,11 +290,11 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
               case TSDEV_CC_DIM2:
               case TSDEV_CC_DIM3:
                   int number;
-                  if(daddr == TSDEV_CC_DIM0)
+                  if(regnum == TSDEV_CC_DIM0)
                       number = 0;
-                  else if(daddr == TSDEV_CC_DIM1)
+                  else if(regnum == TSDEV_CC_DIM1)
                       number = 1;
-                  else if(daddr == TSDEV_CC_DIM2)
+                  else if(regnum == TSDEV_CC_DIM2)
                       number = 2;
                   else
                       number = 3;
@@ -280,7 +309,7 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
                   dir[number] = dim[number] & drir;
                   for(int x = 0; x < 64; x++)
                   {
-                      bitvector = (uint64_t)1 << x;
+                      bitvector = ULL(1) << x;
                       // Figure out which bits have changed
                       if ((dim[number] & bitvector) != (olddim & bitvector))
                       {
@@ -297,7 +326,8 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
                               // 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 0\n");
+                                      " dir interrupt to cpu %d\n",
+                                      x);
 
                           }
 
@@ -324,6 +354,15 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
               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");
           }
@@ -341,15 +380,89 @@ TsunamiCChip::write(MemReqPtr &req, const uint8_t *data)
     return No_Fault;
 }
 
+void
+TsunamiCChip::clearIPI(uint64_t ipintr)
+{
+    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::clearITI(uint64_t itintr)
+{
+    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++) {
-        if (!RTCInterrupting[i]) {
-            misc |= 16 << i;
-            RTCInterrupting[i] = true;
+        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);
         }
@@ -360,9 +473,11 @@ TsunamiCChip::postRTC()
 void
 TsunamiCChip::postDRIR(uint32_t interrupt)
 {
-    uint64_t bitvector = (uint64_t)0x1 << interrupt;
-    drir |= bitvector;
+    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) {
@@ -376,8 +491,10 @@ TsunamiCChip::postDRIR(uint32_t interrupt)
 void
 TsunamiCChip::clearDRIR(uint32_t interrupt)
 {
-    uint64_t bitvector = (uint64_t)0x1 << 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;
@@ -407,11 +524,9 @@ TsunamiCChip::serialize(std::ostream &os)
 {
     SERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
     SERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
-    SERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
-    SERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+    SERIALIZE_SCALAR(ipint);
+    SERIALIZE_SCALAR(itint);
     SERIALIZE_SCALAR(drir);
-    SERIALIZE_SCALAR(misc);
-    SERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
 }
 
 void
@@ -419,11 +534,9 @@ TsunamiCChip::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_ARRAY(dim, Tsunami::Max_CPUs);
     UNSERIALIZE_ARRAY(dir, Tsunami::Max_CPUs);
-    UNSERIALIZE_ARRAY(dirInterrupting, Tsunami::Max_CPUs);
-    UNSERIALIZE_ARRAY(ipiInterrupting, Tsunami::Max_CPUs);
+    UNSERIALIZE_SCALAR(ipint);
+    UNSERIALIZE_SCALAR(itint);
     UNSERIALIZE_SCALAR(drir);
-    UNSERIALIZE_SCALAR(misc);
-    UNSERIALIZE_ARRAY(RTCInterrupting, Tsunami::Max_CPUs);
 }
 
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(TsunamiCChip)
index 3269cf53a13360cdaf542bd576753615cf119f52..05fafa7825077e0925f4ac7574c2bcfb726cdf4a 100644 (file)
@@ -47,7 +47,7 @@ class TsunamiCChip : public PioDevice
     Addr addr;
 
     /** The size of mappad from the above address */
-    static const Addr size = 0xfff;
+    static const Addr size = 0xfffffff;
 
   protected:
     /**
@@ -68,7 +68,6 @@ class TsunamiCChip : public PioDevice
      * One exists for each CPU, the DRIR X DIM = DIR
      */
     uint64_t dir[Tsunami::Max_CPUs];
-    bool dirInterrupting[Tsunami::Max_CPUs];
 
     /**
      * This register contains bits for each PCI interrupt
@@ -76,17 +75,11 @@ class TsunamiCChip : public PioDevice
      */
     uint64_t drir;
 
-    /**
-     * The MISC register contains the CPU we are currently on
-     * as well as bits to ack RTC and IPI interrupts.
-     */
-    uint64_t misc;
+    /** Indicator of which CPUs have an IPI interrupt */
+    uint64_t ipint;
 
-    /** Count of the number of pending IPIs on a CPU */
-    uint64_t ipiInterrupting[Tsunami::Max_CPUs];
-
-    /** Indicator of which CPUs have had an RTC interrupt */
-    bool RTCInterrupting[Tsunami::Max_CPUs];
+    /** Indicator of which CPUs have an RTC interrupt */
+    uint64_t itint;
 
   public:
     /**
@@ -137,6 +130,25 @@ class TsunamiCChip : public PioDevice
      */
     void clearDRIR(uint32_t interrupt);
 
+    /**
+     * post an ipi interrupt  to the CPU.
+     * @param ipintr the cpu number to clear(bitvector)
+     */
+    void clearIPI(uint64_t ipintr);
+
+    /**
+     * clear a timer interrupt previously posted to the CPU.
+     * @param interrupt the cpu number to clear(bitvector)
+     */
+    void clearITI(uint64_t itintr);
+
+    /**
+     * request an interrupt be posted to the CPU.
+     * @param ipreq the cpu number to interrupt(bitvector)
+     */
+    void reqIPI(uint64_t ipreq);
+
+
     /**
      * Serialize this object to the given output stream.
      * @param os The stream to serialize to.
index 876c6bf18f95d87ca4154378ab2a3f5fa201e9ed..3304082a57707e8f1b8b8c82c8b9c89b6285300f 100644 (file)
 #define TSDEV_CC_IIC2   0x1C
 #define TSDEV_CC_IIC3   0x1D
 
+// BigTsunami Registers
+#define TSDEV_CC_BDIMS  0x1000000
+#define TSDEV_CC_BDIRS  0x2000000
+#define TSDEV_CC_IPIQ   0x20  //0xf01a000800
+#define TSDEV_CC_IPIR   0x21  //0xf01a000840
+#define TSDEV_CC_ITIR   0x22  //0xf01a000880
+
 
 // PChip Registers
 #define TSDEV_PC_WSBA0      0x00