Musings on compatibility breaking changes.

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Post Reply
Lerc
Posts: 15
Joined: 21 May 2020, 19:38

Musings on compatibility breaking changes.

Post by Lerc »

So I have had quite some time to ponder the architecture of the Gigatron and ways it could be modified for more capabilities.

Almost any enhancement that could be made to the Gigatron would add chips. From my perspective I'm ok with that provided it is done sparingly with substantial benefit to be gained from those additions. I have my own philosophical view that I'd like to keep it to something that was theoretically buildable around 1979.


Input Tweaking

The standard Gigatron can put 4 things onto the bus. D, RAM, AC and IN Of those only RAM access and Immediate values use the second byte of the instruction. Nabbing the bottom two bits of D and the existing !IE and directing them into pins 13,14,15 of U11b gives a potential for three additional sources to put on the bus. (note U11b is currently being used as a 3 input OR It'll need some of a chip to replace that functionality)

IN0 retains the existing input IN1, IN2, IN3 are available for operations

The thing that stands out as worth adding in this way is a 74xx374 taking in the Output from the ALU bits 1..7 into 0..6 and Carry into bit 7. Placing the carry into a separate register at bit 0 would be more convenient for code but I think combining them into the one register gets you most of the advantages

This means Shift Right is much easier to do.

Code: Select all

    LD [$24],AC
    LD IN1,AC
    AND $7f,AC    // AC now has [$24]>>1        Strictly speaking the AND isn't necessary for a LD there's no carry anyway 
Assuming you latch the IN1 Register on any non-store instruction (CLK2 OR !W maybe?) You can build a decent add with carry, by storing the result then loading from IN1

Code: Select all

   LD [A_Low],AC
   ADD [B_Low],AC
   ST [Result_Low]
   LD IN1,AC
   blt .carry
   LD [A_High],ac
   ADD [B_High],AC
   bra .done
.carry: 
   add 1,AC
   ADD [B_High],AC
.done:
   ST [Result_High]
To get This much I think it only needs the addition of a 74xx374 and a 74xx32

Utilizing the other two inputs would require at least a chip each to feed the bus and then whatever hardware needed to give them values. An easy option would be to to use a couple of 74xx244 chips fed from X and Y. That would make it fully possible to read X and Y which makes it feel a little more like a 6502, but I'm not sure if the benefits would be that great, using Zero page for workspace seems to be working well enough.

Another idea is potentially Latching PC before Jumps, The entire thing or just the Top byte. This could act as a link register which might provide the possibility to do some new things. I'd have to think about it some more, to be worth ding it would have to be significantly better than manually storing the return address in Zero Page.

One input could just be as simple as AC with the nybbles swapped. (surprisingly useful)



Output Tweaking

The first part is easy
[Y,X++],OUT becomes [Y,X++],PIXOUT

[D],OUT goes to the same place as before HSYNC and VSYNC still come from here
[Y,X++],PIXOUT goes to a 74xx273

A couple of gates using the existing !OL IX and !IX should give individual lines.

The PIXOUT 74xx273 goes into a 74xx157 toggled by a clock running at twice the CPU rate (so a clock divider also needed)

This should give a 16 colour highres output. Using my oddball resister net
16pal.png
16pal.png (22.88 KiB) Viewed 1090 times
There's scope for a shift register here too. if the 157 were toggled by a shift register you could do bitmaps in any two of the 16 colours. (or just mono if you eliminate the 273)

I'm still in the speculation stage, but I'm working on putting this into the SimulIDE emulator. It might have to wait for v1.0 stable There are some bugs in the 74series chips on the 0.4.15 version.

Anyway it's 5-10 new chips for varying degrees of new features.
Sugarplum
Posts: 93
Joined: 30 Sep 2020, 22:19

Re: Musings on compatibility breaking changes.

Post by Sugarplum »

I had figured that if I were making mods, I'd expand the left shift to be full and add a right shift. The operand space can be used for those to give the desired distance and possibly the direction. Plus I'd love to add a table-based ALU to add multiplication and division.

I had considered other architectural changes. If you want to get rid of a lot of the bit-banging, you could build an I/O board that uses the ports to pass messages to and from it and let the peripheral boards pass things through the RAM. Without a halt line or DMA, spinlocks can be used in the native code. So you can read the input lines every so often to know when a device wants to pass data and use the output lines to acknowledge the request. Then hold it in a spinlock until the device signals that it is done. So you have the functional equivalent of DMA. So after the acknowledgment, the native ROM can hold itself in a loop and either not touch the RAM, or alternatively, do a trivial read to pass a semaphore to a location. If the RAM is off the bus, the value cannot be returned, so the loop can continue. And the I/O controller could be made to do I/O snooping and have its own memory and only throw I/O lines like "interrupts" when necessary. That could be best done in an FPGA since multiple I/O range tests and caches could be used simultaneously.

I don't know if this is feasible, but an idea to make memory more accessible to external devices is to use a 2nd SRAM and only let it respond to writes on the Gigatron side and let other devices use it for reads all other times. If DMA or even spinlocks as above are used, then both could be written to by devices.

As for changing/adding memory address modes, it is possible to do it in a chip-neutral way and use currently unused gates.
Last edited by Sugarplum on 06 Jun 2023, 12:05, edited 2 times in total.
at67
Site Admin
Posts: 647
Joined: 14 May 2018, 08:29

Re: Musings on compatibility breaking changes.

Post by at67 »

Lerc wrote: 28 Jun 2022, 14:46

Code: Select all

   LD [A_Low],AC
   ADD [B_Low],AC
   ST [Result_Low]
   LD IN1,AC
   blt .carry
   LD [A_High],ac
   ADD [B_High],AC
   bra .done
.carry: 
   add 1,AC
   ADD [B_High],AC
.done:
   ST [Result_High]
A couple of issues with your theoretical code:

1) You add 1 to the high byte for both carry and non carry paths, because of the branch delay slot after bra .done. Moving the bra one instruction up would solve this problem.
2) You have different cycle timings for the two carry paths, this could be solved easily by using nop's, duplicating at junctions, etc.

