This is work being done by Bryson Gullett (bgullet1@vols.utk.edu) and Jackson Mowry (jmowry4@vols.utk.edu).
framework_embedder is a C++ application that converts TENNLab spiking neural
network (SNN) JSON representations into a single C file containing C API code
for simulating the given SNN. The generated API is composed of lightweight C
code that performs no dynamic memory allocation and has no dependencies outside
of the most basic C compiler/toolchain. framework_embedder optimizes generated
C code to only include lines required to simulate the given SNN and its given
parameters. The simple, static, and optimized nature of the C code generated by
framework_embedder makes it a great tool for rapidly evaluating SNNs in
compact embedded systems on a variety of hardware.
Note that this open-source version of framework_embedder does not include
spike encoding or decoding support. These features will be added in the future
once they have been added to the open-source TENNLab neuromorphic framework.
framework_embedder was primarily motivated by the TENNLab Neuromorphic Maker's
Kit, which is a separate (though similar) project. While the Maker's Kit can
also convert TENNLab JSON files into C code, it only targets a single hardware
setup of three Raspberry Pi Pico microcontroller boards that are connected via
serial and digital signals. framework_embedder breaks free of the limitations
of the Maker's Kit as it consists only of software that can be used to target
any device capable of running C code. Here are a few examples of motivating use
cases:
-
Simulating an entire neuromorphic system on a single embedded computer that is connected to the application's true target input device(s) and output device(s)
- e.g. Simulating an SNN that controls an autonomous vehicle on a single low-power microcontroller connected to both a 2D LiDAR and the vehicle's speed controller
-
Simulating an SNN on a target hardware device where it would be normally difficult to setup other SNN-simulation software dependencies
- e.g. Simulating an SNN on a custom Linux image running on an FPGA+CPU system on chip to process radio frequency (RF) data
With these motivations in mind, the primary goals of framework_embedder are
the following:
-
Run & Done: Users should be able to deploy their SNNs to their target hardware with minimal effort, ideally with a single command.
-
Real-Time: Users should be able to run their trained SNNs in an embedded real-time system.
-
Accessibility: Anyone that wants to deploy an SNN to an embedded system should be able to without having to program their own simulator or gain access to scarcely available neuromorphic hardware.
-
Affordability: Cost should not be a barrier for those wanting to deploy SNNs to embedded systems.
-
Portability: Users should be able to run their SNNs on a variety of hardware, depending on what makes most sense for the given application.
Perform the following three simple steps to use the framework_embedder:
-
The following sfotware dependencies are required to build and use the
framework_embedder:- g++ with C++ 11 support
- TENNLab neuromorphic framework
After cloning the TENNLab neuromorphic framework, do one of the following:
-
Set the
frenvironment variable to the absolute path of the cloned framework in the shell that will be running theframework_embedderapp. Setting thisfrenvironment variable in a location such as$HOME/.profileon a UNIX system ensures the environment variable does not have to be re-set manually. Here is an example line that may be added to the end of a UNIX$HOME/.profileto setfr, assuming the framework is cloned into the$HOMEdirectory:export fr="$HOME/framework" -
Alternatively, the user may manually edit the
framework_embeddermakefileby replacing the single instance of$(fr)with the absolute path to the cloned framework.
-
After setting up the dependencies above, the user may run the following in a shell after navigating to this repository's directory:
make allThis compiles the
framework_embedderapp into an executable located in thebin/directory. To delete the executable and force a fresh compilation in the future, run the following:make clean -
After the
framework_embedderhas been compiled, run it using the following shell command:bin/framework_embedderThis will begin reading TENNLab JSON input from stdin until an EOF character is reached. The user will often want to redirect a TENNLab JSON file into stdin instead of manually inputting JSON; this may be done with:
bin/framework_embedder < <path/to/tennlab/json/file>The following types of TENNLab JSON objects are accepted as input to
framework_embedder, assuming they are within the limitations listed in the Limitations section below:- Spiking neural network (SNN)
framework_embeddershould output generated C code to stdout, assuming no errors occur.Note that the generated C code may be redirected to a C header file to act as a only SNN simulation library that can be easily integrated into a C application in a modular way. For example, this may be done with:
bin/framework_embedder < <path/to/tennlab/json/file> > my_c_header_file.h -
The command line argument options for
framework_embedderare as follows:-p,--processor= which processor you'd like code to be generated for; the defaultrispsetting describes sparse RISP whilerispSoAdescribes dense RISP; use dense RISP if you wish to save memory at the cost of event-based performance, <risp|rispSoA> (string [=risp])
The following C functions are generated by framework_embedder when the user
inputs SNN JSON:
-
void apply_spike(unsigned int input_ind, unsigned int time, double value): This function will apply a spike of potential valuevalueto the input neuron with an input neuron zero-based index ofinput_indat timetimerelative to the current timestep of the neuroprocessor. -
void run(double duration): This function will run the SNN forduration, the specified number of timesteps (many neuroprocessors only support discrete timesteps, such as RISP). -
void clear_activity(): This function will clear the SNN of all activity. It resets all neuron and synapse state. -
double output_last_fire(unsigned int output_ind): This function will return the timestep of the output neuron with an output neuron zero-based index ofoutput_ind. The returned timestep will only be for the most recent call of therun()function. -
unsigned int output_count(unsigned int output_ind): This function will return the number of neuronal fires for the output neuron with an output neuron zero-based index ofoutput_ind. The returned fire count will only be for the most recent call of therun()function.
framework_embedder has the following notable limitations:
-
Only SNN JSON for supported neuroprocessors may be used. The following are the only neuroprocessors currently supported:
- Sparse RISP (the conventional event-based version)
- Dense RISP (a non-event-based version that stores internal data more compactly)
-
RISP does not support the following parameters:
weightsinputs_from_weightsnoisy_seednoisy_stddevstdslog
The following link to markdown files that contain examples/tutorials for the framework embedder: