From d22ea5d0012b4067942bb7d9e5cebe95ddd0e5c0 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 25 Feb 1998 19:34:06 +0000 Subject: [PATCH] * PKE unit testing continuing. Confusion over PKE1 double-buffering mechanism is starting to subside. * sky-pke.h (PKE_FLAG_INT_NOLOOP): Added device flag to indicate presence of stalled & interrupted PKEcode. * sky-pke.c (pke_issue): Added PKEcode interrupt bit handling. (pke_flip_dbf): Changed double-buffering logic to match SCEI clarification. (pke_code_*): Added interrupt bit stalling clause. (pke_code_pkems*): Added ITOP/ITOPS transmission code. (pke_code_unpack): Added more careful logic for processing overflows of VU data memory addresses. --- sim/mips/sky-pke.c | 237 +++++++++++++++++++++++++++++++++++++++------ sim/mips/sky-pke.h | 3 +- 2 files changed, 210 insertions(+), 30 deletions(-) diff --git a/sim/mips/sky-pke.c b/sim/mips/sky-pke.c index c9c0adf929a..6685d16b6f0 100644 --- a/sim/mips/sky-pke.c +++ b/sim/mips/sky-pke.c @@ -571,11 +571,26 @@ pke_issue(SIM_DESC sd, struct pke_device* me) 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) { - /* set INT flag in STAT register */ - PKE_REG_MASK_SET(me, STAT, INT, 1); - /* XXX: send interrupt to 5900? */ + /* are we resuming an interrupt-flagged 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); + } + else /* new interrupt-flagged instruction */ + { + /* 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? */ + } } /* decoding */ @@ -828,8 +843,8 @@ pke_pc_operand_bits(struct pke_device* me, int bit_offset, int bit_width, unsign -/* check for stall conditions on indicated devices (path* only on PKE1), do not change status - return 0 iff no stall */ +/* check for stall conditions on indicated devices (path* only on + PKE1), do not change status; return 0 iff no stall */ int pke_check_stall(struct pke_device* me, enum pke_check_target what) { @@ -879,13 +894,11 @@ pke_check_stall(struct pke_device* me, enum pke_check_target what) } -/* flip the DBF bit; recompute TOPS, ITOP & TOP */ +/* PKE1 only: flip the DBF bit; recompute TOPS, TOP */ void pke_flip_dbf(struct pke_device* me) { - /* compute new ITOP and TOP */ - PKE_REG_MASK_SET(me, ITOP, ITOP, - PKE_REG_MASK_GET(me, ITOPS, ITOPS)); + /* compute new TOP */ PKE_REG_MASK_SET(me, TOP, TOP, PKE_REG_MASK_GET(me, TOPS, TOPS)); /* flip DBF */ @@ -897,6 +910,10 @@ pke_flip_dbf(struct pke_device* me) (PKE_REG_MASK_GET(me, BASE, BASE) + (PKE_REG_MASK_GET(me, DBF, DF) * PKE_REG_MASK_GET(me, OFST, OFFSET)))); + /* this is equivalent to last word from okadaa (98-02-25): + 1) TOP=TOPS; + 2) TOPS=BASE + !DBF*OFFSET + 3) DBF=!DBF */ } @@ -908,6 +925,14 @@ pke_flip_dbf(struct pke_device* me) void pke_code_nop(struct pke_device* me, unsigned_4 pkecode) { + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* done */ pke_pc_advance(me, 1); PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); @@ -918,6 +943,15 @@ void pke_code_stcycl(struct pke_device* me, unsigned_4 pkecode) { int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* copy immediate value into CYCLE reg */ PKE_REG_MASK_SET(me, CYCLE, WL, BIT_MASK_GET(imm, 8, 15)); PKE_REG_MASK_SET(me, CYCLE, CL, BIT_MASK_GET(imm, 0, 7)); @@ -931,6 +965,15 @@ void pke_code_offset(struct pke_device* me, unsigned_4 pkecode) { int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* copy 10 bits to OFFSET field */ PKE_REG_MASK_SET(me, OFST, OFFSET, BIT_MASK_GET(imm, 0, 9)); /* clear DBF bit */ @@ -949,14 +992,17 @@ void pke_code_base(struct pke_device* me, unsigned_4 pkecode) { int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* copy 10 bits to BASE field */ PKE_REG_MASK_SET(me, BASE, BASE, BIT_MASK_GET(imm, 0, 9)); - /* clear DBF bit */ - PKE_REG_MASK_SET(me, DBF, DF, 0); - /* clear other DBF bit */ - PKE_REG_MASK_SET(me, STAT, DBF, 0); - /* set TOPS = BASE */ - PKE_REG_MASK_SET(me, TOPS, TOPS, PKE_REG_MASK_GET(me, BASE, BASE)); /* done */ pke_pc_advance(me, 1); PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); @@ -967,6 +1013,15 @@ void pke_code_itop(struct pke_device* me, unsigned_4 pkecode) { int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* copy 10 bits to ITOPS field */ PKE_REG_MASK_SET(me, ITOPS, ITOPS, BIT_MASK_GET(imm, 0, 9)); /* done */ @@ -979,6 +1034,15 @@ void pke_code_stmod(struct pke_device* me, unsigned_4 pkecode) { int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* copy 2 bits to MODE register */ PKE_REG_MASK_SET(me, MODE, MDE, BIT_MASK_GET(imm, 0, 2)); /* done */ @@ -993,6 +1057,14 @@ pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode) int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); unsigned_4 gif_mode; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* set appropriate bit */ if(BIT_MASK_GET(imm, PKE_REG_MSKPATH3_B, PKE_REG_MSKPATH3_E) != 0) gif_mode = GIF_REG_MODE_M3R_MASK; @@ -1011,6 +1083,8 @@ pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode) void pke_code_pkemark(struct pke_device* me, unsigned_4 pkecode) { + /* ignore possible interrupt stall */ + int imm = BIT_MASK_GET(pkecode, PKE_OPCODE_IMM_B, PKE_OPCODE_IMM_E); /* copy 16 bits to MARK register */ PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(imm, 0, 15)); @@ -1025,6 +1099,14 @@ pke_code_pkemark(struct pke_device* me, unsigned_4 pkecode) void pke_code_flushe(struct pke_device* me, unsigned_4 pkecode) { + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW bit */ if(pke_check_stall(me, chk_vu)) { @@ -1048,6 +1130,14 @@ pke_code_flush(struct pke_device* me, unsigned_4 pkecode) { int something_busy = 0; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW, PGW bits */ if(pke_check_stall(me, chk_vu)) { @@ -1087,6 +1177,14 @@ pke_code_flusha(struct pke_device* me, unsigned_4 pkecode) { int something_busy = 0; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW, PGW bits */ if(pke_check_stall(me, chk_vu)) { @@ -1124,6 +1222,14 @@ pke_code_flusha(struct pke_device* me, unsigned_4 pkecode) void pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode) { + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW bit */ if(pke_check_stall(me, chk_vu)) { @@ -1153,6 +1259,9 @@ pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode) & vu_pc, 4); + /* copy ITOPS field to ITOP */ + PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS)); + /* done */ PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); pke_pc_advance(me, 1); @@ -1164,6 +1273,14 @@ pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode) void pke_code_pkemscnt(struct pke_device* me, unsigned_4 pkecode) { + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW bit */ if(pke_check_stall(me, chk_vu)) { @@ -1195,6 +1312,9 @@ pke_code_pkemscnt(struct pke_device* me, unsigned_4 pkecode) & vu_pc, 4); + /* copy ITOPS field to ITOP */ + PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS)); + /* done */ PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); pke_pc_advance(me, 1); @@ -1207,6 +1327,14 @@ pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode) { int something_busy = 0; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute next PEW, PGW bits */ if(pke_check_stall(me, chk_vu)) { @@ -1251,6 +1379,9 @@ pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode) & vu_pc, 4); + /* copy ITOPS field to ITOP */ + PKE_REG_MASK_SET(me, ITOP, ITOP, PKE_REG_MASK_GET(me, ITOPS, ITOPS)); + /* done */ PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); pke_pc_advance(me, 1); @@ -1261,9 +1392,17 @@ pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode) void pke_code_stmask(struct pke_device* me, unsigned_4 pkecode) { - /* check that FIFO has one more word for STMASK operand */ unsigned_4* mask; - + + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + + /* check that FIFO has one more word for STMASK operand */ mask = pke_pc_operand(me, 1); if(mask != NULL) { @@ -1298,6 +1437,14 @@ pke_code_strow(struct pke_device* me, unsigned_4 pkecode) /* check that FIFO has four more words for STROW operand */ unsigned_4* last_op; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + last_op = pke_pc_operand(me, 4); if(last_op != NULL) { @@ -1335,6 +1482,14 @@ pke_code_stcol(struct pke_device* me, unsigned_4 pkecode) /* check that FIFO has four more words for STCOL operand */ unsigned_4* last_op; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + last_op = pke_pc_operand(me, 4); if(last_op != NULL) { @@ -1377,6 +1532,14 @@ pke_code_mpg(struct pke_device* me, unsigned_4 pkecode) if(me->qw_pc != 3 && me->qw_pc != 1) return pke_code_error(me, pkecode); + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* map zero to max+1 */ if(num==0) num=0x100; @@ -1488,6 +1651,14 @@ pke_code_direct(struct pke_device* me, unsigned_4 pkecode) if(me->qw_pc != 3) return pke_code_error(me, pkecode); + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* map zero to max+1 */ if(imm==0) imm=0x10000; @@ -1558,6 +1729,14 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) int n, num_operands; unsigned_4* last_operand_word = NULL; + /* handle interrupts */ + if(BIT_MASK_GET(pkecode, PKE_OPCODE_I_B, PKE_OPCODE_I_E)) + { + PKE_REG_MASK_SET(me, STAT, PIS, 1); + PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_STALL); + return; + } + /* compute PKEcode length, as given in CPU2 spec, v2.1 pg. 11 */ if(wl <= cl) n = num; @@ -1582,23 +1761,18 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) /* compute VU address base */ if(me->pke_number == 0) { - vu_addr_base = VU0_MEM1_WINDOW_START + 16 * BIT_MASK_GET(imm, 0, 9); + vu_addr_base = VU0_MEM1_WINDOW_START; vu_addr_max_size = VU0_MEM1_SIZE; - vutrack_addr_base = VU0_MEM1_SRCADDR_START + 4 * BIT_MASK_GET(imm, 0, 9); + vutrack_addr_base = VU0_MEM1_SRCADDR_START; + r = 0; } else { - vu_addr_base = VU1_MEM1_WINDOW_START + 16 * BIT_MASK_GET(imm, 0, 9); + vu_addr_base = VU1_MEM1_WINDOW_START; vu_addr_max_size = VU1_MEM1_SIZE; - vutrack_addr_base = VU1_MEM1_SRCADDR_START + 4 * BIT_MASK_GET(imm, 0, 9); - if(r) /* double-buffering */ - { - vu_addr_base += 16 * PKE_REG_MASK_GET(me, TOPS, TOPS); - vutrack_addr_base += 4 * PKE_REG_MASK_GET(me, TOPS, TOPS); - } + vutrack_addr_base = VU1_MEM1_SRCADDR_START; } - /* set NUM */ PKE_REG_MASK_SET(me, NUM, NUM, num == 0 ? 0x100 : num ); @@ -1625,10 +1799,15 @@ 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*(cl*(vector_num_out/addrwl) + (vector_num_out%addrwl)); + 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)); } else - vu_addr = vu_addr_base + 16*vector_num_out; + vu_addr = vu_addr_base + 16 * (BIT_MASK_GET(imm, 0, 9) + + (r ? PKE_REG_MASK_GET(me, TOPS, TOPS) : 0) + + vector_num_out); /* check for vu_addr overflow */ while(vu_addr >= vu_addr_base + vu_addr_max_size) diff --git a/sim/mips/sky-pke.h b/sim/mips/sky-pke.h index 98c9e8af349..f8051c2b1e7 100644 --- a/sim/mips/sky-pke.h +++ b/sim/mips/sky-pke.h @@ -183,7 +183,7 @@ typedef unsigned_4 quadword[4]; #define PKE_REG_STAT_PPS_IDLE 0x00 /* ready to execute next instruction */ #define PKE_REG_STAT_PPS_WAIT 0x01 /* not enough words in FIFO */ #define PKE_REG_STAT_PPS_DECODE 0x02 /* decoding instruction */ -#define PKE_REG_STAT_PPS_STALL 0x02 /* alias state for FLUSHE stall */ +#define PKE_REG_STAT_PPS_STALL 0x02 /* alias state for stall (e.g., FLUSHE) */ #define PKE_REG_STAT_PPS_XFER 0x03 /* transferring instruction operands */ /* DBF register */ @@ -399,6 +399,7 @@ struct pke_device #define PKE_FLAG_NONE 0x00 #define PKE_FLAG_PENDING_PSS 0x01 /* PSS bit written-to; set STAT:PSS after current instruction */ +#define PKE_FLAG_INT_NOLOOP 0x02 /* INT PKEcode received; INT/PIS set; suppress loop after resumption */ /* Kludge alert */ -- 2.30.2