* sky-pke.h (pke_fifo*): Exported these formerly private functions.
(pke_device): Added FIFO cache fields.
* sky-pke.c (pke_fifo_reset): New function for GPUIF client -
clear FIFO contents.
(pke_pcrel_fifo): Added caching facility to prevent O(n^2) cost for
searching for consecutive operand words.
* sky-libvpe.c (MEM, uMEM): New/changed macros that perform modulo
calculations to handle out-of-range VU memory addresses.
(*): Replaced many previous uses of MEM[] and state->uMEM[] with
calls to above macros.
* sky-vu.h (struct VectorUnitState): Added qw/dw size fields for
MEM/uMEM buffers, for overflow prevention. Renamed MEM/uMEM fields
to catch all their prior users.
* sky-vu0.c (vu0_attach): Manually align MEM0/MEM1 buffers to force
16-byte alignment. (zalloc is not enough.)
* sky-vu1.c (vu1_attach): Ditto.
(init_vu): Store buffer sizes from allocation into VectorUnitState.
* sky-gpuif.h (GifPath): Use a pke_fifo strucf instead of
temporary fixed-size array for flexible FIFO sizing.
* sky-gpuif.c (SKY_GPU2_REFRESH): This is now an integer value to be
used as a modulus for periodic refresh.
(refresh): New function to send GPU2 refresh code periodically.
(*): Use pke_fifo calls to en/dequeue GPUIF tags & operands.
* sky-pke.h (struct pke_device): Added fields to allow caching of
results from recent FIFO searches.
unsigned, sim_cpu*, sim_cia);
static void pke_reset(struct pke_device*);
static void pke_issue(SIM_DESC, struct pke_device*);
-static unsigned_4 pke_fifo_flush(struct pke_fifo*);
-static struct fifo_quadword* pke_fifo_fit(struct pke_fifo*);
-static inline struct fifo_quadword* pke_fifo_access(struct pke_fifo*, unsigned_4 qwnum);
-static void pke_fifo_old(struct pke_fifo*, unsigned_4 qwnum);
static void pke_pc_advance(struct pke_device*, int num_words);
static struct fifo_quadword* pke_pcrel_fifo(struct pke_device*, int operand_num,
unsigned_4** operand);
{}, 0, /* FIFO write buffer */
{ NULL, 0, 0, 0 }, /* FIFO */
NULL, /* FIFO trace file */
+ -1, -1, 0, 0, 0, /* invalid FIFO cache */
0, 0 /* pc */
};
{}, 0, /* FIFO write buffer */
{ NULL, 0, 0, 0 }, /* FIFO */
NULL, /* FIFO trace file */
+ -1, -1, 0, 0, 0, /* invalid FIFO cache */
0, 0 /* pc */
};
+/* Clear out contents of FIFO; make it really empty. */
+
+void
+pke_fifo_reset(struct pke_fifo* fifo)
+{
+ int i;
+
+ /* clear fifo quadwords */
+ for(i=0; i<fifo->next; i++)
+ {
+ zfree(fifo->quadwords[i]);
+ fifo->quadwords[i] = NULL;
+ }
+
+ /* reset pointers */
+ fifo->origin = 0;
+ fifo->next = 0;
+}
+
+
+
/* Make space for the next quadword in the FIFO. Allocate/enlarge
FIFO pointer block if necessary. Return a pointer to it. */
struct fifo_quadword*
pke_pcrel_fifo(struct pke_device* me, int operand_num, unsigned_4** operand)
{
- int num = operand_num;
+ int num;
int new_qw_pc, new_fifo_pc;
struct fifo_quadword* fq = NULL;
- ASSERT(num > 0);
+ /* check for validity of last search results in cache */
+ if(me->last_fifo_pc == me->fifo_pc &&
+ me->last_qw_pc == me->qw_pc &&
+ operand_num > me->last_num)
+ {
+ /* continue search from last stop */
+ new_fifo_pc = me->last_new_fifo_pc;
+ new_qw_pc = me->last_new_qw_pc;
+ num = operand_num - me->last_num;
+ }
+ else
+ {
+ /* start search from scratch */
+ new_fifo_pc = me->fifo_pc;
+ new_qw_pc = me->qw_pc;
+ num = operand_num;
+ }
- /* snapshot current pointers */
- new_fifo_pc = me->fifo_pc;
- new_qw_pc = me->qw_pc;
+ ASSERT(num > 0);
/* printf("pke %d pcrel_fifo operand_num %d\n", me->pke_number, operand_num); */
/* annote the word where the pseudo-PC 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;
+
+ /* store search results in cache */
+ /* keys */
+ me->last_fifo_pc = me->fifo_pc;
+ me->last_qw_pc = me->qw_pc;
+ /* values */
+ me->last_num = operand_num;
+ me->last_new_fifo_pc = new_fifo_pc;
+ me->last_new_qw_pc = new_qw_pc;
}
return fq;
void pke1_attach(SIM_DESC sd);
void pke1_issue(SIM_DESC sd);
+/* structs declared below */
+struct pke_fifo;
+struct fifo_quadword;
+
+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);
+
/* Quadword data type */
wc_dma = 'D',
wc_pkecode = 'P',
wc_unknown = '?',
- wc_pkedata = '.'
+ wc_pkedata = '.',
+ wc_gpuiftag = 'g'
};
/* quadword FIFO structure for PKE */
-struct pke_fifo
+typedef struct pke_fifo
{
struct fifo_quadword** quadwords; /* pointer to fifo quadwords */
unsigned_4 origin; /* quadword serial number of quadwords[0] */
unsigned_4 length; /* length of quadword pointer array: 0..N */
unsigned_4 next; /* relative index of first unfilled quadword: 0..length-1 */
-};
+} pke_fifo;
#define PKE_FIFO_GROW_SIZE 1000 /* number of quadword pointers to allocate */
#define PKE_FIFO_ARCHEOLOGY 1000 /* number of old quadwords to keep as history */
struct pke_fifo fifo; /* array of FIFO quadword pointers */
FILE* fifo_trace_file; /* stdio stream open in append mode, or 0 for no trace */
+ /* FIFO cache -- curry last search pke_pcrel_fifo results */
+ unsigned_4 last_fifo_pc;
+ unsigned_4 last_qw_pc;
+ unsigned_4 last_num;
+ unsigned_4 last_new_fifo_pc;
+ unsigned_4 last_new_qw_pc;
+
/* PC */
int fifo_pc; /* 0 .. (fifo_num_elements-1): quadword index of next instruction */
int qw_pc; /* 0 .. 3: word index of next instruction */
#include "sky-device.h"
#include "sky-vu0.h"
+/* these are aligned versions of zalloc() pointers - do not zfree()! */
static char* vu0_mem0_buffer = 0;
static char* vu0_mem1_buffer = 0;
NULL /*buffer*/);
vu0_mem0_buffer = zalloc(VU0_MEM0_SIZE);
+ vu0_mem0_buffer = (void*) ALIGN_16((unsigned)vu0_mem0_buffer);
sim_core_attach (sd,
NULL,
0 /*level*/,
vu0_mem0_buffer /*buffer*/);
vu0_mem1_buffer = zalloc(VU0_MEM1_SIZE);
+ vu0_mem1_buffer = (void*) ALIGN_16((unsigned)vu0_mem1_buffer);
sim_core_attach (sd,
NULL,
0 /*level*/,
#define sim_warning printf
+/* these are aligned versions of zalloc() pointers - do not zfree()! */
static char* vu1_umem_buffer = 0;
static char* vu1_mem_buffer = 0;
void init_vu1(void);
-void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer);
+void init_vu(VectorUnitState *state,
+ char* umem_buffer, unsigned umem_dw_size,
+ char* mem_buffer, unsigned mem_qw_size);
#if 0
static void dump_mem() {
NULL /*buffer*/);
vu1_umem_buffer = zalloc(VU1_MEM0_SIZE);
+ vu1_umem_buffer = (void*) ALIGN_16((unsigned)vu1_umem_buffer);
sim_core_attach (sd,
NULL,
0 /*level*/,
0 /*device*/,
vu1_umem_buffer /*buffer*/);
- vu1_mem_buffer = zalloc(VU1_MEM1_SIZE);
+ vu1_mem_buffer = zalloc(VU1_MEM1_SIZE + 2*sizeof(unsigned_16));
+ vu1_mem_buffer = (void*) ALIGN_16((unsigned)vu1_mem_buffer);
sim_core_attach (sd,
NULL,
0 /*level*/,
void getoption(VectorUnitState* state);
void init_vu1(void) {
- init_vu(&vu1_state, &vu1_umem_buffer[0], &vu1_mem_buffer[0]);
+ init_vu(&vu1_state,
+ &vu1_umem_buffer[0], VU1_MEM0_SIZE/8,
+ &vu1_mem_buffer[0], VU1_MEM1_SIZE/16);
}
-void init_vu(VectorUnitState *state, char* umem_buffer, char* mem_buffer)
+void init_vu(VectorUnitState *state,
+ char* umem_buffer, unsigned umem_dw_size,
+ char* mem_buffer, unsigned mem_qw_size)
{
FILE *fp;
int i, j;
u_long data[4];
/* set up memory buffers */
- state->uMEM = (uMEM_Entry_Type *) umem_buffer;
- state->MEM = (MEM_Entry_Type*) mem_buffer;
-
+ state->uMEM_buffer = (uMEM_Entry_Type *) umem_buffer;
+ state->uMEM_size = umem_dw_size;
+ state->MEM_buffer = (MEM_Entry_Type*) mem_buffer;
+ state->MEM_size = mem_qw_size;
+
/* set up run state */
state->runState = VU_READY;