From e23069923b6d8d3d638e3bee4ad1647f37b353e3 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 18 Feb 1998 21:26:38 +0000 Subject: [PATCH] * Started PKE sim unit testing. A number of minor errors were corrected. A few PKE instructions even run correctly! Next missing function of interest: FIFO pruning. * sky-pke.c (pke_issue): Take extra SIM_DESC argument. (pke_attach): Attach correct PKE0/PKE1 device. Open trace file if VIF{0,1}_TRACE_FILE env. var. is defined. (pke_io_write_buffer): Classify words in FIFO quadword. Use kludgey sim_core routines to access DMA registers. (pke_pc_advance): Add PKEcode classification. Correct DMA tag skipping. Emit trace records. (pke_pc_fifo): Add PKEcode operand classification. (pke_check_stall): Perform stall checks against updated register scheme. (pke_code_unpack): Correct operand-count calculation. (pke_code_stmask): Correct instruction skipping. * sky-pke.h (PKE_MEM_WRITE, PKE_MEM_READ): New kludge macros. (BIT_MASK_BTW): Corrected off-by-one error. (enum wordclass): Classify words in a FIFO quadword. * sky-dma.c (dma_io_read_buffer): Correct address checking assertions. * sky-engine.c (engine_run): Pass along SIM_DESC to PKE instruction issue code. --- sim/mips/sky-pke.c | 211 ++++++++++++++++++++++++++++++--------------- sim/mips/sky-pke.h | 61 +++++++++---- 2 files changed, 183 insertions(+), 89 deletions(-) diff --git a/sim/mips/sky-pke.c b/sim/mips/sky-pke.c index 7b906a04cab..9655f871086 100644 --- a/sim/mips/sky-pke.c +++ b/sim/mips/sky-pke.c @@ -1,8 +1,10 @@ /* Copyright (C) 1998, Cygnus Solutions */ + /* Debugguing PKE? */ #define PKE_DEBUG + #include #include "sky-pke.h" #include "sky-dma.h" @@ -24,7 +26,7 @@ static int pke_io_read_buffer(device*, void*, int, address_word, unsigned, sim_cpu*, sim_cia); static int pke_io_write_buffer(device*, const void*, int, address_word, unsigned, sim_cpu*, sim_cia); -static void pke_issue(struct pke_device*); +static void pke_issue(SIM_DESC, 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, @@ -110,15 +112,15 @@ pke1_attach(SIM_DESC sd) /* Issue a PKE instruction if possible */ void -pke0_issue(void) +pke0_issue(SIM_DESC sd) { - pke_issue(& pke0_device); + pke_issue(sd, & pke0_device); } void -pke1_issue(void) +pke1_issue(SIM_DESC sd) { - pke_issue(& pke0_device); + pke_issue(sd, & pke0_device); } @@ -132,40 +134,44 @@ void pke_attach(SIM_DESC sd, struct pke_device* me) { /* register file */ - sim_core_attach (sd, - NULL, - 0 /*level*/, - access_read_write, - 0 /*space ???*/, + sim_core_attach (sd, NULL, 0, access_read_write, 0, (me->pke_number == 0) ? PKE0_REGISTER_WINDOW_START : PKE1_REGISTER_WINDOW_START, PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/, 0 /*modulo*/, - (device*) &pke0_device, + (device*) me, NULL /*buffer*/); /* FIFO port */ - sim_core_attach (sd, - NULL, - 0 /*level*/, - access_read_write, - 0 /*space ???*/, + sim_core_attach (sd, NULL, 0, access_read_write, 0, (me->pke_number == 0) ? PKE0_FIFO_ADDR : PKE1_FIFO_ADDR, sizeof(quadword) /*nr_bytes*/, 0 /*modulo*/, - (device*) &pke1_device, + (device*) me, NULL /*buffer*/); /* source-addr tracking word */ - sim_core_attach (sd, - NULL, - 0 /*level*/, - access_read_write, - 0 /*space ???*/, + sim_core_attach (sd, NULL, 0, access_read_write, 0, (me->pke_number == 0) ? PKE0_SRCADDR : PKE1_SRCADDR, sizeof(unsigned_4) /*nr_bytes*/, 0 /*modulo*/, NULL, zalloc(sizeof(unsigned_4)) /*buffer*/); + + /* attach to trace file if appropriate */ + { + char trace_envvar[80]; + char* trace_filename = NULL; + sprintf(trace_envvar, "VIF%d_TRACE_FILE", me->pke_number); + trace_filename = getenv(trace_envvar); + if(trace_filename != NULL) + { + me->fifo_trace_file = fopen(trace_filename, "w"); + if(me->fifo_trace_file == NULL) + { + perror("VIF FIFO trace error on fopen"); + } + } + } } @@ -431,6 +437,7 @@ pke_io_write_buffer(device *me_, /* FIFO */ struct fifo_quadword* fqw; int fifo_byte = ADDR_OFFSET_QW(addr); /* find byte-offset inside fifo quadword */ + unsigned_4 dma_tag_present = 0; int i; /* collect potentially-partial quadword in write buffer */ @@ -441,7 +448,7 @@ pke_io_write_buffer(device *me_, /* 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))) + BIT_MASK_BTW(0, sizeof(quadword)-1)) return nr_bytes; /* all done - process quadword after clearing flag */ @@ -453,7 +460,7 @@ pke_io_write_buffer(device *me_, /* time to grow */ int new_fifo_buffer_size = me->fifo_buffer_size + 20; void* ptr = realloc((void*) me->fifo, new_fifo_buffer_size*sizeof(quadword)); - + if(ptr == NULL) { /* oops, cannot enlarge FIFO any more */ @@ -461,20 +468,29 @@ pke_io_write_buffer(device *me_, return 0; } + me->fifo = ptr; me->fifo_buffer_size = new_fifo_buffer_size; } /* add new quadword at end of FIFO */ fqw = & me->fifo[me->fifo_num_elements]; + fqw->word_class[0] = fqw->word_class[1] = + fqw->word_class[2] = fqw->word_class[3] = wc_unknown; memcpy((void*) fqw->data, me->fifo_qw_in_progress, sizeof(quadword)); - sim_read(CPU_STATE(cpu), - (SIM_ADDR) (me->pke_number == 0 ? DMA_D0_MADR : DMA_D1_MADR), - (void*) & fqw->source_address, - sizeof(address_word)); - sim_read(CPU_STATE(cpu), - (SIM_ADDR) (me->pke_number == 0 ? DMA_D0_PKTFLAG : DMA_D1_PKTFLAG), - (void*) & fqw->dma_tag_present, - sizeof(unsigned_4)); + ASSERT(sizeof(unsigned_4) == 4); + PKE_MEM_READ((SIM_ADDR) (me->pke_number == 0 ? DMA_D0_MADR : DMA_D1_MADR), + & fqw->source_address, + 4); + PKE_MEM_READ((SIM_ADDR) (me->pke_number == 0 ? DMA_D0_PKTFLAG : DMA_D1_PKTFLAG), + & dma_tag_present, + 4); + + if(dma_tag_present) + { + /* lower two words are DMA tags */ + fqw->word_class[0] = fqw->word_class[1] = wc_dma; + } + me->fifo_num_elements++; @@ -494,7 +510,7 @@ pke_io_write_buffer(device *me_, /* Issue & swallow next PKE opcode if possible/available */ void -pke_issue(struct pke_device* me) +pke_issue(SIM_DESC sd, struct pke_device* me) { struct fifo_quadword* fqw; unsigned_4 fw; @@ -556,7 +572,7 @@ pke_issue(struct pke_device* me) { /* set INT flag in STAT register */ PKE_REG_MASK_SET(me, STAT, INT, 1); - /* XXX: how to send interrupt to R5900? */ + /* XXX: send interrupt to 5900? */ } /* decoding */ @@ -613,43 +629,81 @@ pke_issue(struct pke_device* me) /* advance the PC by given number of data words; update STAT/FQC - field; assume FIFO is filled enough */ + field; assume FIFO is filled enough; classify passed-over words; + write FIFO trace line */ void pke_pc_advance(struct pke_device* me, int num_words) { int num = num_words; - ASSERT(num_words > 0); + struct fifo_quadword* fq = NULL; + int skipped = 0; + ASSERT(num_words >= 0); - while(num > 0) + do { - struct fifo_quadword* fq; - - /* one word skipped */ - num --; - - /* point to next word */ - me->qw_pc ++; - if(me->qw_pc == 4) - { - me->qw_pc = 0; - me->fifo_pc ++; - } + fq = & me->fifo[me->fifo_pc]; /* skip over DMA tag words if present in word 0 or 1 */ - fq = & me->fifo[me->fifo_pc]; - if(fq->dma_tag_present && (me->qw_pc < 2)) + if(fq->word_class[me->qw_pc] == wc_dma) { /* skip by going around loop an extra time */ num ++; + skipped = 1; } - } + else + skipped = 0; + + if(num > 0) /* increment PC */ + { + /* one word skipped */ + num --; + + /* point to next word */ + me->qw_pc ++; + if(me->qw_pc == 4) + { + me->qw_pc = 0; + me->fifo_pc ++; + + /* trace the consumption of this FIFO quadword */ + if(me->fifo_trace_file != NULL) + { + /* assert complete classification */ + ASSERT(fq->word_class[3] != wc_unknown); + ASSERT(fq->word_class[2] != wc_unknown); + ASSERT(fq->word_class[1] != wc_unknown); + ASSERT(fq->word_class[0] != wc_unknown); + + /* print trace record */ + fprintf(me->fifo_trace_file, + "%d 0x%ux_%ux_%ux_%ux 0x%ux %c%c%c%c\n", + (me->pke_number == 0 ? 0 : 1), + (unsigned) fq->data[3], (unsigned) fq->data[2], + (unsigned) fq->data[1], (unsigned) fq->data[0], + (unsigned) fq->source_address, + fq->word_class[3], fq->word_class[2], + fq->word_class[1], fq->word_class[0]); + } + + /* XXX: zap old entries in FIFO */ + + } /* next quadword */ + } /* increment PC */ + } /* eat num words */ + while(num > 0 || skipped); /* clear FQC if FIFO is now empty */ if(me->fifo_num_elements == me->fifo_pc) { PKE_REG_MASK_SET(me, STAT, FQC, 0); } + else /* annote the word where the PC lands as an PKEcode */ + { + ASSERT(fq->word_class[me->qw_pc] == wc_pkecode || + fq->word_class[me->qw_pc] == wc_unknown); + fq->word_class[me->qw_pc] = wc_pkecode; + } } @@ -664,7 +718,7 @@ pke_pc_fifo(struct pke_device* me, int operand_num, unsigned_4** operand) { int num = operand_num; int new_qw_pc, new_fifo_pc; - struct fifo_quadword* operand_fifo = NULL; + struct fifo_quadword* fq = NULL; ASSERT(num > 0); @@ -672,7 +726,7 @@ pke_pc_fifo(struct pke_device* me, int operand_num, unsigned_4** operand) new_fifo_pc = me->fifo_pc; new_qw_pc = me->qw_pc; - while(num > 0) + do { /* one word skipped */ num --; @@ -688,13 +742,13 @@ pke_pc_fifo(struct pke_device* me, int operand_num, unsigned_4** operand) /* check for FIFO underflow */ if(me->fifo_num_elements == new_fifo_pc) { - operand_fifo = NULL; + fq = NULL; break; } /* skip over DMA tag words if present in word 0 or 1 */ - operand_fifo = & me->fifo[new_fifo_pc]; - if(operand_fifo->dma_tag_present && (new_qw_pc < 2)) + fq = & me->fifo[new_fifo_pc]; + if(fq->word_class[new_qw_pc] == wc_dma) { /* mismatch error! */ PKE_REG_MASK_SET(me, STAT, ER0, 1); @@ -702,12 +756,20 @@ pke_pc_fifo(struct pke_device* me, int operand_num, unsigned_4** operand) num ++; } } + while(num > 0); /* return pointer to operand word itself */ - if(operand_fifo != NULL) - *operand = & operand_fifo->data[new_qw_pc]; + if(fq != NULL) + { + *operand = & fq->data[new_qw_pc]; - return operand_fifo; + /* annote the word where the pseudo lands as an PKE operand */ + ASSERT(fq->word_class[new_qw_pc] == wc_pkedata || + fq->word_class[new_qw_pc] == wc_unknown); + fq->word_class[new_qw_pc] = wc_pkedata; + } + + return fq; } @@ -796,19 +858,26 @@ int pke_check_stall(struct pke_device* me, enum pke_check_target what) { int any_stall = 0; + unsigned_4 cop2_stat, gpuif_stat; - /* read GPUIF status word - commonly used */ - unsigned_4 gpuif_stat; + /* read status words */ sim_read(NULL, (SIM_ADDR) (GIF_REG_STAT), (void*) & gpuif_stat, sizeof(unsigned_4)); + sim_read(NULL, + (SIM_ADDR) (COP2_REG_STAT_ADDR), + (void*) & cop2_stat, + sizeof(unsigned_4)); + /* perform checks */ if(what == chk_vu) { - ASSERT(0); - /* XXX: have to check COP2 control register VBS0 / VBS1 bits */ + if(me->pke_number == 0) + any_stall = BIT_MASK_GET(cop2_stat, COP2_REG_STAT_VBS0_B, COP2_REG_STAT_VBS0_E); + else /* if(me->pke_number == 1) */ + any_stall = BIT_MASK_GET(cop2_stat, COP2_REG_STAT_VBS1_B, COP2_REG_STAT_VBS1_E); } else if(what == chk_path1) /* VU -> GPUIF */ { @@ -1091,7 +1160,7 @@ pke_code_pkemscal(struct pke_device* me, unsigned_4 pkecode) 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), + (SIM_ADDR) (me->pke_number == 0 ? VU0_CIA : VU1_CIA), (void*) & vu_pc, sizeof(unsigned_4)); @@ -1127,13 +1196,13 @@ pke_code_pkemscnt(struct pke_device* me, unsigned_4 pkecode) /* read old PC */ sim_read(NULL, - (SIM_ADDR) (me->pke_number == 0 ? VU0_PC_START : VU1_PC_START), + (SIM_ADDR) (me->pke_number == 0 ? VU0_CIA : VU1_CIA), (void*) & vu_pc, sizeof(unsigned_4)); /* rewrite new PC; callback function gets VU running */ sim_write(NULL, - (SIM_ADDR) (me->pke_number == 0 ? VU0_PC_START : VU1_PC_START), + (SIM_ADDR) (me->pke_number == 0 ? VU0_CIA : VU1_CIA), (void*) & vu_pc, sizeof(unsigned_4)); @@ -1188,7 +1257,7 @@ pke_code_pkemscalf(struct pke_device* me, unsigned_4 pkecode) 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), + (SIM_ADDR) (me->pke_number == 0 ? VU0_CIA : VU1_CIA), (void*) & vu_pc, sizeof(unsigned_4)); @@ -1222,7 +1291,7 @@ pke_code_stmask(struct pke_device* me, unsigned_4 pkecode) /* done */ PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); - pke_pc_advance(me, 1); + pke_pc_advance(me, 2); } else { @@ -1472,7 +1541,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 = (((sizeof(unsigned_4) >> vl) * (vn+1) * n)/sizeof(unsigned_4)); + num_operands = ((32 >> vl) * (vn+1) * n)/32; /* confirm that FIFO has enough words in it */ last_operand_word = pke_pc_operand(me, num_operands); @@ -1668,7 +1737,7 @@ pke_code_unpack(struct pke_device* me, unsigned_4 pkecode) /* done */ PKE_REG_MASK_SET(me, STAT, PPS, PKE_REG_STAT_PPS_IDLE); - pke_pc_advance(me, num_operands); + pke_pc_advance(me, 1 + num_operands); } /* PKE FIFO full enough */ else { diff --git a/sim/mips/sky-pke.h b/sim/mips/sky-pke.h index 78f1fbb0545..91ecf658139 100644 --- a/sim/mips/sky-pke.h +++ b/sim/mips/sky-pke.h @@ -11,9 +11,10 @@ /* External functions */ void pke0_attach(SIM_DESC sd); -void pke0_issue(void); +void pke0_issue(SIM_DESC sd); void pke1_attach(SIM_DESC sd); -void pke1_issue(void); +void pke1_issue(SIM_DESC sd); + /* Quadword data type */ @@ -36,9 +37,6 @@ typedef unsigned_4 quadword[4]; /* 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 @@ -50,6 +48,13 @@ typedef unsigned_4 quadword[4]; #define GPUIF_REG_STAT_APATH_E 11 #define GPUIF_REG_STAT_APATH_B 10 +/* COP2 STAT register */ +#define COP2_REG_STAT_ADDR VPU_STAT +#define COP2_REG_STAT_VBS1_E 8 +#define COP2_REG_STAT_VBS1_B 8 +#define COP2_REG_STAT_VBS0_E 0 +#define COP2_REG_STAT_VBS0_B 0 + #endif /* PKE_DEBUG */ @@ -85,10 +90,6 @@ typedef unsigned_4 quadword[4]; #define PKE_REGISTER_WINDOW_SIZE (sizeof(quadword) * PKE_NUM_REGS) -/* virtual addresses for source-addr tracking */ -#define PKE0_SRCADDR 0x20000020 -#define PKE1_SRCADDR 0x20000024 - /* PKE commands */ @@ -286,16 +287,14 @@ typedef unsigned_4 quadword[4]; ((((me)->regs[PKE_REG_MASK][0]) >> (8*(row) + 2*(col))) & 0x03) - - /* operations - replace with those in sim-bits.h when convenient */ /* unsigned 32-bit mask of given width */ -#define BIT_MASK(width) (width == 31 ? 0xffffffff : (((unsigned_4)1) << (width+1)) - 1) +#define BIT_MASK(width) ((width) == 31 ? 0xffffffff : (((unsigned_4)1) << (width+1)) - 1) /* e.g.: BIT_MASK(4) = 00011111 */ /* mask between given given bits numbers (MSB) */ -#define BIT_MASK_BTW(begin,end) (BIT_MASK(end) & ~BIT_MASK(begin)) +#define BIT_MASK_BTW(begin,end) ((BIT_MASK(end) & ~((begin) == 0 ? 0 : BIT_MASK((begin)-1)))) /* e.g.: BIT_MASK_BTW(4,11) = 0000111111110000 */ /* set bitfield value */ @@ -332,15 +331,25 @@ do { \ #define PKE_LIMIT(value,max) ((value) > (max) ? (max) : (value)) +/* Classify words in a FIFO quadword */ +enum wordclass +{ + wc_dma = 'D', + wc_pkecode = 'P', + wc_unknown = '?', + wc_pkedata = '.' +}; + + /* One row in the FIFO */ struct fifo_quadword { /* 128 bits of data */ quadword data; /* source main memory address (or 0: unknown) */ - address_word source_address; - /* DMA tag present in lower 64 bits */ - unsigned_4 dma_tag_present; + unsigned_4 source_address; + /* classification of words in quadword; wc_dma set on DMA tags at FIFO write */ + enum wordclass word_class[4]; }; @@ -365,8 +374,7 @@ struct pke_device struct fifo_quadword* fifo; int fifo_num_elements; /* no. of quadwords occupied in FIFO */ int fifo_buffer_size; /* no. of quadwords of space in FIFO */ - FILE* fifo_trace_file; /* or 0 for no trace */ /* XXX: tracing not done */ - /* XXX: assumes FIFOs grow indefinately */ + FILE* fifo_trace_file; /* or 0 for no trace */ /* PC */ int fifo_pc; /* 0 .. (fifo_num_elements-1): quadword index of next instruction */ @@ -380,4 +388,21 @@ struct pke_device #define PKE_FLAG_PENDING_PSS 0x01 /* PSS bit written-to; set STAT:PSS after current instruction */ +/* Kludge alert */ + +#define PKE_MEM_READ(addr,data,size) \ + do { sim_cpu* cpu; cpu = STATE_CPU(CURRENT_STATE, 0); \ + *(data) = sim_core_read_aligned_##size(cpu, CIA_GET(cpu), sim_core_read_map, \ + (addr)); } while(0) + +#define PKE_MEM_WRITE(addr,data,size) \ + do { sim_cpu* cpu; cpu = STATE_CPU(CURRENT_STATE, 0); \ + unsigned_##size value; \ + memcpy((void*) value, (data), size); \ + sim_core_write_aligned_##size(cpu, CIA_GET(cpu), sim_core_write_map, \ + (addr), value); } while(0) + + + + #endif /* H_PKE_H */ -- 2.30.2