- added first batch of PKE code

- PKE memory region registration
- basic R/W operations
- combined pke[01] -> pke
This commit is contained in:
Frank Ch. Eigler 1998-01-23 00:38:10 +00:00
parent 3b7029b185
commit d1a18c2f83
10 changed files with 435 additions and 166 deletions

View File

@ -48,13 +48,11 @@ gpuif.c
device.h
dma.c
vu0.h
pke0.h
pke.h
vu1.h
pke1.h
vu1.c
vu0.c
pke0.c
pke1.c
pke.c
hardware.c
hardware.h

View File

@ -37,8 +37,7 @@ SIM_OBJS = \
dma.o \
vu0.o \
vu1.o \
pke0.o \
pke1.o \
pke.o \
sim-hload.o \
sim-engine.o \
sim-stop.o \

View File

@ -43,4 +43,12 @@ void dma_attach(SIM_DESC sd);
#define DMA_REGISTER_WINDOW_END 0x10001c70
#define DMA_REGISTER_WINDOW_SIZE (DMA_REGISTER_WINDOW_END - DMA_REGISTER_WINDOW_START)
/* virtual addresses for source-addr tracking */
#define DMA_CHANNEL0_SRCADDR 0x20000000
#define DMA_CHANNEL1_SRCADDR 0x20000004
#define DMA_CHANNEL2_SRCADDR 0x20000008
#define DMA_CHANNEL0_PKTFLAG 0x20000010
#define DMA_CHANNEL1_PKTFLAG 0x20000014
#define DMA_CHANNEL2_PKTFLAG 0x20000018
#endif

View File

@ -4,8 +4,7 @@
#include "gpuif.h"
#include "dma.h"
#include "pke0.h"
#include "pke1.h"
#include "pke.h"
#include "vu0.h"
#include "vu1.h"

306
sim/txvu/pke.c Normal file
View File

