- PKE simulation almost finished. Needed enhancements:
authorFrank Ch. Eigler <fche@redhat.com>
Fri, 13 Feb 1998 23:29:38 +0000 (23:29 +0000)
committerFrank Ch. Eigler <fche@redhat.com>
Fri, 13 Feb 1998 23:29:38 +0000 (23:29 +0000)
  * trace file generation
  * FIFO pruning

- PKE functions still missing due to external dependencies:
  * interrupt to 5900 (igen?)
  * VU busy checking (sky-vu / coprocessor registers)
  * PATH3 masking (sky-gpuif / covert control interface)

sim/mips/sky-pke.c
sim/mips/sky-pke.h

index d54337453a15693c26dd39933334a2d49ea6f92d..1c94c996d120a6d13145a8e2032bbd8034d14a1b 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include "sky-pke.h"
 #include "sky-dma.h"
+#include "sim-bits.h"
 #include "sim-assert.h"
 #include "sky-vu0.h"
 #include "sky-vu1.h"
@@ -26,6 +27,8 @@ static int pke_io_write_buffer(device*, const void*, int, address_word,
 static void pke_issue(struct pke_device*);
 static void pke_pc_advance(struct pke_device*, int num_words);
 static unsigned_4* pke_pc_operand(struct pke_device*, int operand_num);
+static unsigned_4 pke_pc_operand_bits(struct pke_device*, int bit_offset,
+                                     int bit_width, unsigned_4* sourceaddr);
 static struct fifo_quadword* pke_pc_fifo(struct pke_device*, int operand_num, 
                                         unsigned_4** operand);
 static int pke_track_write(struct pke_device*, const void* src, int len,
@@ -67,6 +70,7 @@ struct pke_device pke0_device =
   { "pke0", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
   0, 0,        /* ID, flags */
   {},          /* regs */
+  {}, 0,      /* FIFO write buffer */
   NULL, 0, 0, NULL,  /* FIFO */
   0, 0            /* pc */
 };
@@ -77,6 +81,7 @@ struct pke_device pke1_device =
   { "pke1", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
   1, 0,        /* ID, flags */
   {},          /* regs */
+  {}, 0,       /* FIFO write buffer */
   NULL, 0, 0, NULL, /* FIFO */
   0, 0         /* pc */
 };
@@ -334,12 +339,12 @@ pke_io_write_buffer(device *me_,
              PKE_REG_MASK_SET(me, STAT, INT, 0);
              PKE_REG_MASK_SET(me, STAT, ER0, 0);
              PKE_REG_MASK_SET(me, STAT, ER1, 0);
+             me->flags &= ~PKE_FLAG_PENDING_PSS;
              /* will allow resumption of possible stalled instruction */
            }
          if(BIT_MASK_GET(input[0], 2, 2)) /* STP bit */
            {
-             /* XXX: how to safely abort "currently executing" (=> stalled) instruction? */
-             PKE_REG_MASK_SET(me, STAT, PSS, 1);
+             me->flags |= PKE_FLAG_PENDING_PSS;
            }
          if(BIT_MASK_GET(input[0], 1, 1)) /* FBK bit */
            {
@@ -351,8 +356,9 @@ pke_io_write_buffer(device *me_,
                  prevents re-execution attempt of possible stalled
                  instruction */
              me->fifo_num_elements = me->fifo_pc;
-             /* clear registers */
+             /* clear registers, flag, other state */
              memset(me->regs, 0, sizeof(me->regs));
+             me->fifo_qw_done = 0;
              me->flags = 0;
              me->qw_pc = 0;
            }
@@ -424,10 +430,22 @@ pke_io_write_buffer(device *me_,
     {
       /* FIFO */
       struct fifo_quadword* fqw;
+      int fifo_byte = ADDR_OFFSET_QW(addr);      /* find byte-offset inside fifo quadword */
+      int i;
+
+      /* collect potentially-partial quadword in write buffer */
+      memcpy(((unsigned_1*)& me->fifo_qw_in_progress) + fifo_byte, src, nr_bytes);
+      /* mark bytes written */
+      for(i = fifo_byte; i < fifo_byte + nr_bytes; i++)
+       BIT_MASK_SET(me->fifo_qw_done, i, i, 1);
+
+      /* return if quadword not quite written yet */
+      if(BIT_MASK_GET(me->fifo_qw_done, 0, sizeof(quadword)-1) !=
+        BIT_MASK_BTW(0, sizeof(quadword)))
+       return nr_bytes;
 
-      /* assert transfer size == 128 bits */
-      if(nr_bytes != sizeof(quadword))
-       return 0;
+      /* all done - process quadword after clearing flag */
+      BIT_MASK_SET(me->fifo_qw_done, 0, sizeof(quadword)-1, 0);
 
       /* ensure FIFO has enough elements */
       if(me->fifo_num_elements == me->fifo_buffer_size)
@@ -448,7 +466,7 @@ pke_io_write_buffer(device *me_,
 
       /* add new quadword at end of FIFO */
       fqw = & me->fifo[me->fifo_num_elements];
-      memcpy((void*) fqw->data, src, nr_bytes);
+      memcpy((void*) fqw->data, me->fifo_qw_in_progress, sizeof(quadword));
       sim_read(CPU_STATE(cpu),
               (SIM_ADDR) (me->pke_number == 0 ? DMA_D0_SRCADDR : DMA_D1_SRCADDR),
               (void*) & fqw->source_address,
@@ -485,9 +503,17 @@ pke_issue(struct pke_device* me)
 
   /* 1 -- test go / no-go for PKE execution */
 
+  /* switch on STAT:PSS if PSS-pending and in idle state */
+  if((PKE_REG_MASK_GET(me, STAT, PPS) == PKE_REG_STAT_PPS_IDLE) &&
+     (me->flags & PKE_FLAG_PENDING_PSS) != 0)
+    {
+      me->flags &= ~PKE_FLAG_PENDING_PSS;
+      PKE_REG_MASK_SET(me, STAT, PSS, 1);
+    }
+
   /* check for stall/halt control bits */
-  if(PKE_REG_MASK_GET(me, STAT, PSS) || /* XXX: PSS may be a special case */
-     PKE_REG_MASK_GET(me, STAT, PFS) ||
+  if(PKE_REG_MASK_GET(me, STAT, PFS) ||
+     PKE_REG_MASK_GET(me, STAT, PSS) || /* note special treatment below */
      /* PEW bit not a reason to keep stalling - it's re-checked below */
      /* PGW bit not a reason to keep stalling - it's re-checked below */
      /* maskable stall controls: ER0, ER1, PIS */
@@ -498,7 +524,6 @@ pke_issue(struct pke_device* me)
       /* try again next cycle; no state change */
       return;
     }
-  /* XXX: handle PSS by *skipping* instruction? */
 
   /* confirm availability of new quadword of PKE instructions */
   if(me->fifo_num_elements <= me->fifo_pc)
@@ -531,7 +556,7 @@ pke_issue(struct pke_device* me)
     {
       /* set INT flag in STAT register */
       PKE_REG_MASK_SET(me, STAT, INT, 1);
-      /* XXX: send interrupt to R5900? */
+      /* XXX: how to send interrupt to R5900? */
     }
 
   /* decoding */
@@ -580,7 +605,7 @@ pke_issue(struct pke_device* me)
     pke_code_directhl(me, fw);
   else if(IS_PKE_CMD(cmd, UNPACK))
     pke_code_unpack(me, fw);
-  /* ... other commands ... */
+  /* ... no other commands ... */
   else
     pke_code_error(me, fw);
 }
@@ -705,6 +730,31 @@ pke_pc_operand(struct pke_device* me, int operand_num)
 }
 
 
+/* Return a bit-field extract of given operand# in FIFO, and its
+   source-addr.  `bit_offset' starts at 0, referring to LSB after PKE
+   instruction word.  Width must be >0, <=32.  Assume FIFO is full
+   enough.  Skip over DMA tags, but mark them as an error (ER0). */
+
+unsigned_4
+pke_pc_operand_bits(struct pke_device* me, int bit_offset, int bit_width, unsigned_4* source_addr)
+{
+  unsigned_4* word = NULL;
+  unsigned_4 value;
+  struct fifo_quadword* fifo_operand;
+
+  /* find operand word with bitfield */
+  fifo_operand = pke_pc_fifo(me, (bit_offset / 32) + 1, &word);
+  ASSERT(word != 0);
+
+  /* extract bitfield from word */
+  value = BIT_MASK_GET(*word, bit_offset % 32, bit_width);
+
+  /* extract source addr from fifo word */
+  *source_addr = fifo_operand->source_address;
+
+  return value;
+}
+
 
 
 
@@ -747,30 +797,38 @@ pke_check_stall(struct pke_device* me, enum pke_check_target what)
 {
   int any_stall = 0;
 
-  /* read VU status word - commonly used */
-  unsigned_4 vu_stat;
+  /* read GPUIF status word - commonly used */
+  unsigned_4 gpuif_stat;
   sim_read(NULL,
-          (SIM_ADDR) (me->pke_number == 0 ? VPE0_STAT : VPE1_STAT),
-          (void*) & vu_stat,
+          (SIM_ADDR) (GIF_REG_STAT),
+          (void*) & gpuif_stat,
           sizeof(unsigned_4));
 
   /* perform checks */
   if(what == chk_vu)
     {
-      /* check if VBS bit is set, i.e., VU is busy */
-      if(BIT_MASK_GET(vu_stat, VU_REG_STAT_VBS_B, VU_REG_STAT_VBS_E) == 1)
+      ASSERT(0);
+      /* XXX: have to check COP2 control register VBS0 / VBS1 bits */
+    }
+  else if(what == chk_path1) /* VU -> GPUIF */
+    {
+      if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 1)
        any_stall = 1;
     }
-  else if(what == chk_path1)
+  else if(what == chk_path2) /* PKE -> GPUIF */
     {
-      /* only valid on PKE1 */
-      /* check if VGW bit is set, i.e., PATH1 is busy */
-      if(BIT_MASK_GET(vu_stat, VU_REG_STAT_VGW_B, VU_REG_STAT_VGW_E) == 1)
+      if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 2)
+       any_stall = 1;
+    }
+  else if(what == chk_path3) /* DMA -> GPUIF */
+    {
+      if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 3)
        any_stall = 1;
     }
   else
     {
-      ASSERT(0); /* XXX: not done yet */
+      /* invalid what */
+      ASSERT(0);
     }
 
   /* any stall reasons? */
@@ -889,7 +947,7 @@ void
 pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode)
 {
   ASSERT(0);
-  /* XXX: cannot handle this one yet */
+  /* XXX: no easy interface toward GPUIF for this purpose */
 }
 
 
@@ -1030,7 +1088,7 @@ pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode)
        pke_flip_dbf(me);
 
       /* compute new PC for VU */
-      vu_pc = BIT_MASK_GET(imm, 0, 15); /* XXX: all bits significant? */
+      vu_pc = BIT_MASK_GET(imm, 0, 15);
       /* write new PC; callback function gets VU running */
       sim_write(NULL,
                (SIM_ADDR) (me->pke_number == 0 ? VU0_PC_START : VU1_PC_START),
@@ -1127,7 +1185,7 @@ pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode)
        pke_flip_dbf(me);
 
       /* compute new PC for VU */
-      vu_pc = BIT_MASK_GET(imm, 0, 15); /* XXX: all bits significant? */
+      vu_pc = BIT_MASK_GET(imm, 0, 15);
       /* write new PC; callback function gets VU running */
       sim_write(NULL,
                (SIM_ADDR) (me->pke_number == 0 ? VU0_PC_START : VU1_PC_START),
@@ -1152,8 +1210,16 @@ pke_code_stmask(struct pke_device* me, unsigned_4 pkecode)
     {
       /* "transferring" operand */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
+
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 1);
+
       /* fill the register */
       PKE_REG_MASK_SET(me, MASK, MASK, *mask);
+
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 0);
+
       /* done */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
       pke_pc_advance(me, 1);
@@ -1179,12 +1245,18 @@ pke_code_strow(struct pke_device* me, unsigned_4 pkecode)
       /* "transferring" operand */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
       
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 1);
+
       /* copy ROW registers: must all exist if 4th operand exists */
       me->regs[PKE_REG_R0][0] = * pke_pc_operand(me, 1);
       me->regs[PKE_REG_R1][0] = * pke_pc_operand(me, 2);
       me->regs[PKE_REG_R2][0] = * pke_pc_operand(me, 3);
       me->regs[PKE_REG_R3][0] = * pke_pc_operand(me, 4);
       
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 0);
+
       /* done */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
       pke_pc_advance(me, 5);
