diff options
Diffstat (limited to 'sim/mips/sky-pke.c')
-rw-r--r-- | sim/mips/sky-pke.c | 177 |
1 files changed, 100 insertions, 77 deletions
diff --git a/sim/mips/sky-pke.c b/sim/mips/sky-pke.c index db9ecc420e8..011db64c15c 100644 --- a/sim/mips/sky-pke.c +++ b/sim/mips/sky-pke.c @@ -13,11 +13,7 @@ #include "sky-vu0.h" #include "sky-vu1.h" #include "sky-gpuif.h" - - -/* Imported functions */ - -void device_error (device *me, char* message); /* device.c */ +#include "sky-device.h" /* Internal function declarations */ @@ -526,7 +522,24 @@ pke_issue(SIM_DESC sd, struct pke_device* me) unsigned_4 cmd, intr, num; unsigned_4 imm; - /* 1 -- test go / no-go for PKE execution */ + /* 1 -- fetch PKE instruction */ + + /* confirm availability of new quadword of PKE instructions */ + if(me->fifo_num_elements <= me->fifo_pc) + return; + + /* skip over DMA tag, if present */ + pke_pc_advance(me, 0); + + /* "fetch" instruction quadword and word */ + fqw = & me->fifo[me->fifo_pc]; + fw = fqw->data[me->qw_pc]; + + /* store word in PKECODE register */ + me->regs[PKE_REG_CODE][0] = fw; + + + /* 2 -- 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) && @@ -542,118 +555,109 @@ pke_issue(SIM_DESC sd, struct pke_device* me) /* 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 */ - (PKE_REG_MASK_GET(me, STAT, ER0) && !PKE_REG_MASK_GET(me, ERR, ME0)) || - (PKE_REG_MASK_GET(me, STAT, ER1) && !PKE_REG_MASK_GET(me, ERR, ME1)) || - (PKE_REG_MASK_GET(me, STAT, PIS) && !PKE_REG_MASK_GET(me, ERR, MII))) + PKE_REG_MASK_GET(me, STAT, ER0) || + PKE_REG_MASK_GET(me, STAT, ER1) || + PKE_REG_MASK_GET(me, STAT, PIS)) { - /* try again next cycle; no state change */ + /* (still) stalled */ + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + /* try again next cycle */ return; } - /* confirm availability of new quadword of PKE instructions */ - if(me->fifo_num_elements <= me->fifo_pc) - return; - - - /* 2 -- fetch PKE instruction */ - - /* skip over DMA tag, if present */ - pke_pc_advance(me, 0); - - /* "fetch" instruction quadword and word */ - fqw = & me->fifo[me->fifo_pc]; - fw = fqw->data[me->qw_pc]; - - /* store word in PKECODE register */ - me->regs[PKE_REG_CODE][0] = fw; - /* 3 -- decode PKE instruction */ - /* PKE instruction format: [intr 0:0][pke-command 6:0][num 7:0][immediate 15:0], - so op-code is in top byte. */ + /* decoding */ + if(PKE_REG_MASK_GET(me, STAT, PPS) == PKE_REG_STAT_PPS_IDLE) + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_DECODE); + + /* Extract relevant bits from PKEcode */ intr = BIT_MASK_GET(fw, PKE_OPCODE_I_B, PKE_OPCODE_I_E); cmd = BIT_MASK_GET(fw, PKE_OPCODE_CMD_B, PKE_OPCODE_CMD_E); - num = BIT_MASK_GET(fw, PKE_OPCODE_NUM_B, PKE_OPCODE_NUM_E); - imm = BIT_MASK_GET(fw, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); /* handle interrupts */ if(intr) { - /* are we resuming an interrupt-flagged instruction? */ + /* are we resuming an interrupt-stalled instruction? */ if(me->flags & PKE_FLAG_INT_NOLOOP) { /* clear loop-prevention flag */ me->flags &= ~PKE_FLAG_INT_NOLOOP; - /* mask interrupt bit from instruction word so re-decoded instructions don't stall */ - BIT_MASK_SET(fw, PKE_OPCODE_I_B, PKE_OPCODE_I_E, 0); - intr = 0; + + /* fall through to decode & execute */ + /* The pke_code_* functions should not check the MSB in the + pkecode. */ } else /* new interrupt-flagged instruction */ { + /* XXX: send interrupt to 5900? */ + /* set INT flag in STAT register */ PKE_REG_MASK_SET(me, STAT, INT, 1); /* set loop-prevention flag */ me->flags |= PKE_FLAG_INT_NOLOOP; - /* XXX: send interrupt to 5900? */ + /* set PIS if stall not masked */ + if(!PKE_REG_MASK_GET(me, ERR, MII)) + PKE_REG_MASK_SET(me, STAT, PIS, 1); + + /* suspend this instruction unless it's PKEMARK */ + if(!IS_PKE_CMD(cmd, PKEMARK)) + { + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + else + { + ; /* fall through to decode & execute */ + } } } - /* decoding */ - if(PKE_REG_MASK_GET(me, STAT, PPS) == PKE_REG_STAT_PPS_IDLE) - PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_DECODE); - - /* handle [new - first time] interrupts */ - if(intr) - { - PKE_REG_MASK_SET(me, STAT, PIS, 1); - PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); - /* presume stall state follows; only PKEMARK may go ahead anyway */ - } /* decode & execute */ - if(IS_PKE_CMD(cmd, PKENOP) && !intr) + if(IS_PKE_CMD(cmd, PKENOP)) pke_code_nop(me, fw); - else if(IS_PKE_CMD(cmd, STCYCL) && !intr) + else if(IS_PKE_CMD(cmd, STCYCL)) pke_code_stcycl(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, OFFSET) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, OFFSET)) pke_code_offset(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, BASE) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, BASE)) pke_code_base(me, fw); - else if(IS_PKE_CMD(cmd, ITOP) && !intr) + else if(IS_PKE_CMD(cmd, ITOP)) pke_code_itop(me, fw); - else if(IS_PKE_CMD(cmd, STMOD) && !intr) + else if(IS_PKE_CMD(cmd, STMOD)) pke_code_stmod(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, MSKPATH3) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, MSKPATH3)) pke_code_mskpath3(me, fw); else if(IS_PKE_CMD(cmd, PKEMARK)) pke_code_pkemark(me, fw); - else if(IS_PKE_CMD(cmd, FLUSHE) && !intr) + else if(IS_PKE_CMD(cmd, FLUSHE)) pke_code_flushe(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSH) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSH)) pke_code_flush(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSHA) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, FLUSHA)) pke_code_flusha(me, fw); - else if(IS_PKE_CMD(cmd, PKEMSCAL) && !intr) + else if(IS_PKE_CMD(cmd, PKEMSCAL)) pke_code_pkemscal(me, fw); - else if(IS_PKE_CMD(cmd, PKEMSCNT) && !intr) + else if(IS_PKE_CMD(cmd, PKEMSCNT)) pke_code_pkemscnt(me, fw); - else if(me->pke_number == 1 && IS_PKE_CMD(cmd, PKEMSCALF) && !intr) + else if(me->pke_number == 1 && IS_PKE_CMD(cmd, PKEMSCALF)) pke_code_pkemscalf(me, fw); - else if(IS_PKE_CMD(cmd, STMASK) && !intr) + else if(IS_PKE_CMD(cmd, STMASK)) pke_code_stmask(me, fw); - else if(IS_PKE_CMD(cmd, STROW) && !intr) + else if(IS_PKE_CMD(cmd, STROW)) pke_code_strow(me, fw); - else if(IS_PKE_CMD(cmd, STCOL) && !intr) + else if(IS_PKE_CMD(cmd, STCOL)) pke_code_stcol(me, fw); - else if(IS_PKE_CMD(cmd, MPG) && !intr) + else if(IS_PKE_CMD(cmd, MPG)) pke_code_mpg(me, fw); - else if(IS_PKE_CMD(cmd, DIRECT) && !intr) + else if(IS_PKE_CMD(cmd, DIRECT)) pke_code_direct(me, fw); - else if(IS_PKE_CMD(cmd, DIRECTHL) && !intr) + else if(IS_PKE_CMD(cmd, DIRECTHL)) pke_code_directhl(me, fw); - else if(IS_PKE_CMD(cmd, UNPACK) && !intr) + else if(IS_PKE_CMD(cmd, UNPACK)) pke_code_unpack(me, fw); /* ... no other commands ... */ else @@ -786,7 +790,12 @@ pke_pc_fifo(struct pke_device* me, int operand_num, unsigned_4** operand) if(fq->word_class[new_qw_pc] == wc_dma) { /* mismatch error! */ - PKE_REG_MASK_SET(me, STAT, ER0, 1); + if(! PKE_REG_MASK_GET(me, ERR, ME0)) + { + PKE_REG_MASK_SET(me, STAT, ER0, 1); + /* don't stall just yet -- finish this instruction */ + /* the PPS_STALL state will be entered by pke_issue() next time */ + } /* skip by going around loop an extra time */ num ++; } @@ -1604,7 +1613,7 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) n = num; else n = cl * (num/wl) + PKE_LIMIT(num % wl, cl); - num_operands = ((32 >> vl) * (vn+1) * n)/32; + num_operands = (31 + (32 >> vl) * (vn+1) * n)/32; /* round up to next word */ /* confirm that FIFO has enough words in it */ if(num_operands > 0) @@ -1662,14 +1671,16 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) /* map zero to max+1 */ int addrwl = (wl == 0) ? 0x0100 : wl; vu_addr = vu_addr_base + 16 * (BIT_MASK_GET(imm, 0, 9) + - (r ? PKE_REG_MASK_GET(me, TOPS, TOPS) : 0) + - cl*(vector_num_out/addrwl) + - (vector_num_out%addrwl)); + (vector_num_out / addrwl) * cl + + (vector_num_out % addrwl)); } else vu_addr = vu_addr_base + 16 * (BIT_MASK_GET(imm, 0, 9) + - (r ? PKE_REG_MASK_GET(me, TOPS, TOPS) : 0) + vector_num_out); + + /* handle "R" double-buffering bit */ + if(r) + vu_addr += 16 * PKE_REG_MASK_GET(me, TOPS, TOPS); /* check for vu_addr overflow */ while(vu_addr >= vu_addr_base + vu_addr_max_size) @@ -1693,7 +1704,7 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) /* For cyclic unpack, next operand quadword may come from instruction stream or be zero. */ if((num == 0 && cl == 0 && wl == 0) || /* shortcut clear */ - ((cl < wl) && ((vector_num_out % wl) >= cl))) /* wl != 0, set above */ + ((cl < wl) && ((vector_num_out % wl) >= cl))) /* && short-circuit asserts wl != 0 */ { /* clear operand - used only in a "indeterminate" state */ for(i = 0; i < 4; i++) @@ -1744,6 +1755,10 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) unpacked_data[i] = SEXT32(operand, unitbits-1); } + /* clear remaining top words in vector */ + for(; i<4; i++) + unpacked_data[i] = 0; + /* consumed a vector from the PKE instruction stream */ vector_num_in ++; } /* unpack word from instruction operand */ @@ -1863,9 +1878,17 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) void pke_code_error(struct pke_device* me, unsigned_4 pkecode) { - /* set ER1 flag in STAT register */ - PKE_REG_MASK_SET(me, STAT, ER1, 1); + if(! PKE_REG_MASK_GET(me, ERR, ME1)) + { + /* set ER1 flag in STAT register */ + PKE_REG_MASK_SET(me, STAT, ER1, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + } + else + { + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); + } + /* advance over faulty word */ - PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); pke_pc_advance(me, 1); } |