Gigatron 512k and more

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Sugarplum
Posts: 59
Joined: 30 Sep 2020, 22:19

Re: Gigatron 512k and more

Post by Sugarplum »

Great project!

I'd like to understand more about this since if I go for the 100 Mhz Gigatron project, I don't want to create conflicting standards. I'd like to know how banking works, for instance, and how others are going past 64K. I'd love to incorporate something like this.

On my snooper idea, I considered snooping all the time and letting the FPGA or whatever evaluate what is coming in and work rather asynchronously.

And it seems like you could snoop the sound/lights too and remove that code from ROM.
bmwtcu
Posts: 111
Joined: 01 Nov 2018, 12:02

Re: Gigatron 512k and more

Post by bmwtcu »

His Github writeups seem like a good place to start.
lb3361
Posts: 186
Joined: 17 Feb 2021, 23:07

Re: Gigatron 512k and more

Post by lb3361 »

Sugarplum wrote: 21 Jan 2022, 06:35 I'd like to understand more about this since if I go for the 100 Mhz Gigatron project, I don't want to create conflicting standards. I'd like to know how banking works, for instance, and how others are going past 64K. I'd love to incorporate something like this.
On my snooper idea, I considered snooping all the time and letting the FPGA or whatever evaluate what is coming in and work rather asynchronously.
And it seems like you could snoop the sound/lights too and remove that code from ROM.
The repository is at https://github.com/lb3361/gigatron-lb/t ... sion-crazy (attention, special branch).
One of my goals was to have something that still works with the normal rom but gives additional benefits from a patched one.
Therefore the Gigatron is still doing all the timing. It just does not have to send the pixels (but no harm if it does).

Warning: I have to change the banking scheme because of viewtopic.php?p=2838#p2838
Sugarplum
Posts: 59
Joined: 30 Sep 2020, 22:19

Re: Gigatron 512k and more

Post by Sugarplum »

lb3361 wrote: 21 Jan 2022, 12:13 The repository is at https://github.com/lb3361/gigatron-lb/t ... sion-crazy (attention, special branch).
One of my goals was to have something that still works with the normal ROM but gives additional benefits from a patched one.
Therefore the Gigatron is still doing all the timing. It just does not have to send the pixels (but no harm if it does).

Warning: I have to change the banking scheme because of viewtopic.php?p=2838#p2838
The application I propose such functionality for would be a custom near-Gigatron that would require a ROM rewrite from the start. Since the LUT-based CU would replace the useless/redundant instructions (59+) and the LUT-based ALU could provide more operations, the ROM would need to be rewritten to use those to gain any benefits. If you have more registers, shifting, multiplication, etc., one should use them. So there would be 2 ways to go. One would be to bit-bang much like now and more tightly interleave the vCPU. That could be an option. The other is to go the snooping route even then. The goal wouldn't be so much speed as it would be to add flexibility and features. A video "chip" could add things like text mode. So all you do is send it ASCII and let the controller convert that.

The nice part about sending character set codes is that one could include more drawing characters and you can use multiple character sets. And with the drawing characters, one could have a text mode that includes the best drawing and other characters of all the retro machines, such as Atari, Commodore, and the original PC, giving more flexibility in text-only games and games that use characters as graphics (like much of the C64 games).

So like I posted in the other thread, it would probably be wise to make a Hackaday page for this.
at67
Posts: 479
Joined: 14 May 2018, 08:29

Re: Gigatron 512k and more

Post by at67 »

Awesome project, so much potential, will take a while to digest.
lb3361 wrote: 17 Jan 2022, 20:24 [*] There is already support for a pulse modulation output that can provide 6 bits audio https://github.com/lb3361/gigatron-lb/t ... gs/pwmtest. This cannot be as good as a dedicated DAC with a well controlled power plane, but it comes for free. Hans61 has already carried out some tests. It is not obvious to find a sound program that actually makes use of the six available bits. At67's midi code is optimized for 4 bit outputs. His expertise would be invaluable.
Just change the channel samples to 6bit Sinusoids, either programmatically or using the audio editor built into my editor, with a modified ROM you'll hear the difference between 4bit and 6bit, both in emulation and on real hardware. viewtopic.php?f=4&t=278&start=30

My midi code doesn't know or understand what it is playing on the sound channels, so if you setup emulation or hardware properly, it will playback 6bit or 8bit audio just fine, (four 6bit channels mix into 8bit samples).
lb3361
Posts: 186
Joined: 17 Feb 2021, 23:07

Re: Gigatron 512k and more

