From 12ea2bc18b3bdc3fd355911796324a20c6ebc365 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sat, 12 Mar 2022 10:39:50 +0100 Subject: [PATCH] goblin+jareth console HW scrolling, cleanup --- NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c | 66 +++++++++++-------- sbus-to-ztex-gateware-migen/jareth.py | 26 ++++---- .../jareth_code/jareth_code.rs | 28 ++++---- 3 files changed, 65 insertions(+), 55 deletions(-) diff --git a/NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c b/NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c index cb8d07f..890b017 100644 --- a/NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c +++ b/NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c @@ -133,8 +133,8 @@ static void goblin_reset(struct goblin_softc *); static int init_programs(struct goblin_softc *sc); static int power_on(struct goblin_softc *sc); static int power_off(struct goblin_softc *sc); -static int scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n); -static int fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n); +static int jareth_scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n); +static int jareth_fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n); static const uint32_t program_scroll128[12] = { 0x407c0012,0x00140080,0x201c0013,0x60fc7013,0x00170146,0xfe000148,0x000e10c6,0x010000c9,0x00004005,0xfb000809,0x0000000a,0x0000000a }; static const uint32_t program_fill128[12] = { 0x407c0012,0x00140080,0x607c1013,0x00170146,0xfe800148,0x000e10c6,0x010000c9,0x00004005,0xfb800809,0x0000000a,0x0000000a,0x0000000a }; @@ -361,13 +361,13 @@ goblinioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) case GOBLIN_SCROLL: { struct scrolltest *st = (struct scrolltest *)data; - scroll(sc, st->y0, st->y1, st->x0, st->w, st->n); + jareth_scroll(sc, st->y0, st->y1, st->x0, st->w, st->n); } break; case GOBLIN_FILL: { struct scrolltest *st = (struct scrolltest *)data; - fill(sc, st->y0, st->y1, st->x0, st->w, st->n); + jareth_fill(sc, st->y0, st->y1, st->x0, st->w, st->n); } break; @@ -726,32 +726,39 @@ goblin_reset(struct goblin_softc *sc) #define REG_BASE(reg) (base + (reg * 32)) #define SUBREG_ADDR(reg, off) (REG_BASE(reg) + (off)*4) -static int start_job(struct goblin_softc *sc); -static int wait_job(struct goblin_softc *sc, uint32_t param); +static int start_job(struct goblin_softc *sc, int verbose); +static int wait_job(struct goblin_softc *sc, uint32_t param, int verbose); -static int scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n) { +static int jareth_scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n) { const uint32_t base = 0; const int pidx = 0; int i; power_on(sc); - bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (0x8f800000 + y0 * sc->sc_stride + x0)); - bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (0x8f800000 + y1 * sc->sc_stride + x0)); + if (y0 > y1) { + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (0x8f800000 + y0 * sc->sc_stride + x0)); /* fixme: replace 0x8f800000 by a prom attributes */ + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (0x8f800000 + y1 * sc->sc_stride + x0)); + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,0), (sc->sc_stride)); + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,1), (sc->sc_stride)); + } else { + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (0x8f800000 + y0 * sc->sc_stride + x0 + (n-1) * sc->sc_stride)); /* fixme: replace 0x8f800000 by a prom attributes */ + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (0x8f800000 + y1 * sc->sc_stride + x0 + (n-1) * sc->sc_stride)); + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,0), (-sc->sc_stride)); + bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,1), (-sc->sc_stride)); + } bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,0), (w)); bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,0), (n)); for (i = 1 ; i < 8 ; i++) { bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,i), 0); bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,i), 0); } - bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,0), (sc->sc_stride)); - bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,1), (sc->sc_stride)); jareth_mpstart_write(sc, program_offset[pidx]); jareth_mplen_write(sc, program_len[pidx]); - (void)start_job(sc); + (void)start_job(sc, 0); delay(1); - (void)wait_job(sc, 2); + (void)wait_job(sc, 2, 0); power_off(sc); @@ -759,7 +766,7 @@ static int scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n) } -static int fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n) { +static int jareth_fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n) { const uint32_t base = 0; const int pidx = 1; int i; @@ -780,9 +787,9 @@ static int fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n) jareth_mpstart_write(sc, program_offset[pidx]); jareth_mplen_write(sc, program_len[pidx]); - (void)start_job(sc); + (void)start_job(sc, 0); delay(1); - (void)wait_job(sc, 1); + (void)wait_job(sc, 1, 0); power_off(sc); @@ -827,7 +834,7 @@ jareth_copyrows(void *cookie, int src, int dst, int n) /* int x3 = ri->ri_xorigin + ri->ri_emuwidth - 1; */ /* int y3 = ri->ri_yorigin + dst + n - 1; */ - scroll(sc, y0, y2, x0, ri->ri_emuwidth, n); + jareth_scroll(sc, y0, y2, x0, ri->ri_emuwidth, n); #if 0 if (y0 > y2) { @@ -852,10 +859,11 @@ jareth_copyrows(void *cookie, int src, int dst, int n) #endif } -static int start_job(struct goblin_softc *sc) { +static int start_job(struct goblin_softc *sc, int verbose) { uint32_t status = jareth_status_read(sc); if (status & (1<sc_dev, "START - Jareth status: 0x%08x, still running?\n", status); + if (verbose) + aprint_error_dev(sc->sc_dev, "START - Jareth status: 0x%08x, still running?\n", status); return ENXIO; } jareth_control_write(sc, 1); @@ -864,10 +872,10 @@ static int start_job(struct goblin_softc *sc) { return 0; } -static int wait_job(struct goblin_softc *sc, uint32_t param) { +static int wait_job(struct goblin_softc *sc, uint32_t param, int verbose) { uint32_t status = jareth_status_read(sc); int count = 0; - int max_count = 2000; + int max_count = 3000; int del = 1; const int max_del = 64; static int max_del_seen = 1; @@ -883,23 +891,27 @@ static int wait_job(struct goblin_softc *sc, uint32_t param) { } if (del > max_del_seen) { max_del_seen = del; - aprint_normal_dev(sc->sc_dev, "WAIT - new max delay %d after %d count (param was %u)\n", max_del_seen, count, param); + if (verbose) + aprint_normal_dev(sc->sc_dev, "WAIT - new max delay %d after %d count (param was %u)\n", max_del_seen, count, param); } if (count > max_cnt_seen) { max_cnt_seen = count; - aprint_normal_dev(sc->sc_dev, "WAIT - new max count %d with %d delay (param was %u)\n", max_cnt_seen, del, param); - + if (verbose) + aprint_normal_dev(sc->sc_dev, "WAIT - new max count %d with %d delay (param was %u)\n", max_cnt_seen, del, param); } //jareth_control_write(sc, 0); if (status & (1<sc_dev, "WAIT - Jareth status: 0x%08x (pc 0x%08x), did not finish in time? [inst: 0x%08x ls_status: 0x%08x]\n", status, (status>>1)&0x03ff, jareth_instruction_read(sc), jareth_ls_status_read(sc)); + if (verbose) + aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x (pc 0x%08x), did not finish in time? [inst: 0x%08x ls_status: 0x%08x]\n", status, (status>>1)&0x03ff, jareth_instruction_read(sc), jareth_ls_status_read(sc)); return ENXIO; } else if (status & (1<sc_dev, "WAIT - Jareth status: 0x%08x, sigill [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc)); + if (verbose) + aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x, sigill [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc)); return ENXIO; } else if (status & (1<sc_dev, "WAIT - Jareth status: 0x%08x, aborted [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc)); + if (verbose) + aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x, aborted [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc)); return ENXIO; } else { //aprint_normal_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x [%d] ls_status: 0x%08x\n", status, count, jareth_ls_status_read(sc)); diff --git a/sbus-to-ztex-gateware-migen/jareth.py b/sbus-to-ztex-gateware-migen/jareth.py index 96d269f..119338f 100644 --- a/sbus-to-ztex-gateware-migen/jareth.py +++ b/sbus-to-ztex-gateware-migen/jareth.py @@ -10,19 +10,17 @@ prime_string = "$2^{{255}}-19$" # 2\ :sup:`255`-19 field_latex = "$\mathbf{{F}}_{{{{2^{{255}}}}-19}}$" opcode_bits = 5 # number of bits used to encode the opcode field -opcodes = { # mnemonic : [bit coding, docstring] ; if bit 6 (0x20) is set, shift a +opcodes = { # mnemonic : [bit coding, docstring] ; if bit 6 (0x20) is set, shift a/b/q (star) "UDF" : [-1, "Placeholder for undefined opcodes"], "PSA" : [0, "Wd $\gets$ Ra // pass A"], - "PSB" : [1, "Wd $\gets$ Rb // pass B"], + "PSB" : [1, "Wd $\gets$ Rb // pass B"], # for star version mostly # 2 MSK "XOR" : [3, "Wd $\gets$ Ra ^ Rb // bitwise XOR"], "NOT" : [4, "Wd $\gets$ ~Ra // binary invert"], - "ADD32" : [5, "Wd[x..x+32] $\gets$ Ra[x..x+32] + Rb[x..x+32] // vector 32-bit binary add"], - "SUB32" : [6, "Wd[x..x+32] $\gets$ Ra[x..x+32] - Rb[x..x+32] // vector 32-bit binary add"], - #"ADD" : [5, "Wd $\gets$ Ra + Rb // 256-bit binary add"], - #"SUB" : [6, "Wd $\gets$ Ra - Rb // 256-bit binary subtraction"], + "ADD32V" : [5, "Wd[x..x+32] $\gets$ Ra[x..x+32] + Rb[x..x+32] // vector 32-bit binary add"], + "SUB32V" : [6, "Wd[x..x+32] $\gets$ Ra[x..x+32] - Rb[x..x+32] // vector 32-bit binary add"], "AND" : [7, "Wd $\gets$ Ra & Rb // bitwise AND"], # replace MUL - "BRNZ" : [8, "If Ra != 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if non-zero"], # replace TRD + "BRNZ32" : [8, "If Ra[0:32] != 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if non-zero"], # replace TRD "BRZ" : [9, "If Ra == 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if zero"], "FIN" : [10, "halt execution and assert interrupt to host CPU that microcode execution is done"], "SHL" : [11, "Wd $\gets$ Ra << 1 // shift Ra left by one and store in Wd"], @@ -331,7 +329,7 @@ passthrough. class ExecAddSub(ExecUnit, AutoDoc): def __init__(self, width=256): - ExecUnit.__init__(self, width, ["ADD32", "SUB32"]) + ExecUnit.__init__(self, width, ["ADD32V", "SUB32V"]) self.notes = ModuleDoc(title="Add/Sub ExecUnit Subclass", body=f""" """) @@ -340,9 +338,9 @@ class ExecAddSub(ExecUnit, AutoDoc): self.instruction_out.eq(self.instruction_in), ] self.comb += [ - If(self.instruction.opcode == opcodes["ADD32"][0], + If(self.instruction.opcode == opcodes["ADD32V"][0], [ self.q[x*32:(x+1)*32].eq(self.a[x*32:(x+1)*32] + self.b[x*32:(x+1)*32]) for x in range(0, width//32) ], - ).Elif(self.instruction.opcode == opcodes["SUB32"][0], + ).Elif(self.instruction.opcode == opcodes["SUB32V"][0], [ self.q[x*32:(x+1)*32].eq(self.a[x*32:(x+1)*32] - self.b[x*32:(x+1)*32]) for x in range(0, width//32) ], ), ] @@ -1057,8 +1055,8 @@ Here are the currently implemented opcodes for The Engine: seq.act("EXEC", # not a great name. This is actually where the register file fetches its contents. If(instruction.opcode == opcodes["BRZ"][0], NextState("DO_BRZ"), - ).Elif(instruction.opcode == opcodes["BRNZ"][0], - NextState("DO_BRNZ"), + ).Elif(instruction.opcode == opcodes["BRNZ32"][0], + NextState("DO_BRNZ32"), ).Elif(instruction.opcode == opcodes["FIN"][0], NextState("IDLE"), NextValue(running, 0), @@ -1107,8 +1105,8 @@ Here are the currently implemented opcodes for The Engine: ) ), ) - seq.act("DO_BRNZ", - If(ra_dat != 0, + seq.act("DO_BRNZ32", + If(ra_dat[0:32] != 0, If( (sext_immediate + mpc + 1 < mpc_stop) & (sext_immediate + mpc + 1 >= self.mpstart.fields.mpstart), # validate new PC is in range NextState("FETCH"), NextValue(mpc, sext_immediate + mpc + 1), diff --git a/sbus-to-ztex-gateware-migen/jareth_code/jareth_code.rs b/sbus-to-ztex-gateware-migen/jareth_code/jareth_code.rs index b0bcfab..4b4badf 100644 --- a/sbus-to-ztex-gateware-migen/jareth_code/jareth_code.rs +++ b/sbus-to-ztex-gateware-migen/jareth_code/jareth_code.rs @@ -25,7 +25,7 @@ fn main() -> std::io::Result<()> { // slow setmq %31, %1, #16 and %5, %2, #15 - sub32 %6, %2, %5 + sub32v %6, %2, %5 brz done, %6 loop: psa %18, %16 @@ -33,7 +33,7 @@ fn main() -> std::io::Result<()> { psa* %17, %16 psa %20, %17 store128inc %31, %2, %17 - sub32 %6, %6, #16 + sub32v %6, %6, #16 brz last, %6 loadh128inc %16, %0, %16 loadh128inc %17, %1, %17 @@ -72,16 +72,16 @@ fn main() -> std::io::Result<()> { // store to DST w/ post-increment store256inc %31, %1, %7 // sub 32 (#5 is 32...) from live X count - sub32 %5, %5, #5 + sub32v %5, %5, #5 // if X count is not 0, keep looping - brnz loop_x, %5 + brnz32 loop_x, %5 // decrement Y count - sub32 %3, %3, #1 + sub32v %3, %3, #1 // if 0, finished brz done, %3 // add strides to initial addresses - add32 %0, %0, %4 + add32v %0, %0, %4 // loop to do next line brz loop_y, #0 done: @@ -112,16 +112,16 @@ fn main() -> std::io::Result<()> { // store to DST w/ post-increment store128inc %31, %1, %7 // sub 16 (#16 is 16) from live X count - sub32 %5, %5, #16 + sub32v %5, %5, #16 // if X count is not 0, keep looping - brnz loop_x, %5 + brnz32 loop_x, %5 // decrement Y count - sub32 %3, %3, #1 + sub32v %3, %3, #1 // if 0, finished brz done, %3 // add strides to initial addresses - add32 %0, %0, %4 + add32v %0, %0, %4 // loop to do next line brz loop_y, #0 done: @@ -151,16 +151,16 @@ fn main() -> std::io::Result<()> { // store to DST w/ post-increment store128inc %31, %0, %1 // sub 16 (#16 is 16) from live X count - sub32 %5, %5, #16 + sub32v %5, %5, #16 // if X count is not 0, keep looping - brnz loop_x, %5 + brnz32 loop_x, %5 // decrement Y count - sub32 %3, %3, #1 + sub32v %3, %3, #1 // if 0, finished brz done, %3 // add strides to initial addresses - add32 %0, %0, %4 + add32v %0, %0, %4 // loop to do next line brz loop_y, #0 done: