[Oberon] oberonnet of things

skulski at pas.rochester.edu skulski at pas.rochester.edu
Mon Aug 24 04:25:42 CEST 2015


Chris:

> Instead of then loading Oberon I'll be loading a simple
> command-line processor that will allow you to:
> 1. Upload compiled Oberon object (*.rsc) files
>   via a fast (115200 Baud) RS232 link
> 2. Store them to the SD card
> 3. Execute them from the SD card

This is great. Here I would like to see one more bullet:

  1a. After uploading, execute *.rsc directly from RAM without
      storing to the SD card.

This will allow to test the *.rsc without steps 2 and 3. Only tested
programs would then go to the SD card. Development version need not to be
stored.

> Eventually I hope to be able to eliminate the external SRAM
> and target FPGA devices with sufficient BRAM (e.g. 128 KBytes?).

Eliminating external SRAM is not a good idea. BRAM is a very expensive
form of RAM. If you need lots of RAM, and BRAM is the only option, then
you need to use a high end FPGA only because it has sufficient BRAM. These
high end FPGA are not only expensive, but they also come in larger
footprints than the lower end FPGAs. This translates to larger boards,
more layers, higher power, and more difficult PCB routing.

An established approach in such a situation is to use the system memory
map with different kinds of memory, conventionally named L1, L2, and L3.
The L1 is the fastest on chip RAM, the L3 is the slowest off-chip RAM,
quite often SDRAM. In the present case the L1 would be BRAM, L2 could be a
SRAM chip, and L3 could be SDRAM if it is present. The memories L* may or
may not be contiguous. It is the task of the loader to place different
objects in different L*, perhaps following a loader directive that can
take a form of a special comment, or a new language keyword (Professor
Wirth will probably hate this proposition). For example (I am making it
up):

MODULE Loader_Module*; (* approach #1 *)
(*there can be only one module marked "*" *)
MEMORY L1 = low_addr1 .. high_addr1;
MEMORY L2 = low_addr2 .. high_addr2;
MEMORY L3 = low_addr3 .. high_addr3;
MEMORY L4 = low_addr4 .. high_addr4;
(*... and so on. No limit on the number of L's. *)
(*The new keyword is MEMORY. It is only allowed in the "*" module.*)
(*L1 is a name.*)

MODULE MyModule;
STORAGE L1; (*new keyword is STORAGE*)
(*module code will be placed between low_addr1 .. high_addr1*)

The above can be abbreviated to the following, which requires only one new
keyword STORAGE.

MODULE MyModule; (* approach #2 *)
STORAGE low_addr .. high_addr;
(*module code must be placed between low_addr .. high_addr*)

Approach #2 is more minimalistic, but it would require editing many
locations if the memory layout has changed. Approch #1 may look like an
overkill, but it has the benefit that the memory layout is defined in only
one place.

I also think that storage directives should govern structured variables as
well. Scalar variables can always live in the fastest memory. The storage
of arrays and records should be controlled. In many cases the array may be
used infrequently, or the access may not be time-critical. Such variables
can be placed in the slowest memory. There needs to be a mechanism for
doing this.

Going one step farther, an SPI chip or an SD card can also be defined as
SRAM whose address range is mapped via a memory controller. This opens an
interesting possibility that read-only structures can be assigned to flash
and used like RAM without necessarily loading them into fast RAM. This
mechanism does not require any language change. It can be handled in
firmware.

> All of the above may well be off the topic 'oberonnet of things'
> as my plans do not involve Internet-based targets. However,
> the tools might still be useful for others who are interested
> in working in that space,

I am very interested in your tools.

Regards,
Wojtek




More information about the Oberon mailing list