A better way of writing this code is to use the global constants '0' and '1' hard coded at ram locations 0x00 and 0x80 respectively, (Marcel did this for this exact reason), i.e. converting carry's/borrow's to least significant bits.

Code: Select all

   LD   [A_Low],AC
   ADD  [B_Low],AC
   ST   [R_Low]
   LD   IN1,AC
   ANDA 0x80,X
   LD   [X],AC
   ADD  [A_High],AC
   ADD  [B_High],AC
   ST   [R_High]
Putting the carry into the least significant bit of it's own zero'd register, (as you suggested), would save another two instructions, making it only 7 clock cycles for a 16bit add.

Code: Select all

   LD   [A_Low],AC
   ADD  [B_Low],AC
   ST   [R_Low]
   LD   [C_Flag],AC
   ADD  [A_High],AC
   ADD  [B_High],AC
   ST   [R_High]
Lerc
Posts: 15
Joined: 21 May 2020, 19:38

Re: Musings on compatibility breaking changes.

Post by Lerc »

at67 wrote: 01 Jul 2022, 11:46 A couple of issues with your theoretical code:

1) You add 1 to the high byte for both carry and non carry paths, because of the branch delay slot after bra .done. Moving the bra one instruction up would solve this problem.
2) You have different cycle timings for the two carry paths, this could be solved easily by using nop's, duplicating at junctions, etc.
I entirely expected the branch delay slot to catch me out a few times. It is quite the mental adjustment to make.
A better way of writing this code is to use the global constants '0' and '1' hard coded at ram locations 0x00 and 0x80 respectively, (Marcel did this for this exact reason), i.e. converting carry's/borrow's to least significant bits.
I did not know about these constants. That does make things much nicer indeed.
Putting the carry into the least significant bit of it's own zero'd register, (as you suggested), would save another two instructions, making it only 7 clock cycles for a 16bit add.
But then it's adding a chip for saving two cycles. I figure if I keep pondering I'll figure out something that will provide better gains.
qwertyface
Posts: 68
Joined: 16 Jul 2019, 09:19
Location: UK

Re: Musings on compatibility breaking changes.

Post by qwertyface »

Here's a possible change that might be for the better, and costs no chips: I'm pretty sure that suba is very rarely used in comparison to adda. In some cases it's because we find ourselves wanting to calculate a - b, in cases where we've just calculated b, so that is what we're holding in the accumulator, not a. The solution of course is to arrange to calculate -b, so that we can add rather than subtract. This is how the timing code in vCpu works, for example.

I haven't checked this, but I suspect that an asub instruction would be just as useful as suba. This would subtract the value in the accumulator from the value on the bus, rather than vice versa.

The advantage of this is that it would be possible to negate the accumulator in in a single instruction (asub $00) rather than two.

Just an idle thought.
Post Reply