1
0
mirror of synced 2026-01-11 23:42:59 +00:00

Replace engine-based Jareth by VexRiscv-based 'Jareth' based on NuBusFPGA's goblin accel; also shorten some Forth name to avoid namespace issues.

This commit is contained in:
Romain Dolbeau 2022-08-15 10:28:39 +02:00
parent cd03241fc6
commit 6767363415
13 changed files with 187 additions and 599 deletions

View File

@ -111,32 +111,6 @@ struct wsscreen_descr goblin_defaultscreen = {
NULL /* modecookie */
};
struct scrolltest {
int y0;
int y1;
int x0;
int w;
int n;
int pm;
int rop;
};
/* debug only, to remove */
#define GOBLIN_SCROLL _IOW('X', 0, struct scrolltest)
#define GOBLIN_FILL _IOW('X', 1, struct scrolltest)
#define GOBLIN_FILLROP _IOW('X', 2, struct scrolltest)
#define GOBLIN_COPY _IOW('X', 3, struct scrolltest)
#define GOBLIN_COPYREV _IOW('X', 4, struct scrolltest)
#define JARETH_FN_NUM_FILL 0
#define JARETH_FN_NUM_FILLROP 1
#define JARETH_FN_NUM_COPY 2
#define JARETH_FN_NUM_COPYREV 3
struct jareth_fn {
int off;
int len;
};
#define JARETH_FN _IOWR('j', 0, struct jareth_fn)
static int goblin_ioctl(void *, void *, u_long, void *, int, struct lwp *);
static paddr_t goblin_mmap(void *, void *, off_t, int);
@ -147,34 +121,13 @@ static int goblin_getcmap(struct goblin_softc *, struct wsdisplay_cmap *);
static void goblin_init(struct goblin_softc *);
static void goblin_reset(struct goblin_softc *);
/* Jareth stuff */
enum jareth_verbosity {
jareth_silent,
jareth_silent = 0,
jareth_verbose
};
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 jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n);
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n);
static int jareth_fillrop(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n, int pm, int rop);
static int jareth_copy(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop);
static int jareth_copyrev(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop);
static const uint32_t program_fill[35] = { 0x10000089,0x0f8000c9,0x01bc0014,0x0780000d,0x013c2014,0x001400c0,0x00180000,0x403c0192,0xc03c1033,0x00184185,0x00161146,0xfd800148,0x00226007,0x00208946,0x0020220f,0x00008005,0x00088086,0x01048050,0x07000089,0x001a6087,0x013c6814,0x403c0012,0x00146086,0x01800149,0xe03c1013,0x00165146,0xfe800148,0x0080018e,0xc03c1033,0x000e10c6,0x010000c9,0x00004005,0xfa000809,0x0000000a,0x0000000a };
static const uint32_t program_fillrop[42] = { 0x13800089,0x130000c9,0x01bc0014,0x003c014c,0x0880000d,0x013c2014,0x002000c0,0x00180000,0x403c0192,0x801c0013,0x001c11e2,0xc03c7013,0x00184185,0x00221206,0xfc800208,0x00226007,0x00208946,0x0020220f,0x00008005,0x00088086,0x01048050,0x09000089,0x001a6087,0x013c6814,0x403c0012,0x00206086,0x02800209,0x801c0013,0x001c11c2,0xe03c7013,0x00225206,0xfd800208,0x0180018e,0x801c0013,0x001c11e2,0xc03c7013,0x000e10c6,0x010000c9,0x00004005,0xf8000809,0x0000000a,0x0000000a };
static const uint32_t program_copy[43] = { 0x14000089,0x138000c9,0x01bc0014,0x013c2014,0x00bf0054,0x0900000d,0x002400c0,0x00180000,0x403c0192,0x80a00013,0x403c8033,0x00184185,0x00261246,0xfd000248,0x0026f007,0x00249c06,0x0024224f,0x00240250,0x00009005,0x00089086,0x0a000089,0x013f0814,0x00049045,0x00bf0054,0x001af087,0x403c0012,0x00246086,0xa0a00013,0x02000249,0x603c8033,0x00270246,0x20a08015,0xfe000248,0x0180018d,0x013c6814,0x403c8033,0x013f0814,0x000e10c6,0x010000c9,0x00004005,0xf8000809,0x0000000a,0x0000000a };
static const uint32_t program_copyrev[61] = { 0x1d000089,0x1c8000c9,0x01bc0014,0x00280000,0x002c0040,0x00340080,0x003af007,0x03800389,0x0038ec06,0x0038238f,0x00380390,0x0028e285,0x002ce2c5,0x0034e086,0x11000349,0x013f0814,0x00bf02d4,0x001af347,0x003c6346,0x003c03d0,0x0028f285,0x002cf2c5,0x02000188,0x003c0c00,0x003c03d0,0x0028f286,0x002cf2c6,0x002f02c5,0x003c0c00,0x00bc03d0,0x0028f285,0x003000c0,0x403c0292,0x00246346,0x10a00013,0x0200018d,0x013c6814,0x10a08016,0x503c8033,0x013f0814,0x02000249,0x10a08016,0x503c8033,0x00270246,0xfd800248,0x00321306,0x01000309,0x00284285,0xf7800809,0x04800389,0x013c2014,0x00bf0054,0x002400c0,0x403c0012,0x80a00013,0x403c8033,0x00004005,0x00261246,0xfd000248,0x0000000a,0x0000000a };
static const uint32_t program_scroll128[12] = { 0x407c0012,0x00140080,0x201c0013,0x60fc7013,0x00170146,0xfe000148,0x000e10c6,0x010000c9,
0x00004005,0xfb000809,0x0000000a,0x0000000a };
static const uint32_t* programs[6] = { program_fill, program_fillrop, program_copy, program_copyrev, program_scroll128, NULL };
static const uint32_t program_len[6] = { 35, 42, 43, 61, 12, 0 };
static uint32_t program_offset[6];
static void goblin_set_depth(struct goblin_softc *, int);
@ -212,17 +165,9 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
unsigned long defattr;
volatile struct goblin_fbcontrol *fbc = sc->sc_fbc;
/* boot Jareth if present */
/* 'boot' Jareth if present */
if (sc->sc_has_jareth) {
/* first we need to turn the engine power on ... */
power_on(sc);
if (init_programs(sc)) {
if (init_programs(sc)) {
aprint_normal_dev(sc->sc_dev, "INIT - FAILED\n");
sc->sc_has_jareth = 0;
}
}
power_off(sc);
/* */
}
fb->fb_driver = &goblinfbdriver;
@ -412,58 +357,6 @@ goblinioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
}
break;
case GOBLIN_SCROLL: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_scroll(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n);
}
break;
case GOBLIN_FILL: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_fill(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n);
}
break;
case GOBLIN_FILLROP: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_fillrop(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, st->pm, st->rop);
}
break;
case GOBLIN_COPY: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_copy(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, /* x1 */ st->pm, st->rop);
}
break;
case GOBLIN_COPYREV: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_copyrev(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, /* x1 */ st->pm, st->rop);
}
break;
case JARETH_FN: {
struct jareth_fn *fn = (struct jareth_fn *)data;
int pidx = -1;
if (!sc->sc_has_jareth) {
return ENXIO;
}
switch (fn->off) {
case JARETH_FN_NUM_FILL: pidx = 0; break;
case JARETH_FN_NUM_FILLROP: pidx = 1; break;
case JARETH_FN_NUM_COPY: pidx = 2; break;
case JARETH_FN_NUM_COPYREV: pidx = 3; break;
}
if (pidx != -1) {
fn->off = program_offset[pidx];
fn->len = program_len[pidx];
} else {
fn->off = -1;
fn->len = -1;
}
}
break;
default:
return (ENOTTY);
}
@ -537,15 +430,11 @@ goblinloadcmap(struct goblin_softc *sc, int start, int ncolors)
*/
#define GOBLIN_USER_FBC 0x70000000
#define JARETH_USER_REG 0x70001000
#define JARETH_USER_MICROCODE 0x70002000
#define JARETH_USER_REGFILE 0x70003000
#define GOBLIN_USER_RAM 0x70016000
typedef enum {
goblin_bank_fbc,
goblin_bank_fb,
jareth_bank_reg,
jareth_bank_microcode,
jareth_bank_regfile
} gobo_reg_bank;
struct mmo {
u_long mo_uaddr; /* user (virtual) address */
@ -563,8 +452,6 @@ goblinmmap(dev_t dev, off_t off, int prot)
{ GOBLIN_USER_RAM, 0, goblin_bank_fb },
{ GOBLIN_USER_FBC, 1, goblin_bank_fbc },
{ JARETH_USER_REG, 1, jareth_bank_reg },
{ JARETH_USER_MICROCODE, 4096, jareth_bank_microcode },
{ JARETH_USER_REGFILE, 1024, jareth_bank_regfile },
};
/* device_printf(sc->sc_dev, "requiesting %llx with %d\n", off, prot); */
@ -607,14 +494,6 @@ goblinmmap(dev_t dev, off_t off, int prot)
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_reg_paddr, u,
prot, flags));
case jareth_bank_microcode:
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_microcode_paddr, u,
prot, flags));
case jareth_bank_regfile:
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_regfile_paddr, u,
prot, flags));
}
}
}
@ -791,9 +670,15 @@ goblin_init_screen(void *cookie, struct vcons_screen *scr,
ri->ri_hw = scr;
if (sc->sc_has_jareth) {
device_printf(sc->sc_dev, "Jareth present\n");
ri->ri_ops.copyrows = jareth_copyrows;
ri->ri_ops.eraserows = jareth_eraserows;
device_printf(sc->sc_dev, "Jareth enabled\n");
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_PTR, 0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_PTR, 0);
device_printf(sc->sc_dev, "Jareth console acceleration enabled\n");
/* uint32_t status = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_STATUS); */
/* uint32_t resv0 = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_RESV0); */
/* device_printf(sc->sc_dev, "Jareth sanity check: 0x%08x, 0x%08x\n", status, resv0); */
}
}
@ -832,210 +717,6 @@ goblin_reset(struct goblin_softc *sc)
goblin_set_depth(sc, 8);
}
#define CONFIG_CSR_DATA_WIDTH 32
#define sbusfpga_jareth_softc goblin_softc
#include "dev/sbus/sbusfpga_csr_jareth.h"
#undef sbusfpga_jareth_softc
#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, enum jareth_verbosity verbose);
static int wait_job(struct goblin_softc *sc, uint32_t param, enum jareth_verbosity verbose);
static int jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n) {
const uint32_t base = 0;
const int pidx = 4;
/* int i; */
power_on(sc);
if (y0 > y1) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + 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), (sc->sc_internal_adr + y0 * sc->sc_stride + x0 + (n-1) * sc->sc_stride));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + 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); */
/* } */
jareth_mpstart_write(sc, program_offset[pidx]);
jareth_mplen_write(sc, program_len[pidx]);
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 2, verbose);
power_off(sc);
return 0;
}
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n) {
const uint32_t base = 0;
const int pidx = 0; // fill
int i;
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
for (i = 0 ; i < 8 ; i++) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,i), pat);
}
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));
jareth_mpstart_write(sc, program_offset[pidx]);
jareth_mplen_write(sc, program_len[pidx]);
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_fillrop(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n, int pm, int rop) {
const uint32_t base = 0;
const int pidx = 1; // fillrop
int i;
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
for (i = 0 ; i < 8 ; i++) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,i), pat);
}
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(5,0), (pm));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(5,1), (rop));
jareth_mpstart_write(sc, program_offset[pidx]);
jareth_mplen_write(sc, program_len[pidx]);
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_copy(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop) {
const uint32_t base = 0;
const int pidx = 2; // copy
/* int i; */
/* device_printf(sc->sc_dev, "%s : %d %d %d %d %d %d\n", __PRETTY_FUNCTION__, y0, y1, x0, w, n, x1); */
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
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]);
#if 0
{
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_copyrev(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop) {
const uint32_t base = 0;
const int pidx = 3; // copyrev
/* int i; */
/* device_printf(sc->sc_dev, "%s : %d %d %d %d %d %d\n", __PRETTY_FUNCTION__, y0, y1, x0, w, n, x1); */
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
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]);
#if 0
{
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static void
jareth_copyrows(void *cookie, int src, int dst, int n)
{
@ -1105,158 +786,65 @@ jareth_eraserows(void *cookie, int row, int n, long int attr)
}
}
static int start_job(struct goblin_softc *sc, enum jareth_verbosity verbose) {
uint32_t status = jareth_status_read(sc);
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
if (verbose == jareth_verbose)
aprint_error_dev(sc->sc_dev, "START - Jareth status: 0x%08x, still running?\n", status);
return ENXIO;
static uint32_t wait_for_jareth(struct goblin_softc *sc) {
uint32_t status;
int cnt = 0;
while ((((status = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_STATUS)) & (1<<WORK_IN_PROGRESS_BIT)) != 0) && (cnt < 500)) {
cnt += 2;
delay(cnt);
}
jareth_control_write(sc, 1);
//aprint_normal_dev(sc->sc_dev, "START - Jareth status: 0x%08x\n", jareth_status_read(sc));
return status;
}
static int jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n) {
uint32_t status;
status = wait_for_jareth(sc);
if ((status & (1<<WORK_IN_PROGRESS_BIT)) == 0) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_WIDTH, w);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_HEIGHT, n);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_Y, y0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_Y, y1);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_CMD, (1<<DO_BLIT_BIT));
status = wait_for_jareth(sc);
}
/* if ((status & (1<<WORK_IN_PROGRESS_BIT)) != 0) { */
/* device_printf(sc->sc_dev, "Jareth seems busy/locked (0x%08x)\n", status); */
/* } */
return 0;
}
static int wait_job(struct goblin_softc *sc, uint32_t param, enum jareth_verbosity verbose) {
uint32_t status = jareth_status_read(sc);
int count = 0;
int max_count = 5000;
int del = 1;
const int max_del = 64;
static int max_del_seen = 1;
static int max_cnt_seen = 0;
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n) {
uint32_t status;
while ((status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) && (count < max_count)) {
//uint32_t ls_status = jareth_ls_status_read(sc);
//aprint_normal_dev(sc->sc_dev, "WAIT - ongoing, Jareth status: 0x%08x [%d] ls_status: 0x%08x\n", status, count, ls_status);
count ++;
delay(del * param);
del = del < max_del ? 2*del : del;
status = jareth_status_read(sc);
}
if (del > max_del_seen) {
max_del_seen = del;
if (verbose == jareth_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;
if (verbose == jareth_verbose)
aprint_normal_dev(sc->sc_dev, "WAIT - new max count %d with %d delay (param was %u)\n", max_cnt_seen, del, param);
}
#if 0
{
const uint32_t base = 0;
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
status = wait_for_jareth(sc);
//jareth_control_write(sc, 0);
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
if (verbose == jareth_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)) {
if (verbose == jareth_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)) {
if (verbose == jareth_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));
if ((status & (1<<WORK_IN_PROGRESS_BIT)) == 0) {
//bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_WIDTH, w);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_HEIGHT, n);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_Y, y0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_FGCOLOR, pat);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_CMD, (1<<DO_FILL_BIT));
status = wait_for_jareth(sc);
}
#if 1
device_printf(sc->sc_dev, "last run took %d cycle (eng_clk)\n", jareth_cyc_counter_read(sc));
#endif
/* if ((status & (1<<WORK_IN_PROGRESS_BIT)) != 0) { */
/* device_printf(sc->sc_dev, "Jareth seems busy/locked (0x%08x)\n", status); */
/* } */
return 0;
}
static int init_programs(struct goblin_softc *sc) {
/* the microcode is a the beginning */
int err = 0;
uint32_t i, j;
uint32_t offset = 0;
for (j = 0 ; programs[j] != NULL; j ++) {
program_offset[j] = offset;
for (i = 0 ; i < program_len[j] ; i++) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_microcode, ((offset+i)*4), programs[j][i]);
if ((i%16)==15)
delay(1);
}
offset += program_len[j];
}
jareth_window_write(sc, 0); /* could use window_window to access fields, but it creates a RMW cycle for nothing */
jareth_mpstart_write(sc, 0); /* EC25519 */
jareth_mplen_write(sc, program_len[0]); /* EC25519 */
aprint_normal_dev(sc->sc_dev, "INIT - Jareth status: 0x%08x\n", jareth_status_read(sc));
#if 1
/* double check */
u_int32_t x;
int count = 0;
for (i = 0 ; i < program_len[0] && count < 10; i++) {
x = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_microcode, (i*4));
if (x != programs[0][i]) {
aprint_error_dev(sc->sc_dev, "INIT - Jareth program failure: [%d] 0x%08x <> 0x%08x\n", i, x, programs[0][i]);
err = 1;
count ++;
}
if ((i%8)==7)
delay(1);
}
if ((x = jareth_window_read(sc)) != 0) {
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: window = 0x%08x\n", x);
err = 1;
}
if ((x = jareth_mpstart_read(sc)) != 0) {
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: mpstart = 0x%08x\n", x);
err = 1;
}
if ((x = jareth_mplen_read(sc)) != program_len[0]) {
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: mplen = 0x%08x\n", x);
err = 1;
}
const int test_reg_num = 73;
const uint32_t test_reg_value = 0x0C0FFEE0;
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile, 4*test_reg_num, test_reg_value);
delay(1);
if ((x = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile, 4*test_reg_num)) != test_reg_value) {
aprint_error_dev(sc->sc_dev, "INIT - Jareth register file failure: 0x%08x != 0x%08x\n", x, test_reg_value);
err = 1;
}
#endif
return err;
}
static int power_on(struct goblin_softc *sc) {
int err = 0;
if ((jareth_power_read(sc) & 1) == 0) {
jareth_power_write(sc, 1);
delay(1);
}
return err;
}
static int power_off(struct goblin_softc *sc) {
int err = 0;
jareth_power_write(sc, 0);
return err;
}

