Skip to content

Commit

Permalink
Introduce software examples for Signaloid SoC
Browse files Browse the repository at this point in the history
  • Loading branch information
almidi committed Oct 11, 2024
1 parent 458f6ec commit b02fbe4
Show file tree
Hide file tree
Showing 47 changed files with 3,303 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/jekyll.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
with:
submodules: false
- name: Setup Ruby
uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0
uses: ruby/setup-ruby@086ffb1a2090c870a3f881cc91ea83aa4243d408 # v1.195.0
with:
ruby-version: '3.1' # Not needed with a .ruby-version file
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@ Thumbs.db
docs/_site/
docs/.jekyll-cache/
docs/Gemfile.lock

# Python
__pycache__
4 changes: 2 additions & 2 deletions docs/guides/switch-c0-microsd-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ You can use the `C0_microSD_toolkit.py`, which you can find [here](https://githu

4. Run `sudo python3 ./C0_microSD_toolkit.py -t /dev/disk4 -s` to switch operation mode. If this is successful, the opposite LED of the one that is solid should start blinking (Figures 3 and 4).

| ![inserted C0-microSD switching from bootloader to signaloid core](/assets/images/macbook-animations/switching-from-bootloader-to-signaloid-core.gif) | ![inserted C0-microSD switching from signaloid core to bootloader](/assets/images/macbook-animations/switching-from-signaloid-core-to-bootloader.gif) |
| ![inserted C0-microSD switching from Bootloader to Signaloid SoC](/assets/images/macbook-animations/switching-from-bootloader-to-signaloid-core.gif) | ![inserted C0-microSD switching from Signaloid SoC to Bootloader](/assets/images/macbook-animations/switching-from-signaloid-core-to-bootloader.gif) |
| :---------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------: |
| **Figure 3:** C0-microSD in **Bootloader** mode switching to **Signaloid Soc** mode. | **Figure 4:** C0-microSD in **Signaloid Soc** mode switching to **Bootloader** mode. |

Expand All @@ -39,7 +39,7 @@ You can use the `C0_microSD_toolkit.py`, which you can find [here](https://githu
5. Power-cycle the C0-microSD to load new configuration mode. This means that the LED that was previously flashing, should now be constantly on (Figures 5 and 6).
| ![power cycling from bootloader to signaloid core](/assets/images/macbook-animations/switch-from-bootloader-to-signaloid-core.gif) | ![power cycling from signaloid core to bootloader](/assets/images/macbook-animations/switch-from-signaloid-core-to-bootloader.gif) |
| ![power cycling from Bootloader to Signaloid SoC](/assets/images/macbook-animations/switch-from-bootloader-to-signaloid-core.gif) | ![power cycling from Signaloid SoC to Bootloader](/assets/images/macbook-animations/switch-from-signaloid-core-to-bootloader.gif) |
| :--------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: |
| **Figure 5:** Power cycling the C0-microSD to switch to **Signaloid Soc** mode. | **Figure 6:** Power cycling the C0-microSD to switch to **Bootloader** mode. |
Expand Down
2 changes: 1 addition & 1 deletion docs/hardware-overview/fpga-som/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ When using the Signaloid C0-microSD as a hot-pluggable FPGA SoM, you can plug it
|:--:| :--:|
| **Figure 1:** C0-microSD populating a breadboard using a microSD breakout board. | **Figure 2:** C0-microSD connected to an existing microcontroller platform. |

You can find example designs that use the on-board LEDs along with instructions on how to synthesize and load them to your device in the `examples/` directory of the [C0-microSD-Hardware](https://github.com/signaloid/C0-microSD-hardware) repository.
You can find example designs that use the on-board LEDs along with instructions on how to synthesize and load them to your device in the `rtl-examples/` directory of the [C0-microSD-Hardware](https://github.com/signaloid/C0-microSD-hardware) repository.

{: .note }
> Using the C0-microSD as a programmable FPGA SoM does not require switching between modes of operation. You only need to set your C0-microSD in **Bootloader** mode.
55 changes: 55 additions & 0 deletions docs/hardware-overview/signaloid-soc/compiling-applications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
layout: default
grand_parent: "Hardware Overview"
parent: "Signaloid SoC"

title: "Compiling Applications"
nav_order: 2
---

# Compiling Applications for the Signaloid SoC

## Install the RISC-V GNU cross-compilation toolchain
To compile applications for the built-in Signaloid SoC, you will require the open-source RISC-V GNU cross-compilation toolchain, that you can find [here](https://github.com/riscv-collab/riscv-gnu-toolchain). You can either build the cross-compilation toolchain from source, or install one of the pre-compiled binaries that you can find in the [releases](https://github.com/riscv-collab/riscv-gnu-toolchain/releases) section of the repository. Make sure to install the cross-compilation toolchain for the `RV32I` instruction set.

### Building from source.
You can find general installation instructions in the top-level `README.md` file of the cross-compilation toolchain [repository](https://github.com/riscv-collab/riscv-gnu-toolchain) to install it in your system. For targeting the Signaloid SoC, you must specify the target architecture to be RV32I. To do that, you must follow these steps:

#### Step A: Clone RISC-V GNU cross-compilation toolchain.
```sh
git clone --recursive https://github.com/riscv-collab/riscv-gnu-toolchain.git
```

#### Step B: Install gcc (macOS 14+ only)
This is a necessary step for macOS 14+ with Apple clang version 15.0.0 (clang-1500.3.9.4). Ignore this step in older macOS versions and Linux.

Install `gcc-mp-13` and `g++-mp-13` using:
```sh
sudo port install gcc-13
```

Set `CC` and `CXX` environment variables so that the following configure picks them up:
```sh
export CXX=g++-mp-13 CC=gcc-mp-13
```

#### Step C: Configure the cross-compilation toolchain installation
Configure the Makefiles to build for the RISC-V R32I ISA with the `ilp32` application binary interface (ABI). Note that the `--prefix` flag sets where you wish the cross-compilation toolchain to be installed. You need to modify `/path/to/installation/dir` accordingly. The `disable-gdb` disables the build of `gdb`. You can remove it if you wish to build `gdb`.
```bash
./configure --prefix=/path/to/installation/dir --with-arch=rv32i --with-abi=ilp32 --disable-gdb
```

#### Step D: Build
You can start the build by executing:
```sh
make
```
You can optionally instruct `make` to parallelize the build process using the `-j` flag. For example, to use four parallel workers you need to execute:
```sh
make -j4
```

The build process takes some minutes. If it is successful, you should see the cross-compilation toolchain in the installation directory that you specified using the prefix argument in the configuration step.

## Compile your application
You can find Makefile examples for compiling applications for the Signaloid SoC in the `signaloid-soc-examples/` directory of the official C0-microSD [repository](https://github.com/signaloid/C0-microSD-hardware). When compiling the examples, make sure to modify each Makefile to correctly point to your toolchain installation path.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ grand_parent: "Hardware Overview"
parent: "Signaloid SoC"

title: "Flashing Applications"
nav_order: 2
nav_order: 3
---

# Flashing Applications to the C0-microSD
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 12 additions & 0 deletions signaloid-soc-examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Example applications for the Signaloid SoC
This directory contains example applications for running on the Signaloid SoC. Specifically:
- `breathe-led/` contains an small that applies a "breathing" effect on the Signaloid SoC status LED using soft PWM. This example does not involve a host application.
- `basic-arithmetic/` contains a basic example that executes arithmetics (addition, subtraction, multiplication, and division) on two floating-point values. For this example, we provide two implementations for the host application, written in C and Python.
- `common/` contains the required linker script and initialization script for compiling applications for the Signaloid SoC.

## Getting Started
### Install the RISC-V GNU toolchain
These examples require the open-source RISC-V GNU toolchain, that you can find [here](https://github.com/riscv-collab/riscv-gnu-toolchain), for targeting the Signaloid SoC. You can either build the toolchain from source, or install one of the pre-compiled binaries that you can find in the [releases](https://github.com/riscv-collab/riscv-gnu-toolchain/releases) section of the repository. You can find more details in the Signaloid C0-microSD [documentation page](https://c0-microsd-docs.signaloid.io/hardware-overview/signaloid-soc/compiling-applications).

### Python requirements
Additionally, the `C0_microSD_toolkit.py` Python script, which is necessary for flashing new binaries to the device, and switching between `Bootloader` and `Signaloid SoC` modes requires `Python3.8` and above.
30 changes: 30 additions & 0 deletions signaloid-soc-examples/basic-arithmetic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Basic arithmetic example for Signaloid SoC
This is a simple [Signaloid SoC](https://c0-microsd-docs.signaloid.io/hardware-overview/signaloid-soc/) example that executes basic arithmetics (addition, subtraction, multiplication, and division) on two floating-point values. The application running on the Signaloid SoC is designed to work in conjunction with a "master" host application that sends parameters and issues commands. The host application communicates with the Signaloid SoC via the SD interface by issuing block reads/writes to a set of pre-determined [addresses](https://c0-microsd-docs.signaloid.io/hardware-overview/signaloid-soc/communication-scheme.html). For this example, we provide two implementations for the host application, written in C and Python.

Directories:
- `signaloid-soc-application/` contains the source code for the Signaloid SoC application.
- `host-application/` contains a C-based application that runs on the host machine and communicates with the Signaloid SoC.
- `host-application/` contains a Python based application that runs on the host machine and communicates with the Signaloid SoC.

# How to use:
## Build and flash the Signaloid SoC application
1. Make sure the C0-microSD is in `Bootloader` mode and connected.
2. Navigate to the `signaloid-soc-application/` directory.
3. Modify the `Makefile` to point to your `RV32I` toolchain[^1].
4. Run `make` to build the application.
5. Run `make flash DEVICE=/dev/diskx`, where `/dev/diskX` is the C0-microSD device path[^2], to flash the application.
6. Run `make switch DEVICE=/dev/diskx`, where `/dev/diskX` is the C0-microSD device path, to switch to the Signaloid SoC (the green LED should blink).
7. Power cycle the C0-microSD. The green LED should light up[^3].

## Build and run the C based host application
1. Navigate to the `host-application` directory.
2. Run `make` to build the application.
3. Run `sudo ./host-application /dev/diskX` where `/dev/diskX` is the C0-microSD device path.

## Run the Python based host application
1. Navigate to the `python-host-application` directory.
2. Run `sudo python3 host_application.py /dev/diskX A B` where `/dev/diskX` is the C0-microSD device path, and `A` and `B` are floating point values.

[^1]: You will need to install the [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) on your system. Make sure the toolchain supports `RV32I`.
[^2]: Guide: [Identify the Signaloid C0-microSD](https://c0-microsd-docs.signaloid.io/guides/identify-c0-microsd.html).
[^3]: Guide: [Switch between Operation Modes](https://c0-microsd-docs.signaloid.io/guides/switch-c0-microsd-mode.html)
32 changes: 32 additions & 0 deletions signaloid-soc-examples/basic-arithmetic/host-application/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Copyright (c) 2024, Signaloid.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#

CC = gcc
TOOLKIT_LIB = ../../../submodules/C0-microSD-utilities/src/c/lib/*
TOOLKIT_INCLUDE = ../../../submodules/C0-microSD-utilities/src/c/include/
INCLUDES = -I$(TOOLKIT_INCLUDE)

host-application: main.c
$(CC) $(INCLUDES) -o host-application main.c $(TOOLKIT_LIB)

clean:
rm -f host-application
201 changes: 201 additions & 0 deletions signaloid-soc-examples/basic-arithmetic/host-application/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright (c) 2024, Signaloid.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>
#include <stdbool.h>
#include <errno.h>

#include "C0microSDConstants.h"
#include "C0microSDHostUtils.h"

enum
{
kCalculateNoCommand = 0,
kCalculateAddition = 1,
kCalculateSubtraction = 2,
kCalculateMultiplication = 3,
kCalculateDivision = 4,
};

enum
{
kReturnSuccess = 0,
kReturnError = 1,
};

/**
* @brief Sends a command to the Signaloid SoC and parses the output buffer.
*
* @param device: Path to C0-microSD.
* @param command: Command to execute.
* @param readBuffer: Pointer to temp buffer for storing the Signaloid SoC MISO buffer data.
* @return The first 4 bytes of the result buffer parsed as float.
*/
float
calculateDataFP(char * device, uint32_t command, float * readBuffer)
{
float returnValue = NAN;
SignaloidSoCStatus deviceStatus;

printf("Start calculation of command: %u\n", command);
/*
* Instruct Signaloid C0-microSD compute module which command to execute
*/
hostUtilsSendSignaloidSoCCommand(device, command);

printf("Waiting for calculation to finish\n");
while (1)
{
/*
* Get status of Signaloid C0-microSD compute module
*/
deviceStatus = hostUtilsReadSignaloidSoCStatusRegister(device);

if (deviceStatus == kSignaloidSoCStatusCalculating)
{
/*
* Signaloid C0-microSD compute module is still calculating
*/
printf(".\n");
sleep(1);
}
else if (deviceStatus == kSignaloidSoCStatusDone)
{
/*
* Signaloid C0-microSD completed calculation
* Read the output of Signaloid C0-microSD calculation
*/
hostUtilsReadSignaloidSoCMISOBuffer(device, readBuffer);
returnValue = readBuffer[0];
break;
}
else if (deviceStatus == kSignaloidSoCStatusInvalidCommand)
{
printf("ERROR: Device returned 'Unknown CMD'\n");
break;
}
else if (deviceStatus != kSignaloidSoCStatusWaitingForCommand)
{
printf("ERROR: Device returned 'Unknown CMD'\n");
break;
}
}

/*
* Send ack to Signaloid C0-microSD compute module
*/
while (hostUtilsReadSignaloidSoCStatusRegister(device) != kSignaloidSoCStatusWaitingForCommand)
{
hostUtilsSendSignaloidSoCCommand(device, kCalculateNoCommand);
}

return returnValue;
}

int
main(int argc, char * argv[])
{
C0microSDConfigurationStatus configurationStatus;
float MISOBuffer[kSignaloidSoCCommonConstantsMISOBufferSizeWords];
float MOSIBuffer[kSignaloidSoCCommonConstantsMOSIBufferSizeWords];
float valueA;
float valueB;
float calculatedResult = 0.0f;

if (argc != 4)
{
/*
* Ensure exactly three arguments are provided
*/
printf("Usage: %s <device path> <float1> <float2>\n", argv[0]);
return kReturnError;
}

char *endptr;

/*
* Attempt to convert the second argument to a float
*/
errno = 0;
valueA = strtof(argv[2], &endptr);
if ((errno != 0) || (endptr == argv[2]) || (*endptr != '\0'))
{
printf("Error: '%s' is not a valid floating-point number.\n", argv[2]);
return kReturnError;
}

/*
* Attempt to convert the third argument to a float
*/
errno = 0;
valueB = strtof(argv[3], &endptr);
if ((errno != 0) || (endptr == argv[3]) || (*endptr != '\0'))
{
printf("Error: '%s' is not a valid floating-point number.\n", argv[3]);
return kReturnError;
}

printf("Device target: %s\n", argv[1]);
printf("First float parameter: %f\n", valueA);
printf("Second float parameter: %f\n", valueB);

printf("\nReading C0-microSD status\n");
configurationStatus = hostUtilsReadC0microSDConfigurationStatus(argv[1]);
hostUtilsAssertSignaloidSoCStatus(configurationStatus);
hostUtilsPrintC0microSDConfigurationStatus(configurationStatus);

printf("\nInitializing input floating-point data buffer\n\n");
MOSIBuffer[0] = valueA;
MOSIBuffer[1] = valueB;
hostUtilsWriteSignaloidSoCMOSIBuffer(argv[1], (void *) MOSIBuffer);

/*
* Calculate addition of valueA and valueB
*/
calculatedResult = calculateDataFP(argv[1], kCalculateAddition, MISOBuffer);
printf("Calculated output of addition: %f\n\n", calculatedResult);

/*
* Calculate subtraction of valueA and valueB
*/
calculatedResult = calculateDataFP(argv[1], kCalculateSubtraction, MISOBuffer);
printf("Calculated output of subtraction: %f\n\n", calculatedResult);

/*
* Calculate multiplication of valueA and valueB
*/
calculatedResult = calculateDataFP(argv[1], kCalculateMultiplication, MISOBuffer);
printf("Calculated output of multiplication: %f\n\n", calculatedResult);

/*
* Calculate division of valueA and valueB
*/
calculatedResult = calculateDataFP(argv[1], kCalculateDivision, MISOBuffer);
printf("Calculated output of division: %f\n\n", calculatedResult);

printf("Done...\n");
return kReturnSuccess;
}
Loading

0 comments on commit b02fbe4

Please sign in to comment.