From 5cae610328befb6fc1cfe851ace43231ad42faba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Lanzend=C3=B6rfer?= <leviathan@libresilicon.com>
Date: Thu, 4 Jul 2024 22:41:34 +0100
Subject: [PATCH] Updat firmware

---
 firmware/firmware.c    | 29 ++++++++++++++++++++------
 firmware/include/rnn.h | 17 ++++++++--------
 firmware/rnn.c         | 46 +++++++++++++++++++++++-------------------
 3 files changed, 57 insertions(+), 35 deletions(-)

diff --git a/firmware/firmware.c b/firmware/firmware.c
index bc8835f..29893e1 100644
--- a/firmware/firmware.c
+++ b/firmware/firmware.c
@@ -79,7 +79,9 @@ void main()
       TRAIN_STORE_LEARNING_RATE,
       TRAIN_STORE_DECAY_RATE,
       TRAIN_RUN_EPOCHS,
-      TRAIN_RUN_SINGLE_EPOCH
+      TRAIN_RUN_SINGLE_EPOCH,
+      // The fun part: Inference
+      PREDICT
     } command_mode;
     command_mode = START;
 
@@ -93,13 +95,12 @@ void main()
     int new_value;
 
     // Training
-    uint32_t new_token;
-    uint32_t token_series[MAX_NUM_TOKENS];
+    uint16_t new_token;
+    uint16_t token_series[MAX_NUM_TOKENS];
     int token_counter = 0;
     uint32_t learning_rate = 0;
     uint32_t decay_rate = 0;
     uint32_t epoch_value = 0;
-    
 
     while(true) {
 
@@ -145,6 +146,9 @@ void main()
                 else if(!strcmp(msg,"TRAIN")) {
                     command_mode = TRAIN;
                 }
+                else if(!strcmp(msg,"PREDICT")) {
+                    command_mode = PREDICT;
+                }
                 break;
             
             case INIT:
@@ -249,11 +253,15 @@ void main()
 
             case WRITE_LAYER_WEIGHTS:
                 response = "END";
-                if(value_write_counter<current_max_num_values) {
+                if((value_write_counter<current_max_num_values) && (current_layer_value == LAYER_VALUE_TYPE_WEIGHTS) ) {
                     response = numstr;
                     new_value = atoi(numstr);
                     set_layer_weight(current_layer, neuron_idx, value_write_counter, new_value);
                     value_write_counter++;
+                } else if (current_layer_value == LAYER_VALUE_TYPE_BIAS) {
+                    response = numstr;
+                    new_value = atoi(numstr);
+                    set_layer_bias(current_layer, neuron_idx, new_value);
                 }
                 break;
 
@@ -286,7 +294,7 @@ void main()
                     new_token = atoi(numstr);
                     token_series[token_counter] = new_token;
                     token_counter++;
-                    response = numstr;
+                    response = itoa(token_counter, numstr, 10);
                 } else {
                     response = "END";
                 }
@@ -316,6 +324,15 @@ void main()
                 response = itoa(new_value, numstr, 10);
                 break;
 
+            case PREDICT:
+                new_token = atoi(numstr);
+                for(int i=0;i<MSGBUF;i++) {
+                    numstr[i]=0;
+                }
+                new_token = predict_next_token(new_token);
+                response = itoa(new_token, numstr, 10);
+                break;
+
         }
         write_response(response);
     }
diff --git a/firmware/include/rnn.h b/firmware/include/rnn.h
index 9f8fa6d..943e91a 100644
--- a/firmware/include/rnn.h
+++ b/firmware/include/rnn.h
@@ -22,7 +22,8 @@
 
 #define TRAINING_SINGLE_SHOT (1<<8)
 
-#define ENCODER_WEIGHT_COUNT (NUM_INPUT_SYNAPSES+NUM_INPUT_NEURONS)
+//#define ENCODER_WEIGHT_COUNT (NUM_INPUT_SYNAPSES+NUM_INPUT_NEURONS)
+#define ENCODER_WEIGHT_COUNT (NUM_INPUT_SYNAPSES)
 #define HIDDEN_WEIGHT_COUNT (NUM_INPUT_NEURONS+NUM_HIDDEN_NEURONS_H)
 #define DECODER_WEIGHT_COUNT (NUM_HIDDEN_NEURONS_H)
 
