f49fbbe7794a02fb56cb65460b24e83647c879d3
[processor-sdk/open-amp.git] / apps / matrix_multiply / matrix_multiply.c
1 /* This is a sample demonstration application that showcases usage of remoteproc
2 and rpmsg APIs on the remote core. This application is meant to run on the remote CPU 
3 running baremetal code. This applicationr receives two matrices from the master, 
4 multiplies them and returns the result to the master core. */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include "openamp/open_amp.h"
12 #include "rsc_table.h"
13 #include "platform_info.h"
15 #define MAX_SIZE                6
16 #define NUM_MATRIX              2
17 #define SHUTDOWN_MSG            0xEF56A55A
19 #define raw_printf(format, ...) printf(format, ##__VA_ARGS__)
20 #define LPRINTF(format, ...) raw_printf("CLIENT> " format, ##__VA_ARGS__)
21 #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
23 typedef struct _matrix {
24         unsigned int size;
25         unsigned int elements[MAX_SIZE][MAX_SIZE];
26 } matrix;
28 /* Internal functions */
29 static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);
30 static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);
31 static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *,
32                           unsigned long);
34 /* Globals */
35 static struct rpmsg_channel *app_rp_chnl;
36 static struct _matrix i_matrix[2];
37 static struct _matrix e_matrix;
38 static unsigned int result_returned = 0;
39 static int err_cnt = 0;;
40 static struct rpmsg_endpoint *rp_ept;
41 static struct remote_proc *proc = NULL;
42 static struct rsc_table_info rsc_info;
43 extern const struct remote_resource_table resources;
44 extern struct rproc_info_plat_local proc_table;
46 /* External functions */
47 extern void init_system();
48 extern void cleanup_system();
50 int __attribute__((weak)) _gettimeofday(struct timeval *tv,
51                                         void *tz)
52 {
53         (void)tv;
54         (void)tz;
55         return 0;
56 }
58 static void matrix_print(struct _matrix *m)
59 {
60         unsigned int i, j;
62         /* Generate two random matrices */
63         LPRINTF("Printing matrix... \n");
65         for (i = 0; i < m->size; ++i) {
66                 for (j = 0; j < m->size; ++j)
67                         raw_printf(" %u ", m->elements[i][j]);
68                 raw_printf("\n");
69         }
70 }
72 static void generate_matrices(int num_matrices,
73                               unsigned int matrix_size, void *p_data)
74 {
75         unsigned int i, j, k;
76         struct _matrix *p_matrix = p_data;
77         unsigned long value;
80         for (i = 0; i < (unsigned int)num_matrices; i++) {
81                 /* Initialize workload */
82                 p_matrix[i].size = matrix_size;
84                 //LPRINTF("Input matrix %d \n", i);
85                 for (j = 0; j < matrix_size; j++) {
86                         //printf("\n");
87                         for (k = 0; k < matrix_size; k++) {
89                                 value = (rand() & 0x7F);
90                                 value = value % 10;
91                                 p_matrix[i].elements[j][k] = value;
92                                 //printf(" %u ", p_matrix[i].elements[j][k]);
93                         }
94                 }
95                 //printf("\n");
96         }
98 }
100 static void matrix_multiply(const matrix * m, const matrix * n, matrix * r)
102         unsigned int i, j, k;
104         memset(r, 0x0, sizeof(matrix));
105         r->size = m->size;
107         for (i = 0; i < m->size; ++i) {
108                 for (j = 0; j < n->size; ++j) {
109                         for (k = 0; k < r->size; ++k) {
110                                 r->elements[i][j] +=
111                                     m->elements[i][k] * n->elements[k][j];
112                         }
113                 }
114         }
117 /* Application entry point */
118 int main()
120         int shutdown_msg = SHUTDOWN_MSG;
121         int c;
122         int status = 0;
124         /* Initialize HW system components */
125         init_system();
127         rsc_info.rsc_tab = (struct resource_table *)&resources;
128         rsc_info.size = sizeof(resources);
130         LPRINTF("Compute thread unblocked ..\n");
131         LPRINTF("It will generate two random matrices.\n");
132         LPRINTF("Send to the remote and get the computation result back.\n");
133         LPRINTF("It will then check if the result is expected.\n");
135         /* Initialize RPMSG framework */
136         status =
137             remoteproc_resource_init(&rsc_info, &proc_table,
138                                      rpmsg_channel_created,
139                                      rpmsg_channel_deleted, rpmsg_read_cb,
140                                      &proc, 1);
141         if (status) {
142                 LPERROR("Failed  to initialize remoteproc resource.\n");
143                 return -1;
144         }
146         LPRINTF("Remote proc resource initialized.\n");
147         while (!app_rp_chnl) {
148                 hil_poll(proc->proc, 0);
149         }
151         LPRINTF("RPMSG channel has created.\n");
152         err_cnt = 0;
153         srand(time(NULL));
154         for (c = 0; c < 200; c++) {
155                 generate_matrices(2, MAX_SIZE, i_matrix);
156                 matrix_multiply(&i_matrix[0], &i_matrix[1],
157                                 &e_matrix);
158                 result_returned = 0;
159                 status = rpmsg_send(app_rp_chnl, i_matrix, sizeof(i_matrix));
161                 if (status) {
162                         LPRINTF("Error sending data...\n");
163                         break;
164                 }
165                 LPRINTF("Matrix multiply: sent : %u\n", sizeof(i_matrix));
166                 do {
167                         hil_poll(proc->proc, 0);
168                 } while (!result_returned && !err_cnt && app_rp_chnl);
170                 if (err_cnt && !app_rp_chnl)
171                         break;
172         }
174         if (app_rp_chnl) {
175                 /* Send shutdown message to remote */
176                 rpmsg_send(app_rp_chnl, &shutdown_msg, sizeof(int));
177         }
178         sleep(1);
179         LPRINTF("Quitting application .. Matrix multiplication end\n");
181         LPRINTF("**********************************\n");
182         LPRINTF(" Test Results: Error count = %d \n", err_cnt);
183         LPRINTF("**********************************\n");
185         remoteproc_resource_deinit(proc);
186         cleanup_system();
188         return 0;
191 static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl)
193         app_rp_chnl = rp_chnl;
194         rp_ept = rpmsg_create_ept(rp_chnl, rpmsg_read_cb, RPMSG_NULL,
195                                   RPMSG_ADDR_ANY);
198 static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl)
200         (void)rp_chnl;
201         rpmsg_destroy_ept(rp_ept);
202         LPRINTF("%s\n", __func__);
203         app_rp_chnl = NULL;
204         rp_ept = NULL;
207 static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
208                           void *priv, unsigned long src)
210         (void)rp_chnl;
211         (void)priv;
212         (void)src;
213         struct _matrix *r_matrix = (struct _matrix *)data;
214         int i, j;
215         if (len != sizeof(struct _matrix)) {
216                 LPERROR("Received matrix is of invalid len: %d:%d\n",
217                         (int)sizeof(struct _matrix), len);
218                 err_cnt++;
219                 return;
220         }
221         for (i = 0; i < MAX_SIZE; i++) {
222                 for (j = 0; j < MAX_SIZE; j++) {
223                         if (r_matrix->elements[i][j] !=
224                                 e_matrix.elements[i][j]) {
225                                 err_cnt++;
226                                 break;
227                         }
228                 }
229         }
230         if (err_cnt) {
231                 LPERROR("Result mismatched...\n");
232                 LPERROR("Expected matrix:\n");
233                 matrix_print(&e_matrix);
234                 LPERROR("Actual matrix:\n");
235                 matrix_print(r_matrix);
236         } else {
237                 result_returned = 1;
238         }