This project implements a simple feedforward Artificial Neural Network (ANN) completely in RISC-V Assembly. The network is designed to classify handwritten decimal digits (from raw PGM format images) using pre-trained weight matrices.
The implementation reads the input image and the necessary weight matrices from binary files, performs the required linear algebra operations and activation functions, and outputs the predicted digit.
The main execution pipeline is handled by the classify function, which performs the following steps:
- Data Loading: Reads the weight matrices (
m0andm1) and the input image (input) from binary files. - Data Conversion: Converts the raw byte data into 32-bit integer arrays for processing.
- Hidden Layer Computation: Computes the hidden layer
husing Matrix Multiplication and a ReLU activation function:h = ReLU(matmul(m0, input)). - Output Layer Computation: Computes the final output array
ousing Matrix Multiplication:o = matmul(m1, h). - Classification: Uses the
argmaxfunction on the output arrayoto determine the highest scoring class, which corresponds to the predicted decimal digit.
The program includes several modular assembly routines to handle specific tasks:
abs: Computes the absolute value of an integer.relu: Applies the Rectified Linear Unit (ReLU) activation function in-place on an array.argmax: Returns the index of the largest element in an array.dotproduct: Computes the dot product of two integer arrays.matmul: Performs matrix multiplication of two integer matrices.read_file: Handles system calls to read data from files into memory.turn_int: Converts an array of bytes (chars) into 32-bit integers, with optional offset and value adjustments.classify: The main orchestrator that runs the neural network inference.
The code incorporates several optimizations to improve computational efficiency:
- Memory Access Minimization: Reuses pointers and minimizes memory accesses for faster execution.
- Efficient Data Conversion: Direct conversion of bytes to integers using optimized offsets, reducing redundant instructions.
- Optimized Matrix Multiplication: Explicit register usage and manual index control during matrix operations to speed up the
matmulroutine. - In-place ReLU: The ReLU activation function modifies the array directly in memory, avoiding unnecessary memory allocation and copying.
- Efficient Stack Management: Optimized use of the stack for context preservation and restoration during function calls.
MIT License © 2025 Guilherme Marques.