View File

@ -160,7 +160,7 @@ goblinattach_sbus(device_t parent, device_t self, void *args)
aprint_normal_dev(self, "Goblin framebuffer internally @ %p\n", (void*)sc->sc_internal_adr);
if (sc->sc_has_jareth) {
if (sa->sa_nreg < 5) {
if (sa->sa_nreg < 3) {
aprint_error(": Not enough registers spaces for Jareth\n");
sc->sc_has_jareth = 0;
} else {
@ -176,35 +176,10 @@ goblinattach_sbus(device_t parent, device_t self, void *args)
} else {
sc->sc_jareth_reg_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
aprint_normal_dev(self, "Jareth registers @ %p\n", (void*)sc->sc_bhregs_jareth);
/* map microcode */
if (sbus_bus_map(sc->sc_bustag,
sa->sa_reg[3].oa_space /* sa_slot */,
sa->sa_reg[3].oa_base /* sa_offset */,
sa->sa_reg[3].oa_size /* sa_size */,
BUS_SPACE_MAP_LINEAR,
&sc->sc_bhregs_microcode) != 0) {
aprint_error(": cannot map Jareth microcode\n");
sc->sc_has_jareth = 0;
} else {
sc->sc_jareth_microcode_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[3].oa_space, sa->sa_reg[3].oa_base);
aprint_normal_dev(self, "Jareth microcode @ %p\n", (void*)sc->sc_bhregs_microcode);
/* map register file */
if (sbus_bus_map(sc->sc_bustag,
sa->sa_reg[4].oa_space /* sa_slot */,
sa->sa_reg[4].oa_base /* sa_offset */,
sa->sa_reg[4].oa_size /* sa_size */,
BUS_SPACE_MAP_LINEAR,
&sc->sc_bhregs_regfile) != 0) {
aprint_error(": cannot map Jareth regfile\n");
sc->sc_has_jareth = 0;
} else {
sc->sc_jareth_regfile_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[4].oa_space, sa->sa_reg[4].oa_base);
aprint_normal_dev(self, "Jareth regfile @ %p\n", (void*)sc->sc_bhregs_regfile);
}
}
}
}
} else {
}
if (!sc->sc_has_jareth) {
aprint_normal_dev(self, "Jareth not available\n");
}

