Close

SPAM-1 'C' Compiler - good progress

A project log for SPAM-1 - 8 Bit CPU

8 Bit CPU in 7400 with full Verilog simulator and toolchain

john-lonerganJohn Lonergan 11/30/2020 at 19:250 Comments

Hot on the heels of writing an assembler I decided to take my learning and have a go at a higher level language with C-family syntax. 

To be honest the syntax so far looks more like groovy (or even Kotlin) , because of the lack of typing and the use of the "var" keyword and the "main()" function approach looks like Kotlin.

This is being written in Scala because it's a great language for this kind of thing due to its pattern matching and also it's Parser Combinator library which makes parsing a breeze (mostly).

An example of a countdown program is shown  below.

The steps in the automated tests are 

- compile the "SPAM-C" code into Asm files

- assemble the generated Asm file into ROM images

- run the ROM images in the verilog simulator

These steps happen automatically in the test and this has helped spot loads of potential issues along the way.

SPAM-C code .....

def main() {
     var a=10;
     while(a>0) {
         var a=a-1;
         putchar(a)
     }
 }

The compiler spits out this assembler which is then assembled and the verilog simulator invoked so I get to see the program running too.

root_function_main_a: EQU 0
; (0) ENTER root_function_main @ function
      ; (1)  ENTER root_function_main @ statementVar
             [:root_function_main_a] = 10
      ; (1)  EXIT  root_function_main @ statementVar
      ; (1)  ENTER root_function_main_whileCond1 @ whileCond
             root_function_main_whileCond1__2__check:
             ; (2)   ENTER root_function_main_whileCond1 @ condition
                     REGA = [:root_function_main_a]
                     REGA = REGA PASS_A 0 _S
             ; (2)   EXIT  root_function_main_whileCond1 @ condition
             PCHITMP = <:root_function_main_whileCond1__2__top
             PC = >:root_function_main_whileCond1__2__top _GT
             PCHITMP = <:root_function_main_whileCond1__2__bot
             PC = >:root_function_main_whileCond1__2__bot
             root_function_main_whileCond1__2__top:
             ; (2)   ENTER root_function_main_whileCond1 @ statementEqVarOpConst
                     REGA = [:root_function_main_a]
                     REGA = REGA - 1
                     [:root_function_main_a] = REGA
             ; (2)   EXIT  root_function_main_whileCond1 @ statementEqVarOpConst
             ; (2)   ENTER root_function_main_whileCond1_putcharN @ statementPutcharName
                     root_function_main_whileCond1_putcharN__wait_3:
                     PCHITMP = <:root_function_main_whileCond1_putcharN__transmit_4
                     PC = >:root_function_main_whileCond1_putcharN__transmit_4 _DO
                     PCHITMP = <:root_function_main_whileCond1_putcharN__wait_3
                     PC = <:root_function_main_whileCond1_putcharN__wait_3
                     root_function_main_whileCond1_putcharN__transmit_4:
                     UART = [:root_function_main_a]
             ; (2)   EXIT  root_function_main_whileCond1_putcharN @ statementPutcharName
             PCHITMP = <:root_function_main_whileCond1__2__check
             PC = >:root_function_main_whileCond1__2__check
             root_function_main_whileCond1__2__bot:
      ; (1)  EXIT  root_function_main_whileCond1 @ whileCond
      PCHITMP = <:root_end
      PC = >:root_end
; (0) EXIT  root_function_main @ function
root_end:
END

Discussions