add a byte-reversed access mode to accel registers, avoid the byte-reverse on the host

This commit is contained in:
Romain Dolbeau 2022-06-04 11:11:28 +02:00
parent fbcfe3152c
commit 9a50f36153
3 changed files with 74 additions and 48 deletions

View File

@ -67,6 +67,9 @@ static inline unsigned long brev(const unsigned long r) {
#define WAIT_FOR_HW(accel) \
while (accel->reg_status & brev(1<<WORK_IN_PROGRESS_BIT))
#define WAIT_FOR_HW_LE(accel_le) \
while (accel_le->reg_status & (1<<WORK_IN_PROGRESS_BIT))
#define uint8_t unsigned char
#define uint16_t unsigned short
#define uint32_t unsigned long
@ -378,7 +381,7 @@ struct qdstuff {
int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Pattern* pat, PixMapPtr dstpix, PixMapPtr srcpix, Rect *dstrect, Rect *srcrect) {
struct goblin_bt_regs* bt = (struct goblin_bt_regs*)(p_fb_base + GOBLIN_BT_OFFSET);
struct goblin_accel_regs* accel = (struct goblin_accel_regs*)(p_fb_base + GOBLIN_ACCEL_OFFSET);
struct goblin_accel_regs* accel_le = (struct goblin_accel_regs*)(p_fb_base + GOBLIN_ACCEL_OFFSET_LE);
struct qdstuff* qdstack = (struct qdstuff*)(stack - sizeof(struct qdstuff));
short height = qdstack->MINRECT.bottom - qdstack->MINRECT.top;
short dstshift = qdstack->DSTSHIFT;
@ -520,23 +523,23 @@ int hwblit(char* stack, char* p_fb_base, /* short dstshift, */ short mode, Patte
return 0;
#else
WAIT_FOR_HW(accel);
WAIT_FOR_HW_LE(accel_le);
accel->reg_width = brev(width);
accel->reg_height = brev(height);
accel->reg_bitblt_dst_x = brev(dstv.left << dstshift);
accel->reg_bitblt_dst_y = brev(dstv.top);
accel_le->reg_width = (width);
accel_le->reg_height = (height);
accel_le->reg_bitblt_dst_x = (dstv.left << dstshift);
accel_le->reg_bitblt_dst_y = (dstv.top);
if (mode == 0) {
accel->reg_bitblt_src_x = brev(srcv.left << dstshift);
accel->reg_bitblt_src_y = brev(srcv.top);
accel->reg_cmd = brev(1<<DO_BLIT_BIT);
accel_le->reg_bitblt_src_x = (srcv.left << dstshift);
accel_le->reg_bitblt_src_y = (srcv.top);
accel_le->reg_cmd = (1<<DO_BLIT_BIT);
} else if (mode == 8) {
accel->reg_fgcolor = qdstack->EXPAT[0];
accel->reg_cmd = brev(1<<DO_FILL_BIT);
accel_le->reg_fgcolor = (qdstack->EXPAT[0]);
accel_le->reg_cmd = (1<<DO_FILL_BIT);
}
WAIT_FOR_HW(accel);
WAIT_FOR_HW_LE(accel_le);
return 1;
#endif

View File

@ -3,8 +3,9 @@
#define GOBLIN_FB_BASE 0xFC000000 // FIXME !!!!
#define GOBLIN_BT_OFFSET 0x00900000
#define GOBLIN_ACCEL_OFFSET 0x00901000
#define GOBLIN_BT_OFFSET 0x00900000
#define GOBLIN_ACCEL_OFFSET 0x00901000
#define GOBLIN_ACCEL_OFFSET_LE 0x00901800
#define u_int32_t volatile unsigned long
@ -14,6 +15,7 @@
// cmd
#define DO_BLIT_BIT 0 // hardwired in goblin_accel.py
#define DO_FILL_BIT 1 // hardwired in goblin_accel.py
#define DO_TEST_BIT 3 // hardwired in goblin_accel.py
#define FUN_DONE_BIT 31
@ -30,19 +32,20 @@ struct goblin_bt_regs {
};
struct goblin_accel_regs {
u_int32_t reg_status;
u_int32_t reg_status; // 0
u_int32_t reg_cmd;
u_int32_t reg_r5_cmd;
u_int32_t resv0;
u_int32_t reg_width;
u_int32_t reg_width; // 4
u_int32_t reg_height;
u_int32_t reg_fgcolor;
u_int32_t resv2;
u_int32_t reg_bitblt_src_x;
u_int32_t reg_bitblt_src_x; // 8
u_int32_t reg_bitblt_src_y;
u_int32_t reg_bitblt_dst_x;
u_int32_t reg_bitblt_dst_y;
u_int32_t reg_chk_adr; // 12
u_int32_t reg_chk_val;
};

View File

@ -42,52 +42,72 @@ class GoblinAccel(Module): # AutoCSR ?
# global status register reg_status
WORK_IN_PROGRESS_BIT = 0
# replicate all registers in both endianess
# we want to avoid byte-reversal on either the host or the Vex
bus_dat_w_endian = Signal(32)
bus_dat_r_endian = Signal(32)
self.comb += [
If(bus.adr[9], # 9 on bus is 11 for host
bus_dat_w_endian[24:32].eq(bus.dat_w[ 0: 8]),
bus_dat_w_endian[16:24].eq(bus.dat_w[ 8:16]),
bus_dat_w_endian[ 8:16].eq(bus.dat_w[16:24]),
bus_dat_w_endian[ 0: 8].eq(bus.dat_w[24:32]),
bus.dat_r[24:32].eq(bus_dat_r_endian[ 0: 8]),
bus.dat_r[16:24].eq(bus_dat_r_endian[ 8:16]),
bus.dat_r[ 8:16].eq(bus_dat_r_endian[16:24]),
bus.dat_r[ 0: 8].eq(bus_dat_r_endian[24:32]),
).Else(
bus_dat_w_endian.eq(bus.dat_w),
bus.dat_r.eq(bus_dat_r_endian),
)
]
self.submodules.wishbone_fsm = wishbone_fsm = FSM(reset_state = "Reset")
wishbone_fsm.act("Reset",
NextValue(bus.ack, 0),
NextState("Idle"))
wishbone_fsm.act("Idle",
If(bus.cyc & bus.stb & bus.we & ~bus.ack, #write
Case(bus.adr[0:10], { #
Case(bus.adr[0:9], { # bit 9 is used for endianess, so not there
"default": [ ],
# 0: reg_status R/O
0: [ NextValue(reg_status, bus.dat_w) ], # debug, remove me
1: [ NextValue(reg_cmd, bus.dat_w),
NextValue(do_blit, bus.dat_w[DO_BLIT_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
NextValue(do_fill, bus.dat_w[DO_FILL_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
NextValue(do_test, bus.dat_w[DO_TEST_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
0: [ NextValue(reg_status, bus_dat_w_endian) ], # debug, remove me
1: [ NextValue(reg_cmd, bus_dat_w_endian),
NextValue(do_blit, bus_dat_w_endian[DO_BLIT_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
NextValue(do_fill, bus_dat_w_endian[DO_FILL_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
NextValue(do_test, bus_dat_w_endian[DO_TEST_BIT] & ~reg_status[WORK_IN_PROGRESS_BIT]),
],
2: [ NextValue(reg_r5_cmd, bus.dat_w) ],
2: [ NextValue(reg_r5_cmd, bus_dat_w_endian) ],
# 3
4: [ NextValue(reg_width, bus.dat_w) ],
5: [ NextValue(reg_height, bus.dat_w) ],
6: [ NextValue(reg_fgcolor, bus.dat_w) ],
4: [ NextValue(reg_width, bus_dat_w_endian) ],
5: [ NextValue(reg_height, bus_dat_w_endian) ],
6: [ NextValue(reg_fgcolor, bus_dat_w_endian) ],
# 7
8: [ NextValue(reg_bitblt_src_x, bus.dat_w) ],
9: [ NextValue(reg_bitblt_src_y, bus.dat_w) ],
10: [ NextValue(reg_bitblt_dst_x, bus.dat_w) ],
11: [ NextValue(reg_bitblt_dst_y, bus.dat_w) ],
12: [ NextValue(reg_chk_adr, bus.dat_w) ],
13: [ NextValue(reg_chk_val, bus.dat_w) ],
8: [ NextValue(reg_bitblt_src_x, bus_dat_w_endian) ],
9: [ NextValue(reg_bitblt_src_y, bus_dat_w_endian) ],
10: [ NextValue(reg_bitblt_dst_x, bus_dat_w_endian) ],
11: [ NextValue(reg_bitblt_dst_y, bus_dat_w_endian) ],
12: [ NextValue(reg_chk_adr, bus_dat_w_endian) ],
13: [ NextValue(reg_chk_val, bus_dat_w_endian) ],
}),
NextValue(bus.ack, 1),
).Elif(bus.cyc & bus.stb & ~bus.we & ~bus.ack, #read
Case(bus.adr[0:10], {
"default": [ NextValue(bus.dat_r, 0xDEADBEEF) ],
0: [ NextValue(bus.dat_r, reg_status) ],
1: [ NextValue(bus.dat_r, reg_cmd) ],
2: [ NextValue(bus.dat_r, reg_r5_cmd) ],
Case(bus.adr[0:9], { # bit 9 is used for endianess, so not there
"default": [ NextValue(bus_dat_r_endian, 0xDEADBEEF) ],
0: [ NextValue(bus_dat_r_endian, reg_status) ],
1: [ NextValue(bus_dat_r_endian, reg_cmd) ],
2: [ NextValue(bus_dat_r_endian, reg_r5_cmd) ],
# 3
4: [ NextValue(bus.dat_r, reg_width) ],
5: [ NextValue(bus.dat_r, reg_height) ],
6: [ NextValue(bus.dat_r, reg_fgcolor) ],
4: [ NextValue(bus_dat_r_endian, reg_width) ],
5: [ NextValue(bus_dat_r_endian, reg_height) ],
6: [ NextValue(bus_dat_r_endian, reg_fgcolor) ],
# 7
8: [ NextValue(bus.dat_r, reg_bitblt_src_x) ],
9: [ NextValue(bus.dat_r, reg_bitblt_src_y) ],
10: [ NextValue(bus.dat_r, reg_bitblt_dst_x) ],
11: [ NextValue(bus.dat_r, reg_bitblt_dst_y) ],
12: [ NextValue(bus.dat_r, reg_chk_adr) ],
13: [ NextValue(bus.dat_r, reg_chk_val) ],
8: [ NextValue(bus_dat_r_endian, reg_bitblt_src_x) ],
9: [ NextValue(bus_dat_r_endian, reg_bitblt_src_y) ],
10: [ NextValue(bus_dat_r_endian, reg_bitblt_dst_x) ],
11: [ NextValue(bus_dat_r_endian, reg_bitblt_dst_y) ],
12: [ NextValue(bus_dat_r_endian, reg_chk_adr) ],
13: [ NextValue(bus_dat_r_endian, reg_chk_val) ],
}),
NextValue(bus.ack, 1),
).Else(