Skip to content
This repository has been archived by the owner on Feb 10, 2021. It is now read-only.

SdbVsFdt

Samuel A. Falvo II edited this page Apr 16, 2016 · 2 revisions

I'm only one person, making a home-made, open-sourced computer design for myself. There are, however, literally hundreds of FPGA development boards that someone out there may want to port Kestrel to. It's easy enough to update the system firmware (currently, a Forth interpreter with very minimal hardware requirements) to run on any new environment. But, what if they want to run a more sophisticated operating system? Even keeping with the stock Forth firmware, what if someone wants to publish a program that can, for example, take advantage of color if it's available? Or sound?

We need a way to describe the configuration of a Kestrel product without imbuing a sense of dread on the maintainer, but with enough detail that configuration-sensitive software can take advantage of the information. Two standards exist to address this specific problem: Flattened Device Tree and Self-Describing Bus.

The problems with FDT is that it's both verbose and more difficult to use. However, it is substantially more flexible and powerful than SDB. It can describe a wide variety of things, not necessarily hardware related. For example, it can describe individual cores running on a CPU, it can describe devices attached to I2C or SPI interfaces, and more. It's an out-growth of the Open Firmware project, by Mitch Bradley.

The problems with SDB is it's perhaps a bit too simple. It's goal is to describe only devices which are CPU-addressable. It provides no extant support for interrupts, and it's limited to 64-bit address spaces, making its current definition unsuitable for RV128-based processors should one want to adopt one.

Unlike FDT, however, SDB has the advantage that its descriptors can be provided by a configuration-sensitive ROM independent of the BIOS that ships with the motherboard. What do I mean by a configuration-sensitive ROM? Imagine two completely different Kestrel-3 systems. The first is a first-generation Kestrel-3 emulator running on someone's laptop. The second is a custom-built FPGA-based computer with three expansion slots.

In the former configuration, the SDB is almost redundant, since the firmware already knows about everything the emulator has to offer. Still, we symbolically describe the contents of the configuration ROM below:

interconnect="e Emulator", dev=K3E_EMULATOR, version=1
device="cpu", dev=POLARIS_CPU, class=RV64IS, version=1
device="ram", dev=RAM, class=RAM, version=1, low=0, high=$FEFFFF
device="framebuf", dev=MGIA, class=MGIA, version=2, low=$FF0000, high=$FFFFFF
device="gpio", dev=GPIA2, class=GPIA2, version=1, low=$0100000000000000, high=$010000000000000F
device="keyboard", dev=KIA, class=KIA, version=2, low=$0200000000000000, high=$0200000000000001
device="config", dev=ROM, class=SDBROM, version=1, low=$0F00000000000000, high=$0F000000000003FF
device="rom", dev=ROM, class=BOOTROM, version=1, low=$FFFFFFFFFFF00000, high=$FFFFFFFFFFFFFFFF

Meanwhile, for the more complex hardware we might find the following in SDB configuration ROM:

+-----+
|     |<=======.========.========.========.========.========.===>...
| CPU |        |        |        |        |        |        |
|     |======.========.========.========.========.========.=====>...
+-----+      | |      | |      | |      | |      | |      | |
   |       +-----+  +-----+  +-----+  +-----+  +-----+  +-----+
   |       |     |  |     |  |     |  |     |  |     |  |     |
   |       | RAM |  | ROM |  |  0  |  |  1  |  |  2  |  | SDB |
   |       |     |  |     |  |     |  |     |  |     |  |     |
   |       +-----+  +-----+  +-----+  +-----+  +-----+  +-----+
   |                            | slot   | slot   | slot  /\
   |                            |        |        |       ||
   `----------------------------`========`========`=======''  Device Detected signals
interconnect="LowRISC daydream", dev=K3MOBO, version=14
device="compute0", dev=LOWRISC_CPU, class=RV64GS, version=1
device="compute1", dev=LOWRISC_CPU, class=RV64GS, version=1
empty
empty
device="minion0", dev=LOWRISC_MINION, class=RV32IMA, version=1
device="minion1", dev=LOWRISC_MINION, class=RV32IMA, version=1
device="minion2", dev=LOWRISC_MINION, class=RV32IMA, version=1
device="minion3", dev=LOWRISC_MINION, class=RV32IMA, version=1
empty
empty
empty
empty
device="ram", dev=RAM, class=RAM, version=1, low=0, high=$3FEFFFF
bridge "K3 I/O", ptr=...
    interconnect "On-board I/O"
    device="framebuf", dev=RAM, class=MGIA, version=1, low=$3FF0000, high=$3FFFFFF
    device="gpio", dev=GPIA2, class=GPIA2, version=1, low=$0100000000000000, high=$010000000000000F
    device="keyboard", dev=KIA, class=KIA, version=2, low=$0200000000000000, high=$0200000000000001
    device="video", dev=CGIA, class=CGIA1, version=1, low=$0300000000000000, high=$0300000000000FFF
    device="config", dev=ROM, class=SDBROM, version=1, low=$0F00000000000000, high=$0F000000000003FF
bridge "Expansion", ptr=...
    interconnect "HypotheticalAdapter"
    bridge "slot0", ptr=$1000000000000000
    empty
    bridge "slot2", ptr=$3000000000000000
device="rom", dev=ROM, class=BOOTROM, version=1, low=$FFFFFFFFFFF00000, high=$FFFFFFFFFFFFFFFF

What makes a description like this "configuration sensitive" is that this "ROM" really isn't a ROM in the conventional sense; rather, it can be a conventional FPGA core which takes as inputs "device present" signals, and configures the appropriate SDB ROM image appropriately. For example, illustrated above, the motherboard might be configured to use a 2-core, 4-minion LowRISC processor. But, space is reserved for up to 4 main cores and 8 minions if the user wants to upgrade the processor. Likewise, in the "Expansion", the hardware might see an expansion card in slots 0 and 2, but not 1. If a card is ever inserted into slot 1, that middle empty descriptor would be replaced with a correctly configured bridge entry.

In this way, a Kestrel-3 system firmware image can detect at boot-time the initial configuration of the system; if it checks this configuration periodically or in response to an interrupt, it can even do so after cold boot. This is something FDT is incapable of describing in a practical manner.

Another problem with FDT versus SDB is intended audience. FDT is intended strictly for a loaded operating system, such as Linux; the belief is that the FDT is part of the system firmware image. However, SDB is intended to be used by both a loaded operating system and the system firmware, thus reducing the number of hardware-specific firmware images needed.

Considering that SDB is capable of doing most of what I'd want to use FDT for, that it optionally can be extended to support features like hot-swapped peripherals, and it allows me to maintain a reduced number of hardware-specific system firmware images, I've decided that the Kestrel-3 will adopt SDB going forward.

Clone this wiki locally