@@ -1210,12 +1282,18 @@ pke_code_stcol(struct pke_device* me, unsigned_4 pkecode)
       /* "transferring" operand */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
       
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 1);
+
       /* copy COL registers: must all exist if 4th operand exists */
       me->regs[PKE_REG_C0][0] = * pke_pc_operand(me, 1);
       me->regs[PKE_REG_C1][0] = * pke_pc_operand(me, 2);
       me->regs[PKE_REG_C2][0] = * pke_pc_operand(me, 3);
       me->regs[PKE_REG_C3][0] = * pke_pc_operand(me, 4);
       
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, 0);
+
       /* done */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
       pke_pc_advance(me, 5);
@@ -1244,15 +1322,7 @@ pke_code_mpg(struct pke_device* me, unsigned_4 pkecode)
   if(last_mpg_word != NULL)
     {
       /* perform implied FLUSHE */
-      /* read VU status word */
-      unsigned_4 vu_stat;
-      sim_read(NULL,
-              (SIM_ADDR) (me->pke_number == 0 ? VPE0_STAT : VPE1_STAT),
-              (void*) & vu_stat,
-              sizeof(unsigned_4));
-      
-      /* check if VBS bit is clear, i.e., VU is idle */
-      if(BIT_MASK_GET(vu_stat, VU_REG_STAT_VBS_B, VU_REG_STAT_VBS_E) == 0)
+      if(pke_check_stall(me, chk_vu))
        {
          /* VU idle */
          int i;
@@ -1268,10 +1338,10 @@ pke_code_mpg(struct pke_device* me, unsigned_4 pkecode)
              unsigned_4* operand;
              struct fifo_quadword* fq = pke_pc_fifo(me, num, & operand);
              
-             /* imm: in 64-bit units for MPG instruction */
-             
-             /* XXX: set NUM */
+             /* set NUM */
+             PKE_REG_MASK_SET(me, NUM, NUM, (num*2 - i) / 2);
              
+             /* imm: in 64-bit units for MPG instruction */
              /* VU*_MEM0 : instruction memory */
              vu_addr_base = (me->pke_number == 0) ?
                VU0_MEM0_WINDOW_START : VU0_MEM0_WINDOW_START;
@@ -1292,6 +1362,9 @@ pke_code_mpg(struct pke_device* me, unsigned_4 pkecode)
                        (void*) & fq->source_address,
                        sizeof(unsigned_4));
            } /* VU xfer loop */
