X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fmips%2Fsky-pke.c;h=6e318750eaab4a3dd451b946204bef9178341142;hb=c0a4c3ba170e91bf93d16e0a6340980f6d62901a;hp=cf7408b0684785298e50f80d7f555e79726765d3;hpb=fa803dc60f0bf01297674c41d001798e18ade4dc;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/mips/sky-pke.c b/sim/mips/sky-pke.c index cf7408b068..6e318750ea 100644 --- a/sim/mips/sky-pke.c +++ b/sim/mips/sky-pke.c @@ -4,15 +4,16 @@ #include "config.h" #include -#include "sky-pke.h" -#include "sky-dma.h" +#include "sim-main.h" #include "sim-bits.h" #include "sim-assert.h" -#include "sky-vu0.h" -#include "sky-vu1.h" +#include "sky-pke.h" +#include "sky-dma.h" +#include "sky-vu.h" #include "sky-gpuif.h" #include "sky-device.h" + #ifdef HAVE_STRING_H #include #else @@ -64,6 +65,11 @@ static void pke_code_direct(struct pke_device* me, unsigned_4 pkecode); static void pke_code_directhl(struct pke_device* me, unsigned_4 pkecode); static void pke_code_unpack(struct pke_device* me, unsigned_4 pkecode); static void pke_code_error(struct pke_device* me, unsigned_4 pkecode); +unsigned_4 pke_fifo_flush(struct pke_fifo*); +void pke_fifo_reset(struct pke_fifo*); +struct fifo_quadword* pke_fifo_fit(struct pke_fifo*); +struct fifo_quadword* pke_fifo_access(struct pke_fifo*, unsigned_4 qwnum); +void pke_fifo_old(struct pke_fifo*, unsigned_4 qwnum); @@ -192,6 +198,70 @@ pke_attach(SIM_DESC sd, struct pke_device* me) } +/* Read PKE Pseudo-PC into buf in target order */ +int +read_pke_pc (struct pke_device *me, void *buf) +{ + *((int *) buf) = H2T_4( (me->fifo_pc << 2) | me->qw_pc ); + return 4; +} + + +/* Read PKE reg into buf in target order */ +int +read_pke_reg (struct pke_device *me, int reg_num, void *buf) +{ + /* handle reads to individual registers; clear `readable' on error */ + switch (reg_num) + { + /* handle common case of register reading, side-effect free */ + /* PKE1-only registers*/ + case PKE_REG_BASE: + case PKE_REG_OFST: + case PKE_REG_TOPS: + case PKE_REG_TOP: + case PKE_REG_DBF: + if (me->pke_number == 0) + { + *((int *) buf) = 0; + break; + } + /* fall through */ + + /* PKE0 & PKE1 common registers*/ + case PKE_REG_STAT: + case PKE_REG_ERR: + case PKE_REG_MARK: + case PKE_REG_CYCLE: + case PKE_REG_MODE: + case PKE_REG_NUM: + case PKE_REG_MASK: + case PKE_REG_CODE: + case PKE_REG_ITOPS: + case PKE_REG_ITOP: + case PKE_REG_R0: + case PKE_REG_R1: + case PKE_REG_R2: + case PKE_REG_R3: + case PKE_REG_C0: + case PKE_REG_C1: + case PKE_REG_C2: + case PKE_REG_C3: + *((int *) buf) = H2T_4(me->regs[reg_num][0]); + break; + + /* handle common case of write-only registers */ + case PKE_REG_FBRST: + *((int *) buf) = 0; + break; + + default: + ASSERT(0); /* tests above should prevent this possibility */ + } + + return 4; +} + /* Handle a PKE read; return no. of bytes read */ @@ -225,68 +295,15 @@ pke_io_read_buffer(device *me_, /* register bank */ int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4; int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */ - int readable = 1; quadword result; /* clear result */ result[0] = result[1] = result[2] = result[3] = 0; - /* handle reads to individual registers; clear `readable' on error */ - switch(reg_num) - { - /* handle common case of register reading, side-effect free */ - /* PKE1-only registers*/ - case PKE_REG_BASE: - case PKE_REG_OFST: - case PKE_REG_TOPS: - case PKE_REG_TOP: - case PKE_REG_DBF: - if(me->pke_number == 0) - readable = 0; - /* fall through */ - /* PKE0 & PKE1 common registers*/ - case PKE_REG_STAT: - case PKE_REG_ERR: - case PKE_REG_MARK: - case PKE_REG_CYCLE: - case PKE_REG_MODE: - case PKE_REG_NUM: - case PKE_REG_MASK: - case PKE_REG_CODE: - case PKE_REG_ITOPS: - case PKE_REG_ITOP: - case PKE_REG_R0: - case PKE_REG_R1: - case PKE_REG_R2: - case PKE_REG_R3: - case PKE_REG_C0: - case PKE_REG_C1: - case PKE_REG_C2: - case PKE_REG_C3: - result[0] = H2T_4(me->regs[reg_num][0]); - break; - - /* handle common case of write-only registers */ - case PKE_REG_FBRST: - readable = 0; - break; - - default: - ASSERT(0); /* test above should prevent this possibility */ - } + read_pke_reg (me, reg_num, result); /* perform transfer & return */ - if(readable) - { - /* copy the bits */ - memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes); - /* okay */ - } - else - { - /* return zero bits */ - memset(dest, 0, nr_bytes); - } + memcpy(dest, ((unsigned_1*) &result) + reg_byte, nr_bytes); return nr_bytes; /* NOTREACHED */ @@ -305,8 +322,104 @@ pke_io_read_buffer(device *me_, return 0; } +/* Write PKE reg from buf, which is in target order */ +int +write_pke_reg (struct pke_device *me, int reg_num, const void *buf) +{ + int writeable = 1; + /* make words host-endian */ + unsigned_4 input = T2H_4( *((unsigned_4 *) buf) ); + + /* handle writes to individual registers; clear `writeable' on error */ + switch (reg_num) + { + case PKE_REG_FBRST: + /* Order these tests from least to most overriding, in case + multiple bits are set. */ + if(BIT_MASK_GET(input, PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E)) + { + /* clear a bunch of status bits */ + PKE_REG_MASK_SET(me, STAT, PSS, 0); + PKE_REG_MASK_SET(me, STAT, PFS, 0); + PKE_REG_MASK_SET(me, STAT, PIS, 0); + 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, PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E)) + { + me->flags |= PKE_FLAG_PENDING_PSS; + } + if(BIT_MASK_GET(input, PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E)) + { + PKE_REG_MASK_SET(me, STAT, PFS, 1); + } + if(BIT_MASK_GET(input, PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E)) + { + pke_reset(me); + } + break; + + case PKE_REG_ERR: + /* copy bottom three bits */ + BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input, 0, 2)); + break; + + case PKE_REG_MARK: + /* copy bottom sixteen bits */ + PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input, 0, 15)); + /* reset MRK bit in STAT */ + PKE_REG_MASK_SET(me, STAT, MRK, 0); + break; + + /* handle common case of read-only registers */ + /* PKE1-only registers - not really necessary to handle separately */ + case PKE_REG_BASE: + case PKE_REG_OFST: + case PKE_REG_TOPS: + case PKE_REG_TOP: + case PKE_REG_DBF: + if(me->pke_number == 0) + writeable = 0; + /* fall through */ + /* PKE0 & PKE1 common registers*/ + case PKE_REG_STAT: + /* ignore FDR bit for PKE1_STAT -- simulator does not implement PKE->RAM transfers */ + case PKE_REG_CYCLE: + case PKE_REG_MODE: + case PKE_REG_NUM: + case PKE_REG_MASK: + case PKE_REG_CODE: + case PKE_REG_ITOPS: + case PKE_REG_ITOP: + case PKE_REG_R0: + case PKE_REG_R1: + case PKE_REG_R2: + case PKE_REG_R3: + case PKE_REG_C0: + case PKE_REG_C1: + case PKE_REG_C2: + case PKE_REG_C3: + writeable = 0; + break; + + default: + ASSERT(0); /* test above should prevent this possibility */ + } + + /* perform return */ + if(! writeable) + { + return 0; /* error */ + } + + return 4; +} + -/* Handle a PKE read; return no. of bytes written */ +/* Handle a PKE write; return no. of bytes written */ int pke_io_write_buffer(device *me_, @@ -338,7 +451,6 @@ pke_io_write_buffer(device *me_, /* register bank */ int reg_num = ADDR_TRUNC_QW(addr - my_reg_start) >> 4; int reg_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside register bank */ - int writeable = 1; quadword input; /* clear input */ @@ -347,95 +459,7 @@ pke_io_write_buffer(device *me_, /* write user-given bytes into input */ memcpy(((unsigned_1*) &input) + reg_byte, src, nr_bytes); - /* make words host-endian */ - input[0] = T2H_4(input[0]); - /* we may ignore other words */ - - /* handle writes to individual registers; clear `writeable' on error */ - switch(reg_num) - { - case PKE_REG_FBRST: - /* Order these tests from least to most overriding, in case - multiple bits are set. */ - if(BIT_MASK_GET(input[0], PKE_REG_FBRST_STC_B, PKE_REG_FBRST_STC_E)) - { - /* clear a bunch of status bits */ - PKE_REG_MASK_SET(me, STAT, PSS, 0); - PKE_REG_MASK_SET(me, STAT, PFS, 0); - PKE_REG_MASK_SET(me, STAT, PIS, 0); - 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], PKE_REG_FBRST_STP_B, PKE_REG_FBRST_STP_E)) - { - me->flags |= PKE_FLAG_PENDING_PSS; - } - if(BIT_MASK_GET(input[0], PKE_REG_FBRST_FBK_B, PKE_REG_FBRST_FBK_E)) - { - PKE_REG_MASK_SET(me, STAT, PFS, 1); - } - if(BIT_MASK_GET(input[0], PKE_REG_FBRST_RST_B, PKE_REG_FBRST_RST_E)) - { - pke_reset(me); - } - break; - - case PKE_REG_ERR: - /* copy bottom three bits */ - BIT_MASK_SET(me->regs[PKE_REG_ERR][0], 0, 2, BIT_MASK_GET(input[0], 0, 2)); - break; - - case PKE_REG_MARK: - /* copy bottom sixteen bits */ - PKE_REG_MASK_SET(me, MARK, MARK, BIT_MASK_GET(input[0], 0, 15)); - /* reset MRK bit in STAT */ - PKE_REG_MASK_SET(me, STAT, MRK, 0); - break; - - /* handle common case of read-only registers */ - /* PKE1-only registers - not really necessary to handle separately */ - case PKE_REG_BASE: - case PKE_REG_OFST: - case PKE_REG_TOPS: - case PKE_REG_TOP: - case PKE_REG_DBF: - if(me->pke_number == 0) - writeable = 0; - /* fall through */ - /* PKE0 & PKE1 common registers*/ - case PKE_REG_STAT: - /* ignore FDR bit for PKE1_STAT -- simulator does not implement PKE->RAM transfers */ - case PKE_REG_CYCLE: - case PKE_REG_MODE: - case PKE_REG_NUM: - case PKE_REG_MASK: - case PKE_REG_CODE: - case PKE_REG_ITOPS: - case PKE_REG_ITOP: - case PKE_REG_R0: - case PKE_REG_R1: - case PKE_REG_R2: - case PKE_REG_R3: - case PKE_REG_C0: - case PKE_REG_C1: - case PKE_REG_C2: - case PKE_REG_C3: - writeable = 0; - break; - - default: - ASSERT(0); /* test above should prevent this possibility */ - } - - /* perform return */ - if(! writeable) - { - ; /* error */ - } - + write_pke_reg (me, reg_num, input); return nr_bytes; /* NOTREACHED */ @@ -1069,16 +1093,19 @@ pke_check_stall(struct pke_device* me, enum pke_check_target what) } else if(what == chk_path1) /* VU -> GPUIF */ { + ASSERT(me->pke_number == 1); if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 1) any_stall = 1; } else if(what == chk_path2) /* PKE -> GPUIF */ { + ASSERT(me->pke_number == 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 */ { + ASSERT(me->pke_number == 1); if(BIT_MASK_GET(gpuif_stat, GPUIF_REG_STAT_APATH_B, GPUIF_REG_STAT_APATH_E) == 3) any_stall = 1; } @@ -1223,12 +1250,12 @@ pke_code_mskpath3(struct pke_device* me, unsigned_4 pkecode) /* set appropriate bit */ if(BIT_MASK_GET(imm, PKE_REG_MSKPATH3_B, PKE_REG_MSKPATH3_E) != 0) - gif_mode = GIF_REG_MODE_M3R_MASK; + gif_mode = GIF_REG_STAT_M3P; else gif_mode = 0; - /* write register; patrickm code will look at M3R bit only */ - PKE_MEM_WRITE(me, GIF_REG_MODE, & gif_mode, 4); + /* write register to "read-only" register; gpuif code will look at M3P bit only */ + PKE_MEM_WRITE(me, GIF_REG_VIF_M3P, & gif_mode, 4); /* done */ pke_pc_advance(me, 1); @@ -1976,20 +2003,12 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) switch(PKE_REG_MASK_GET(me, MODE, MDE)) { case PKE_MODE_ADDROW: /* add row registers to output data */ + case PKE_MODE_ACCROW: /* same .. later conditionally accumulate */ for(i=0; i<4; i++) /* exploit R0..R3 contiguity */ unpacked_data[i] += me->regs[PKE_REG_R0 + i][0]; break; - case PKE_MODE_ACCROW: /* add row registers to output data; accumulate */ - for(i=0; i<4; i++) - { - /* exploit R0..R3 contiguity */ - unpacked_data[i] += me->regs[PKE_REG_R0 + i][0]; - me->regs[PKE_REG_R0 + i][0] = unpacked_data[i]; - } - break; - case PKE_MODE_INPUT: /* pass data through */ default: /* specified as undefined */ ; @@ -2010,6 +2029,11 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) { case PKE_MASKREG_INPUT: masked_value = & unpacked_data[i]; + + /* conditionally accumulate */ + if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW) + me->regs[PKE_REG_R0 + i][0] = unpacked_data[i]; + break; case PKE_MASKREG_ROW: /* exploit R0..R3 contiguity */ @@ -2038,6 +2062,11 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) { /* no mask - just copy over entire unpacked quadword */ memcpy(vu_new_data, unpacked_data, sizeof(unpacked_data)); + + /* conditionally store accumulated row results */ + if(PKE_REG_MASK_GET(me, MODE, MDE) == PKE_MODE_ACCROW) + for(i=0; i<4; i++) + me->regs[PKE_REG_R0 + i][0] = unpacked_data[i]; } /* write new VU data word at address; reverse words if needed */