Post by lb3361 »

New native instructions

I did not realize this was possible until a couple day ago when I finally found the time to fix my flawed extended memory banking scheme (see viewtopic.php?p=2838#p2838). This fix required lots of changes: the extended ctrl codes, the verilog, the rom, the demo programs, and even the compiler which gained support to place vCPU routines in specific memory ranges, which can be useful when one swap memory banks. Then I realized that when a ctrl instruction is executing --which I know because the SRAM signals /OE and /WE are both low--, I can also see the value of the AC register on the ALU pins of the output register. This happens because ctrl() is just a st() instruction in disguise.

This gave me the idea to extend the set of native operations in order to provide direct access to the whole 512K ram instead of banking things around. To do so, I am stealing parts of the extended ctrl code space that is not used because it cannot be used from vCPU because the SYS_ExpanderControl call clears the low two bits of the ctrl code. Since all usable extended ctrl codes end with 0000, we can use 0001, 0010, and 0011 for additional opcodes.

The current CPLD program (see https://github.com/lb3361/gigatron-lb/b ... /rtl/top.v, only 314 lines) implements a new Z register and a couple new native instructions.

Code: Select all

ENCODING          OPCODE     DESCRIPTION         
C141/ctrl(0x41)   --           no operation
C1d2/ctrl(0xd2)   ld(d,Z)      load immediate d into register Z
C151/ctrl(0x51)   ld(AC,Z)     copy AC into register Z
C161/ctrl(0x61)   ld(Y,Z)      copy Y into register Z
C171/ctrl(0x71)   ld(V,Z)      copy three upper bits of the current video bank into Z,
                               using AC<7> to decide whether targeting even or odd pixels.
But how then do we use the register Z? Well, we use prefix instructions that change the addressing mode of the next Gigatron opcode which can be a load or store. For instance, instruction ld([Y,X]) becomes ld([Z,Y,X]) which uses bits from the Z register to form a large enough address to access all the RAM as a big linear space. More exactly the prefixes change the addressing mode of the next instruction as follow:

Code: Select all

               [d],AC      -->  [Z,0,d],AC
               [X],AC      -->  [Z,0,X],AC
               [Y,d],AC    -->  [Z,Y,d],AC
               [Y,X],AC    -->  [Z,Y,X],AC
               [d],X       -->  [Z,0,d],X
               [d],Y       -->  [Z,0,d],Y
               [d],OUT     -->  [Z,0,d],OUT    (load only)
               [Y,X++],OUT -->  [Z,Y,X++],OUT  (load only)
               [Y,X++]     -->  [Z,Y,X++]      (store only)
The prefix instruction are the same as the instructions above with an additional bit that indicates that the addressing mode
of the next executed instruction must be changed.

Code: Select all

ENCODING          OPCODE          DESCRIPTION         
C1c1/ctrl(0xc1)   far()            prefix for next insn
C1d3/ctrl(0xd2)   far(d,Z)         same as ld(d,Z) + prefix
C1d1/ctrl(0xd1)   far(AC,Z)        same as ld(AC,Z) + prefix
C1e1/ctrl(0xe1)   far(Y,Z)         same as ld(Y,Z) + prefix
C1f1/ctrl(0xf1)   far(V,Z)         same as ld(V,Z) + prefix
All this seems nice but is far from being tested. I wrote the new CPLD program and checked that the Gigatron still runs normally. I have to write a native SYS call to exercise these new opcodes and see how well this works. Overall I am quite confident except for the ld(AC,Z) instructions because I am not sure the ALU has already produced AC when I process the ctrl() instruction. The next step is to update the native assembler to understand things like adda([Z,Y,0x23],X) and generate the correct program. The next next step is to provide new vCPU instructions that work with the large linear address space. Or maybe convince at67 to have a look at this ;-)

The CPLD is now 94% full with 9/144 macrocells remaining. What can we do with these?

[Update] - Going from 6 bits audio to 8 bits audio takes two more macrocells. Let's see whether it helps.
Last edited by lb3361 on 21 Feb 2022, 22:58, edited 3 times in total.
lb3361
Posts: 186
Joined: 17 Feb 2021, 23:07

Re: Gigatron 512k and more

Post by lb3361 »

High resolution Mandelbrot

This is a rewritten version of the Mandelbrot program in 320x240 resolution. I had to change the fixed point format to have 8 bits of fractional part because one cannot otherwise separate the pixels for the zoomed displays. Although it has been rewritten in vCPU + C https://github.com/lb3361/gigatron-lb/t ... mandelbrot, it remains quite close to the original. I also use qwertyface's multiplication trick to great effect because we now have plenty of memory to store a table of squares.

Speedwise, we have to compute four times more pixels per screen, but the Gigatron 512k is about four times faster than a standard Gigatron in default mode 1. The big speedup remains qwertyface's multiplication trick which goes about five times faster than the old code in this application (big table, no overflow checks, no fallback to normal multiplication.)

20220129_203443.jpg
20220129_203443.jpg (4.06 MiB) Viewed 800 times

I surprise myself thinking that 320x240 is high resolution :-)

