03: Reading and Writing SDRAM - Improved

We’re now going to re-write the host-program from our previous example program, which used SpiNNaker to add two numbers together. In particular, some higher-level facilities of the MachineController will be used to make the host application simpler and more robust. The SpiNNaker application kernel, however, will remain unchanged.

The source files used in this tutorial can be downloaded below:

Reliably stopping applications

Now that we’re starting to allocate machine resources and write more complex programs it is important to be sure that the stop signal is sent to the machine at the end of our host application’s execution. Rather than inserting a call to send_signal() into every exit code path, Rig provides the application() context manager which automatically sends a stop signal when the block ends:

with mc.application():
    # ...Application code...

When execution leaves an application() block, whether by reaching the end of the block, returning early from the function which contains it or encountering an exception, the stop signal is sent automatically.

In our new host program, we surround our application logic with an application() block. The boot() command is purposely placed outside the block since if the boot process fails, it is neither necessary nor possible to send a stop signal.

File-like memory access

When working with SDRAM it can be easy to accidentally access memory outside the range of an allocated buffer. To provide safer and more convenient access to SDRAM the sdram_alloc_as_filelike() method produces a file-like MemoryIO object for the allocated memory. This object can be used just like a conventional file, for example using read(), write() and seek() methods. All writes and reads to the file are automatically constrained to the allocated block of SDRAM preventing accidental corruption of memory. Additionally, users of an allocated block of memory need not know anything about the chip or address of the memory and may even be oblivious to the fact that they’re using anything other than a normal file. This can simplify application code by avoiding the need to pass around additional information.

We replace the previous calls to sdram_alloc(), write() and read() with:

    sdram = mc.sdram_alloc_as_filelike(12, x=0, y=0, tag=1)
    sdram.write(data)
    result_data = sdram.read(4)

Just like files, reads and writes occur immediately after the data the previous read and write encountered. seek() must be used move the ‘read head’ to other locations in memory. Note that in this case since the result value is written immediately after the two input values we do not need to seek before reading.

In the next part of the tutorial we’ll use what we’ve learnt to take our first steps towards building a real application: a digital circuit simulator. Onward to part 04!