In my previous post, I had introduced the Oberon programming language. But there’s more.
Project Oberon also comprises the Oberon operating system, and the RISC5 processor.There’s a book, now available as PDF and updated in 2013, which describes the whole technology stack. All the source code is freely available, allowing to study and understand everything down to the bits and logic gates.
Embedded Oberon makes the Oberon system and language available on commercially available target Xilinx FPGA boards. It’s a subset of the operating system, as it forgoes the screen, keyboard, and mouse. The editing and compilation of Oberon modules is done on a Windows PC, while the board only runs a minimal core of the Oberon system. Via the Astrobe terminal, you can execute commands on the remote board, connected via USB.1
Embedded Oberon is directly based on Project Oberon, and it offers the same openness as regards availability of Oberon source code and Verilog design files. Chris makes this complete Astrobe for RISC5 environment freely available. Amazing.
Until recently, I had focused on the Oberon programming language, and Cortex M3 microprocessor targets. Lots of mind-games to keep my ageing brain up to speed there. In April, I decided to have a closer look at the Oberon system. I already had one of the target boards supported by Embedded Oberon, so why not?
Wirth has always made his own hardware. The Oberon system was running on the Ceres2 workstation. It was also ported to many other architectures, including the Macintosh, plain-vanilla PCs, as well as Sun’s SPARCstation, IBM’s RISC System/6000, and HP’s HP-RISC. At ETH, several hundred networked Ceres computers were used on a daily basis, by faculty members, students, and the secretaries. Back then, almost every scientific article that came out of the Institute for Computer Systems was written using one of Oberon’s document preparation systems.
Even more important, the student’s education was based on hardware, operating software, network, programming languages, and tools developed in-house. Now that’s hands-on, in depth education, if you can explore the whole technology stack during a teaching curriculum, and have its creators explain it, and answer questions. All simple enough that students could explore and understand everything.
There were Oberon systems using portable object code, and just-in-time compilation before Java had it. The Java HotSpot client compiler was modelled after the Oberon compiler.
The Art of Simplicity
We all know that the general development in the industry did not go the route of parsimony and simplicity of solutions. Complex problems might require complex solutions. But today we have complex solutions to pretty simple problems. Bloatware. Lots of bling. Case in point, web pages. Or the editor I use to write this, Visual Studio Code. It’s a powerful editor, with integrated Git features, a Unix command shell, and more. Very useful. But it’s one of those Electron abominations, 250 MBytes on the disk, and I am afraid to even check the memory use. It would just make me sad.
The framework bloat has also taken hold of programming languages. Check out Swift, Apple’s language creation. I am sure it’s powerful and very well structured – Chris Lattner is a super-smart guy –, and well suited to cope with the complexity of today’s fancy user interfaces, multi-core architectures, complex APIs, and networking everywhere, but I doubt programmers outside of a small circle of experts understand the language in-depth. Most will use it based on examples and tutorials to just make their application work, debugging it into existence. And that’s probably good enough to create one more application that they can only sell for close to nothing in the app store. I guess I’d do the same, were I in their shoes. But my claim stands, Swift is a huge language, and not really understanding what you do as programmer is a Bad Thing.™ Grumpy old engineer talking, I know.
Back to Oberon, which is still here: the latest updates are pretty recent, there are still a few enthusiasts that keep it alive and kicking, among them Wirth himself, even though he retired in 1999. Which is really heartening – he’s 86 now. I can only wish to have his acuity should I ever live that long.
No, I don’t think the Oberon system has a lot of practical use these days. Not because it’s not useful, but simply because of today’s working environments in offices and labs. As said, the world has decided to go down the route to exploit – and waste – all what’s currently possible, technology-wise, with often doubtful outcomes as regards system stability and security, and not what is actually useful for the tasks at hand. Shiny and simple on the surface, but woe betide if something doesn’t work. Did you ever have the Apple Photos library not sync? Good luck analysing and fixing that. There’s not even a Sync Now button. You have to sit and hope for the best. It’s just silly.
Even Wirth writes his articles using Microsoft Word now. But Oberon is an exemplar of simplicity and restraint, an interesting object of exploration, and maybe even more so in the future, when our trade rediscovers the value of masterful simplicity and in-depth understanding, not least in the light of increased needs for security and privacy. Oberon does not have backdoors, and there will never be a buffer overflow that can be exploited. The first you can check yourself, as it’s possible to explore and understand the whole source code, and the second is inhibited by the Oberon language and compiler. And you can study the source code of the compiler as well. It’s about 3,000 lines of code. In words: three thousand lines.
A single person can explore and understand every aspect of, and even tinker with, not a toy exercise set-up, but a fully functioning system. Every computer science student should study the Oberon system. It would be only a few weeks of their curriculum, and provide a sound foundation of understanding going forward, from language and compiler design to operating system structure and processor design.
When tinkering with Embedded Oberon, and something did not work as expected and I was wondering, Hm, what’s going on here, it initially took me a minute or so to realise that I could simply look at the system source code to find out. It’s baffling. Unexpected.
With all the praise, I have to mention a few issues. While the system architecture, the concepts, and the algorithms are strong, the coding style is not, at least for my understanding. First, the code directly contains hardware addresses, and status and control bit numbers. Any changes to the hardware, ie. the FPGA-based processor with all peripheral devices, requires sifting through the low level code to make the corresponding changes. See Kernel.mod for example, with its references to hardware specifics for the SPI SD card driver. An abstraction layer of modules with constant definitions would not have been a big deal, it seems to me.
Second, some variable name choices are less than ideal. See System.Trap: variables
w – really? And third, in the same vein, there’s no consistency regarding upper and lower case choice for variable and constant names. Again, see Kernel.mod. Right on the same declaration line, there are upper and lower case variable names. I might be picky, but following a consistent naming scheme – whatever it is, I don’t venture into the “what is right” territory, full of landmines – helps me reading code. Wirth underlines again and again that programs are written for humans to read. I personally also find his habit of “saving a few lines”, ie. packing the program code overly densely, unhelpful.
OK, back to the good stuff. I can even check out the processor design, which leads us to Oberon’s RISC5 processor.
The RISC5 Processor
In an article, published in 2015, Wirth writes (emphasis mine):
A few years ago, my friend Paul Reed suggested that I revise and reprint the book because of its value for teaching system design, and because it serves as a good starting point to help would-be innovators build dependable systems from scratch.
There was a big obstacle, however. The compiler I originally developed targeted a processor that has essentially disappeared. Thus, my solution was to rewrite a compiler for a modern processor. But after doing quite a bit of research, I couldn’t find a processor that satisfied my criteria for clarity, regularity and simplicity. So I designed my own.
Wirth uses a Field Programmable Gate Array (FPGA) to implement his design as actual hardware. FPGAs are basically a box of Lego bricks to create whatever you want, the bricks being logic gates, look up tables, RAM modules, logic shifters, PLLs, and so on. You create your design on a PC, using a Hardware Description Language (HDL), create a so called bitstream file, and use this file to configure the actual FPGA chip. You can create anything that can be implemented with digital logic, from multi-channel logic analysers to CPUs, including peripheral devices.
From the book:
The design of the processor to be described here in detail was guided by two intentions. The first was to present an architecture that is distinct in its regularity, minimal in the number of features, yet complete and realistic. It should be ideal to present and explain the main principles of processors. In particular, it should connect the subjects of architectural and compiler design, of hardware and software, which are so closely interconnected.
As the moniker implies, it’s a RISC processor, with about 20 (in words: twenty) instructions. Reduced indeed. It even provides floating point operations. Wirth argues that if you have the right addressing modes, combined with a highly regular set of operations – vertical to the addressing modes – in concert with the programming language, you get by with a minimal number of instructions.
Now you have vertical integration, from the processor to the programming language and compiler to the operating system. One has to wonder if Apple will start to implement ARM instruction set extensions for the Swift language, and operating system specifics, into their “Apple Silicon”.
The Verilog2 design files are right there on the Project Oberon website, for the CPU, as well all the peripheral devices. Astrobe for RISC5 comes with its specific Verilog sources, which only differ from the originals insofar as adaptations were necessary for the supported target boards.
So here I was, with a transparent stack of concepts and technologies, documented and inspectable through all the source code and hardware design files:
- hardware boards with FPGAs
- processor design
- Embedded Oberon system
- Astrobe Oberon language cross compiler3
The processor also includes peripherals, such as SPI, I2C, RS232, and digital IO pins. That is, all you need for designing a control system, reading sensors, and driving actuators.
I had no idea what I was getting into. It was the pure fascination of having this kind of openness for exploration, and the related curiosity that motivated me to have a peek around.
As outlined above, Embedded Oberon is a subset of the complete Oberon operating system. It essentially consists of:
- file system on the SD card on the target board
- dynamic linking loader for modules
- hyper-text-based command interpreter for commands issued via the Astrobe console on the PC
- very simple background task system
- uploader for cross-compiled modules
- boot loader
Absent from the Astrobe cross development tools on Windows is a linker. Your program consists of source Oberon modules, as specified by the respective
IMPORT statements, and the compiler will create single compiled modules, not a linked binary. Only when executing the program will the dynamic linking loader of the Oberon system recursively pull the required modules from the disk into memory, making the modules’ exported interfaces actually available via specific hardware addresses, and fixing up the callers’ address references accordingly.
With its clever, but simple user interface, Embedded Oberon is not meant for programs with rich user interactions. There is the hypertext-based command invocation, but the output is limited to a serial terminal.
But remember the remark about the RISC5 peripherals suited for interaction with sensors and actuators? Exactly. And there’s the FPGA. Stay tuned for the final follow up. Final, promised.
Technically it’s a serial connection, via USB. ↩︎
I don’t have the source for the cross compiler on Windows, but it closely follows the original compiler on the Oberon system, with some documented extensions. ↩︎