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:
- Host program
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!