Another big step for ELIUS

One of the odd things about working with bare-metal and operating system level software is how tiny things can seem like huge steps when you know what is going on behind the scenes. In this case the "one small step" is the traditional "hello world", something that ELIUS has not really been able to up to now.

To get to this point required several key improvements.

The first bit was to add the beginnings of hardware emulation to my test system. As you may recall if you have been following along, I am building this code on a more traditional desktop computer so that I can test that it works without having to guess what is going on inside the "black box" of a Raspberry Pi with no other operating system. At some point in the future I hope that the CORNELIUS platform will be solid enough to use for further development, but that seems a long way away at the moment.

I had already built a "virtual RAM" for testing. The whole ELIUS system uses four simple calls to access memory (read/write byte/word). The test harness used to just complain if the code tried to access any memory it should not be touching. Now there is a way of mapping a virtual device to a block of memory, so that reads/writes to that block are passed to the virtual device code for processing.

The first virtual device I added was the Raspberry Pi mini-UART which I have been using for my diagnostics while working out how to drive the Raspberry Pi hardware. The virtual version is even more "mini", though. For now it just implements writing a byte to the data transfer register, and I have coded that as printing a character to the screen of the development system. Once the new virtual UART is plugged in, I can use ELIUS to define a word to write to it:

[539054084 B!] [cput] def

That strange number is the decimal equivalent of 0x20215040, the address of the real UART IO register, so (if the appropriate UART set-up has been done first) this should also write a character over the wire on the Raspberry Pi.

To use this, put the ASCII code for a character on the stack, and call it:

65 cput

Will display an 'A'.

This is useful, but it's not really "hello world" yet.

To do that, we could do a long series of cput, one for each character, but that is very clumsy, and not really a good or concise approach. It did prompt me to make a new primitive, though. I defined 'prim_each_c' (and bound it to the ELIUS word eachc) to loop through each character of a string in the string pool, push it onto the stack, and call some supplied code:

void prim-each_c(void) {
  address code = pop();
  address string = pop();
  int len = word_read(string + PENT_LEN);
  for (int i = 0; i < len; ++i) {
    push(byte_read(string+PENT_DATA+i));
    definition(code);
  }

Now I can define some more ELIUS:

[[cput] eachc] [print] def
[print 10 cput] [println] def

We now have two useful words to print a string either with or without a newline at the end.

To test how well this sort of thing works, I also added a simple read-eval-print-loop (REPL) which grabs entered characters and places them in the input buffer until return is pressed, at which point it evaluates the buffer, dumps the stack, and waits for more input.

Putting it all together I can finally do:

elius-hello

Leave a Reply

Your email address will not be published. Required fields are marked *