+
+         /* check NUM */
+         ASSERT(PKE_REG_MASK_GET(me, NUM, NUM) == 0);
          
          /* done */
          PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
@@ -1346,7 +1419,7 @@ pke_code_direct(struct pke_device* me, unsigned_4 pkecode)
          /* write to GPUIF FIFO only with full word */
          if(i%4 == 3)
            {
-             address_word gpuif_fifo = GPUIF_PATH2_FIFO_ADDR+(i/4);
+             address_word gpuif_fifo = GIF_PATH2_FIFO_ADDR+(i/4);
              pke_track_write(me, fifo_data, sizeof(quadword),
                              (SIM_ADDR) gpuif_fifo, fq->source_address);
            } /* write collected quadword */
@@ -1380,13 +1453,14 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
   int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E);
   int cmd = BIT_MASK_GET(pkecode, PKE_OPCODE_CMD_B, PKE_OPCODE_CMD_E);
   int num = BIT_MASK_GET(pkecode, PKE_OPCODE_NUM_B, PKE_OPCODE_NUM_E);
-
-  short vn = BIT_MASK_GET(cmd, 2, 3);
+  short vn = BIT_MASK_GET(cmd, 2, 3); /* unpack shape controls */
   short vl = BIT_MASK_GET(cmd, 0, 1);
