Logging of events is provided by two modules:

  • Log: Store all logging data into a storage area in the FPGA that survives a system reset. By default, no data is written to the console.1
  • LogView: Via a command, read all stored logging data, and “translate” it to readable messages.


Module Log serves three purposes:

  • define all possible events that can be logged
  • define a RECORD for log entries that needs to be “filled” in by the logging process
  • provide a device driver for the FPGA-based log data store

Log entries can be made for four different event types:

  • Log.Trap: done in trap handler
  • Log.Abort: done in abort handler
  • Log.System: used in system modules (Oberon, Processes, Errors)
  • Log.Process: used in module Processes

For each event type, a cause is, or needs to be, provided:

  • trap: the trap number as given by the trap instruction inserted by the compiler
  • abort: the abort cause number argument given to SysCtrl.AbortInt
  • system and process: as defined in Log

Apart from event and cause, the record type Log.Entry provides a set of fields to hold the different data for all the different log types, for example:

  • the mnemonic id of the process
  • addresses
  • time stamp
  • module name

Not all log entry data fields are used for each log type.

The FPGA-based store is a set of memory areas, each of which can hold the amount of raw data of one log entry. In addition, there are two registers to store the put index and the get index, respectively, to implement a circular buffer. The circular buffer functionality is implemented in software in Log. The two registers for the two indices allow to store the state of the circular buffer across system resets and reloads.

Log.Put stores a log entry into the next available memory area in the FPGA.

A set of procedures (Log.BeginGet, Log.EndGet, Log.GetNext, Log.GetMore) serve to read out the log entries.


Command LogView.List reads all log entries, writing a readable message to the console for each.

This command can be installed in Log to print to the console each logged event as it occurs.

  1. With an unsupervised control system, there might not even be a console, or it’s off. Also – and arguably more important –, writing to the console is time consuming. At 15,200 Baud, the transmission of one ASCII character will take about 87 microseconds, so even a short log message of 12 characters takes more than one millisecond, which is a lot when ten or so processes are sharing a five millisecond time window. The output buffer alleviates that issue for short messages. ↩︎