interactive testing
[gnucap-felix.git] / src / extlib.cc
blob98ad84f7e1959a56defb0f28560c0a9cccf30b57
1 /*$Id$
2 * vim:sw=2:et:ts=8:
3 * Copyright (C) 2009 Kevin Cameron
4 * Author: Kevin Cameron
6 * This file is a part of plugin "Gnucap-Icarus" to "Gnucap",
7 * the Gnu Circuit Analysis Package
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3, or (at your option)
12 * any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 *------------------------------------------------------------------
24 * Dynamic binding of PWL signal sources to external simulators
26 #include "u_lang.h"
27 #include "globals.h"
28 #include "e_card.h"
29 #include "e_cardlist.h"
30 #include "s_tr.h"
31 #include "extlib.h"
32 #include "bm.h"
33 //#include "vvp.h"
34 #include "d_vvp.h"
36 # include "vvp/compile.h"
37 # include "vvp/schedule.h"
38 # include "vvp/vpi_priv.h"
39 # include "vvp/statistics.h"
40 # include "vvp/vvp_cleanup.h"
41 # include <cstdio>
42 # include <csignal>
43 # include <cstdlib>
44 # include <cstring>
45 # include <unistd.h>
46 /*--------------------------------------------------------------------------*/
47 /*--------------------------------------------------------------------------*/
49 inline double digital_time(void)
51 return double(schedule_simtime() * (long double) pow(10.0,vpip_get_time_precision())) ;
54 // static std::list<ExtLib*> Libs;
56 void ExtLib::set_active(void *,double time)
58 if (active) {
59 if (time >= next_time) {
60 return;
62 } else {
63 active = 1;
65 next_time = time;
66 if (time > now) {
67 CKT_BASE::_sim->new_event(time);
70 /*--------------------------------------------------------------------------*/
71 void ExtLib::SetActive(void *dl,void *handle,double time)
72 // extLib ^^
74 SpcDllData *spd = (SpcDllData *)dl;
75 ExtLib *lib = ExtLib::Sdd2El(spd);
76 lib->set_active(handle,time);
78 /*--------------------------------------------------------------------------*/
79 int ExtLib::init(const char *args) {
81 trace0("ExtLib::init");
83 #ifdef DLINKED
84 const char* e;
85 vhbn = (typeof(vhbn))dlsym(handle,"vpi_handle_by_name");
86 assert(vhbn);
87 bindnet = (typeof(bindnet))dlsym(handle,"bindnet");
88 assert(bindnet);
89 startsim = (typeof(startsim))dlsym(handle,"startsim");
90 assert(startsim);
91 endsim = (typeof(endsim))dlsym(handle,"endsim");
92 assert(endsim);
93 contsim = (typeof(contsim))dlsym(handle,"contsim");
94 assert(contsim);
95 so_main = (typeof(so_main))dlsym(handle,"so_main");
96 if(!so_main){
97 error(bDANGER, "so: %s\n", dlerror());
99 assert(so_main);
100 activate = (typeof(activate))SetActive;
101 assert(activate);
102 #else
103 startsim = &vvp::startsim;
104 //bindnet = &vvp::bindnet;
105 //assert(bindnet);
106 assert(startsim);
107 endsim = &vvp::endsim;
108 assert(endsim);
109 contsim = &vvp::contsim;
110 assert(contsim);
111 so_main = &vvp::init;
112 if(!so_main){
113 error(bDANGER, "so: %s\n", dlerror());
115 assert(so_main);
116 //activate = &vvp::SetActive;
117 //assert(activate);
118 #endif
120 return( (*so_main)(args) );
125 void ExtSig::SetActive(void *,void *sig,double time)
127 // SpcDllData *spd = (SpcDllData *)dl;
129 ((ExtSig*)sig)->set_active(time);
130 trace1("ExtSig::SetActive", (intptr_t)sig );
133 void ExtSig::set_active(double ) {
136 void PrintInst(FILE *fp,struct __vpiScope *scope);
137 extern int SpcDebug;
139 void PrintInst(FILE *fp,struct __vpiScope *scope)
141 if (scope->scope) {
142 PrintInst(fp,scope->scope);
143 fputs(".",fp);
145 fputs(scope->name,fp);
147 /*-----------------------------------------------------*/
149 bool have_ivl_version = true;
151 double vvp::SimTimeD = 0.0;
152 double vvp::SimTimeA = 0.0;
153 // double SimTimeA = 0.0;
154 double vvp::SimTimeDlast = 0.0;
155 double vvp::SimDelayD = -1.0;
157 sim_mode vvp::SimState = SIM_ALL;
160 // Provide dummies
161 inline static void my_getrusage(struct rusage *) { }
162 inline static void print_rusage(struct rusage *, struct rusage *){};
163 /*--------------------------------------------------------------------*/
165 //from vvp_vpi.cc
166 void vvp::vvp_vpi_init()
168 trace0("not doing anything");
170 /*------------------------------------------------*/
171 // replacement for main...
172 int vvp::init(const char* design_path)
174 static int vvp_return_value;
175 ofstream debug_file;
176 const char *logfile_name = 0x0;
177 FILE *logfile = 0x0;
178 extern void vpi_set_vlog_info(int, char**);
179 extern bool stop_is_finish;
181 stop_is_finish = false;
183 vpip_module_path[vpip_module_path_cnt++] = ".";
184 stop_is_finish = true;
186 if (char*path = getenv("VVP_DEBUG")) {
187 debug_file.open(path, ios::out);
190 /* This is needed to get the MCD I/O routines ready for
191 anything. It is done early because it is plausible that the
192 compile might affect it, and it is cheap to do. */
194 if (logfile_name) {
195 if (!strcmp(logfile_name, "-"))
196 logfile = stderr;
197 else {
198 logfile = fopen(logfile_name, "w");
199 if (!logfile) {
200 perror(logfile_name);
201 exit(1);
203 //setvbuf(logfile, log_buffer, _IOLBF, sizeof(log_buffer));
207 // vpip_mcd_init(logfile); // not shared yet.
208 vpip_mcd_init(logfile);
211 trace0( "Init VVP ...\n");
212 vvp_vpi_init();
214 char *argv[]={0};
215 vpi_set_vlog_info(0, argv );
217 trace0( "Compiling VVP "+(string)design_path);
218 COMPILE*c=new COMPILE();
219 c->init();
221 // for m in modules...
222 // vpip_load_module("bindsigs2");
223 int ret_cd = c->design(design_path);
225 trace1( " ...\n", ret_cd);
227 destroy_lexor();
228 print_vpi_call_errors();
229 if (ret_cd) return ret_cd;
231 if (!have_ivl_version) {
232 if (c->verbose_flag) vpi_mcd_printf(1, "... ");
233 vpi_mcd_printf(1, "Warning: vvp input file may not be correct "
234 "version!\n");
237 vpi_mcd_printf(1, "Compile cleanup...\n");
239 c->cleanup();
241 if (c->errors > 0) {
242 vpi_mcd_printf(1, "%s: Program not runnable, %u errors.\n",
243 design_path, c->errors);
244 load_module_delete();
245 return c->errors;
248 #ifdef DO_TRACE
249 fprintf(stdout, "vpi_mcd_printf ...\n");
250 vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%zu bytes)\n",
251 (long unsigned)count_functors, vvp_net_fun_t::heap_total());
252 vpi_mcd_printf(1, " %8lu logic\n", count_functors_logic);
253 vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif);
254 vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv);
255 vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig);
256 vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%zu bytes)\n",
257 count_filters, vvp_net_fil_t::heap_total());
258 vpi_mcd_printf(1, " ... %8lu opcodes (%zu bytes)\n",
259 count_opcodes, size_opcodes);
260 vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets);
261 vpi_mcd_printf(1, " ... %8lu vvp_nets (%zu bytes)\n",
262 count_vvp_nets, size_vvp_nets);
263 vpi_mcd_printf(1, " ... %8lu arrays (%lu words)\n",
264 count_net_arrays, count_net_array_words);
265 vpi_mcd_printf(1, " ... %8lu memories\n",
266 count_var_arrays+count_real_arrays);
267 vpi_mcd_printf(1, " %8lu logic (%lu words)\n",
268 count_var_arrays, count_var_array_words);
269 vpi_mcd_printf(1, " %8lu real (%lu words)\n",
270 count_real_arrays, count_real_array_words);
271 vpi_mcd_printf(1, " ... %8lu scopes\n", count_vpi_scopes);
274 vpi_mcd_printf(1, "Not Running ...\n");
275 // schedule_simulate();
277 #endif
279 return vvp_return_value;
281 /*--------------------------------------------------------------------*/
282 void vvp::signals_capture(void)
284 trace0("vvp::signals_capture not implemented");
286 void vvp::signals_revert(void)
288 signal(SIGINT, SIG_DFL);
290 /*--------------------------------------------------------------------*/
291 /*--------------------------------------------------------------------*/
292 /*--------------------------------------------------------------------*/
293 double vvp::getdtime(struct event_time_s *et)
295 return (double) et->delay * pow(10.0,vpip_get_time_precision());
297 /*--------------------------------------------------------------------
298 enum sim_mode {SIM_ALL,
299 SIM_INIT,SIM_CONT0,SIM_CONT1,
300 SIM_PREM,SIM_DONE};
301 --------------------------------------------------------------------*/
302 sim_mode vvp::schedule_simulate_m(sim_mode mode)
304 trace3("schedule_simulate_m", mode, SimTimeA, SimTimeD);
305 struct event_s *cur = 0;
306 struct event_time_s *ctim = 0;
307 double d_dly;
309 switch (mode) {
310 case SIM_CONT0: if ((ctim = schedule_list())){
311 trace1("schedule list", ctim->delay);
312 goto sim_cont0;
314 goto done;
315 case SIM_CONT1: goto sim_cont1;
316 default:
317 break;
320 assert(schedule_simtime()==0);
322 trace0("starting vvp");
324 vpiEndOfCompile();
325 exec_init_list();
326 vpiStartOfSim();
328 signals_capture();
329 trace1("signals_capture Done", schedule_runnable());
331 trace0("schedule_list?");
332 if (schedule_runnable())
333 while (schedule_list()) {
334 trace2("schedule list ... ", mode, schedule_stopped() );
336 if (schedule_stopped()) {
337 schedule_start();
338 incomplete();
339 // stop_handler(0);
340 // You can finish from the debugger without a time change.
341 if (!schedule_runnable()) break;
342 goto cycle_done;
345 /* ctim is the current time step. */
346 ctim = schedule_list();
348 /* If the time is advancing, then first run the
349 postponed sync events. Run them all. */
350 if (ctim->delay > 0) {
351 switch (mode) {
352 case SIM_CONT0:
353 case SIM_CONT1:
354 case SIM_INIT:
356 trace0("SIM_SOME");
357 d_dly = getdtime(ctim);
358 if (d_dly > 0) {
359 trace0("skip ExtPWL");
360 //doExtPwl(sched_list->nbassign,ctim);
361 SimDelayD = d_dly; return SIM_CONT0;
362 sim_cont0:
363 double dly = getdtime(ctim),
364 te = SimTimeDlast + dly;
366 trace4("cont0", SimTimeDlast, te, dly, SimTimeA);
368 if (te > SimTimeA) {
369 SimDelayD = te - SimTimeA;
370 trace1("schedule_sim SimTimeD PREM", SimDelayD);
371 return SIM_PREM;
373 trace1("schedule_sim SimTimeD increasing...",dly);
374 SimTimeD = SimTimeDlast + dly;
376 break;
377 default:
378 fprintf(stderr,"deffault?\n");
381 if (!schedule_runnable()) break;
382 schedule_sim(schedule_simtime() + ctim->delay);
383 ctim->delay = 0;
385 vpiNextSimTime();
389 /* If there are no more active events, advance the event
390 queues. If there are not events at all, then release
391 the event_time object. */
392 if (ctim->active == 0) {
393 ctim->active = ctim->nbassign;
394 ctim->nbassign = 0;
396 if (ctim->active == 0) {
397 ctim->active = ctim->rwsync;
398 ctim->rwsync = 0;
400 /* If out of rw events, then run the rosync
401 events and delete this time step. This also
402 deletes threads as needed. */
403 if (ctim->active == 0) {
404 trace0("rosync");
405 run_rosync(ctim);
406 schedule_enlist( ctim->next);
407 switch (mode) {
408 case SIM_CONT0:
409 case SIM_CONT1:
410 case SIM_INIT:
412 d_dly = getdtime(ctim);
413 if (d_dly > 0) {
414 trace0("noextPWL again");
415 // doExtPwl(sched_list->nbassign,ctim);
416 SimDelayD = d_dly;
417 delete ctim;
418 return SIM_CONT1;
419 sim_cont1:
420 untested();
421 // SimTimeD += ???;
422 goto cycle_done;
424 default:
425 trace1("default ", mode);
427 delete ctim;
428 goto cycle_done;
433 /* Pull the first item off the list. If this is the last
434 cell in the list, then clear the list. Execute that
435 event type, and delete it. */
436 cur = ctim->active->next;
437 if (cur->next == cur) {
438 ctim->active = 0;
439 } else {
440 ctim->active->next = cur->next;
442 cur->run_run();
444 delete (cur);
446 cycle_done:;
447 trace0("cycle done");
450 if (SIM_ALL == mode) {
452 signals_revert();
454 // Execute post-simulation callbacks
455 vpiPostsim();
458 done:
459 trace1("schedule_simulate_m done.", SimTimeD);
460 return SIM_DONE;
462 /*--------------------------------------------------------------------*/
463 double vvp::startsim(const char *)
465 SimDelayD = -1;
466 SimState = schedule_simulate_m(SIM_INIT);
467 SimTimeDlast = SimTimeD;
468 return SimDelayD;
470 /*--------------------------------------------------------------------*/
471 double vvp::contsim(const char *,double time)
473 trace5("contsim", time, SimTimeA, SimTimeD, SimTimeDlast, digital_time());
474 SimTimeA = time;
475 assert(CKT_BASE::_sim->_time0 == time );
476 SimDelayD = -1;
478 SimState = SIM_CONT0;
479 while (SimTimeDlast < time) {
480 trace1("contsim loop", time);
481 SimState = schedule_simulate_m(SimState);
482 SimTimeDlast = SimTimeD;
483 trace1("contsim loop", SimTimeD);
484 if (SIM_PREM <= SimState) break;
487 return SimDelayD;
489 /*------------------------------------------------------*/
490 void vvp::endsim()
492 vpi_handle_by_name("foo",NULL);
495 /*------------------------------------------------------*/
497 void *vvp::bindnet(const char *,char ,int *,
498 void *,void (*)(void *,void *,double))
500 return NULL;