-  short vnvl = BIT_MASK_GET(cmd, 0, 3);
   int m = BIT_MASK_GET(cmd, 4, 4);
-  short cl = PKE_REG_MASK_GET(me, CYCLE, CL);
+  short cl = PKE_REG_MASK_GET(me, CYCLE, CL); /* cycle controls */
   short wl = PKE_REG_MASK_GET(me, CYCLE, WL);
+  int r = BIT_MASK_GET(imm, 15, 15); /* indicator bits in imm value */
+  int sx = BIT_MASK_GET(imm, 14, 14);
+
   int n, num_operands;
   unsigned_4* last_operand_word;
   
@@ -1405,38 +1479,40 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
   if(last_operand_word != NULL)
     {
       address_word vu_addr_base;
-      int operand_num, vector_num;
+      int vector_num;
       
       /* "transferring" operand */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_XFER);
       
       /* don't check whether VU is idle */
-      
+
+      /* compute VU address base */
       if(me->pke_number == 0)
        vu_addr_base = VU0_MEM1_WINDOW_START + BIT_MASK_GET(imm, 0, 9);
       else
        {
          vu_addr_base = VU1_MEM1_WINDOW_START + BIT_MASK_GET(imm, 0, 9);
-         if(BIT_MASK_GET(imm, 15, 15)) /* fetch R flag from imm word */
-           vu_addr_base += PKE_REG_MASK_GET(me, TOPS, TOPS);
+         if(r) vu_addr_base += PKE_REG_MASK_GET(me, TOPS, TOPS);
        }