View File

@ -59,3 +59,30 @@
#define GOBOFB_VIDEOCTRL_ON 0x1
#define GOBOFB_INTR_CLEAR_CLEAR 0x0
#define GOBOFB_ACCEL_REG_STATUS 0x00
#define GOBOFB_ACCEL_REG_CMD 0x04
#define GOBOFB_ACCEL_REG_R5_CMD 0x08
#define GOBOFB_ACCEL_REG_RESV0 0x0C
#define GOBOFB_ACCEL_REG_WIDTH 0x10
#define GOBOFB_ACCEL_REG_HEIGHT 0x14
#define GOBOFB_ACCEL_REG_FGCOLOR 0x18
#define GOBOFB_ACCEL_REG_RESV2 0x1C
#define GOBOFB_ACCEL_REG_SRC_X 0x20
#define GOBOFB_ACCEL_REG_SRC_Y 0x24
#define GOBOFB_ACCEL_REG_DST_X 0x28
#define GOBOFB_ACCEL_REG_DST_Y 0x2C
#define GOBOFB_ACCEL_REG_SRC_STRIDE 0x30
#define GOBOFB_ACCEL_REG_DST_STRIDE 0x34
#define GOBOFB_ACCEL_REG_SRC_PTR 0x38
#define GOBOFB_ACCEL_REG_DST_PTR 0x3c
// status
#define WORK_IN_PROGRESS_BIT 0
// cmd
#define DO_BLIT_BIT 0 // hardwired in goblin_accel.py
#define DO_FILL_BIT 1 // hardwired in goblin_accel.py
#define DO_PATT_BIT 2 // hardwired in goblin_accel.py
#define DO_TEST_BIT 3 // hardwired in goblin_accel.py

