1
0
mirror of synced 2026-03-05 10:24:10 +00:00

goblin+jareth console HW scrolling, cleanup

This commit is contained in:
Romain Dolbeau
2022-03-12 10:39:50 +01:00
parent a87e7eaa6b
commit 12ea2bc18b
3 changed files with 65 additions and 55 deletions

View File

@@ -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<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
aprint_error_dev(sc->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<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
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));
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<<CSR_JARETH_STATUS_SIGILL_OFFSET)) {
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));
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<<CSR_JARETH_STATUS_ABORT_OFFSET)) {
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));
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));

View File

@@ -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),

View File

@@ -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: