From dd3d1caeff82d4643e45a699aa35124d582e17c9 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Sun, 6 Mar 2022 19:22:06 +0100 Subject: [PATCH] working on goblin --- sbus-to-ztex-gateware-migen/goblin.fth | 159 ++++++++++++++++++ .../sbus_to_fpga_prom.py | 16 +- .../sbus_to_fpga_soc.py | 37 +++- 3 files changed, 199 insertions(+), 13 deletions(-) create mode 100644 sbus-to-ztex-gateware-migen/goblin.fth diff --git a/sbus-to-ztex-gateware-migen/goblin.fth b/sbus-to-ztex-gateware-migen/goblin.fth new file mode 100644 index 0000000..4641a40 --- /dev/null +++ b/sbus-to-ztex-gateware-migen/goblin.fth @@ -0,0 +1,159 @@ +: openbios-video-width + h# SBUSFPGA_CG3_WIDTH +; + +: openbios-video-height + h# SBUSFPGA_CG3_HEIGHT +; + +: depth-bits + h# 8 +; + +: line-bytes + h# SBUSFPGA_CG3_WIDTH +; + +sbusfpga_regionaddr_goblin_bt constant goblin-off-dac +h# 20 constant /goblin-off-dac + +h# 800000 constant goblin-off-fb +h# SBUSFPGA_CG3_BUFSIZE constant /goblin-off-fb + +: >goblin-reg-spec ( offset size -- encoded-reg ) + >r 0 my-address d+ my-space encode-phys r> encode-int encode+ +; + +: goblin-reg + \ FIXME: we don't have to do this like the cg3... + h# 0 h# 1000000 >goblin-reg-spec + " reg" property +; + +: do-map-in ( offset size -- virt ) + >r my-space r> " map-in" $call-parent +; + +: do-map-out ( virt size ) + " map-out" $call-parent +; + +\ +\ DAC +\ + +-1 value goblin-dac +-1 value fb-addr + +: dac! ( data reg# -- ) + goblin-dac + l! +; + +external + +: color! ( r g b c# -- ) + h# 18 << h# 14 dac! ( r g b ) + swap rot ( b g r ) + h# 18 << h# 18 dac! ( b g ) + h# 18 << h# 18 dac! ( b ) + h# 18 << h# 18 dac! ( ) +; + +headerless + +\ +\ Mapping +\ + +: dac-map + goblin-off-dac /goblin-off-dac do-map-in to goblin-dac +; + +: dac-unmap + goblin-dac /goblin-off-dac do-map-out + -1 to goblin-dac +; + +: fb-map + goblin-off-fb /goblin-off-fb do-map-in to fb-addr +; + +: fb-unmap + goblin-off-fb /goblin-off-fb do-map-out + -1 to fb-addr +; + +: map-regs + dac-map fb-map +; + +: unmap-regs + dac-unmap fb-unmap +; + +\ +\ Installation +\ + +" goblin" device-name +" display" device-type +" RDOL,sbusfpga" model + +: qemu-goblin-driver-install ( -- ) + goblin-dac -1 = if + map-regs + + 0 h# 4 dac! \ disable irq + + fb-map + + \ Initial palette taken from Sun's "Writing FCode Programs" + h# ff h# ff h# ff h# 0 color! \ Background white + h# 0 h# 0 h# 0 h# ff color! \ Foreground black + h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo + + fb-addr to frame-buffer-adr + default-font set-font + + frame-buffer-adr encode-int " address" property \ CHECKME + + h# 3 h# 8 dac! \ enable DMA, VTG + + openbios-video-width openbios-video-height over char-width / over char-height / + fb8-install + then +; + +: qemu-goblin-driver-remove ( -- ) + goblin-dac -1 <> if + unmap-regs + fb-unmap + -1 to frame-buffer-adr + " address" delete-attribute + then +; + +: qemu-goblin-driver-init + + goblin-reg + + openbios-video-height encode-int " height" property + openbios-video-width encode-int " width" property + depth-bits encode-int " depth" property + line-bytes encode-int " linebytes" property + + h# 39 encode-int 0 encode-int encode+ " intr" property + + \ Monitor sense. Some searching suggests that this is + \ 5 for 1024x768 and 7 for 1152x900 + h# 7 encode-int " monitor-sense" property + + " RDOL" encode-string " manufacturer" property + " ISO8859-1" encode-string " character-set" property + h# c encode-int " cursorshift" property + + ['] qemu-goblin-driver-install is-install + ['] qemu-goblin-driver-remove is-remove +; + +qemu-goblin-driver-init diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py index 17ca500..7fcebc9 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py @@ -9,6 +9,7 @@ from migen import * import bw2_fb import cg3_fb import cg6_fb +import goblin_fb def get_header_map_stuff(gname, name, size, type="csr", reg=True): @@ -103,11 +104,12 @@ def get_prom(soc, bw2=False, cg3=False, cg6=False, + goblin=False, cg3_res=None, sdcard=False, jareth=False): - framebuffer = (bw2 or cg3 or cg6) + framebuffer = (bw2 or cg3 or cg6 or goblin) r = "fcode-version2\nfload prom_csr_{}.fth\n".format(version.replace(".", "_")) @@ -212,13 +214,17 @@ def get_prom(soc, cg3_file = open("bw2.fth") elif (cg3): cg3_file = open("cg3.fth") - else: + elif (cg6): cg3_file = open("cg6.fth") + elif (goblin): + cg3_file = open("goblin.fth") cg3_lines = cg3_file.readlines() if (bw2): buf_size=bw2_fb.bw2_rounded_size(hres, vres) - else: + elif (cg3 or cg6): buf_size=cg3_fb.cg3_rounded_size(hres, vres) + elif (goblin): + buf_size=goblin_fb.goblin_rounded_size(hres, vres) 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" @@ -231,9 +237,11 @@ def get_prom(soc, elif (cg3): r += get_header_map_stuff("cg3extraregs", "cg3", 4096, reg=False) r += "fload cg3_init.fth\ncg3_init!\n" - else: + elif (cg6): r += get_header_map_stuff("cg6extraregs", "cg6", 4096, reg=False) r += "fload cg6_init.fth\ncg6_init!\n" + elif (goblin): + r += "\n" if (sdcard or jareth): r += "finish-device\nnew-device\n" diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py index 06c98d6..f54b6ff 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py @@ -40,6 +40,7 @@ import bw2_fb import cg3_fb import cg6_fb import cg6_accel +import goblin_fb # Wishbone stuff from sbus_wb import WishboneDomainCrossingMaster @@ -211,8 +212,8 @@ class SBusFPGA(SoCCore): #if self.irq.enabled: #self.irq.add(name, use_loc_if_exists=True) - def __init__(self, variant, version, sys_clk_freq, trng, usb, sdram, engine, i2c, bw2, cg3, cg6, cg3_res, sdcard, jareth, **kwargs): - framebuffer = (bw2 or cg3 or cg6) + def __init__(self, variant, version, sys_clk_freq, trng, usb, sdram, engine, i2c, bw2, cg3, cg6, goblin, cg3_res, sdcard, jareth, **kwargs): + framebuffer = (bw2 or cg3 or cg6 or goblin) print(f"Building SBusFPGA for board version {version}") @@ -231,11 +232,14 @@ class SBusFPGA(SoCCore): if (framebuffer): hres = int(cg3_res.split("@")[0].split("x")[0]) vres = int(cg3_res.split("@")[0].split("x")[1]) + cg3_fb_size = 0 if (bw2): cg3_fb_size = bw2_fb.bw2_rounded_size(hres, vres) - else: + elif (cg3 or cg6): cg3_fb_size = cg3_fb.cg3_rounded_size(hres, vres) - print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the CG3/CG6") + elif (goblin): + cg3_fb_size = goblin_fb.goblin_rounded_size(hres, vres) + print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the Framebuffer") else: hres = 0 vres = 0 @@ -275,7 +279,7 @@ class SBusFPGA(SoCCore): #"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) - "cg6_bt": 0x00200000, # required for compatibility, bt_regs for cg6 + "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 @@ -518,9 +522,12 @@ class SBusFPGA(SoCCore): elif (cg3): self.submodules.cg3 = cg3_fb.cg3(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga") # clock_domain for the VGA side, cg3 is running in cd_sys self.bus.add_slave("cg3_bt", self.cg3.bus, SoCRegion(origin=self.mem_map.get("cg3_bt", None), size=0x1000, cached=False)) - else: + elif (cg6): self.submodules.cg6 = cg6_fb.cg6(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga") # clock_domain for the VGA side, cg6 is running in cd_sys self.bus.add_slave("cg6_bt", self.cg6.bus, SoCRegion(origin=self.mem_map.get("cg6_bt", None), size=0x1000, cached=False)) + elif (goblin): + self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga", irq_line=Signal()) # clock_domain for the VGA side, cg6 is running in cd_sys + self.bus.add_slave("goblin_bt", self.goblin.bus, SoCRegion(origin=self.mem_map.get("cg6_bt", None), size=0x1000, cached=False)) if (cg6): self.submodules.cg6_accel = cg6_accel.CG6Accel(soc = self, base_fb = base_fb, hres = hres, vres = vres) @@ -578,6 +585,7 @@ def main(): parser.add_argument("--cg3", action="store_true", help="add a CG3 framebuffer [V1.2+VGA_RGB222 pmod]") parser.add_argument("--cg3-res", default="1152x900@76Hz", help="Specify the CG3/CG6 resolution") parser.add_argument("--cg6", action="store_true", help="add a CG6 framebuffer [V1.2+VGA_RGB222 pmod]") + parser.add_argument("--goblin", action="store_true", help="add a Goblin framebuffer [V1.2+VGA_RGB222 pmod]") parser.add_argument("--sdcard", action="store_true", help="add a sdcard {no SW yet}") parser.add_argument("--jareth", action="store_true", help="add a Jareth vector core [all]") builder_args(parser) @@ -590,11 +598,20 @@ def main(): print(" ***** WARNING ***** : USB on V1.0 is an ugly hack \n"); if (args.i2c): print(" ***** WARNING ***** : I2C on V1.x is for testing the core \n"); - if ((args.bw2 or args.cg3 or args.cg6) and (args.version == "V1.0")): + if ((args.bw2 or args.cg3 or args.cg6 or args.goblin) and (args.version == "V1.0")): print(" ***** ERROR ***** : VGA not supported on V1.0\n") assert(False) - if ((args.bw2 and args.cg3) or (args.bw2 and args.cg6) or (args.cg3 and args.cg6)): - print(" ***** ERROR ***** : can't have more than one of BW2, CG3 and CG6\n") + fbcount = 0 + if (args.bw2): + fbcount = fbcount + 1 + if (args.cg3): + fbcount = fbcount + 1 + if (args.cg6): + fbcount = fbcount + 1 + if (args.goblin): + fbcount = fbcount + 1 + if (fbcount > 1): + print(" ***** ERROR ***** : can't have more than one of BW2, CG3, CG6 and Goblin\n") assert(False) soc = SBusFPGA(**soc_core_argdict(args), @@ -609,6 +626,7 @@ def main(): bw2=args.bw2, cg3=args.cg3, cg6=args.cg6, + goblin=args.goblin, cg3_res=args.cg3_res, sdcard=args.sdcard, jareth=args.jareth) @@ -658,6 +676,7 @@ def main(): bw2=args.bw2, cg3=args.cg3, cg6=args.cg6, + goblin=args.goblin, cg3_res=args.cg3_res, sdcard=args.sdcard, jareth=args.jareth)