The GT1 file is 6KB long. I am not including it here because it certainly won't work on a normal Gigatron.

For the curious, here is the memory map. Note the 8KB buffer containing squares at address 0x1e00 (the screen buffer is now elsewhere, in banks 12 to 15). Most of the code is related to using the cprintf to display the time. Although it is lighter than it used to be, it links plenty of code that this program does not use directly (memset, division) and also the console support which is useful because it sets up the high-res display, something I would have to do otherwise.

Code: Select all

$ glcc -map=32k,./mandelbrot.ovl -rom=v5a mandelbrot.o fixed8.s ../libcon_h/libcon_h.a -o mandelbrot.gt1 --frags

Fragment map
	0200-0223 (36 bytes)     CODE  _gt1exec                     _gt1exec.s            
	0224-0277 (84 bytes)     CODE  _cons_set_bank               libcon_h.a(cons_bank.s)
	0278-02d8 (97 bytes)     CODE  _console_printchars          libcon_h.a(cons_printchar.s)
	02da-02db (2 bytes)      DATA  lastFrame                    mandelbrot.c          
	02dc-02dc (1 byte)       DATA  separator                    mandelbrot.c          
	02de-02df (2 bytes)      DATA  clock0                       mandelbrot.c          
	02e0-02e1 (2 bytes)      DATA  clockM                       mandelbrot.c          
	02e2-02e3 (2 bytes)      DATA  clockH                       mandelbrot.c          
	02e4-02e7 (4 bytes)      DATA  bayer                        mandelbrot.c          
	02e8-02f2 (11 bytes)     DATA  .56                          mandelbrot.c          
	02f4-02f7 (4 bytes)      DATA  __glink_magic_init           libcon_h.a(cons_output.c)
	02f8-02f9 (2 bytes)      DATA  __glink_magic_init           libc.a(_start.s)      
	0300-035b (92 bytes)     CODE  _printonechar                libcon_h.a(cons_printchar.s)
	035c-03a4 (73 bytes)     CODE  _console_clear               libcon_h.a(cons_clear.s)
	03a5-03e4 (64 bytes)     DATA  levels                       mandelbrot.c          
	03e6-03ed (8 bytes)      DATA  .6                           libcon_h.a(cons_setup.c)
	03ee-03f5 (8 bytes)      DATA  console_state                libcon_h.a(cons_output.c)
	03f6-03f7 (2 bytes)      DATA  __glink_magic_fini           libc.a(_start.s)      
	03f8-03f9 (2 bytes)      DATA  .79                          libc.a(_doprint.c)    
	0400-0420 (33 bytes)     DATA  .37                          mandelbrot.c          
	0422-0443 (34 bytes)     DATA  console_info                 libcon_h.a(cons_geom.c)
	0444-0454 (17 bytes)     DATA  .msg                         libc.a(raise_zdiv.s)  
	0455-045d (9 bytes)      DATA  .13                          libc.a(_doprint.c)    
	045e-0465 (8 bytes)      DATA  .14                          libc.a(_doprint.c)    
	0466-0476 (17 bytes)     DATA  .108                         libc.a(_doprint.c)    
	0477-0486 (16 bytes)     DATA  .109                         libc.a(_doprint.c)    
	0487-0489 (3 bytes)      DATA  .95                          libc.a(_doprint.c)    
	048a-048c (3 bytes)      DATA  .82                          libc.a(_doprint.c)    
	048d-048e (2 bytes)      DATA  .70                          libc.a(_doprint.c)    
	048f-0490 (2 bytes)      DATA  .67                          libc.a(_doprint.c)    
	0491-0491 (1 byte)       DATA  .64                          libc.a(_doprint.c)    
	0492-0497 (6 bytes)      DATA  bell                         libc.a(cons_ctrl.c)   
	0498-04a5 (14 bytes)     DATA  .31                          libc.a(cons_ctrl.c)   
	04a6-04a7 (2 bytes)      DATA  __glink_magic_bss            libc.a(_init1.c)      
	0800-0864 (101 bytes)    CODE  move_pen                     mandelbrot.c          
	0865-08fe (154 bytes)    CODE  worm (1/2)                   mandelbrot.c          
	0900-0949 (74 bytes)     CODE  worm (2/2)                   mandelbrot.c          
	094a-09cc (131 bytes)    CODE  prep_squares                 mandelbrot.c          
	09cd-09fe (50 bytes)     CODE  update_clock (1/2)           mandelbrot.c          
	0a00-0ac2 (195 bytes)    CODE  update_clock (2/2)           mandelbrot.c          
	0ac3-0aff (61 bytes)     CODE  do_pixel                     mandelbrot.c          
	0b00-0b7e (127 bytes)    CODE  do_grayout                   mandelbrot.c          
	0b7f-0bcc (78 bytes)     CODE  go                           mandelbrot.c          
	0bcd-0bff (51 bytes)     CODE  main (1/2)                   mandelbrot.c          
	0c00-0c5f (96 bytes)     CODE  main (2/2)                   mandelbrot.c          
	0c60-0c9b (60 bytes)     CODE  slowmul                      fixed8.s(slowmul.s)   
	0c9c-0cff (100 bytes)    CODE  mul2                         fixed8.s(mul2.s)      
	0d00-0d4a (75 bytes)     CODE  calc_pixel                   fixed8.s(calcpixel.s) 
	0d4b-0d90 (70 bytes)     CODE  check_calc                   fixed8.s(checkcalc.s) 
	0d91-0dff (111 bytes)    CODE  console_exitm_msgfunc (1/2)  libcon_h.a(cons_setup.c)
	0e00-0e1e (31 bytes)     CODE  console_exitm_msgfunc (2/2)  libcon_h.a(cons_setup.c)
	0e1f-0e40 (34 bytes)     CODE  _console_setup               libcon_h.a(cons_setup.c)
	0e41-0e88 (72 bytes)     CODE  cons_addr                    libcon_h.a(cons_output.c)
	0e89-0eb8 (48 bytes)     CODE  console_clear_screen         libcon_h.a(cons_output.c)
	0eb9-0eeb (51 bytes)     CODE  console_clear_to_eol         libcon_h.a(cons_output.c)
	0eec-0ef5 (10 bytes)     CODE  SYS_ExpanderControl          libc.a(sys_expandercontrol.s)
	0ef6-0eff (10 bytes)     CODE  _@_modu                      libc.a(rt_modu.s)     
	0f00-0f60 (97 bytes)     CODE  scroll                       libcon_h.a(cons_output.c)
	0f61-0ffd (157 bytes)    CODE  console_print (1/2)          libcon_h.a(cons_output.c)
	1000-1063 (100 bytes)    CODE  console_print (2/2)          libcon_h.a(cons_output.c)
	1064-10f8 (149 bytes)    CODE  _console_reset               libcon_h.a(cons_geom.c)
	1100-1148 (73 bytes)     CODE  memset                       libc.a(memset.s)      
	1149-1170 (40 bytes)     CODE  _memscan0                    libc.a(memchr.s)      
	1171-11c1 (81 bytes)     CODE  memchr                       libc.a(memchr.s)      
	11c2-11e6 (37 bytes)     CODE  .callchain                   libc.a(_start.s)      
	11e7-11f3 (13 bytes)     CODE  _@_raise_zdiv                libc.a(raise_zdiv.s)  
	11f4-11fe (11 bytes)     CODE  _doprint_double              libc.a(_doprint_double.s)
	1200-125a (91 bytes)     CODE  _start                       libc.a(_start.s)      
	125b-1265 (11 bytes)     CODE  _doprint_long                libc.a(_doprint_long.s)
	1266-1299 (52 bytes)     CODE  raise                        libc.a(raise.s)       
	129a-12ce (53 bytes)     CODE  utoa                         libc.a(utoa.s)        
	12cf-12ec (30 bytes)     CODE  itoa                         libc.a(itoa.s)        
	1300-1357 (88 bytes)     CODE  _doprint_putc                libc.a(_doprint.c)    
	1358-13b4 (93 bytes)     CODE  _doprint_puts                libc.a(_doprint.c)    
	13b5-13ff (75 bytes)     CODE  parsespec (1/2)              libc.a(_doprint.c)    
	1400-14c4 (197 bytes)    CODE  parsespec (2/2)              libc.a(_doprint.c)    
	14c5-14fe (58 bytes)     CODE  do_str (1/2)                 libc.a(_doprint.c)    
	1500-1585 (134 bytes)    CODE  do_str (2/2)                 libc.a(_doprint.c)    
	1586-15ac (39 bytes)     CODE  upcase                       libc.a(_doprint.c)    
	15ad-15fc (80 bytes)     CODE  _doprint_num (1/3)           libc.a(_doprint.c)    
	1600-16ff (256 bytes)    CODE  _doprint_num (2/3)           libc.a(_doprint.c)    
	1700-174b (76 bytes)     CODE  _doprint_num (3/3)           libc.a(_doprint.c)    
	174c-17bc (113 bytes)    CODE  do_int                       libc.a(_doprint.c)    
	17bd-17fa (62 bytes)     CODE  _doprint (1/3)               libc.a(_doprint.c)    
	1800-1846 (71 bytes)     CODE  _doprint_conv_info           libc.a(_doprint.c)    
	1847-18ff (185 bytes)    CODE  _doprint (2/3)               libc.a(_doprint.c)    
	1900-19ad (174 bytes)    CODE  _doprint (3/3)               libc.a(_doprint.c)    
	19ae-19e3 (54 bytes)     CODE  strlen                       libc.a(strlen.c)      
	19e4-19fa (23 bytes)     CODE  _@_wcopy                     libc.a(rt_wcopy.s)    
	1a00-1ae0 (225 bytes)    CODE  _console_ctrl                libc.a(cons_ctrl.c)   
	1ae1-1afd (29 bytes)     CODE  _@_bcopy                     libc.a(rt_bcopy.s)    
	1b00-1b2c (45 bytes)     CODE  dpf                          libc.a(cprintf.c)     
	1b2d-1b76 (74 bytes)     CODE  vcprintf                     libc.a(cprintf.c)     
	1b77-1bb0 (58 bytes)     CODE  cprintf                      libc.a(cprintf.c)     
	1bb1-1bfd (77 bytes)     CODE  _@_save_ff                   libc.a(rt_save.s)     
	1c00-1c54 (85 bytes)     CODE  _init_bss                    libc.a(_init1.c)      
	1c55-1ca0 (76 bytes)     CODE  _@_rtrn_ff                   libc.a(rt_save.s)     
	1ca1-1cd0 (48 bytes)     CODE  __@divworker                 libc.a(rt_divworker.s)
	1cd1-1cec (28 bytes)     CODE  __@shrsysfn                  libc.a(rt_shrtable.s) 
	1d00-1d3d (62 bytes)     CODE  _@_divu                      libc.a(rt_divu.s)     
	1d3e-1d5f (34 bytes)     CODE  _@_shru                      libc.a(rt_shru.s)     
	1d60-1d7f (32 bytes)     CODE  _@_shrs                      libc.a(rt_shru.s)     
	1e00-3dff (8192 bytes)   BSS   squares                      mandelbrot.c  