@ -0,0 +1,306 @@
/* Copyright (C) 1998, Cygnus Solutions */
#include "pke.h"
#include <stdlib.h>
/* Imported functions */
void device_error (device *me, char* message); /* device.c */
/* Internal function declarations */
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 data */
struct pke_device pke0_device =
{
{ "pke0", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
0, 0, /* ID, flags */
PKE0_REGISTER_WINDOW_START, PKE0_FIFO_START, /* memory-mapping addresses */
{}, /* regs */
NULL, 0, 0, NULL, /* FIFO */
0 /* pc */
};
struct pke_device pke1_device =
{
{ "pke1", &pke_io_read_buffer, &pke_io_write_buffer }, /* device */
1, 0, /* ID, flags */
PKE1_REGISTER_WINDOW_START, PKE1_FIFO_START, /* memory-mapping addresses */
{}, /* regs */
NULL, 0, 0, NULL, /* FIFO */
0 /* pc */
};
/* External functions */
/* Attach PKE0 addresses to main memory */
void
pke0_attach(SIM_DESC sd)
{
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
pke0_device.register_memory_addr,
PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/,
0 /*modulo*/,
(device*) &pke0_device,
NULL /*buffer*/);
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
pke0_device.fifo_memory_addr,
sizeof(quadword) /*nr_bytes*/,
0 /*modulo*/,
(device*) &pke1_device,
NULL /*buffer*/);
}
/* Attach PKE1 addresses to main memory */
void
pke1_attach(SIM_DESC sd)
{
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
pke1_device.register_memory_addr,
PKE_REGISTER_WINDOW_SIZE /*nr_bytes*/,
0 /*modulo*/,
(device*) &pke1_device,
NULL /*buffer*/);
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
pke1_device.fifo_memory_addr,
sizeof(quadword) /*nr_bytes*/,
0 /*modulo*/,
(device*) &pke1_device,
NULL /*buffer*/);
}
/* Issue a PKE0 instruction if possible */
void
pke0_issue()
{
pke_issue(& pke0_device);
}
/* Issue a PKE1 instruction if possible */
void
pke1_issue()
{
pke_issue(& pke0_device);
}
/* Internal functions */
/* Handle a PKE read; return no. of bytes read */
int
pke_io_read_buffer(device *me_,
void *dest,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
/* downcast to gather embedding pke_device struct */
struct pke_device* me = (struct pke_device*) me_;
/* enforce that an access does not span more than one quadword */
address_word low = ADDR_TRUNC_QW(addr);
address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
if(low != high)
return 0;
/* classify address & handle */
if(addr >= me->register_memory_addr &&
addr < me->register_memory_addr + PKE_REGISTER_WINDOW_SIZE)
{
/* register bank */
int reg_num = ADDR_TRUNC_QW(addr - me->register_memory_addr) >> 4;
int readable = 1;
/* ensure readibility of register: all okay except PKE1-only ones read on PKE0 */
switch(reg_num)
{
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) /* PKE0 cannot access these registers */
readable = 0;
}
/* perform read & return */
if(readable)
{
/* find byte-offset inside register bank */
int reg_byte = ADDR_OFFSET_QW(addr);
void* src = ((unsigned_1*) (& me->regs[reg_num])) + reg_byte;
/* copy the bits */
memcpy(dest, src, nr_bytes);
/* okay */
return nr_bytes;
}
else
{
/* error */
return 0;
}
/* NOTREACHED */
}
else if(addr >= me->fifo_memory_addr &&
addr < me->fifo_memory_addr + sizeof(quadword))
{
/* FIFO */
/* XXX: FIFO is not readable. */
return 0;
}
/* NOTREACHED */
}
/* Handle a PKE read; return no. of bytes written */
int
pke_io_write_buffer(device *me_,
const void *src,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
/* downcast to gather embedding pke_device struct */
struct pke_device* me = (struct pke_device*) me_;
/* enforce that an access does not span more than one quadword */
address_word low = ADDR_TRUNC_QW(addr);
address_word high = ADDR_TRUNC_QW(addr + nr_bytes - 1);
if(low != high)
return 0;
/* classify address & handle */
if(addr >= me->register_memory_addr &&
addr < me->register_memory_addr + PKE_REGISTER_WINDOW_SIZE)
{
/* register bank */
int reg_num = ADDR_TRUNC_QW(addr - me->register_memory_addr) >> 4;
int writeable = 1;
/* ensure readibility of register: all okay except PKE1-only ones read on PKE0 */
switch(reg_num)
{
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) /* PKE0 cannot access these registers */
writeable = 0;
}
/* perform write & return */
if(writeable)
{
/* find byte-offset inside register bank */
int reg_byte = ADDR_OFFSET_QW(addr);
void* dest = ((unsigned_1*) (& me->regs[reg_num])) + reg_byte;
/* copy the bits */
memcpy(dest, src, nr_bytes);
return nr_bytes;
}
else
{
/* error */
return 0;
}
/* NOTREACHED */
}
else if(addr >= me->fifo_memory_addr &&
addr < me->fifo_memory_addr + sizeof(quadword))
{
/* FIFO */
/* assert transfer size == 128 bits */
if(nr_bytes != sizeof(quadword))
return 0;
/* ensure FIFO has enough elements */
if(me->fifo_num_elements == me->fifo_buffer_size)
{
/* 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 */
device_error(me_, "Cannot enlarge FIFO buffer\n");
return 0;
}
me->fifo_buffer_size = new_fifo_buffer_size;
}
/* add new quadword at end of FIFO */
memcpy(& me->fifo[++me->fifo_num_elements], src, nr_bytes);
/* okay */
return nr_bytes;
}
/* NOTREACHED */
}
/* Issue & swallow one PKE opcode if possible */
void
pke_issue(struct pke_device* me)
{
}

117
sim/txvu/pke.h Normal file
View File

@ -0,0 +1,117 @@
/* Copyright (C) 1998, Cygnus Solutions */
#ifndef H_PKE_H
#define H_PKE_H
#include "sim-main.h"
#include "device.h"
/* External functions */
void pke0_attach(SIM_DESC sd);
void pke0_issue();
void pke1_attach(SIM_DESC sd);
void pke1_issue();
/* Quadword data type */
typedef unsigned int quadword[4];
/* truncate address to quadword */
#define ADDR_TRUNC_QW(addr) ((addr) & ~0x0f)
/* extract offset in quadword */
#define ADDR_OFFSET_QW(addr) ((addr) & 0x0f)
/* SCEI memory mapping information */
#define PKE0_REGISTER_WINDOW_START 0x10000800
#define PKE1_REGISTER_WINDOW_START 0x10000A00
#define PKE0_FIFO_START 0x10008000
#define PKE1_FIFO_START 0x10008010
/* Quadword indices of PKE registers. Actual registers sit at bottom
32 bits of each quadword. */
#define PKE_REG_STAT 0x00
#define PKE_REG_FBRST 0x01
#define PKE_REG_ERR 0x02
#define PKE_REG_MARK 0x03
#define PKE_REG_CYCLE 0x04
#define PKE_REG_MODE 0x05
#define PKE_REG_NUM 0x06
#define PKE_REG_MASK 0x07
#define PKE_REG_CODE 0x08
#define PKE_REG_ITOPS 0x09
#define PKE_REG_BASE 0x0a /* pke1 only */
#define PKE_REG_OFST 0x0b /* pke1 only */
#define PKE_REG_TOPS 0x0c /* pke1 only */
#define PKE_REG_ITOP 0x0d
#define PKE_REG_TOP 0x0e /* pke1 only */
#define PKE_REG_DBF 0x0f /* pke1 only */
#define PKE_REG_R0 0x10
#define PKE_REG_R1 0x11
#define PKE_REG_R2 0x12
#define PKE_REG_R3 0x13
#define PKE_REG_C0 0x14
#define PKE_REG_C1 0x15
#define PKE_REG_C2 0x16
#define PKE_REG_C3 0x17
/* one plus last index */
#define PKE_NUM_REGS 0x18
#define PKE_REGISTER_WINDOW_SIZE (sizeof(quadword) * PKE_NUM_REGS)
/* virtual addresses for source-addr tracking */
#define PKE0_SRCADDR 0x20000020
#define PKE1_SRCADDR 0x20000024
/* 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;
};
/* PKE internal state: FIFOs, registers, handle to VU friend */
struct pke_device
{
/* common device info */
device dev;
/* identity: 0=PKE0, 1=PKE1 */
int pke_number;
int flags;
address_word register_memory_addr;
address_word fifo_memory_addr;
/* quadword registers */
quadword regs[PKE_NUM_REGS];
/* FIFO */
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 */
/* index into FIFO of current instruction */
int program_counter;
};
/* Flags for PKE.flags */
#define PKE_FLAG_NONE 0
/* none at present */
#endif /* H_PKE_H */

