98ffc91fb2cd8c8ffb8235407fff2532360f853b
[litex.git] / litex / build / sim / core / sim.c
1 /* Copyright (C) 2017 LambdaConcept */
2
3 #include <string.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <signal.h>
7 #ifndef _WIN32
8 #include <netinet/in.h>
9 # ifdef _XOPEN_SOURCE_EXTENDED
10 # include <arpa/inet.h>
11 # endif
12 #include <sys/socket.h>
13 #endif
14 #include <stdlib.h>
15 #include "error.h"
16 #include "modules.h"
17 #include "pads.h"
18 #include "veril.h"
19
20 #include <event2/listener.h>
21 #include <event2/util.h>
22 #include <event2/event.h>
23
24 void litex_sim_init(void **out);
25 void litex_sim_dump();
26
27 struct session_list_s {
28 void *session;
29 char tickfirst;
30 struct ext_module_s *module;
31 struct session_list_s *next;
32 };
33
34 uint64_t timebase_ps = 1;
35 uint64_t sim_time_ps = 0;
36 struct session_list_s *sesslist=NULL;
37 struct event_base *base=NULL;
38
39 static int litex_sim_initialize_all(void **sim, void *base)
40 {
41 struct module_s *ml=NULL;
42 struct module_s *mli=NULL;
43 struct ext_module_list_s *mlist=NULL;
44 struct ext_module_list_s *pmlist=NULL;
45 //struct ext_module_list_s *mlisti=NULL;
46 struct pad_list_s *plist=NULL;
47 struct pad_list_s *pplist=NULL;
48 struct session_list_s *slist=NULL;
49 void *vsim=NULL;
50 int i;
51 int ret = RC_OK;
52
53 /* Load external modules */
54 ret = litex_sim_load_ext_modules(&mlist);
55 if(RC_OK != ret)
56 {
57 goto out;
58 }
59 for(pmlist = mlist; pmlist; pmlist=pmlist->next)
60 {
61 if(pmlist->module->start)
62 {
63 pmlist->module->start(base);
64 }
65 }
66
67 /* Load configuration */
68 ret = litex_sim_file_parse("sim_config.js", &ml, &timebase_ps);
69 if(RC_OK != ret)
70 {
71 goto out;
72 }
73 /* Init generated */
74 litex_sim_init(&vsim);
75
76 /* Get pads from generated */
77 ret = litex_sim_pads_get_list(&plist);
78 if(RC_OK != ret)
79 {
80 goto out;
81 }
82
83 for(mli = ml; mli; mli=mli->next)
84 {
85
86 /* Find the module in the external module */
87 pmlist = NULL;
88 ret = litex_sim_find_ext_module(mlist, mli->name, &pmlist );
89 if(RC_OK != ret)
90 {
91 goto out;
92 }
93 if(NULL == pmlist)
94 {
95 eprintf("Could not find module %s\n", mli->name);
96 continue;
97 }
98
99 slist=(struct session_list_s *)malloc(sizeof(struct session_list_s));
100 if(NULL == slist)
101 {
102 ret = RC_NOENMEM;
103 goto out;
104 }
105 memset(slist, 0, sizeof(struct session_list_s));
106
107 slist->tickfirst = mli->tickfirst;
108 slist->module = pmlist->module;
109 slist->next = sesslist;
110 ret = pmlist->module->new_sess(&slist->session, mli->args);
111 if(RC_OK != ret)
112 {
113 goto out;
114 }
115 sesslist = slist;
116
117 /* For each interface */
118 for(i = 0; i < mli->niface; i++)
119 {
120 /*Find the pads */
121 pplist=NULL;
122 ret = litex_sim_pads_find(plist, mli->iface[i].name, mli->iface[i].index, &pplist);
123 if(RC_OK != ret)
124 {
125 goto out;
126 }
127 if(NULL == pplist)
128 {
129 eprintf("Could not find interface %s with index %d\n", mli->iface[i].name, mli->iface[i].index);
130 continue;
131 }
132 ret = pmlist->module->add_pads(slist->session, pplist);
133 if(RC_OK != ret)
134 {
135 goto out;
136 }
137 }
138 }
139 *sim = vsim;
140 out:
141 return ret;
142 }
143
144 int litex_sim_sort_session()
145 {
146 struct session_list_s *s;
147 struct session_list_s *sprev=sesslist;
148
149 if(!sesslist->next)
150 {
151 return RC_OK;
152 }
153
154 for(s = sesslist->next; s; s=s->next)
155 {
156 if(s->tickfirst)
157 {
158 sprev->next = s->next;
159 s->next = sesslist;
160 sesslist=s;
161 s=sprev;
162 continue;
163 }
164 sprev = s;
165 }
166
167 return RC_OK;
168 }
169
170 struct event *ev;
171
172 static void cb(int sock, short which, void *arg)
173 {
174 struct session_list_s *s;
175 void *vsim=arg;
176 struct timeval tv;
177 tv.tv_sec = 0;
178 tv.tv_usec = 0;
179 int i;
180
181 for(i = 0; i < 1000; i++)
182 {
183 for(s = sesslist; s; s=s->next)
184 {
185 if(s->tickfirst)
186 s->module->tick(s->session, sim_time_ps);
187 }
188
189 litex_sim_eval(vsim);
190 litex_sim_dump();
191
192 for(s = sesslist; s; s=s->next)
193 {
194 if(!s->tickfirst)
195 s->module->tick(s->session, sim_time_ps);
196 }
197
198 sim_time_ps = litex_sim_increment_time(timebase_ps);
199
200 if (litex_sim_got_finish()) {
201 event_base_loopbreak(base);
202 break;
203 }
204 }
205
206 if (!evtimer_pending(ev, NULL)) {
207 event_del(ev);
208 evtimer_add(ev, &tv);
209 }
210 }
211
212 int main(int argc, char *argv[])
213 {
214 void *vsim=NULL;
215 struct timeval tv;
216
217 int ret;
218
219 #ifdef _WIN32
220 WSADATA wsa_data;
221 WSAStartup(0x0201, &wsa_data);
222 #endif
223
224
225 base = event_base_new();
226 if(!base)
227 {
228 eprintf("Can't allocate base\n");
229 ret=RC_ERROR;
230 goto out;
231 }
232
233 litex_sim_init_cmdargs(argc, argv);
234 if(RC_OK != (ret = litex_sim_initialize_all(&vsim, base)))
235 {
236 goto out;
237 }
238
239 if(RC_OK != (ret = litex_sim_sort_session()))
240 {
241 goto out;
242 }
243
244 tv.tv_sec = 0;
245 tv.tv_usec = 0;
246 ev = event_new(base, -1, EV_PERSIST, cb, vsim);
247 event_add(ev, &tv);
248 event_base_dispatch(base);
249 #if VM_COVERAGE
250 litex_sim_coverage_dump();
251 #endif
252 out:
253 return ret;
254 }