-      
-      /* XXX: vu_addr overflow check */
-      
+
+      /* set NUM */
+      PKE_REG_MASK_SET(me, NUM, NUM, num);
+
       /* transfer given number of vectors */
-      operand_num = 1; /* word index into instruction stream: 1..num_operands */
-      vector_num = 0;  /* vector number being processed: 0..num-1 */
-      while(operand_num <= num_operands)
+      vector_num = 0;  /* output vector number being processed */
+      do
        {
          quadword vu_old_data;
          quadword vu_new_data;
          quadword unpacked_data;
          address_word vu_addr;
-         struct fifo_quadword* fq;
+         unsigned_4 source_addr = 0;
          int i;
          
-         /* XXX: set NUM */
-         
+         /* decrement NUM */
+         PKE_REG_MASK_SET(me, NUM, NUM,
+                          PKE_REG_MASK_GET(me, NUM, NUM) - 1);
+             
          /* compute VU destination address, as bytes in R5900 memory */
          if(cl >= wl)
            {
@@ -1446,13 +1522,12 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
            }
          else
            vu_addr = vu_addr_base + 16*vector_num;
+
+         /* XXX: can vu_addr overflow? */
          
          /* read old VU data word at address */
          sim_read(NULL, (SIM_ADDR) vu_addr, (void*) & vu_old_data, sizeof(vu_old_data));
          
-         /* Let sourceaddr track the first operand */
-         fq = pke_pc_fifo(me, operand_num, NULL);
-         
          /* For cyclic unpack, next operand quadword may come from instruction stream
             or be zero. */
          if((cl < wl) && ((vector_num % wl) >= cl)) /* wl != 0, set above */
@@ -1463,78 +1538,51 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
            }
          else
            {
-             /* compute unpacked words from instruction stream */
-             switch(vnvl)
+             /* compute packed vector dimensions */
+             int vectorbits, unitbits;
+
+             if(vl < 3) /* PKE_UNPACK_*_{32,16,8} */
                {
-               case PKE_UNPACK_S_32:
-               case PKE_UNPACK_V2_32:
-               case PKE_UNPACK_V3_32:
-               case PKE_UNPACK_V4_32:
-                 /* copy (vn+1) 32-bit values */
-                 for(i = 0; i < vn+1; i++)
-                   {
-                     unsigned_4* operand = pke_pc_operand(me, operand_num);
-                     unpacked_data[i] = *operand;
-                     operand_num ++;
-                   }
-                 break;
-                 
-               case PKE_UNPACK_S_16:
-               case PKE_UNPACK_V2_16:
-               case PKE_UNPACK_V3_16:
-               case PKE_UNPACK_V4_16:
-                 /* copy (vn+1) 16-bit values, packed two-per-word */
-                 for(i=0; i<vn+1; i+=2)
-                   {
-                     unsigned_4* operand = pke_pc_operand(me, operand_num);
-                     unpacked_data[i] = BIT_MASK_GET_SX(*operand, 0, 15, 31);
-                     unpacked_data[i+1] = BIT_MASK_GET_SX(*operand, 16, 31, 31);
-                     operand_num ++;
-                   }
-                 break;
-                 
-               case PKE_UNPACK_S_8:
-               case PKE_UNPACK_V2_8:
-               case PKE_UNPACK_V3_8:
-               case PKE_UNPACK_V4_8:
-                 /* copy (vn+1) 8-bit values, packed four-per-word */
-                 for(i=0; i<vn+1; i+=4)
-                   {
-                     unsigned_4* operand = pke_pc_operand(me, operand_num);
-                     unpacked_data[i] = BIT_MASK_GET_SX(*operand, 0, 7, 31);
-                     unpacked_data[i+1] = BIT_MASK_GET_SX(*operand, 8, 15, 31);
-                     unpacked_data[i+2] = BIT_MASK_GET_SX(*operand, 16, 23, 31);
-                     unpacked_data[i+3] = BIT_MASK_GET_SX(*operand, 24, 31, 31);
-                     operand_num ++;
-                   }
-                 break;
-                 
-               case PKE_UNPACK_V4_5:
-                 /* copy four 1/5/5/5-bit values, packed into a sixteen-bit */
-                 for(i=0; i<vn+1; i+=4)
-                   {
-                     unsigned_4* operand = pke_pc_operand(me, operand_num);
-                     unpacked_data[i] = BIT_MASK_GET_SX(*operand, 0, 4, 31);
-                     unpacked_data[i+1] = BIT_MASK_GET_SX(*operand, 5, 9, 31);
-                     unpacked_data[i+2] = BIT_MASK_GET_SX(*operand, 10, 14, 31);
-                     unpacked_data[i+3] = BIT_MASK_GET_SX(*operand, 15, 15, 31);
-                     operand_num ++;
-                   }
-                 break;
+                 unitbits = (32 >> vl);
+                 vectorbits = unitbits * (vn+1);
+               }
+             else if(vl == 3 && vn == 3) /* PKE_UNPACK_V4_5 */
+               {
+                 unitbits = 5;
+                 vectorbits = 16;
+               }
+             else /* illegal unpack variant */
+               {
+                 /* treat as illegal instruction */
+                 pke_code_error(me, pkecode);
+                 return;
+               }
+             
+             /* loop over columns */
+             for(i=0; i<=vn; i++)
+               {
+                 unsigned_4 operand;
 
-                 /* XXX: handle multiple rows of data in same word */ 
-                 /* clue: increment operand_num less frequently */
+                 /* offset in bits in current operand word */
+                 int bitoffset =
+                   (vector_num * vectorbits) + (i * unitbits); /* # of bits from PKEcode */
 
-               default: /* bad UNPACK code */
-                 {
-                   /* treat as illegal instruction */
-                   pke_code_error(me, pkecode);
-                   return;
-                 }               
+                 /* last unit of V4_5 is only one bit wide */
+                 if(vl == 3 && vn == 3 && i == 3) /* PKE_UNPACK_V4_5 */
+                   unitbits = 1;
+
+                 /* fetch bitfield operand */
+                 operand = pke_pc_operand_bits(me, bitoffset, unitbits, & source_addr);
+
+                 /* selectively sign-extend; not for V4_5 1-bit value */
+                 if(sx && unitbits > 0)
+                   unpacked_data[i] = SEXT32(operand, unitbits-1);
+                 else
+                   unpacked_data[i] = operand;
                }
-           }
+           } /* unpack word from instruction operand */
          