@@ -113,7 +114,7 @@ void set_layer_alpha(
 /*
  * Run inference
  */
-uint32_t predict_next_token(uint32_t token);
+uint16_t predict_next_token(uint16_t token);
 
 /*
  * Run trainingg
@@ -123,7 +124,7 @@ uint32_t predict_next_token(uint32_t token);
  * The mask is an XOR value of the bits of the supposed
  * output and what the network actually delivered
  */
-uint32_t mask_back_propgatation(uint32_t mask);
+uint16_t mask_back_propgatation(uint16_t mask);
 
 /*
  * Access the LSFR output inside the ANN controller
@@ -165,8 +166,8 @@ char* run_training(
     int num_epochs,
     uint32_t learning_rate_zero,
     uint32_t decay_rate,
-    uint32_t *xp,
-    uint32_t xn
+    uint16_t *xp,
+    int xi
 );
 
 /*
@@ -180,10 +181,10 @@ char* run_training(
  * Returns 0 when successful
  * Returns 1 when unsuccessful
  */
-uint32_t run_training_single_epoch(
+int run_training_single_epoch(
     int epoch,
     uint32_t learning_rate_zero,
     uint32_t decay_rate,
-    uint32_t *xp,
-    uint32_t xi
+    uint16_t *xp,
+    int xi
 );
diff --git a/firmware/rnn.c b/firmware/rnn.c
index b1e5f02..810774d 100644
--- a/firmware/rnn.c
+++ b/firmware/rnn.c
@@ -131,9 +131,9 @@ void set_layer_alpha(
 /*
  * Run inference
  */
-uint32_t predict_next_token(uint32_t token)
+uint16_t predict_next_token(uint16_t token)
 {
-    uint32_t ret;
+    uint16_t ret;
     ann_cmd = RUN_INFERENCE|INFERENCE_START;
     ann_value1 = token;
     ann_cmd = RUN_INFERENCE|INFERENCE_FETCH;
@@ -149,7 +149,7 @@ uint32_t predict_next_token(uint32_t token)
  * The mask is an XOR value of the bits of the supposed
  * output and what the network actually delivered
  */
-uint32_t mask_back_propgatation(uint32_t mask)
+uint16_t mask_back_propgatation(uint16_t mask)
 {
     ann_cmd = RUN_TRAINING|TRAINING_SINGLE_SHOT;
     ann_value1 = mask;
@@ -256,17 +256,18 @@ void set_bias_values(int bias)
  * Returns 0 when successful
  * Returns 1 when unsuccessful
  */
-uint32_t run_training_single_epoch(
+int run_training_single_epoch(
     int epoch,
     uint32_t learning_rate_zero,
     uint32_t decay_rate,
-    uint32_t *xp,
-    uint32_t xi
+    uint16_t *xp,
+    int xi
 )
 {
+    int error;
     int last_val;
-    uint32_t train_mask;
-    uint32_t y = xp[xi];;
+    uint16_t train_mask;
+    uint16_t y = xp[xi-1];;
 
     /*
      * Revert the LSTM states
@@ -276,16 +277,17 @@ uint32_t run_training_single_epoch(
      * Put all the prior tokens of the time series
      * into the LSTM for reaching the state we wish to train on
      */
-    for(int xpi=0; xpi<xi; xpi++) {
+    for(int xpi=0; xpi<xi-1; xpi++) {
         last_val = predict_next_token(xp[xpi]);
     }
+
     /*
      * Check whether the network has already been trained
      * Set return value to zero and exit the loop if so
      */
     train_mask = last_val ^ y;
-    if(!train_mask) {
-        return train_mask;
+    if(last_val==y) {
+        return 0;
     }
     /*
      * Determine the training mask my finding out which
@@ -293,8 +295,11 @@ uint32_t run_training_single_epoch(
      */
     set_alpha(learning_rate_zero/(1+(decay_rate*epoch)));
     mask_back_propgatation(train_mask);
-    
-    return train_mask;
+
+    error = 0;
+    for(int i=0;i<32;i++)
+        error+=(train_mask>>i)&1;
+    return error;
 }
 
 
@@ -313,13 +318,13 @@ int run_training_epochs(
     int num_epochs,
     uint32_t learning_rate_zero,
     uint32_t decay_rate,
-    uint32_t *xp,
-    uint32_t xi
+    uint16_t *xp,
+    int xi
 )
 {
     int last_val;
-    uint32_t train_mask;
-    uint32_t y = xp[xi];;
+    uint16_t train_mask;
+    uint16_t y = xp[xi];;
 
     for(int epoch=0; epoch<num_epochs;epoch++) {
         if(run_training_single_epoch(
@@ -349,8 +354,8 @@ char* run_training(
     int num_epochs,
     uint32_t learning_rate_zero,
     uint32_t decay_rate,
-    uint32_t *xp,
-    uint32_t xn
+    uint16_t *xp,
+    int xn
 )
 {
     int last_val;
@@ -367,7 +372,7 @@ char* run_training(
      * xi tells the functions where y is located in the array (x -> y)
      * xi must be xn-1 at most
      */
-    for(uint32_t xi=1; xi<xn; xi++) {
+    for(int xi=1; xi<xn; xi++) {
         ret = run_training_epochs(
             num_epochs,
             learning_rate_zero,
@@ -391,4 +396,3 @@ char* run_training(
 
     return msgbuf;
 }
-
-- 
GitLab