1
0
mirror of synced 2026-04-13 07:04:31 +00:00

CG6 accel emulation (still slow)

This commit is contained in:
Romain Dolbeau
2021-10-30 10:03:11 +02:00
parent f5a1067806
commit a85542d029
3 changed files with 181 additions and 40 deletions

View File

@@ -369,7 +369,7 @@ struct cg6_fbc {
void from_reset(void) __attribute__ ((noreturn)); // nothrow,
static inline void flush_cache(void) {
asm volatile(".word 0x0000500F\n"); // flush the Dcache so that we get updated data
//asm volatile(".word 0x0000500F\n"); // flush the Dcache so that we get updated data
}
typedef unsigned int unsigned_param_type;
@@ -415,6 +415,9 @@ static void bitblit(const unsigned_param_type xs,
const unsigned char gxop
);
static void print_hexword(unsigned int v, unsigned int bx, unsigned int by);
static void show_status_on_screen(void);
asm(".global _start\n"
"_start:\n"
// ".word 0x0000500F\n" // flush cache ; should not be needed after reset
@@ -438,6 +441,8 @@ asm(".global _start\n"
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
//#define TRACE_ON_SCREEN
#define DEBUG
#ifdef DEBUG
#define SHOW_FUN(a) fbc->fbc_r5_status[0] = a
@@ -466,7 +471,6 @@ void from_reset(void) {
case CG6_ALU_FILL: // ____ff00 console
case CG6_ALU_COPY: // ____cccc equivalent to fill if patterns == 1 (... which is the case with GX_PATTERN_ONES)
case ROP_FILL(GX_ROP_CLEAR, GX_ROP_SET): // ____ff00 Draw/GXcopy in X11
// //case ROP_FILL(GX_ROP_SET, GX_ROP_SET): // ____ffff Draw/GXset in X11
case ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET): // ____cccc Blit/GXcopy in X11
{
switch (mode) {
@@ -491,7 +495,7 @@ void from_reset(void) {
break;
}
} break;
case CG6_ALU_FLIP: { // ____5555 console
case CG6_ALU_FLIP: { // ____5555 console -> put ~dst everywhere
switch (mode)
{
case (GX_BLIT_SRC | GX_MODE_COLOR8): // invert
@@ -505,7 +509,7 @@ void from_reset(void) {
break;
}
} break;
case ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT): { // ____55aa Draw/GXxor in X11
case ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT): { // ____55aa Draw/GXxor in X11 -> put ~dst if src is 1, put dst if src is 0
switch (mode)
{
case (GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0):
@@ -537,12 +541,12 @@ void from_reset(void) {
case FUN_BLIT: {
switch (alu)
{
case CG6_ALU_COPY: // ____cccc console
case ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET): // ____ff00 Blit/GXcopy in X11
case CG6_ALU_COPY: // ____cccc console -> put the src
case ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET): // ____ff00 Blit/GXcopy in X11 -> put 1 if src is 1, put 0 if src is 0 (!)
{
switch (mode) {
case (GX_BLIT_SRC | GX_MODE_COLOR8): // console
case (GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0): // X11 FIXME:planemask?
case (GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0):
{
const unsigned_param_type xs = fbc->fbc_x0;
const unsigned_param_type ys = fbc->fbc_y0;
@@ -563,7 +567,7 @@ void from_reset(void) {
break;
}
} break;
case ROP_BLIT(GX_ROP_SET, GX_ROP_SET): // ____ffff Blit/GXset in X11
case ROP_BLIT(GX_ROP_SET, GX_ROP_SET): // ____ffff Blit/GXset in X11 -> put 1 everywhere
{
switch (mode) {
case (GX_BLIT_SRC | GX_MODE_COLOR8): // console
@@ -588,10 +592,10 @@ void from_reset(void) {
break;
}
} break;
case ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT): // ____6666 Blit/GXxor in X11
case ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT): // ____6666 Blit/GXxor in X11 -> xor everywhere
{
switch (mode) {
case (GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0): // X11 FIXME:planemask?
case (GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0):
{
const unsigned_param_type xs = fbc->fbc_x0;
const unsigned_param_type ys = fbc->fbc_y0;
@@ -647,7 +651,13 @@ void from_reset(void) {
const unsigned int yd = fbc->fbc_next_y0;
const unsigned int we = xde - xdsr + 1;
const unsigned int xoff = xds - xdsr;
if ((xde >= xds) && (xoff<we)) {
if ((xoff == 0) && (we == 4) && ((xdsr & 0x3) == 0)) {
unsigned char *dptr = (((unsigned char *)BASE_FB) + mul_HRES(yd) + xdsr);
unsigned int bits = fbc->fbc_next_font;
unsigned int rbits;
asm("rev8 %0, %1\n" : "=r"(rbits) : "r"(bits));
*((unsigned int*)dptr) = rbits;
} else if ((xde >= xds) && (xoff<we)) {
unsigned int bits = fbc->fbc_next_font;
#if 1
unsigned int rbits;
@@ -674,7 +684,7 @@ void from_reset(void) {
break;
}
} break;
case (GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET)): // console, also X11 OpaqueStipple/GXcopy FIXME:planemask?
case (GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET)): // ____fc30 console, also X11 OpaqueStipple/GXcopy FIXME:planemask?
{
switch (mode) {
case (GX_BLIT_NOSRC | GX_MODE_COLOR1):
@@ -772,8 +782,12 @@ void from_reset(void) {
break;
}
// make sure we have nothing left in the cache
finish:
#ifdef TRACE_ON_SCREEN
show_status_on_screen();
#endif
// make sure we have nothing left in the cache
flush_cache();
fbc->fbc_r5_cmd = FUN_DONE;
@@ -784,7 +798,7 @@ void from_reset(void) {
}
#define bitblit_proto_int(a, b, suf) \
static void bitblit##a##b##suf(const unsigned_param_type xs, \
static void bitblit##a##b##suf(const unsigned_param_type xs, \
const unsigned_param_type ys, \
const unsigned_param_type wi, \
const unsigned_param_type re, \
@@ -862,7 +876,7 @@ static void bitblit(const unsigned_param_type xs,
/* don't bother */
break;
case 0x6: // GXxor
rectfill(xd, yd, wi, re, 0); // FIXME: pixelmask
rectfill_pm(xd, yd, wi, re, 0, pm);
break;
}
}
@@ -1238,3 +1252,101 @@ static void bitblit_bwd_bwd_copy(const unsigned_param_type xs,
}
#endif
#ifdef TRACE_ON_SCREEN
#include "blit_font.h"
static void print_hex(unsigned char v, unsigned char* line_fb);
static void print_hex(unsigned char v, unsigned char* line_fb) {
unsigned int x, y;
const unsigned char *pbits = font + v * 8;
for (y = 0 ; y < 8 ; y++) { // line in char
const unsigned char bits = pbits[y];
for (x = 0 ; x < 8 ; x++) { // bits in line
unsigned char data = - ((bits>>(7-x))&1); // 0xff or 0x00
line_fb[x] = data;
}
line_fb += HRES;
}
}
static void print_hexword(unsigned int v, unsigned int bx, unsigned int by) {
unsigned int i, j;
#if 0
unsigned int x, y;
#endif
unsigned char* base_fb = (((unsigned char *)BASE_FB) + mul_HRES(by) + bx);
for (i = 0 ; i < 8 ; i++) { // nibbles in v
unsigned char* line_fb = base_fb;
unsigned int bidx = (v >> (28-i*4) & 0xF);
#if 0
const unsigned char *pbits = font + bidx * 8;
for (y = 0 ; y < 8 ; y++) { // line in char
const unsigned char bits = pbits[y];
for (x = 0 ; x < 8 ; x++) { // bits in line
unsigned char data = - ((bits>>(7-x))&1); // 0xff or 0x00
line_fb[x] = data;
}
line_fb += HRES;
}
#else
print_hex(bidx, line_fb);
#endif
base_fb += 8;
}
}
static void show_status_on_screen(void) {
struct cg6_fbc* fbc = (struct cg6_fbc*)BASE_FBC;
unsigned int cmd = fbc->fbc_r5_cmd;
unsigned int alu = fbc->fbc_alu;
unsigned int mode = fbc->fbc_mode;
unsigned int bx = 0;
unsigned int by = 768 + ((cmd & 0xF)*32);
unsigned char* base_fb = (((unsigned char *)BASE_FB) + mul_HRES(by) + bx);
print_hex(cmd & 0xF, base_fb);
bx += 16;
print_hexword(alu, bx, by);
bx += 72;
print_hexword(mode, bx, by);
bx -= 72;
by += 8;
if ((cmd & 0xF) == FUN_DRAW) {
print_hexword(fbc->fbc_arectx_prev, bx, by);
bx += 72;
print_hexword(fbc->fbc_arecty_prev, bx, by);
bx -= 72;
by += 8;
print_hexword(fbc->fbc_arectx, bx, by);
bx += 72;
print_hexword(fbc->fbc_arecty, bx, by);
bx -= 72;
by += 8;
print_hexword(fbc->fbc_pm, bx, by);
bx -= 88;
} else if ((cmd & 0xF) == FUN_BLIT) {
print_hexword(fbc->fbc_x0, bx, by);
bx += 72;
print_hexword(fbc->fbc_y0, bx, by);
bx += 72;
print_hexword(fbc->fbc_x1, bx, by);
bx += 72;
print_hexword(fbc->fbc_y1, bx, by);
bx -= 216;
by += 8;
print_hexword(fbc->fbc_x2, bx, by);
bx += 72;
print_hexword(fbc->fbc_y2, bx, by);
bx += 72;
print_hexword(fbc->fbc_x3, bx, by);
bx += 72;
print_hexword(fbc->fbc_y3, bx, by);
bx -= 216;
by += 8;
print_hexword(fbc->fbc_pm, bx, by);
bx -= 88;
}
print_hexword(fbc->fbc_s, bx, by);
}
#endif

View File

@@ -21,4 +21,4 @@ if test "x$1" != "xASM"; then
fi
$GCC $OPT -c -o blit.o -march=$ARCH -mabi=ilp32 -mstrict-align -fno-builtin-memset -nostdlib -ffreestanding -nostartfiles blit.s &&
$GCCLINK $OPT -o blit -march=$ARCH -mabi=ilp32 -T blit.lds -nostartfiles blit.o &&
$OBJCOPY -O binary -j .text blit blit.raw
$OBJCOPY -O binary -j .text -j .rodata blit blit.raw

View File

@@ -25,8 +25,8 @@ class CG6Accel(Module): # AutoCSR ?
fbc_incy = Signal(COORD_BITS)
fbc_clipminx = Signal(COORD_BITS)
fbc_clipminy = Signal(COORD_BITS)
fbc_clipmaxx = Signal(COORD_BITS)
fbc_clipmaxy = Signal(COORD_BITS)
fbc_clipmaxx = Signal(COORD_BITS+1) # need the 13th bit as X11 uses 4096 for clipmaxx (console uses 4095)
fbc_clipmaxy = Signal(COORD_BITS+1) # need the 13th bit as X11 uses 4096 for clipmaxx (console uses 4095)
fbc_fg = Signal(8)
fbc_bg = Signal(8)
fbc_alu = Signal(32)
@@ -34,7 +34,7 @@ class CG6Accel(Module): # AutoCSR ?
fbc_arectx = Signal(COORD_BITS)
fbc_arecty = Signal(COORD_BITS)
# extra stuff for compatibility
# extra stuff for the Vex core
fbc_arectx_prev = Signal(COORD_BITS) # after fbc_arecty (600) - R/O
fbc_arecty_prev = Signal(COORD_BITS) # after fbc_arectx_prev (601) - R/O
fbc_r5_cmd = Signal(32) # to communicate with Vex (602)
@@ -44,8 +44,13 @@ class CG6Accel(Module): # AutoCSR ?
fbc_next_x1 = Signal(COORD_BITS)
fbc_next_y0 = Signal(COORD_BITS)
# do-some-work flags
fbc_do_draw = Signal()
fbc_do_blit = Signal()
# for GX global status register fbc_s
GX_FULL_BIT = 29
GX_INPROGRESS_BIT = 28
font_layout = [
("font", 32),
@@ -54,7 +59,13 @@ class CG6Accel(Module): # AutoCSR ?
("y0", COORD_BITS),
]
# depth is because the current 'font' is a bit slow, so we need to buffer a lot...
self.submodules.fbc_fifo_font = SyncFIFOBuffered(width=layout_len(font_layout),depth=1024)
self.submodules.fbc_fifo_font = SyncFIFOBuffered(width=layout_len(font_layout),depth=2048)
#fifo_overflow = Signal()
#self.comb += fifo_overflow.eq(self.fbc_fifo_font.we & ~self.fbc_fifo_font.writable)
#draw_blit_overflow = Signal()
fbc_fifo_font_in = Record(font_layout)
fbc_fifo_font_out = Record(font_layout)
self.comb += [
@@ -67,14 +78,16 @@ class CG6Accel(Module): # AutoCSR ?
NextValue(bus.ack, 0),
NextState("Idle"))
wishbone_fsm.act("Idle",
self.fbc_fifo_font.we.eq(0),
If(bus.cyc & bus.stb & bus.we & ~bus.ack, #write
Case(bus.adr[0:10], {
Case(bus.adr[0:11], {
"default": [ ],
# 0: fbc_config R/O
1: [ NextValue(fbc_mode, bus.dat_w) ],
2: [ NextValue(fbc_clip, bus.dat_w) ],
# 3: <nothing>, pad2
4: [ NextValue(fbc_s, bus.dat_w) ], # 0x010
4: [ # NextValue(fbc_s, bus.dat_w)
], # 0x010
# 5: fbc_draw R/O
# 6: fbc_blit R/O
7: [ self.fbc_fifo_font.we.eq(1),
@@ -147,23 +160,28 @@ class CG6Accel(Module): # AutoCSR ?
}),
NextValue(bus.ack, 1),
).Elif(bus.cyc & bus.stb & ~bus.we & ~bus.ack, #read
Case(bus.adr[0:10], {
Case(bus.adr[0:11], {
"default": [ NextValue(bus.dat_r, 0xDEADBEEF) ],
0: [ NextValue(bus.dat_r, fbc_config) ],
1: [ NextValue(bus.dat_r, fbc_mode) ],
2: [ NextValue(bus.dat_r, fbc_clip) ],
# 3: pad2
4: [ NextValue(bus.dat_r, fbc_s) ],
4: [ NextValue(bus.dat_r, fbc_s),
#NextValue(bus.dat_r, Replicate(fbc_s[GX_INPROGRESS_BIT] | fbc_do_draw | fbc_do_blit | self.fbc_fifo_font.readable, 32)) ],
],
# 5: fbc_draw R/O -> start a "draw" on R
5: [ NextValue(fbc_do_draw, 1),
NextValue(bus.dat_r, 0)
5: [ NextValue(fbc_do_draw, ~fbc_s[GX_INPROGRESS_BIT]), # ignore command while working
NextValue(bus.dat_r, 0),
#NextValue(draw_blit_overflow, draw_blit_overflow | fbc_do_draw | fbc_do_blit),
#NextValue(draw_blit_overflow, draw_blit_overflow | fbc_s[GX_INPROGRESS_BIT]),
],
# 6: fbc_blit R/O -> start a "blit" on R
6: [ NextValue(fbc_do_blit, 1),
NextValue(bus.dat_r, 0)
6: [ NextValue(fbc_do_blit, ~fbc_s[GX_INPROGRESS_BIT]), # ignore command while working
NextValue(bus.dat_r, 0),
#NextValue(draw_blit_overflow, draw_blit_overflow | fbc_do_draw | fbc_do_blit),
#NextValue(draw_blit_overflow, draw_blit_overflow | fbc_s[GX_INPROGRESS_BIT]),
],
# 7: fbc_font W/O -> start a "font" on W
# 7: [ NextValue(bus.dat_r, fbc_font) ],
# 8-31: pad3
32: [ NextValue(bus.dat_r, fbc_x[0]) ], # 0x080
33: [ NextValue(bus.dat_r, fbc_y[0]) ],
@@ -232,20 +250,31 @@ class CG6Accel(Module): # AutoCSR ?
FUN_FONT_NEXT_REQ_BIT = 29
FUN_FONT_NEXT_DONE_BIT = 28
# for GX global status register
#GX_FULL_BIT = 29
GX_INPROGRESS_BIT = 28
# to hold the Vex in reset
# could be sent to fbc_s[GX_INPROGRESS_BIT] ?
local_reset = Signal(reset = 1)
#timeout_rst = 0xFFFFFFF
#timeout = Signal(28, reset = timeout_rst)
pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
self.comb += pad_SBUS_DATA_OE_LED.eq(~local_reset);
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_r5_cmd[1]); # blitting
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_pm != 0); # planemasking
#pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
#self.comb += pad_SBUS_DATA_OE_LED.eq(~local_reset)
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_r5_cmd[1]) # blitting
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_pm != 0) # planemasking
#self.comb += pad_SBUS_DATA_OE_LED.eq(fifo_overflow)
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_s[GX_INPROGRESS_BIT])
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_s[GX_INPROGRESS_BIT])
#self.comb += pad_SBUS_DATA_OE_LED.eq(draw_blit_overflow)
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_do_draw & fbc_s[GX_INPROGRESS_BIT])
#self.comb += pad_SBUS_DATA_OE_LED.eq(fbc_do_blit & fbc_s[GX_INPROGRESS_BIT])
self.sync += fbc_s[GX_FULL_BIT].eq(fbc_do_draw | fbc_do_blit | self.fbc_fifo_font.readable)
self.sync += fbc_s[27].eq(fbc_do_draw)
self.sync += fbc_s[26].eq(fbc_do_blit)
self.sync += fbc_s[25].eq(self.fbc_fifo_font.readable)
self.sync += fbc_s[24].eq(~local_reset)
#self.sync += fbc_s[0].eq(draw_blit_overflow)
#fbc_s[GX_FULL_BIT].eq(fbc_do_draw | fbc_do_blit | self.fbc_fifo_font.readable)
self.sync += [
self.fbc_fifo_font.re.eq(0),
@@ -324,9 +353,9 @@ class CG6Accel(Module): # AutoCSR ?
i_iBusWishbone_DAT_MISO = ibus.dat_r,
o_iBusWishbone_DAT_MOSI = ibus.dat_w,
o_iBusWishbone_SEL = ibus.sel,
i_iBusWishbone_ERR = ibus.err,
o_iBusWishbone_CTI = ibus.cti,
o_iBusWishbone_BTE = ibus.bte,
#i_iBusWishbone_ERR = ibus.err,
#o_iBusWishbone_CTI = ibus.cti,
#o_iBusWishbone_BTE = ibus.bte,
o_dBusWishbone_CYC = dbus.cyc,
o_dBusWishbone_STB = dbus.stb,
i_dBusWishbone_ACK = dbus.ack,