-         /* compute replacement word - function of vn, vl, mask */
+         /* compute replacement word */
          if(m) /* use mask register? */
            {
              /* compute index into mask register for this word */
@@ -1577,9 +1625,9 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
                    }
                  
                  /* copy masked value for column */
-                 memcpy(& vu_new_data[i], masked_value, sizeof(unsigned_4));
+                 vu_new_data[i] = *masked_value;
                } /* loop over columns */
-           }
+           } /* mask */
          else
            {
              /* no mask - just copy over entire unpacked quadword */
@@ -1611,11 +1659,12 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode)
 
          /* write replacement word */
          pke_track_write(me, vu_new_data, sizeof(vu_new_data),
-                         (SIM_ADDR) vu_addr, fq->source_address);
+                         (SIM_ADDR) vu_addr, source_addr);
 
          /* next vector please */
          vector_num ++;
        } /* vector transfer loop */
+      while(PKE_REG_MASK_GET(me, NUM, NUM) > 0);
 
       /* done */
       PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE);
index c378c640eb0110292f76efe3cc2e6505f58f42b3..78f1fbb05450d4a93ca6b3a1c34bb5dd34c6a636 100644 (file)
@@ -27,10 +27,30 @@ typedef unsigned_4 quadword[4];
 
 /* SCEI memory mapping information */
 
