File indexing completed on 2024-04-06 12:21:27
0001 #ifndef NNET_DENSE_H_
0002 #define NNET_DENSE_H_
0003
0004 #include "nnet_common.h"
0005 #include "nnet_mult.h"
0006 #include <math.h>
0007
0008 namespace nnet {
0009
0010 struct dense_config {
0011
0012 typedef float bias_t;
0013 typedef float weight_t;
0014 typedef float accum_t;
0015
0016
0017 static const unsigned n_in = 10;
0018 static const unsigned n_out = 10;
0019
0020
0021 int io_type = io_parallel;
0022 int strategy = latency;
0023 int reuse_factor = 1;
0024 static const bool store_weights_in_bram = false;
0025 int n_zeros = 0;
0026
0027
0028 template <class x_T, class y_T>
0029 using product = nnet::product::mult<x_T, y_T>;
0030 };
0031
0032 template <class data_T, class res_T, typename CONFIG_T>
0033 void dense(data_T data[CONFIG_T::n_in],
0034 res_T res[CONFIG_T::n_out],
0035 typename CONFIG_T::weight_t weights[CONFIG_T::n_in * CONFIG_T::n_out],
0036 typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) {
0037 data_T cache;
0038 typename CONFIG_T::accum_t mult[CONFIG_T::n_in * CONFIG_T::n_out];
0039 typename CONFIG_T::accum_t acc[CONFIG_T::n_out];
0040
0041
0042 for (unsigned ii = 0; ii < CONFIG_T::n_in; ii++) {
0043 cache = data[ii];
0044 for (unsigned jj = 0; jj < CONFIG_T::n_out; jj++) {
0045 unsigned index = ii * CONFIG_T::n_out + jj;
0046 mult[index] = CONFIG_T::template product<data_T, typename CONFIG_T::weight_t>::product(cache, weights[index]);
0047 }
0048 }
0049
0050
0051 for (unsigned iacc = 0; iacc < CONFIG_T::n_out; iacc++) {
0052 acc[iacc] = (typename CONFIG_T::accum_t)biases[iacc];
0053 }
0054
0055
0056 for (unsigned ii = 0; ii < CONFIG_T::n_in; ii++) {
0057 for (unsigned jj = 0; jj < CONFIG_T::n_out; jj++) {
0058 unsigned index = ii * CONFIG_T::n_out + jj;
0059 acc[jj] += mult[index];
0060 }
0061 }
0062
0063
0064 for (unsigned ires = 0; ires < CONFIG_T::n_out; ires++) {
0065
0066 res[ires] = cast<data_T, res_T, CONFIG_T>(acc[ires]);
0067 }
0068 }
0069
0070 }
0071
0072 #endif