View File

@ -1,61 +0,0 @@
/* Copyright (C) 1998, Cygnus Solutions
*/
#include "sim-main.h"
#include "device.h"
#include "pke0.h"
void
pke0_issue()
{
}
int
pke0_io_read_buffer(device *me,
void *dest,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
printf("%s: Read!\n", me->name);
return nr_bytes;
}
int
pke0_io_write_buffer(device *me,
const void *source,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
printf("%s: Write!\n", me->name);
return nr_bytes;
}
device pke0_device =
{
"pke0",
&pke0_io_read_buffer,
&pke0_io_write_buffer
};
void
pke0_attach(SIM_DESC sd)
{
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
PKE0_REGISTER_WINDOW_START,
PKE0_REGISTER_WINDOW_SIZE /*nr_bytes*/,
0 /*modulo*/,
&pke0_device,
NULL /*buffer*/);
}

View File

@ -1,18 +0,0 @@
/* Copyright (C) 1998, Cygnus Solutions
*/
#ifndef PKE0_H_
#define PKE0_H_
#include "sim-main.h"
void pke0_attach(SIM_DESC sd);
void pke0_issue();
#define PKE0_REGISTER_WINDOW_START 0x10000800
#define PKE0_REGISTER_WINDOW_END 0x10000980
#define PKE0_REGISTER_WINDOW_SIZE (PKE0_REGISTER_WINDOW_END - PKE0_REGISTER_WINDOW_START)
#endif

View File

@ -1,61 +0,0 @@
/* Copyright (C) 1998, Cygnus Solutions
*/
#include "sim-main.h"
#include "device.h"
#include "pke1.h"
void
pke1_issue()
{
}
int
pke1_io_read_buffer(device *me,
void *dest,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
printf("%s: Read!\n", me->name);
return nr_bytes;
}
int
pke1_io_write_buffer(device *me,
const void *source,
int space,
address_word addr,
unsigned nr_bytes,
sim_cpu *processor,
sim_cia cia)
{
printf("%s: Write!\n", me->name);
return nr_bytes;
}
device pke1_device =
{
"pke1",
&pke1_io_read_buffer,
&pke1_io_write_buffer
};
void
pke1_attach(SIM_DESC sd)
{
sim_core_attach (sd,
NULL,
0 /*level*/,
access_read_write,
0 /*space ???*/,
PKE1_REGISTER_WINDOW_START,
PKE1_REGISTER_WINDOW_SIZE /*nr_bytes*/,
0 /*modulo*/,
&pke1_device,
NULL /*buffer*/);
}

View File

@ -1,18 +0,0 @@
/* Copyright (C) 1998, Cygnus Solutions
*/
#ifndef PKE1_H_
#define PKE1_H_
#include "sim-main.h"
void pke1_attach(SIM_DESC sd);
void pke1_issue();
#define PKE1_REGISTER_WINDOW_START 0x10000a00
#define PKE1_REGISTER_WINDOW_END 0x10000b80
#define PKE1_REGISTER_WINDOW_SIZE (PKE1_REGISTER_WINDOW_END - PKE1_REGISTER_WINDOW_START)
#endif