View File

@ -58,16 +58,12 @@ struct goblin_softc {
bus_addr_t sc_reg_fbc_paddr; /* phys address for device mmap() */
bus_addr_t sc_fb_paddr; /* phys address for device mmap() */
bus_addr_t sc_jareth_reg_paddr; /* phys address for device mmap() */
bus_addr_t sc_jareth_microcode_paddr; /* phys address for device mmap() */
bus_addr_t sc_jareth_regfile_paddr; /* phys address for device mmap() */
uint32_t sc_size; /* full memory size */
int sc_opens; /* number of open() to track 8/24 bits */
int sc_has_jareth; /* whether we have a Jareth vector engine available */
uint32_t sc_internal_adr;
bus_space_handle_t sc_bhregs_jareth; /* bus handle */
bus_space_handle_t sc_bhregs_microcode; /* bus handle */
bus_space_handle_t sc_bhregs_regfile; /* bus handle */
volatile struct goblin_fbcontrol *sc_fbc; /* control registers */
#if NWSDISPLAY > 0

View File

@ -17,7 +17,7 @@
h# SBUSFPGA_CG3_WIDTH h# 8 /
;
sbusfpga_regionaddr_bw2_bt constant bw2-off-dac
sfra_bw2_bt constant bw2-off-dac
h# 20 constant /bw2-off-dac
h# 800000 constant bw2-off-fb

View File

@ -16,7 +16,7 @@
h# SBUSFPGA_CG3_WIDTH
;
sbusfpga_regionaddr_cg3_bt constant cg3-off-dac
sfra_cg3_bt constant cg3-off-dac
h# 20 constant /cg3-off-dac
h# 800000 constant cg3-off-fb

View File

@ -17,7 +17,7 @@
h# SBUSFPGA_CG3_WIDTH
;
sbusfpga_regionaddr_cg6_bt constant cg6-off-dac
sfra_cg6_bt constant cg6-off-dac
h# 20 constant /cg6-off-dac
h# 800000 constant cg6-off-fb

View File

@ -1,6 +1,6 @@
-1 instance value fbc-virt
: map-in-fbc ( -- ) my-sbus-address sbusfpga_regionaddr_cg6_fbc + my-sbus-space h# 2000 map-in is fbc-virt ;
: map-in-fbc ( -- ) my-sbus-address sfra_cg6_fbc + my-sbus-space h# 2000 map-in is fbc-virt ;
: map-out-fbc ( -- ) fbc-virt h# 2000 map-out ;
: fbc! ( val off -- )

View File

@ -14,7 +14,7 @@
h# SBUSFPGA_CG3_WIDTH
;
sbusfpga_regionaddr_goblin_bt constant goblin-off-dac
sfra_goblin_bt constant goblin-off-dac
h# 200 constant /goblin-off-dac
h# 1000000 constant goblin-off-fb
@ -24,12 +24,10 @@ h# 200000 constant /goblin-mapped-fb
h# 8f000000 constant goblin-internal-fb
: goblin-reg
my-address sbusfpga_regionaddr_goblin_bt + my-space encode-phys /goblin-off-dac encode-int encode+
my-address sfra_goblin_bt + my-space encode-phys /goblin-off-dac encode-int encode+
my-address goblin-off-fb + my-space encode-phys encode+ /goblin-off-fb encode-int encode+
h# 1 goblin-has-jareth = if
my-address sbusfpga_csraddr_jareth + my-space encode-phys encode+ h# 1000 encode-int encode+
my-address sbusfpga_regionaddr_jareth-microcode + my-space encode-phys encode+ h# 1000 encode-int encode+
my-address sbusfpga_regionaddr_jareth-regfile + my-space encode-phys encode+ h# 1000 encode-int encode+
my-address sfra_goblin_accel + my-space encode-phys encode+ h# 1000 encode-int encode+
then
" reg" property
;

View File

@ -8,7 +8,7 @@ fload prom_csr.fth
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ LEDs
\ Absolute minimal stuff; name & registers def.
" RDOL,led" device-name
my-address sbusfpga_csraddr_leds + my-space h# 4 reg
my-address sfca_leds + my-space h# 4 reg
\ we don't support ET or HWORD
h# 7d xdrint " slave-burst-sizes" attribute
h# 7d xdrint " burst-sizes" attribute
@ -21,7 +21,7 @@ my-space constant my-sbus-space
: map-in ( adr space size -- virt ) " map-in" $call-parent ;
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-led ( -- ) my-sbus-address sbusfpga_csraddr_leds + my-sbus-space h# 4 map-in is led-virt ;
: map-in-led ( -- ) my-sbus-address sfca_leds + my-sbus-space h# 4 map-in is led-virt ;
: map-out-led ( -- ) led-virt h# 4 map-out ;
: setled! ( pattern -- )
@ -44,7 +44,7 @@ new-device
" generic-ohci" device-name
\ USB registers are in the device space, not the CSR space
my-address sbusfpga_regionaddr_usb_host_ctrl + my-space h# 1000 reg
my-address sfra_usb_host_ctrl + my-space h# 1000 reg
\ we don't support ET or anything non-32bits
h# 7c xdrint " slave-burst-sizes" attribute
h# 7c xdrint " burst-sizes" attribute
@ -60,7 +60,7 @@ my-space constant my-sbus-space
: map-in ( adr space size -- virt ) " map-in" $call-parent ;
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-regs ( -- ) my-sbus-address sbusfpga_regionaddr_usb_host_ctrl + my-sbus-space h# 1000 map-in is regs-virt ;
: map-in-regs ( -- ) my-sbus-address sfra_usb_host_ctrl + my-sbus-space h# 1000 map-in is regs-virt ;
: map-out-regs ( -- ) regs-virt h# 1000 map-out ;
: my-reset! ( -- )
@ -93,13 +93,13 @@ new-device
\ Absolute minimal stuff; name & registers def.
" RDOL,sdram" device-name
\ three pages of registers:
my-address sbusfpga_csraddr_ddrphy + my-space xdrphys \ Offset#1
my-address sfca_ddrphy + my-space xdrphys \ Offset#1
h# 1000 xdrint xdr+ \ Merge size#1
my-address sbusfpga_csraddr_sdram + my-space xdrphys xdr+ \ Merge offset#2
my-address sfca_sdram + my-space xdrphys xdr+ \ Merge offset#2
h# 1000 xdrint xdr+ \ Merge size#2
my-address sbusfpga_csraddr_exchange_with_mem + my-space xdrphys xdr+ \ Merge offset#3
my-address sfca_exchange_with_mem + my-space xdrphys xdr+ \ Merge offset#3
h# 1000 xdrint xdr+ \ Merge size#3
\ my-address sbusfpga_regionaddr_main_ram + my-space xdrphys xdr+ \ Merge offset#4
\ my-address sfra_main_ram + my-space xdrphys xdr+ \ Merge offset#4
\ h# 10000 xdrint xdr+ \ Merge size#4
" reg" attribute
@ -117,9 +117,9 @@ my-space constant my-sbus-space
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-mregs ( -- )
my-sbus-address sbusfpga_csraddr_ddrphy + my-sbus-space h# 1000 map-in is mregs-ddrphy-virt
my-sbus-address sbusfpga_csraddr_sdram + my-sbus-space h# 1000 map-in is mregs-sdram-virt
my-sbus-address sbusfpga_csraddr_exchange_with_mem + my-sbus-space h# 1000 map-in is mregs-exchange_with_mem-virt
my-sbus-address sfca_ddrphy + my-sbus-space h# 1000 map-in is mregs-ddrphy-virt
my-sbus-address sfca_sdram + my-sbus-space h# 1000 map-in is mregs-sdram-virt
my-sbus-address sfca_exchange_with_mem + my-sbus-space h# 1000 map-in is mregs-exchange_with_mem-virt
;
: map-out-mregs ( -- )
mregs-ddrphy-virt h# 1000 map-out
@ -143,7 +143,7 @@ new-device
\ Absolute minimal stuff; name & registers def.
" RDOL,neorv32trng" device-name
my-address sbusfpga_csraddr_trng + my-space h# 8 reg
my-address sfca_trng + my-space h# 8 reg
\ we don't support ET or HWORD
h# 7d xdrint " slave-burst-sizes" attribute
h# 7d xdrint " burst-sizes" attribute
@ -156,7 +156,7 @@ my-space constant my-sbus-space
: map-in ( adr space size -- virt ) " map-in" $call-parent ;
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-trng ( -- ) my-sbus-address sbusfpga_csraddr_trng + my-sbus-space h# 8 map-in is trng-virt ;
: map-in-trng ( -- ) my-sbus-address sfca_trng + my-sbus-space h# 8 map-in is trng-virt ;
: map-out-trng ( -- ) trng-virt h# 8 map-out ;
: disabletrng! ( -- )
@ -185,11 +185,11 @@ new-device
\ we split the memory space in two
\ 0x1000 @ 0x0 for the microcode
\ 0x10000 @ 0x10000 for the register file
my-address sbusfpga_csraddr_curve25519engine + my-space xdrphys \ Offset#1
my-address sfca_curve25519engine + my-space xdrphys \ Offset#1
h# 1000 xdrint xdr+ \ Merge size#1
my-address sbusfpga_regionaddr_curve25519engine + my-space xdrphys xdr+ \ Merge offset#2
my-address sfra_curve25519engine + my-space xdrphys xdr+ \ Merge offset#2
h# 1000 xdrint xdr+ \ Merge size#2
my-address sbusfpga_regionaddr_curve25519engine h# 10000 + + my-space xdrphys xdr+ \ Merge offset#3
my-address sfra_curve25519engine h# 10000 + + my-space xdrphys xdr+ \ Merge offset#3
h# 10000 xdrint xdr+ \ Merge size#3
" reg" attribute
@ -208,9 +208,9 @@ my-space constant my-sbus-space
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-curve25519engine ( -- )
my-sbus-address sbusfpga_csraddr_curve25519engine + my-sbus-space h# 1000 map-in is curve25519engine-virt
my-sbus-address sbusfpga_regionaddr_curve25519engine + my-sbus-space h# 1000 map-in is curve25519engine-microcode-virt
my-sbus-address sbusfpga_regionaddr_curve25519engine h# 10000 + + my-sbus-space h# 10000 map-in is curve25519engine-regfile-virt
my-sbus-address sfca_curve25519engine + my-sbus-space h# 1000 map-in is curve25519engine-virt
my-sbus-address sfra_curve25519engine + my-sbus-space h# 1000 map-in is curve25519engine-microcode-virt
my-sbus-address sfra_curve25519engine h# 10000 + + my-sbus-space h# 10000 map-in is curve25519engine-regfile-virt
;
: map-out-curve25519engine ( -- )
curve25519engine-virt h# 1000 map-out
@ -229,7 +229,7 @@ new-device
\ Absolute minimal stuff; name & registers def.
" RDOL,sbusstat" device-name
my-address sbusfpga_csraddr_sbus_bus_stat + my-space h# 100 reg
my-address sfca_sbus_bus_stat + my-space h# 100 reg
\ we don't support ET or HWORD
h# 7d xdrint " slave-burst-sizes" attribute
h# 7d xdrint " burst-sizes" attribute
@ -242,7 +242,7 @@ my-space constant my-sbus-space
: map-in ( adr space size -- virt ) " map-in" $call-parent ;
: map-out ( virt size -- ) " map-out" $call-parent ;
: map-in-sbus_bus_stat ( -- ) my-sbus-address sbusfpga_csraddr_sbus_bus_stat + my-sbus-space h# 100 map-in is sbus_bus_stat-virt ;
: map-in-sbus_bus_stat ( -- ) my-sbus-address sfca_sbus_bus_stat + my-sbus-space h# 100 map-in is sbus_bus_stat-virt ;
: map-out-sbus_bus_stat ( -- ) sbus_bus_stat-virt h# 100 map-out ;
end0

View File

@ -127,9 +127,9 @@ def get_csr_header(regions, constants, csr_base=None, with_access_functions=True
def get_csr_forth_header(csr_regions, mem_regions, device_irq_map, constants, csr_base=None):
r = "\\ auto-generated base regions for CSRs in the PROM\n"
for name, region in csr_regions.items():
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_csraddr_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sfca_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
for name, region in mem_regions.items():
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sbusfpga_regionaddr_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
r += "h# " + hex(region.origin).replace("0x", "") + " constant " + "sfra_{}".format(name.replace("video_framebuffer", "vid_fb")) + "\n"
for device, irq in device_irq_map.items():
if ((irq < 7) and (irq > 0)):
r += "h# " + hex(irq).replace("0x", "") + " constant " + "sbusfpga_irq_{}".format(device) + "\n"

View File

@ -13,21 +13,27 @@ import goblin_fb
def get_header_map_stuff(gname, name, size, type="csr", reg=True):
shorten = { "csr" : "c",
"region" : "r" }
r = ""
if (reg):
r += f"my-address sbusfpga_{type}addr_{name} + my-space h# {size:x} reg\n"
r += f"my-address sf{shorten[type]}a_{name} + my-space h# {size:x} reg\n"
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
r += "headers\n"
r += f"-1 instance value {name}-virt\nmy-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
r += f": map-in-{gname} ( -- ) my-sbus-address sbusfpga_{type}addr_{name} + my-sbus-space h# {size:x} map-in to {name}-virt ;\n"
r += f": map-in-{gname} ( -- ) my-sbus-address sf{shorten[type]}a_{name} + my-sbus-space h# {size:x} map-in to {name}-virt ;\n"
r += f": map-out-{gname} ( -- ) {name}-virt h# {size:x} map-out ;\n"
return r
def get_header_map2_stuff(gname, name1, name2, size1, size2, type1="csr", type2="csr"):
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
shorten = { "csr" : "c",
"region" : "r" }
r = f"my-address sf{shorten[type1]}a_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
r += f"my-address sf{shorten[type2]}a_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
r += "\" reg\" property\n"
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
@ -37,8 +43,8 @@ def get_header_map2_stuff(gname, name1, name2, size1, size2, type1="csr", type2=
r += "my-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
r += f": map-in-{gname} ( -- )\n"
r += f"my-sbus-address sbusfpga_{type1}addr_{name1} + my-sbus-space h# {size1:x} map-in to {name1}-virt\n"
r += f"my-sbus-address sbusfpga_{type2}addr_{name2} + my-sbus-space h# {size2:x} map-in to {name2}-virt\n"
r += f"my-sbus-address sf{shorten[type1]}a_{name1} + my-sbus-space h# {size1:x} map-in to {name1}-virt\n"
r += f"my-sbus-address sf{shorten[type2]}a_{name2} + my-sbus-space h# {size2:x} map-in to {name2}-virt\n"
r += ";\n"
r += f": map-out-{gname} ( -- )\n"
r += f"{name1}-virt h# {size1:x} map-out\n"
@ -47,10 +53,13 @@ def get_header_map2_stuff(gname, name1, name2, size1, size2, type1="csr", type2=
return r
def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1="csr", type2="csr", type3="csr", doreg=True):
shorten = { "csr" : "c",
"region" : "r" }
if (doreg):
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
r += f"my-address sbusfpga_{type3}addr_{name3} + my-space encode-phys encode+ h# {size3:x} encode-int encode+\n"
r = f"my-address sf{shorten[type1]}a_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
r += f"my-address sf{shorten[type2]}a_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
r += f"my-address sf{shorten[type3]}a_{name3} + my-space encode-phys encode+ h# {size3:x} encode-int encode+\n"
r += "\" reg\" property\n"
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
@ -63,9 +72,9 @@ def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1
r += "my-address constant my-sbus-address\nmy-space constant my-sbus-space\n"
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
r += f": map-in-{gname} ( -- )\n"
r += f"my-sbus-address sbusfpga_{type1}addr_{name1} + my-sbus-space h# {size1:x} map-in to {name1}-virt\n"
r += f"my-sbus-address sbusfpga_{type2}addr_{name2} + my-sbus-space h# {size2:x} map-in to {name2}-virt\n"
r += f"my-sbus-address sbusfpga_{type3}addr_{name3} + my-sbus-space h# {size3:x} map-in to {name3}-virt\n"
r += f"my-sbus-address sf{shorten[type1]}a_{name1} + my-sbus-space h# {size1:x} map-in to {name1}-virt\n"
r += f"my-sbus-address sf{shorten[type2]}a_{name2} + my-sbus-space h# {size2:x} map-in to {name2}-virt\n"
r += f"my-sbus-address sf{shorten[type3]}a_{name3} + my-sbus-space h# {size3:x} map-in to {name3}-virt\n"
r += ";\n"
r += f": map-out-{gname} ( -- )\n"
r += f"{name1}-virt h# {size1:x} map-out\n"
@ -75,10 +84,13 @@ def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1
return r
def get_header_mapx_stuff(gname, names, sizes, types, doreg=True):
shorten = { "csr" : "c",
"region" : "r" }
if (doreg):
r = f"my-address sbusfpga_{types[0]}addr_{names[0]} + my-space encode-phys h# {sizes[0]:x} encode-int encode+\n"
r = f"my-address sf{shorten[types[0]]}a_{names[0]} + my-space encode-phys h# {sizes[0]:x} encode-int encode+\n"
for i in range(1, len(names)):
r += f"my-address sbusfpga_{types[i]}addr_{names[i]} + my-space encode-phys encode+ h# {sizes[i]:x} encode-int encode+\n"
r += f"my-address sf{shorten[types[i]]}a_{names[i]} + my-space encode-phys encode+ h# {sizes[i]:x} encode-int encode+\n"
r += "\" reg\" property\n"
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
@ -91,7 +103,7 @@ def get_header_mapx_stuff(gname, names, sizes, types, doreg=True):
r += ": map-in ( adr space size -- virt ) \" map-in\" $call-parent ;\n: map-out ( virt size -- ) \" map-out\" $call-parent ;\n";
r += f": map-in-{gname} ( -- )\n"
for i in range(0, len(names)):
r += f"my-sbus-address sbusfpga_{types[i]}addr_{names[i]} + my-sbus-space h# {sizes[i]:x} map-in to {names[i]}-virt\n"
r += f"my-sbus-address sf{shorten[types[i]]}a_{names[i]} + my-sbus-space h# {sizes[i]:x} map-in to {names[i]}-virt\n"
r += ";\n"
r += f": map-out-{gname} ( -- )\n"
for i in range(0, len(names)):
@ -129,7 +141,7 @@ def get_prom(soc,
if (stat):
r += "\" RDOL,sbusstat\" device-name\n"
r += get_header_map_stuff("sbus_bus_stat", "sbus_bus_stat", 256)
if (trng or usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
if (trng or usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (trng):
@ -141,7 +153,7 @@ def get_prom(soc,
r += " map-out-trng\n"
r += ";\n"
r += "disabletrng!\n"
if (usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
if (usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (usb):
@ -161,7 +173,7 @@ def get_prom(soc,
r += " map-out-usb_host_ctrl\n"
r += ";\n"
r += "my-reset!\n"
if ((sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
if ((sdram or not sdram) or engine or i2c or framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (sdram):
@ -187,15 +199,15 @@ def get_prom(soc,
assert(False)
r += "fload sdram_init.fth\ninit!\n"
if (engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
if (engine or i2c or framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (engine):
r += "\" betrustedc25519e\" device-name\n"
r += ": sbusfpga_regionaddr_curve25519engine-microcode sbusfpga_regionaddr_curve25519engine ;\n"
r += ": sbusfpga_regionaddr_curve25519engine-regfile sbusfpga_regionaddr_curve25519engine h# 10000 + ;\n"
r += ": sfra_curve25519engine-microcode sfra_curve25519engine ;\n"
r += ": sfra_curve25519engine-regfile sfra_curve25519engine h# 10000 + ;\n"
r += get_header_mapx_stuff("curve25519engine", [ "curve25519engine", "curve25519engine-microcode", "curve25519engine-regfile" ], [ 4096, 4096, 65536 ] , ["csr", "region", "region" ] )
if (i2c or framebuffer or sdcard or (jareth and not goblin)):
if (i2c or framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (i2c):
@ -210,7 +222,7 @@ def get_prom(soc,
r += " \" lm75\" encode-string \" compatible\" property\n"
r += " h# 48 encode-int \" addr\" property\n"
r += " finish-device\n"
if (framebuffer or sdcard or (jareth and not goblin)):
if (framebuffer or sdcard):
r += "finish-device\nnew-device\n"
if (framebuffer):
@ -221,18 +233,13 @@ def get_prom(soc,
if (goblin):
if (jareth):
# first add the jareth stuff so we can use it from the goblin init
r += ": sbusfpga_regionaddr_jareth-microcode sbusfpga_regionaddr_jareth ;\n"
r += ": sbusfpga_regionaddr_jareth-regfile sbusfpga_regionaddr_jareth h# 10000 + ;\n"
r += get_header_mapx_stuff("jareth", [ "jareth", "jareth-microcode", "jareth-regfile" ], [ 4096, 4096, 4096 ], ["csr", "region", "region" ], doreg=False )
r += get_header_mapx_stuff("jareth", [ "goblin_accel" ], [ 4096 ], [ "region" ], doreg=False )
r += "h# 1 constant goblin-has-jareth\n"
r += "fload goblin_jareth_define.fth\n"
r += "fload goblin_jareth_init.fth\n"
else:
# use some placeholder so the 'reg' proeperty works
r += "h# -1 constant sbusfpga_csraddr_jareth\n"
r += "h# -1 constant sbusfpga_regionaddr_jareth-microcode\n"
r += "h# -1 constant sbusfpga_regionaddr_jareth-regfile\n"
# use some placeholder so the 'reg' property works
r += "h# -1 constant sfra_jareth-regs\n"
r += "h# 0 constant goblin-has-jareth\n"
if (bw2):
@ -249,7 +256,7 @@ def get_prom(soc,
elif (cg3 or cg6):
buf_size=cg3_fb.cg3_rounded_size(hres, vres)
elif (goblin):
buf_size=goblin_fb.goblin_rounded_size(hres, vres)
buf_size=goblin_fb.goblin_rounded_size(hres, vres, "SBus")
for line in cg3_lines:
r += line.replace("SBUSFPGA_CG3_WIDTH", hres_h).replace("SBUSFPGA_CG3_HEIGHT", vres_h).replace("SBUSFPGA_CG3_BUFSIZE", f"{buf_size:x}")
#r += "\" LITEX,fb\" device-name\n"
@ -267,7 +274,7 @@ def get_prom(soc,
r += "fload cg6_init.fth\ncg6_init!\n"
elif (goblin):
r += "\n"
if (sdcard or (jareth and not goblin)):
if (sdcard):
r += "finish-device\nnew-device\n"
if (sdcard):
@ -283,14 +290,6 @@ def get_prom(soc,
r += "sdcard-init!\n"
r += "fload sdcard.fth\n"
r += "fload sdcard_access.fth\n"
if (jareth):
r += "finish-device\nnew-device\n"
if (jareth and not goblin): # if there's a goblin, jareth is part of it
r += "\" jareth\" device-name\n"
r += ": sbusfpga_regionaddr_jareth-microcode sbusfpga_regionaddr_jareth ;\n"
r += ": sbusfpga_regionaddr_jareth-regfile sbusfpga_regionaddr_jareth h# 10000 + ;\n"
r += get_header_mapx_stuff("jareth", [ "jareth", "jareth-microcode", "jareth-regfile" ], [ 4096, 4096, 4096 ] , ["csr", "region", "region" ] )
r += "end0\n"

View File

@ -39,6 +39,7 @@ import cg3_fb
import cg6_fb
import cg6_accel
import goblin_fb
import goblin_accel
# Wishbone stuff
from sbus_wb import WishboneDomainCrossingMaster
@ -63,7 +64,7 @@ class _CRG(Module):
# self.clock_domains.cd_por = ClockDomain() # 48 MHz native, reset'ed by SBus, power-on-reset timer
if (usb):
self.clock_domains.cd_usb = ClockDomain() # 48 MHZ PLL, reset'ed by SBus (via pll), for USB controller
if (engine): # also used for Jareth
if (engine):
self.clock_domains.cd_clk50 = ClockDomain() # 50 MHz (gated) for curve25519engine -> eng_clk
#self.clock_domains.cd_clk100 = ClockDomain() # 100 MHz for curve25519engine -> sys_clk
self.clock_domains.cd_clk200 = ClockDomain() # 200 MHz (gated) for curve25519engine -> rf_clk
@ -119,7 +120,7 @@ class _CRG(Module):
#platform.add_false_path_constraints(self.cd_sys.clk, self.cd_sbus.clk)
#platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_sys.clk)
##platform.add_false_path_constraints(self.cd_native.clk, self.cd_sys.clk)
if (engine): # also used for Jareth
if (engine):
pll.create_clkout(self.cd_clk50, sys_clk_freq/2, ce=pll.locked & self.curve25519_on)
platform.add_platform_command("create_generated_clock -name clk50 [get_pins {{{{MMCME2_ADV/CLKOUT{}}}}}]".format(num_clk))
num_clk = num_clk + 1
@ -237,7 +238,7 @@ class SBusFPGA(SoCCore):
elif (cg3 or cg6):
cg3_fb_size = cg3_fb.cg3_rounded_size(hres, vres)
elif (goblin):
cg3_fb_size = goblin_fb.goblin_rounded_size(hres, vres)
cg3_fb_size = goblin_fb.goblin_rounded_size(hres, vres, "SBus")
print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the Framebuffer")
else:
hres = 0
@ -277,15 +278,15 @@ class SBusFPGA(SoCCore):
"usb_host": 0x00080000, # OHCI registers are here, not in CSR
#"usb_shared_mem": 0x00090000, # unused ATM
"curve25519engine": 0x000a0000, # includes microcode (4 KiB@0) and registers (16 KiB @ 64 KiB)
"jareth": 0x000c0000, # includes microcode (4 KiB@0) and registers (2 KiB @ 64 KiB)
"jareth": 0x000c0000, # a.k.a. goblin_accel (now)
"cg6_bt": 0x00200000, # required for compatibility, bt_regs for cg6 and goblin
#"cg6_dhc": 0x00240000, # required for compatibility, unused
"cg6_alt": 0x00280000, # required for compatibility
"cg6_fhc": 0x00300000, # required for compatibility
#"cg6_thc": 0x00301000, # required for compatibility
"cg3_bt": 0x00400000, # required for compatibility, bt_regs for cg3 & bw2
"cg6_accel_rom": 0x00410000, # R5 microcode
"cg6_accel_ram": 0x00420000, # R5 microcode working space (stack)
"cg6_accel_rom": 0x00410000, # R5 microcode # also "jareth"
"cg6_accel_ram": 0x00420000, # R5 microcode working space (stack) # also "jareth"
"cg6_fbc": 0x00700000, # required for compatibility
#"cg6_tec": 0x00701000, # required for compatibility
"cg3_pixels": 0x00800000, # required for compatibility, 1/2/4/8 MiB for now (up to 0x00FFFFFF inclusive) (bw2, cg3 and cg6 idem)
@ -295,7 +296,7 @@ class SBusFPGA(SoCCore):
"dvma_bridge": 0xfc000000, # required to match DVMA virtual addresses
}
self.mem_map.update(wb_mem_map)
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, usb_clk_freq=48e6, engine=(engine or jareth), framebuffer=framebuffer, pix_clk=litex.soc.cores.video.video_timings[cg3_res]["pix_clk"])
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, usb_clk_freq=48e6, engine=engine, framebuffer=framebuffer, pix_clk=litex.soc.cores.video.video_timings[cg3_res]["pix_clk"])
#self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6) # SBus max
@ -381,6 +382,7 @@ class SBusFPGA(SoCCore):
avail_sdram = avail_sdram - cg3_fb_size
base_fb = self.wb_mem_map["main_ram"] + avail_sdram
self.wb_mem_map["video_framebuffer"] = base_fb
print(f"Base FrameBuffer address is {base_fb:x}")
else:
print("***** ERROR ***** Can't have a FrameBuffer without main ram\n")
assert(False)
@ -511,8 +513,7 @@ class SBusFPGA(SoCCore):
self.bus.add_master(name="curve25519engineLS", master=self.curve25519engine.busls)
else:
self.comb += self.curve25519engine.busls.connect(self.wishbone_slave_sys)
if (not jareth):
self.comb += self.crg.curve25519_on.eq(self.curve25519engine.power.fields.on)
self.comb += self.crg.curve25519_on.eq(self.curve25519engine.power.fields.on)
if (i2c):
self.submodules.i2c = RTLI2C(platform, pads=platform.request("i2c"))
@ -552,16 +553,20 @@ class SBusFPGA(SoCCore):
self.add_ram("cg6_accel_rom", origin=self.mem_map["cg6_accel_rom"], size=rounded_cg6_rom_len, contents=cg6_rom_data, mode="r")
self.add_ram("cg6_accel_ram", origin=self.mem_map["cg6_accel_ram"], size=2**12, mode="rw")
if (jareth):
from jareth import Jareth;
self.submodules.jareth = ClockDomainsRenamer({"eng_clk":"clk50", "rf_clk":"clk200", "mul_clk":"clk100_gated"})(Jareth(platform=platform,prefix=self.mem_map.get("jareth", None), memoryport=self.sdram.crossbar.get_port(mode="both", data_width=128))) # , "sys":"clk100"
self.bus.add_slave("jareth", self.jareth.bus, SoCRegion(origin=self.mem_map.get("jareth", None), size=0x20000, cached=False))
self.bus.add_master(name="jarethLS", master=self.jareth.busls) # Jareth doesn't need the DVMA
if (not engine):
self.comb += self.crg.curve25519_on.eq(self.jareth.power.fields.on)
else:
self.comb += self.crg.curve25519_on.eq(self.jareth.power.fields.on | self.curve25519engine.power.fields.on)
if (jareth):
self.submodules.goblin_accel = goblin_accel.GoblinAccelSBus(soc = self)
self.bus.add_slave("goblin_accel", self.goblin_accel.bus, SoCRegion(origin=self.mem_map.get("jareth", None), size=0x1000, cached=False))
self.bus.add_master(name="goblin_accel_r5_i", master=self.goblin_accel.ibus)
self.bus.add_master(name="goblin_accel_r5_d", master=self.goblin_accel.dbus)
goblin_rom_file = "blit_goblin.raw"
goblin_rom_data = soc_core.get_mem_data(goblin_rom_file, "little")
goblin_rom_len = 4*len(goblin_rom_data);
rounded_goblin_rom_len = 2**log2_int(goblin_rom_len, False)
print(f"GOBLIN ROM is {goblin_rom_len} bytes, using {rounded_goblin_rom_len}")
assert(rounded_goblin_rom_len <= 2**16)
self.add_ram("goblin_accel_rom", origin=self.mem_map["cg6_accel_rom"], size=rounded_goblin_rom_len, contents=goblin_rom_data, mode="r")
self.add_ram("goblin_accel_ram", origin=self.mem_map["cg6_accel_ram"], size=2**12, mode="rw")
print("IRQ to Device map:\n")
print(platform.irq_device_map)
print("Device to IRQ map:\n")