axelb
Posts: 26
Joined: 07 Jan 2021, 06:27

Re: Gigatron 512k and more

Post by axelb »

Very impressive ! Where do you capture the banking information (address 4d)? Is it done somewhere in the libraries or directly by the CLPD?
Also the Z register concept for providing far pointers sounds very exciting. In your description above do you actually mean ld([Y,X]) will become ld([Z,Y,X]) ?
lb3361
Posts: 186
Joined: 17 Feb 2021, 23:07

Re: Gigatron 512k and more

Post by lb3361 »

axelb wrote: 02 Feb 2022, 07:49 Very impressive ! Where do you capture the banking information (address 4d)? Is it done somewhere in the libraries or directly by the CLPD?
I am not sure what you mean by "capturing the banking information" and in which context.

Update: Just realized that address 4d is the "bank" variable of the Mandelbrot program. This is used by 'SYS_ExpanderControl(ctrl)' in 'do_pixel()' or 'do_grayout()' because address 4d is the high byte of the int variable 'ctrl'. Going to add a comment in the code.

axelb wrote: 02 Feb 2022, 07:49 Also the Z register concept for providing far pointers sounds very exciting. In your description above do you actually mean ld([Y,X]) will become ld([Z,Y,X]) ?
Correct. I will edit the post.
veekoo
Posts: 78
Joined: 07 Jun 2021, 07:07

Re: Gigatron 512k and more

Post by veekoo »

Cool upgrade! This must replace multiple hardware updates what we have seen. I am currently working with 64K RAM update and burning ROM. The surface mount tech is really beyond what I can do.
Post Reply