-#define PKE0_REGISTER_WINDOW_START 0x10000800
-#define PKE1_REGISTER_WINDOW_START 0x10000A00
-#define PKE0_FIFO_ADDR             0x10008000
-#define PKE1_FIFO_ADDR             0x10008010
+#define PKE0_REGISTER_WINDOW_START 0x10003800
+#define PKE1_REGISTER_WINDOW_START 0x10003C00
+#define PKE0_FIFO_ADDR             0x10004000
+#define PKE1_FIFO_ADDR             0x10005000
+
+
+/* and now a few definitions that rightfully belong elsewhere */ 
+#ifdef PKE_DEBUG
+
+/* VU PC pseudo-registers */ /* omitted from 1998-01-22 e-mail plans */
+#define VU0_PC_START 0x20025000
+#define VU1_PC_START 0x20026000
+
+/* VU source-addr tracking tables */ /* changed from 1998-01-22 e-mail plans */
+#define VU0_MEM0_SRCADDR_START 0x21000000
+#define VU0_MEM1_SRCADDR_START 0x21004000
+#define VU1_MEM0_SRCADDR_START 0x21008000
+#define VU1_MEM1_SRCADDR_START 0x2100C000
+
+/* GPUIF STAT register */
+#define GPUIF_REG_STAT_APATH_E 11
+#define GPUIF_REG_STAT_APATH_B 10
+
+#endif /* PKE_DEBUG */
 
 
 /* Quadword indices of PKE registers.  Actual registers sit at bottom
@@ -189,6 +209,10 @@ typedef unsigned_4 quadword[4];
 #define PKE_REG_MODE_MDE_E 1
 #define PKE_REG_MODE_MDE_B 0
 
+/* NUM register */
+#define PKE_REG_NUM_NUM_E 9
+#define PKE_REG_NUM_NUM_B 0
+
 /* MARK register */
 #define PKE_REG_MARK_MARK_E 15
 #define PKE_REG_MARK_MARK_B 0
@@ -262,34 +286,10 @@ typedef unsigned_4 quadword[4];
 ((((me)->regs[PKE_REG_MASK][0]) >> (8*(row) + 2*(col))) & 0x03)
 
 
-/* and now a few definitions that rightfully belong elsewhere */ 
-#ifdef PKE_DEBUG
 
-/* GPUIF addresses */
-#define GPUIF_PATH3_FIFO_ADDR  0x10008020    /* data from CORE        */
-#define GPUIF_PATH1_FIFO_ADDR  0x10008030    /* data from VU1         */ 
-#define GPUIF_PATH2_FIFO_ADDR  0x10008040    /* data from PKE1        */
 
-/* VU STAT register */
-#define VU_REG_STAT_VGW_E 4
-#define VU_REG_STAT_VGW_B 4
-#define VU_REG_STAT_VBS_E 0
-#define VU_REG_STAT_VBS_B 0
+/* operations - replace with those in sim-bits.h when convenient */
 
-/* VU PC pseudo-registers */ /* omitted from 1998-01-22 e-mail plans */
-#define VU0_PC_START 0x20025000
-#define VU1_PC_START 0x20026000
-
-/* VU source-addr tracking tables */ /* changed from 1998-01-22 e-mail plans */
-#define VU0_MEM0_SRCADDR_START 0x21000000
-#define VU0_MEM1_SRCADDR_START 0x21004000
-#define VU1_MEM0_SRCADDR_START 0x21008000
-#define VU1_MEM1_SRCADDR_START 0x2100C000
-
-#endif /* PKE_DEBUG */
-
-
-/* operations  */
 /* unsigned 32-bit mask of given width */
 #define BIT_MASK(width) (width == 31 ? 0xffffffff : (((unsigned_4)1) << (width+1)) - 1)
 /* e.g.: BIT_MASK(4) = 00011111 */
@@ -354,9 +354,13 @@ struct pke_device
   int pke_number;
   int flags;
 
-  /* quadword registers */
+  /* quadword registers: data in [0] word only */
   quadword regs[PKE_NUM_REGS];
 
+  /* write buffer for FIFO address */
+  quadword fifo_qw_in_progress;
+  int fifo_qw_done; /* bitfield */
+
   /* FIFO */
   struct fifo_quadword* fifo;
   int fifo_num_elements; /* no. of quadwords occupied in FIFO */
@@ -372,8 +376,8 @@ struct pke_device
 
 /* Flags for PKE.flags */
 
-#define PKE_FLAG_NONE 0
-/* none at present */
+#define PKE_FLAG_NONE        0x00
+#define PKE_FLAG_PENDING_PSS 0x01 /* PSS bit written-to; set STAT:PSS after current instruction */
 
 
 #endif /* H_PKE_H */