1 /****************************************************************************
2 Copyright (C) 1987-2015 by Jeffery P. Hansen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 Last edit by hansen on Mon Feb 2 13:45:47 2009
19 ****************************************************************************/
20 #include "thyme.h"
21
22 #ifndef DEBUG
23 #define DEBUG 0
24 #endif
25
26 /*****************************************************************************
27 *
28 * Create a new CodeBlock
29 *
30 * Returns: Newly created and initialized CodeBlock.
31 *
32 *****************************************************************************/
new_CodeBlock(ModuleInst * mi)33 CodeBlock *new_CodeBlock(ModuleInst *mi)
34 {
35 CodeBlock *cb = (CodeBlock *) malloc(sizeof(CodeBlock));
36 CodeBlock_init(cb,mi);
37 return cb;
38 }
39
40 /*****************************************************************************
41 *
42 * Delete a CodeBlock
43 *
44 * Parameters:
45 * cb CodeBlock to be deleted.
46 *
47 *****************************************************************************/
delete_CodeBlock(CodeBlock * cb)48 void delete_CodeBlock(CodeBlock *cb)
49 {
50 CodeBlock_uninit(cb);
51 free(cb);
52 }
53
54 /*****************************************************************************
55 *
56 * Initialize a CodeBlock
57 *
58 * Parameters:
59 * cb CodeBlock to be initialized.
60 *
61 *****************************************************************************/
CodeBlock_init(CodeBlock * cb,ModuleInst * mi)62 void CodeBlock_init(CodeBlock *cb,ModuleInst *mi)
63 {
64 cb->cb_length = 0;
65 cb->cb_nalloced = BCODE_BLOCKSIZE;
66 cb->cb_module = mi;
67 cb->cb_instructions = (ByteCode*) malloc(sizeof(ByteCode)*BCODE_BLOCKSIZE);
68 }
69
70 /*****************************************************************************
71 *
72 * Resize a codeblock to use the minimum number of bytes.
73 *
74 *****************************************************************************/
CodeBlock_close(CodeBlock * cb)75 void CodeBlock_close(CodeBlock *cb)
76 {
77 ByteCode *oldBC = cb->cb_instructions;
78
79 cb->cb_nalloced = cb->cb_length;
80 cb->cb_instructions = (ByteCode*) malloc(sizeof(ByteCode)*cb->cb_nalloced);
81 memcpy(cb->cb_instructions, oldBC, sizeof(ByteCode)*cb->cb_nalloced);
82 free(oldBC);
83 }
84
85 /*****************************************************************************
86 *
87 * Uninitialize a CodeBlock
88 *
89 * Parameters:
90 * cb CodeBlock to be uninitialized.
91 *
92 *****************************************************************************/
CodeBlock_uninit(CodeBlock * cb)93 void CodeBlock_uninit(CodeBlock *cb)
94 {
95 free(cb->cb_instructions);
96 }
97
98 /*****************************************************************************
99 *
100 * Allocate and return the next empty ByteCode in a CodeBlock
101 *
102 * Paramaters:
103 * cb CodeBlock to use.
104 *
105 * Returns: Next unused ByteCode in cb.
106 *
107 *****************************************************************************/
CodeBlock_nextEmpty(CodeBlock * cb)108 ByteCode *CodeBlock_nextEmpty(CodeBlock *cb)
109 {
110 if (cb->cb_length >= cb->cb_nalloced) {
111 cb->cb_nalloced += BCODE_BLOCKSIZE;
112 cb->cb_instructions = (ByteCode*) realloc(cb->cb_instructions,sizeof(ByteCode)*cb->cb_nalloced);
113 }
114
115 return cb->cb_instructions + cb->cb_length++;
116 }
117
CodeBlock_copy(CodeBlock * dst,unsigned dpos,CodeBlock * src,unsigned start,unsigned stop)118 void CodeBlock_copy(CodeBlock *dst,unsigned dpos,CodeBlock *src,unsigned start,unsigned stop)
119 {
120 if (stop >= src->cb_length)
121 stop = src->cb_length -1;
122 unsigned copySize = (stop-start+1);
123 unsigned reqLen = dpos + copySize; /* Required length */
124
125 if (reqLen >= dst->cb_nalloced) {
126 dst->cb_nalloced = reqLen;
127 dst->cb_instructions = (ByteCode*) realloc(dst->cb_instructions,sizeof(ByteCode)*dst->cb_nalloced);
128 }
129
130 memcpy(CodeBlock_get(dst,dpos),CodeBlock_get(src,start),sizeof(ByteCode)*copySize);
131 #if 0
132 {
133 int i;
134 unsigned *ptr = (unsigned*) CodeBlock_get(dst,dpos);
135 int n = sizeof(ByteCode)*(stop-start+1)/sizeof(unsigned);
136
137 printf("copy %d <- %d..%d n=%d\n",dpos,start,stop,n);
138 printf(" dst:");
139 for (i = 0;i <= n;i++) {
140 printf("%08x",ptr[i]);
141 }
142 printf("\n");
143
144 ptr = (unsigned*) CodeBlock_get(src,start);
145 printf(" src:");
146 for (i = 0;i <= n;i++) {
147 printf("%08x",ptr[i]);
148 }
149 printf("\n");
150 }
151 #endif
152 }
153
154
155
156 /*****************************************************************************
157 *
158 * BCEnd initialization function
159 *
160 * Parameters:
161 * bc ByteCode object to initialize
162 *
163 *****************************************************************************/
BCEnd_init(ByteCode * bc)164 void BCEnd_init(ByteCode *bc)
165 {
166 bc->bc_func = (BCfunc*) BCEnd_exec;
167 }
168
169
170 /*****************************************************************************
171 *
172 * Execute BCEnd instruction
173 *
174 * Parameters:
175 * bc ByteCode object to execute
176 * t Thread that is executing instruction
177 *
178 *****************************************************************************/
BCEnd_exec(BCEnd * bc,VGThread * t)179 void BCEnd_exec(BCEnd *bc,VGThread *t)
180 {
181 #if DEBUG
182 vgio_echo("%p: BCEnd\n",t);
183 #endif
184 VGThread_kill(t);
185 if (t->t_parent)
186 VGThread_childEndNotify(t->t_parent);
187 }
188
189 /*****************************************************************************
190 *
191 * BCNoop initialization function
192 *
193 * Parameters:
194 * bc ByteCode object to initialize as an BCNoop
195 *
196 *****************************************************************************/
BCNoop_init(ByteCode * bc)197 void BCNoop_init(ByteCode *bc)
198 {
199 bc->bc_func = (BCfunc*) BCNoop_exec;
200 }
201
202 /*****************************************************************************
203 *
204 * Execute BCNoop instruction
205 *
206 * Parameters:
207 * bc ByteCode object to execute
208 * t Thread that is executing instruction
209 *
210 *****************************************************************************/
BCNoop_exec(BCNoop * bc,VGThread * t)211 void BCNoop_exec(BCNoop *bc,VGThread *t)
212 {
213 #if DEBUG
214 vgio_echo("%p: BCNoop\n",t);
215 #endif
216 t->t_pc++;
217 }
218
219 /*****************************************************************************
220 *
221 * BCOpr initialization function
222 *
223 * Parameters:
224 * bc ByteCode object to initialize
225 * func Value function to execute
226 * r Destination Value
227 * a,b,c Source Value objects
228 *
229 *****************************************************************************/
BCOpr_init(ByteCode * bc,valueop_f * func,Value * r,Value * a,Value * b,Value * c)230 void BCOpr_init(ByteCode *bc,valueop_f *func,Value*r,Value*a,Value*b,Value*c)
231 {
232 if (!func)
233 abort();
234
235 bc->bc_func = (BCfunc*) BCOpr_exec;
236 bc->bc_opr.o_op = func;
237 bc->bc_opr.o_dest = r;
238 bc->bc_opr.o_opr[0] = a;
239 bc->bc_opr.o_opr[1] = b;
240 bc->bc_opr.o_opr[2] = c;
241 }
242
243 /*****************************************************************************
244 *
245 * Execute BCOpr instruction
246 *
247 * Parameters:
248 * bc ByteCode object to execute
249 * t Thread that is executing instruction
250 *
251 *****************************************************************************/
BCOpr_exec(BCOpr * bc,VGThread * t)252 void BCOpr_exec(BCOpr *bc,VGThread *t)
253 {
254 (*bc->o_op)(bc->o_dest,bc->o_opr[0],bc->o_opr[1],bc->o_opr[2]);
255 t->t_pc++;
256 #if DEBUG
257 {
258 OpDesc *od = OpDesc_findFunc(bc->o_op);
259 const char *op = "[?]\0[?]";
260
261 if (od) op = od->od_text;
262
263 vgio_echo("%p: BCOpr: ",t);
264 Value_print(bc->o_dest,stdout);
265 vgio_echo(" = ");
266 if (bc->o_opr[0]) Value_print(bc->o_opr[0],stdout);
267 if (bc->o_opr[1]) {
268 vgio_echo(" %s ",op);
269 Value_print(bc->o_opr[1],stdout);
270 }
271 if (bc->o_opr[2]) {
272 op = strend((char*)op) + 1;
273 vgio_echo(" %s ",op);
274 Value_print(bc->o_opr[2],stdout);
275 }
276
277
278 vgio_echo("\n");
279 }
280 #endif
281 }
282
283 /*****************************************************************************
284 *
285 * BCGoto initialization function
286 *
287 * Parameters:
288 * bc ByteCode object to initialize
289 * cond Condition value (or null for unconditional branch)
290 * neg If non-zero, branch condition is revered
291 * cb CodeBlock in which destination is contained
292 * offset Offset into CodeBlock to branch to.
293 *
294 *****************************************************************************/
BCGoto_init(ByteCode * bc,Value * cond,int neg,CodeBlock * cb,unsigned offset)295 void BCGoto_init(ByteCode *bc, Value *cond,int neg,CodeBlock *cb,unsigned offset)
296 {
297 BCGoto *g = (BCGoto*)bc;
298
299 g->g_func = (BCfunc*) BCGoto_exec;
300 g->g_cond = cond;
301 g->g_block = cb;
302 g->g_offset = offset;
303 g->g_neg = neg;
304 }
305
306 /*****************************************************************************
307 *
308 * Execute BCGoto instruction
309 *
310 * Parameters:
311 * bc ByteCode object to execute
312 * t Thread that is executing instruction
313 *
314 *****************************************************************************/
BCGoto_exec(BCGoto * g,VGThread * t)315 void BCGoto_exec(BCGoto *g,VGThread *t)
316 {
317 int doskip = (g->g_cond && (Value_isZero(g->g_cond)||!Value_isLogic(g->g_cond)));
318
319 if (g->g_neg) doskip = !doskip;
320 if (doskip) {
321 #if DEBUG
322 vgio_echo("%p: BCGoto: nojump\n",t);
323 #endif
324 t->t_pc++;
325 } else {
326 #if DEBUG
327 vgio_echo("%p: BCGoto: jump %p:%x\n",t,g->g_block,g->g_offset);
328 #endif
329 t->t_pc = CodeBlock_first(g->g_block) + g->g_offset;
330 }
331 }
332
333 /*****************************************************************************
334 *
335 * BCTask initialization function
336 *
337 * Parameters:
338 * bc ByteCode object to initialize
339 * func System task function pointer
340 * context Optional task context used by delayed execution tasks.
341 * numArgs Number of arguments
342 * args Array of values
343 *
344 *****************************************************************************/
BCTask_init(ByteCode * bc,systask_f * func,TaskContext * context,Value * rval,int numArgs,void ** args)345 void BCTask_init(ByteCode *bc,systask_f *func,TaskContext *context,Value *rval,int numArgs,void **args)
346 {
347 BCTask *t = (BCTask*)bc;
348
349 t->t_func = (BCfunc*) BCTask_exec;
350 t->t_context = context;
351 t->t_task = func;
352 t->t_rvalue = rval;
353 t->t_numArgs = numArgs;
354 t->t_args = args;
355
356 }
357
358 /*****************************************************************************
359 *
360 * Execute BCTask instruction
361 *
362 * Parameters:
363 * bc ByteCode object to execute
364 * t Thread that is executing instruction
365 *
366 *****************************************************************************/
BCTask_exec(BCTask * t,VGThread * th)367 void BCTask_exec(BCTask *t,VGThread *th)
368 {
369 #if DEBUG
370 vgio_echo("%p: BCTask(%s) in %s\n",t,SysTask_findName(t->t_task),th->t_modCtx->mc_path);
371 #endif
372 (*t->t_task)(th,t->t_rvalue,t->t_numArgs,t->t_args,t->t_context);
373 th->t_pc++;
374 }
375
376 /*****************************************************************************
377 *
378 * BCDelay initialization function
379 *
380 * Parameters:
381 * bc ByteCode object to initialize
382 * t Amount of delay
383 *
384 *****************************************************************************/
BCDelay_init(ByteCode * bc,deltatime_t t)385 void BCDelay_init(ByteCode *bc,deltatime_t t)
386 {
387 BCDelay *d = (BCDelay*)bc;
388
389 d->d_func = (BCfunc*) BCDelay_exec;
390 d->d_delay = t;
391 }
392
393 /*****************************************************************************
394 *
395 * Execute BCDelay instruction
396 *
397 * Parameters:
398 * bc ByteCode object to execute
399 * t Thread that is executing instruction
400 *
401 *****************************************************************************/
BCDelay_exec(BCDelay * d,VGThread * t)402 void BCDelay_exec(BCDelay *d,VGThread *t)
403 {
404 if (d->d_delay == 0)
405 VGThread_delayToEnd(t);
406 else
407 VGThread_delay(t,d->d_delay);
408 #if DEBUG
409 vgio_echo("%p: BCDelay %d\n",t,d->d_delay);
410 #endif
411 t->t_pc++;
412 }
413
414 /*****************************************************************************
415 *
416 * BCTrigger initialization function
417 *
418 * Parameters:
419 * bct ByteCode object to initialize
420 * t Triggering event
421 *
422 *****************************************************************************/
BCTrigger_init(ByteCode * bc,Trigger * t)423 void BCTrigger_init(ByteCode *bc,Trigger *t)
424 {
425 BCTrigger *bct = (BCTrigger*)bc;
426
427 bct->t_func = (BCfunc*) BCTrigger_exec;
428 bct->t_trigger = t;
429 }
430
431 /*****************************************************************************
432 *
433 * Execute BCTrigger instruction
434 *
435 * Parameters:
436 * bc ByteCode object to execute
437 * t Thread that is executing instruction
438 *
439 *****************************************************************************/
BCTrigger_exec(BCTrigger * bct,VGThread * t)440 void BCTrigger_exec(BCTrigger *bct,VGThread *t)
441 {
442 #if DEBUG
443 char buf[STRMAX],*p;
444 ListElem *le;
445
446 p = buf;
447 for (le = List_first(bct->t_trigger->t_posedges);le;le = List_next(bct->t_trigger->t_posedges,le)) {
448 Net *n = ListElem_obj(le);
449 p += sprintf(p," %s",Net_getName(n));
450 }
451 vgio_echo("%p: BCTrigger on %s\n",t,buf);
452 #endif
453 VGThread_eventWait(t,bct->t_trigger);
454 t->t_pc++;
455 }
456
457 /*****************************************************************************
458 *
459 * BCLock initialization function
460 *
461 * Parameters:
462 * bct ByteCode object to initialize
463 * t Triggering event
464 * value Semephore variable
465 *
466 *****************************************************************************/
BCLock_init(ByteCode * bc,Trigger * t,Value * value)467 void BCLock_init(ByteCode *bc,Trigger *t, Value *value)
468 {
469 BCLock *bcl = (BCLock*)bc;
470
471 bcl->l_func = (BCfunc*) BCLock_exec;
472 bcl->l_trigger = t;
473 bcl->l_value = value;
474 }
475
476 /*****************************************************************************
477 *
478 * Execute BCLock instruction
479 *
480 * Parameters:
481 * bc ByteCode object to execute
482 * t Thread that is executing instruction
483 *
484 * If the semephore variable is zero, we set it to one and advance the PC. Otherwise
485 * we wait for a change in the semephore value and reexecute ourself.
486 *
487 *****************************************************************************/
BCLock_exec(BCLock * bcl,VGThread * t)488 void BCLock_exec(BCLock *bcl,VGThread *t)
489 {
490 #if DEBUG
491 char buf[STRMAX],*p;
492 ListElem *le;
493
494 p = buf;
495 for (le = List_first(bcl->l_trigger->t_posedges);le;le = List_next(bct->t_trigger->t_posedges,le)) {
496 Net *n = ListElem_obj(le);
497 p += sprintf(p," %s",Net_getName(n));
498 }
499 vgio_echo("%p: BCLock on %s\n",t,buf);
500 #endif
501
502 if (Value_isZero(bcl->l_value)) {
503 Value_one(bcl->l_value);
504 t->t_pc++;
505 } else
506 VGThread_eventWait(t,bcl->l_trigger);
507 }
508
509 /*****************************************************************************
510 *
511 * BCCopy initialization function
512 *
513 * Parameters:
514 * bc ByteCode object to initialize
515 * dst Destination Value for copy
516 * src Source Value for copy
517 *
518 *****************************************************************************/
BCCopy_init(ByteCode * bc,Value * dst,Value * src)519 void BCCopy_init(ByteCode *bc, Value*dst, Value*src)
520 {
521 BCCopy *c = (BCCopy*)bc;
522
523 c->c_func = (BCfunc*) BCCopy_exec;
524 c->c_dst = dst;
525 c->c_src = src;
526 }
527
528 /*****************************************************************************
529 *
530 * Execute BCCopy instruction
531 *
532 * Parameters:
533 * bc ByteCode object to execute
534 * t Thread that is executing instruction
535 *
536 *****************************************************************************/
BCCopy_exec(BCCopy * c,VGThread * t)537 void BCCopy_exec(BCCopy *c, VGThread *t)
538 {
539 int nd = Value_nbits(c->c_dst);
540 int ns = Value_nbits(c->c_src);
541
542 if (nd == ns)
543 Value_copy(c->c_dst,c->c_src);
544 else if (nd < ns)
545 Value_copyRange(c->c_dst,0,c->c_src,ns-1,0);
546 else {
547 Value_zero(c->c_dst);
548 Value_copyRange(c->c_dst,0,c->c_src,ns-1,0);
549 }
550
551 #if DEBUG
552 vgio_echo("%p: BCCopy: ",t);
553 Value_print(c->c_dst,stdout);
554 vgio_echo(" = ");
555 Value_print(c->c_src,stdout);
556 vgio_echo("\n");
557 #endif
558
559 t->t_pc++;
560 }
561
562 /*****************************************************************************
563 *
564 * BCCopyRange initialization function
565 *
566 * Parameters:
567 * bc ByteCode object to initialize
568 * dst Destination Value for copy
569 * dLsb LSB in destination
570 * src Source Value for copy
571 * sLSB LSB in source
572 * width Bits to copy
573 *
574 *****************************************************************************/
BCCopyRange_init(ByteCode * bc,Value * dst,unsigned dLsb,Value * src,Value * sLsb,unsigned width)575 void BCCopyRange_init(ByteCode *bc, Value *dst, unsigned dLsb,Value *src,Value *sLsb, unsigned width)
576 {
577 BCCopyRange *r = (BCCopyRange*)bc;
578
579 r->r_func = (BCfunc*) BCCopyRange_exec;
580 r->r_dst = dst;
581 r->r_dLsb = dLsb;
582 r->r_src = src;
583 r->r_sLsb = sLsb;
584 r->r_width = width;
585 }
586
BCCopyRange_exec(BCCopyRange * r,VGThread * t)587 void BCCopyRange_exec(BCCopyRange *r, VGThread *t)
588 {
589 unsigned sLsb;
590
591 if (!r->r_sLsb)
592 sLsb = 0;
593 else if (Value_toInt(r->r_sLsb,&sLsb) < 0) {
594 /*
595 * Source bit is unknown.
596 */
597 Value *x = new_Value(r->r_width);
598 Value_unknown(x);
599 Value_copyRange(r->r_dst, r->r_dLsb, x,r->r_width-1,0);
600 delete_Value(x);
601 t->t_pc++;
602
603 #if DEBUG
604 vgio_echo("%p: BCCopyRange(",t);
605 Value_print(r->r_dst, stdout);
606 vgio_echo(", %d, ",r->r_dLsb);
607 Value_print(r->r_src, stdout);
608 vgio_echo(", [? +: %d])\n",r->r_width-1);
609 #endif
610
611 return;
612 }
613
614 /*
615 * Normal case
616 */
617 Value_copyRange(r->r_dst, r->r_dLsb, r->r_src,sLsb+r->r_width-1,sLsb);
618 t->t_pc++;
619
620 #if DEBUG
621 vgio_echo("%p: BCCopyRange(",t);
622 Value_print(r->r_dst, stdout);
623 vgio_echo(", %d, ",r->r_dLsb);
624 Value_print(r->r_src, stdout);
625 vgio_echo(", [%d:%d])\n",sLsb+r->r_width-1,sLsb);
626 #endif
627 }
628
629 /*****************************************************************************
630 *
631 * Initialize a BCMemFetch instruction
632 *
633 *****************************************************************************/
BCMemFetch_init(ByteCode * bc,Net * n,Value * addr,Value * data)634 void BCMemFetch_init(ByteCode *bc,Net *n, Value *addr, Value *data)
635 {
636 BCMemFetch *m = (BCMemFetch*)bc;
637
638 m->m_func = (BCfunc*) BCMemFetch_exec;
639 m->m_net = n;
640 m->m_addr = addr;
641 m->m_data = data;
642 }
643
644 /*****************************************************************************
645 *
646 * Executete a BCMemFetch instruction
647 *
648 *****************************************************************************/
BCMemFetch_exec(BCMemFetch * bmo,VGThread * t)649 void BCMemFetch_exec(BCMemFetch *bmo,VGThread *t)
650 {
651 Memory *m = &bmo->m_net->n_data.memory;
652 unsigned addr;
653
654 if (Value_toInt(bmo->m_addr,&addr) < 0) {
655 Value_unknown(bmo->m_data);
656 #if DEBUG
657 vgio_echo("%p: BCMemFetch: %s[?]=?",t,Net_getName(bmo->m_net));
658 #endif
659 } else {
660 Memory_setFlags(m, MF_INITIALIZED);
661 Memory_get(m, addr, bmo->m_data);
662 Memory_accessNotify(m, addr, 0);
663 #if DEBUG
664 vgio_echo("%p: BCMemFetch: %s[%x]=",t,Net_getName(bmo->m_net), addr);
665 Value_print(bmo->m_data, stdout);
666 vgio_printf("\n");
667 #endif
668 }
669
670 t->t_pc++;
671 }
672
673 /*****************************************************************************
674 *
675 * Initialize a BCNbMemPut instruction
676 *
677 *****************************************************************************/
BCNbMemPutD_init(ByteCode * bc,Net * n,Value * addr,Value * netLsb,Value * data,unsigned valLsb,unsigned width,deltatime_t delay)678 void BCNbMemPutD_init(ByteCode *bc,Net *n, Value *addr, Value *netLsb, Value *data,
679 unsigned valLsb,unsigned width,deltatime_t delay)
680 {
681 BCNbMemPutD *m = (BCNbMemPutD*)bc;
682
683 m->m_func = (BCfunc*) BCNbMemPutD_exec;
684 m->m_net = n;
685 m->m_addr = addr;
686 m->m_netLsb = netLsb;
687 m->m_data = data;
688 m->m_valLsb = valLsb;
689 m->m_width = width;
690 m->m_delay = delay;
691 }
692
693 /*****************************************************************************
694 *
695 * Executete a BCNbMemPut instruction
696 *
697 *****************************************************************************/
BCNbMemPutD_exec(BCNbMemPutD * mpd,VGThread * thread)698 void BCNbMemPutD_exec(BCNbMemPutD *mpd,VGThread *thread)
699 {
700 unsigned netLsb = 0;
701 EvQueue *Q = VGThread_getQueue(thread);
702 Event *e;
703
704 #if DEBUG
705 vgio_echo("%p: BCNbMemPutD(%p) #%d\n",thread,mpd,mpd->m_delay);
706 #endif
707
708 if (mpd->m_netLsb) {
709 if (Value_toInt(mpd->m_netLsb,&netLsb) < 0) {
710 /*
711 * An LSB was specified but it contains unknown bits
712 */
713 Value *xs = new_Value(Value_nbits(mpd->m_data));
714 Value_unknown(xs);
715 e = new_EvMem(mpd->m_net, mpd->m_addr, netLsb, xs, mpd->m_valLsb+mpd->m_width-1,mpd->m_valLsb);
716 EvQueue_enqueueAfter(Q,e,mpd->m_delay);
717 delete_Value(xs);
718 thread->t_pc++;
719 return;
720 }
721 } else
722 netLsb = 0;
723
724 e = new_EvMem(mpd->m_net, mpd->m_addr, netLsb, mpd->m_data, mpd->m_valLsb+mpd->m_width-1,mpd->m_valLsb);
725 EvQueue_enqueueAfter(Q,e,mpd->m_delay);
726 thread->t_pc++;
727 }
728
729 /*****************************************************************************
730 *
731 * Initialize a BCNbMemPut instruction
732 *
733 *****************************************************************************/
BCNbMemPutE_init(ByteCode * bc,Net * n,Value * addr,Value * netLsb,Value * data,unsigned valLsb,unsigned width,Trigger * trigger)734 void BCNbMemPutE_init(ByteCode *bc,Net *n, Value *addr, Value *netLsb, Value *data,
735 unsigned valLsb,unsigned width,Trigger *trigger)
736 {
737 BCNbMemPutE *m = (BCNbMemPutE*)bc;
738
739 m->m_func = (BCfunc*) BCNbMemPutE_exec;
740 m->m_net = n;
741 m->m_addr = addr;
742 m->m_netLsb = netLsb;
743 m->m_data = data;
744 m->m_valLsb = valLsb;
745 m->m_width = width;
746 m->m_trigger = trigger;
747 }
748
749 /*****************************************************************************
750 *
751 * Executete a BCNbMemPut instruction
752 *
753 *****************************************************************************/
BCNbMemPutE_exec(BCNbMemPutE * mpe,VGThread * thread)754 void BCNbMemPutE_exec(BCNbMemPutE *mpe,VGThread *thread)
755 {
756 unsigned netLsb = 0;
757 /** @TODO to remove */
758 /* EvQueue *Q = VGThread_getQueue(thread); */
759 Event *e;
760
761 #if DEBUG
762 vgio_echo("%p: BCNbMemPutE(%p)\n",thread,mpe);
763 #endif
764
765 if (mpe->m_netLsb) {
766 if (Value_toInt(mpe->m_netLsb,&netLsb) < 0) {
767 /*
768 * An LSB was specified but it contains unknown bits
769 */
770 Value *xs = new_Value(Value_nbits(mpe->m_data));
771 Value_unknown(xs);
772 e = new_EvMem(mpe->m_net, mpe->m_addr, netLsb, xs, mpe->m_valLsb+mpe->m_width-1,mpe->m_valLsb);
773 Trigger_enqueue(mpe->m_trigger, e);
774 delete_Value(xs);
775 thread->t_pc++;
776 return;
777 }
778 } else
779 netLsb = 0;
780
781 e = new_EvMem(mpe->m_net, mpe->m_addr, netLsb, mpe->m_data, mpe->m_valLsb+mpe->m_width-1,mpe->m_valLsb);
782 Trigger_enqueue(mpe->m_trigger, e);
783 thread->t_pc++;
784 }
785
786 /*****************************************************************************
787 *
788 * Initialize a BCMemPut instruction
789 *
790 *****************************************************************************/
BCMemPut_init(ByteCode * bc,Net * n,Value * addr,Value * netLsb,Value * data,unsigned valLsb,unsigned width)791 void BCMemPut_init(ByteCode *bc,Net *n, Value *addr, Value *netLsb, Value *data,unsigned valLsb,unsigned width)
792 {
793 BCMemPut *m = (BCMemPut*)bc;
794
795 m->m_func = (BCfunc*) BCMemPut_exec;
796 m->m_net = n;
797 m->m_addr = addr;
798 m->m_netLsb = netLsb;
799 m->m_data = data;
800 m->m_valLsb = valLsb;
801 m->m_width = width;
802 }
803
804 /*****************************************************************************
805 *
806 * Executete a BCMemPut instruction
807 *
808 *****************************************************************************/
BCMemPut_exec(BCMemPut * bmo,VGThread * t)809 void BCMemPut_exec(BCMemPut *bmo,VGThread *t)
810 {
811 Memory *m = &bmo->m_net->n_data.memory;
812 unsigned addr;
813 unsigned netLsb = 0;
814
815 if (Value_toInt(bmo->m_addr,&addr) < 0) {
816 #if DEBUG
817 vgio_echo("%p: BCMemPut: %s[?]=?",t,Net_getName(bmo->m_net));
818 #endif
819 if ((Memory_getFlags(m) & MF_INITIALIZED))
820 errorRun(ERR_MEMADDR,Net_getName(bmo->m_net));
821 goto done;
822 } else {
823 Memory_setFlags(m, MF_INITIALIZED);
824 if (bmo->m_netLsb && Value_toInt(bmo->m_netLsb,&netLsb) < 0) {
825 errorRun(ERR_MEMBITS,Net_getName(bmo->m_net));
826 goto done;
827 } else if (Net_nbits(bmo->m_net) == bmo->m_width) {
828 Net_memSet(bmo->m_net, addr, bmo->m_data);
829 } else
830 Net_memSetRange(bmo->m_net, addr, netLsb, bmo->m_data, bmo->m_valLsb+bmo->m_width-1, bmo->m_valLsb);
831 }
832
833 #if DEBUG
834 vgio_echo("%p: BCMemPut: %s[%x][%d:%d]=",t,Net_getName(bmo->m_net), addr,bmo->m_width+netLsb-1,netLsb);
835 Value_print(bmo->m_data, stdout);
836 vgio_printf("[%d:%d]\n",bmo->m_width+bmo->m_valLsb-1,bmo->m_valLsb);
837 #endif
838 done:
839 t->t_pc++;
840 }
841
842 /*****************************************************************************
843 *
844 * BCRaise initialization function
845 *
846 * Parameters:
847 * bc ByteCode object to initialize
848 * net Destination Net for assignment
849 *
850 *****************************************************************************/
BCRaise_init(ByteCode * bc,Net * net)851 void BCRaise_init(ByteCode *bc, Net *net)
852 {
853 BCRaise *r = (BCRaise*)bc;
854
855 r->r_func = (BCfunc*) BCRaise_exec;
856 r->r_net = net;
857 }
858
859 /*****************************************************************************
860 *
861 * Execute BCRaise instruction
862 *
863 * Parameters:
864 * bc ByteCode object to execute
865 * t Thread that is executing instruction
866 *
867 *****************************************************************************/
BCRaise_exec(BCRaise * r,VGThread * t)868 void BCRaise_exec(BCRaise *r, VGThread *t)
869 {
870 Net_set(r->r_net, 0);
871
872 #if DEBUG
873 vgio_echo("%p: BCRaise: %s\n",t,r->r_net->n_name);
874 #endif
875
876 t->t_pc++;
877 }
878
879 /*****************************************************************************
880 *
881 * BCAsgn initialization function
882 *
883 * Parameters:
884 * bc ByteCode object to initialize
885 * net Destination Net for assignment
886 * netLsb Least significant bit in assignment
887 * value Value to assign
888 * valLsb Least significant bit in value
889 * width Width of value to copy
890 *
891 *****************************************************************************/
BCAsgn_init(ByteCode * bc,Net * net,Value * netLsb,Value * value,unsigned valLsb,unsigned width)892 void BCAsgn_init(ByteCode *bc, Net *net, Value *netLsb, Value *value, unsigned valLsb, unsigned width)
893 {
894 BCAsgn *a = (BCAsgn*)bc;
895
896 a->a_func = (BCfunc*) BCAsgn_exec;
897 a->a_net = net;
898 a->a_netLsb = netLsb;
899 a->a_value = value;
900 a->a_valLsb = valLsb;
901 a->a_width = width;
902 }
903
904 /*****************************************************************************
905 *
906 * Execute BCAsgn instruction
907 *
908 * Parameters:
909 * bc ByteCode object to execute
910 * t Thread that is executing instruction
911 *
912 *****************************************************************************/
BCAsgn_exec(BCAsgn * a,VGThread * t)913 void BCAsgn_exec(BCAsgn *a, VGThread *t)
914 {
915 int nd = Net_nbits(a->a_net);
916 int ns = Value_nbits(a->a_value);
917 unsigned netLsb = 0;
918
919 if (nd == a->a_width && ns == a->a_width) {
920 Net_set(a->a_net, a->a_value);
921 } else {
922
923 /*
924 * If an lsb is specified but it is unknown, set the target net to unknown
925 * since we do not know where we are writing the value.
926 */
927 if (a->a_netLsb) {
928 if (Value_toInt(a->a_netLsb,&netLsb) < 0) {
929 Net_makeUnknown(a->a_net);
930 return;
931 }
932 } else
933 netLsb = 0;
934
935 Net_setRange(a->a_net, netLsb,a->a_value,a->a_valLsb+a->a_width-1,a->a_valLsb);
936 }
937
938 #if DEBUG
939 vgio_echo("%p: BCAsgn: %s[%d:%d] = ",t,a->a_net->n_name,netLsb+a->a_width-1,netLsb);
940 Value_print(a->a_value,stdout);
941 vgio_echo("[%d:%d]\n",a->a_valLsb+a->a_width-1,a->a_valLsb);
942 #endif
943
944 t->t_pc++;
945 }
946
947 /*****************************************************************************
948 *
949 * BCNbAsgnD initialization function
950 *
951 * Parameters:
952 * bc ByteCode object to initialize
953 * net Destination Net for assignment
954 * netLsb Least significant bit in assignment
955 * value Value to assign
956 * valLsb Least significant bit in value
957 * width Width of value to copy
958 * delay Delay after which to queue assignment.
959 *
960 *****************************************************************************/
BCNbAsgnD_init(ByteCode * bc,Net * net,Value * netLsb,Value * value,unsigned valLsb,unsigned width,deltatime_t delay)961 void BCNbAsgnD_init(ByteCode *bc, Net *net, Value *netLsb, Value *value,
962 unsigned valLsb, unsigned width,deltatime_t delay)
963 {
964 BCNbAsgnD *a = (BCNbAsgnD*)bc;
965
966 a->a_func = (BCfunc*) BCNbAsgnD_exec;
967 a->a_net = net;
968 a->a_netLsb = netLsb;
969 a->a_value = value;
970 a->a_valLsb = valLsb;
971 a->a_width = width;
972 a->a_delay = delay;
973 }
974
975 /*****************************************************************************
976 *
977 * Execute BCNbAsgnD instruction
978 *
979 * Parameters:
980 * bc ByteCode object to execute
981 * t Thread that is executing instruction
982 *
983 *****************************************************************************/
BCNbAsgnD_exec(BCNbAsgnD * a,VGThread * thread)984 void BCNbAsgnD_exec(BCNbAsgnD *a, VGThread *thread)
985 {
986 unsigned netLsb = 0;
987 EvQueue *Q = VGThread_getQueue(thread);
988 Event *e;
989
990 #if DEBUG
991 vgio_echo("%p: BCNbAsgnD(%p) #%d\n",thread,a,a->a_delay);
992 #endif
993
994 if (a->a_netLsb) {
995 if (Value_toInt(a->a_netLsb,&netLsb) < 0) {
996 /*
997 * An LSB was specified but it contains unknown bits
998 */
999 Value *xs = new_Value(Value_nbits(a->a_value));
1000 Value_unknown(xs);
1001 e = new_EvNet(a->a_net, netLsb, xs, a->a_valLsb+a->a_width-1,a->a_valLsb);
1002 EvQueue_enqueueAfter(Q,e,a->a_delay);
1003 delete_Value(xs);
1004 thread->t_pc++;
1005 return;
1006 }
1007 } else
1008 netLsb = 0;
1009
1010 e = new_EvNet(a->a_net, netLsb, a->a_value, a->a_valLsb+a->a_width-1,a->a_valLsb);
1011 EvQueue_enqueueAfter(Q,e,a->a_delay);
1012 thread->t_pc++;
1013 }
1014
1015
1016 /*****************************************************************************
1017 *
1018 * BCNbAsgnE initialization function
1019 *
1020 * Parameters:
1021 * bc ByteCode object to initialize
1022 * net Destination Net for assignment
1023 * netLsb Least significant bit in assignment
1024 * value Value to assign
1025 * valLsb Least significant bit in value
1026 * width Width of value to copy
1027 * trigger Triggering event for assigment.
1028 *
1029 *****************************************************************************/
BCNbAsgnE_init(ByteCode * bc,Net * net,Value * netLsb,Value * value,unsigned valLsb,unsigned width,Trigger * trigger)1030 void BCNbAsgnE_init(ByteCode *bc, Net *net, Value *netLsb, Value *value, unsigned valLsb, unsigned width,Trigger *trigger)
1031 {
1032 BCNbAsgnE *a = (BCNbAsgnE*)bc;
1033
1034 a->a_func = (BCfunc*) BCNbAsgnE_exec;
1035 a->a_net = net;
1036 a->a_netLsb = netLsb;
1037 a->a_value = value;
1038 a->a_valLsb = valLsb;
1039 a->a_width = width;
1040 a->a_trigger = trigger;
1041 }
1042
1043 /*****************************************************************************
1044 *
1045 * Execute BCNbAsgnE instruction
1046 *
1047 * Parameters:
1048 * bc ByteCode object to execute
1049 * t Thread that is executing instruction
1050 *
1051 *****************************************************************************/
BCNbAsgnE_exec(BCNbAsgnE * a,VGThread * thread)1052 void BCNbAsgnE_exec(BCNbAsgnE *a, VGThread *thread)
1053 {
1054 unsigned netLsb = 0;
1055 Event *e;
1056
1057 #if DEBUG
1058 vgio_echo("%p: BCNbAsgnE\n",thread);
1059 #endif
1060
1061 if (a->a_netLsb) {
1062 if (Value_toInt(a->a_netLsb,&netLsb) < 0) {
1063 /*
1064 * An LSB was specified but it contains unknown bits
1065 */
1066 Value *xs = new_Value(Value_nbits(a->a_value));
1067 Value_unknown(xs);
1068 e = new_EvNet(a->a_net, netLsb, xs, a->a_valLsb+a->a_width-1,a->a_valLsb);
1069 Trigger_enqueue(a->a_trigger ,e);
1070 delete_Value(xs);
1071 thread->t_pc++;
1072 return;
1073 }
1074 } else
1075 netLsb = 0;
1076
1077 e = new_EvNet(a->a_net, netLsb, a->a_value, a->a_valLsb+a->a_width-1,a->a_valLsb);
1078 Trigger_enqueue(a->a_trigger ,e);
1079 thread->t_pc++;
1080 }
1081
1082 /*****************************************************************************
1083 *
1084 * BCWireAsgnD initialization function
1085 *
1086 * Parameters:
1087 * bc ByteCode object to initialize
1088 * net Destination Net for assignment
1089 * netLsb Least significant bit in assignment
1090 * value Value to assign
1091 * valLsb Least significant bit in value
1092 * width Width of value to copy
1093 * delay Delay after which to queue assignment.
1094 *
1095 *****************************************************************************/
BCWireAsgnD_init(ByteCode * bc,Net * net,int id,Value * netLsb,Value * value,unsigned valLsb,unsigned width,deltatime_t delay)1096 void BCWireAsgnD_init(ByteCode *bc, Net *net, int id, Value *netLsb, Value *value,
1097 unsigned valLsb, unsigned width,deltatime_t delay)
1098 {
1099 BCWireAsgnD *a = (BCWireAsgnD*)bc;
1100
1101 a->a_func = (BCfunc*) BCWireAsgnD_exec;
1102 a->a_net = net;
1103 a->a_id = id;
1104 a->a_netLsb = netLsb;
1105 a->a_value = value;
1106 a->a_valLsb = valLsb;
1107 a->a_width = width;
1108 a->a_delay = delay;
1109 }
1110
1111 /*****************************************************************************
1112 *
1113 * Execute BCWireAsgnD instruction
1114 *
1115 * Parameters:
1116 * bc ByteCode object to execute
1117 * t Thread that is executing instruction
1118 *
1119 *****************************************************************************/
BCWireAsgnD_exec(BCWireAsgnD * a,VGThread * thread)1120 void BCWireAsgnD_exec(BCWireAsgnD *a, VGThread *thread)
1121 {
1122 unsigned netLsb = 0;
1123 EvQueue *Q = VGThread_getQueue(thread);
1124 Event *e;
1125
1126 if (a->a_netLsb) {
1127 if (Value_toInt(a->a_netLsb,&netLsb) < 0) {
1128 Value *xs = new_Value(Value_nbits(a->a_value));
1129 Value_unknown(xs);
1130 e = new_EvNet(a->a_net, netLsb, xs, a->a_valLsb+a->a_width-1,a->a_valLsb);
1131 EvQueue_enqueueAfter(Q,e,a->a_delay);
1132
1133 #if DEBUG
1134 vgio_echo("%p: BCWireAsgnD: #%d %s[%d:%d] = ",thread,a->a_delay,Net_getName(a->a_net),a->a_valLsb+a->a_width-1);
1135 Value_print(xs,stdout);
1136 vgio_echo("\n");
1137 #endif
1138
1139 delete_Value(xs);
1140 thread->t_pc++;
1141 return;
1142 }
1143 } else {
1144 netLsb = 0;
1145 }
1146
1147 e = new_EvDriver(a->a_net, a->a_id, netLsb, a->a_value, a->a_valLsb+a->a_width-1,a->a_valLsb);
1148 EvQueue_enqueueAfter(Q,e,a->a_delay);
1149
1150 #if DEBUG
1151 vgio_echo("%p: BCWireAsgnD: #%d %s = ",thread,a->a_delay,Net_getName(a->a_net));
1152 Value_print(a->a_value,stdout);
1153 vgio_echo("\n");
1154 #endif
1155
1156 thread->t_pc++;
1157 }
1158
1159 /*****************************************************************************
1160 *
1161 * Initialize a BCSpawn instruction.
1162 *
1163 *****************************************************************************/
BCSpawn_init(ByteCode * bc,CodeBlock * cb,unsigned offset)1164 void BCSpawn_init(ByteCode *bc,CodeBlock *cb,unsigned offset)
1165 {
1166 BCSpawn *s = (BCSpawn*)bc;
1167
1168 s->s_func = (BCfunc*) BCSpawn_exec;
1169 s->s_block = cb;
1170 s->s_offset = offset;
1171 }
1172
1173 /*****************************************************************************
1174 *
1175 * Execute a BCSpawn instruction.
1176 *
1177 *****************************************************************************/
BCSpawn_exec(BCSpawn * s,VGThread * thread)1178 void BCSpawn_exec(BCSpawn *s,VGThread *thread)
1179 {
1180 VGThread *child = VGThread_spawn(thread,s->s_block,s->s_offset);
1181 VGThread_start(child);
1182 VGThread_delay(child,0);
1183 thread->t_pc++;
1184
1185 #if DEBUG
1186 vgio_echo("%p: BCSpawn(%u) -> %p\n",thread,s->s_offset,child);
1187 #endif
1188 }
1189
1190 /*****************************************************************************
1191 *
1192 * Initialize a BCWait instruction.
1193 *
1194 *****************************************************************************/
BCWait_init(ByteCode * bc)1195 void BCWait_init(ByteCode *bc)
1196 {
1197 BCWait *w = (BCWait*)bc;
1198
1199 w->w_func = (BCfunc*) BCWait_exec;
1200 }
1201
1202 /*****************************************************************************
1203 *
1204 * Execute a BCWait instruction.
1205 *
1206 *****************************************************************************/
BCWait_exec(BCWait * w,VGThread * thread)1207 void BCWait_exec(BCWait *w,VGThread *thread)
1208 {
1209 VGThread_suspend(thread);
1210 thread->t_pc++;
1211 #if DEBUG
1212 vgio_echo("%p: BCWait()\n",thread);
1213 #endif
1214 }
1215
1216 /*****************************************************************************
1217 *
1218 * Initialize a BCSubr instruction
1219 *
1220 *****************************************************************************/
BCSubr_init(ByteCode * bc,CodeBlock * block,unsigned offset)1221 void BCSubr_init(ByteCode *bc,CodeBlock *block,unsigned offset)
1222 {
1223 BCSubr *s = (BCSubr*)bc;
1224
1225 s->s_func = (BCfunc*) BCSubr_exec;
1226 s->s_block = block;
1227 s->s_offset = offset;
1228 }
1229
1230 /*****************************************************************************
1231 *
1232 * Execute a BCSubr instruction
1233 *
1234 *****************************************************************************/
BCSubr_exec(BCSubr * s,VGThread * t)1235 void BCSubr_exec(BCSubr *s,VGThread *t)
1236 {
1237 #if DEBUG
1238 vgio_echo("%p: BCSubr: jump %p:%x\n",t,s->s_block,s->s_offset);
1239 #endif
1240 t->t_callStack = new_VGFrame(t->t_pc+1, t->t_callStack);
1241 t->t_pc = CodeBlock_first(s->s_block) + s->s_offset;
1242 }
1243
1244 /*****************************************************************************
1245 *
1246 * Initialize a BCReturn instruction
1247 *
1248 *****************************************************************************/
BCReturn_init(ByteCode * bc)1249 void BCReturn_init(ByteCode *bc)
1250 {
1251 BCReturn *r = (BCReturn*)bc;
1252
1253 r->r_func = (BCfunc*) BCReturn_exec;
1254 }
1255
1256 /*****************************************************************************
1257 *
1258 * Execute a BCReturn instruction
1259 *
1260 *****************************************************************************/
BCReturn_exec(BCReturn * r,VGThread * t)1261 void BCReturn_exec(BCReturn *r,VGThread *t)
1262 {
1263 VGFrame *vgf = t->t_callStack;
1264
1265 #if DEBUG
1266 vgio_echo("%p: BCReturn\n",t);
1267 #endif
1268
1269 if (!vgf) {
1270 errorRun(ERR_IE_RETURN);
1271
1272 VGThread_kill(t);
1273 if (t->t_parent)
1274 VGThread_childEndNotify(t->t_parent);
1275 return;
1276 }
1277
1278 t->t_callStack = vgf->f_next;
1279 t->t_pc = vgf->f_pc;
1280 delete_VGFrame(vgf);
1281 }
1282
1283 /*****************************************************************************
1284 *
1285 * Initialize a BCDebugPrint instruction
1286 *
1287 *****************************************************************************/
BCDebugPrint_init(ByteCode * bc,char * msg,...)1288 void BCDebugPrint_init(ByteCode *bc,char *msg,...)
1289 {
1290 BCDebugPrint *dp = (BCDebugPrint*)bc;
1291 char buf[STRMAX];
1292 va_list ap;
1293
1294 va_start(ap, msg);
1295 vsprintf(buf,msg,ap);
1296 va_end(ap);
1297
1298 dp->dp_func = (BCfunc*) BCDebugPrint_exec;
1299 dp->dp_message = strdup(buf);
1300
1301 }
1302
1303 /*****************************************************************************
1304 *
1305 * Execute a BCDebugPrint instruction
1306 *
1307 *****************************************************************************/
BCDebugPrint_exec(BCDebugPrint * dp,VGThread * t)1308 void BCDebugPrint_exec(BCDebugPrint *dp,VGThread *t)
1309 {
1310 #if DEBUG
1311 vgio_echo("%p: BCDebugPrint()\n",t);
1312 #endif
1313 printf("%s",dp->dp_message);
1314 t->t_pc++;
1315 }
1316
1317
1318
1319 /*****************************************************************************
1320 *
1321 * Create a new VGThread object.
1322 *
1323 * Parameters:
1324 * cb Codeblock in which to begin execution
1325 * pc Thread program counter
1326 * modCtx Module context in which thread was declared.
1327 * mitem Module item this thread manages if applicable
1328 *
1329 *****************************************************************************/
new_VGThread(CodeBlock * cb,unsigned pc,ModuleInst * modCtx,ModuleItem * mitem)1330 VGThread *new_VGThread(CodeBlock *cb,unsigned pc,ModuleInst *modCtx,ModuleItem *mitem)
1331 {
1332 VGThread *thread = (VGThread *) malloc(sizeof(VGThread));
1333
1334 VGThread_init(thread,cb,pc,modCtx,mitem);
1335
1336 return thread;
1337 }
1338
1339 /*****************************************************************************
1340 *
1341 * Destroy a VGThread object.
1342 *
1343 * Parameters:
1344 * thread VGThread object to be destroyed.
1345 *
1346 *****************************************************************************/
delete_VGThread(VGThread * thread)1347 void delete_VGThread(VGThread *thread)
1348 {
1349 VGThread_uninit(thread);
1350 free(thread);
1351 }
1352
1353 /*****************************************************************************
1354 *
1355 * Constructor for VGThread objects.
1356 *
1357 * Parameters:
1358 * thread Thread to be constructed.
1359 * cb Codeblock in which to begin execution
1360 * pc Thread program counter
1361 * modCtx Module context in which thread was declared.
1362 * mitem Module item this thread manages if applicable
1363 *
1364 *****************************************************************************/
VGThread_init(VGThread * thread,CodeBlock * cb,unsigned pc,ModuleInst * modCtx,ModuleItem * mitem)1365 void VGThread_init(VGThread *thread,CodeBlock *cb,unsigned pc, ModuleInst *modCtx,ModuleItem *mitem)
1366 {
1367 thread->t_pending = 0;
1368 thread->t_state = TS_ACTIVE;
1369 thread->t_isLive = 1;
1370 thread->t_wait = 0;
1371 thread->t_start_block = cb;
1372 thread->t_start_pc = pc;
1373 thread->t_pc = 0;
1374 thread->t_modCtx = modCtx;
1375 thread->t_mitem = mitem;
1376 thread->t_next = 0;
1377 thread->t_numChild = 0;
1378 thread->t_parent = 0;
1379 thread->t_callStack = 0;
1380 }
1381
VGThread_start(VGThread * thread)1382 void VGThread_start(VGThread *thread)
1383 {
1384 thread->t_pc = CodeBlock_first(thread->t_start_block) + thread->t_start_pc;
1385 }
1386
VGThread_kill(VGThread * t)1387 void VGThread_kill(VGThread *t)
1388 {
1389 /* vgio_echo("killing thread %p.\n",t);*/
1390 t->t_pending = 0;
1391 t->t_state = TS_BLOCKED;
1392 t->t_isLive = 0;
1393
1394 if (t->t_mitem)
1395 ModuleItem_killNotify(t->t_mitem);
1396 }
1397
1398
1399 /*****************************************************************************
1400 *
1401 * Spawn a child thread.
1402 *
1403 * Parameters:
1404 * parent Parent thread initiating the spawn
1405 * cb Codeblock to execute in
1406 * offset Offset of starting address.
1407 *
1408 *****************************************************************************/
VGThread_spawn(VGThread * parent,CodeBlock * cb,unsigned offset)1409 VGThread *VGThread_spawn(VGThread *parent,CodeBlock *cb,unsigned offset)
1410 {
1411 VGThread *child = new_VGThread(cb, offset, parent->t_modCtx, parent->t_mitem);
1412
1413 child->t_parent = parent;
1414 parent->t_numChild++;
1415
1416 return child;
1417 }
1418
1419 /*****************************************************************************
1420 *
1421 * Receive notification that a child thread has terminated.
1422 *
1423 *****************************************************************************/
VGThread_childEndNotify(VGThread * thread)1424 void VGThread_childEndNotify(VGThread *thread)
1425 {
1426 if (--thread->t_numChild == 0 && !VGThread_isActive(thread)) {
1427 VGThread_delay(thread,0);
1428 }
1429 }
1430
1431 /*****************************************************************************
1432 *
1433 * Uninitialize a VGThread object.
1434 *
1435 * Parameters:
1436 * thread VGThread object to be destroyed.
1437 *
1438 *****************************************************************************/
VGThread_uninit(VGThread * thread)1439 void VGThread_uninit(VGThread *thread)
1440 {
1441 /* nothing to do now - placeholder for future use. */
1442 }
1443
VGThread_goto(VGThread * thread,CodeBlock * codeBlock,unsigned offset)1444 void VGThread_goto(VGThread *thread,CodeBlock *codeBlock,unsigned offset)
1445 {
1446 thread->t_pc = CodeBlock_get(codeBlock,offset);
1447 }
1448
1449
1450 /*****************************************************************************
1451 *
1452 * Execute a thread until it is suspended.
1453 *
1454 * Parameters:
1455 * thread Thread to execute.
1456 *
1457 *****************************************************************************/
VGThread_exec(VGThread * thread)1458 void VGThread_exec(VGThread *thread)
1459 {
1460 VGThread_resume(thread);
1461 while (VGThread_isActive(thread)) {
1462 if (do_input_check) {
1463 EvQueue *Q = VGThread_getQueue(thread);
1464 VGThread_suspend(thread);
1465 EvQueue_enqueueAtHead(Q,new_EvThread(thread));
1466 } else
1467 VGThread_doNextInsruction(thread);
1468 }
1469 }
1470
1471 /*****************************************************************************
1472 *
1473 * Suspend execution of a thread for t time units.
1474 *
1475 * Parameters:
1476 * thread Thread to be suspended.
1477 * delay Number of epochs to wait before resuming thread.
1478 *
1479 *****************************************************************************/
VGThread_delay(VGThread * thread,deltatime_t delay)1480 void VGThread_delay(VGThread *thread,deltatime_t delay)
1481 {
1482 EvQueue *Q = VGThread_getQueue(thread);
1483
1484 VGThread_suspend(thread);
1485 EvQueue_enqueueAfter(Q,new_EvThread(thread), delay);
1486 }
1487
1488 /*****************************************************************************
1489 *
1490 * Suspend execution of a thread until end of epoch .
1491 *
1492 * Parameters:
1493 * thread Thread to be suspended.
1494 *
1495 *****************************************************************************/
VGThread_delayToEnd(VGThread * thread)1496 void VGThread_delayToEnd(VGThread *thread)
1497 {
1498 EvQueue *Q = VGThread_getQueue(thread);
1499
1500 VGThread_suspend(thread);
1501 EvQueue_enqueueInactive(Q,new_EvThread(thread));
1502 }
1503
1504 /*****************************************************************************
1505 *
1506 * Suspend execution of a thread until a triggering event occurs.
1507 *
1508 * Parameters:
1509 * thread Thread to be suspended
1510 * trigger Trigger on which to wait.
1511 *
1512 *****************************************************************************/
VGThread_eventWait(VGThread * thread,Trigger * trigger)1513 void VGThread_eventWait(VGThread *thread,Trigger *trigger)
1514 {
1515 VGThread_suspend(thread);
1516 Trigger_enqueue(trigger,new_EvThread(thread));
1517 }
1518
1519 /*****************************************************************************
1520 *
1521 * Create a thread stack frame object
1522 *
1523 * Parameters:
1524 * bc Stack frame address
1525 * next Next element on stack frame
1526 *
1527 *****************************************************************************/
new_VGFrame(ByteCode * bc,VGFrame * next)1528 VGFrame *new_VGFrame(ByteCode *bc,VGFrame *next)
1529 {
1530 VGFrame *vgf = (VGFrame *) malloc(sizeof(VGFrame));
1531
1532 vgf->f_pc = bc;
1533 vgf->f_next = next;
1534
1535 return vgf;
1536 }
1537
1538 /*****************************************************************************
1539 *
1540 * Destroy a thread stack frame object
1541 *
1542 *****************************************************************************/
delete_VGFrame(VGFrame * vgf)1543 void delete_VGFrame(VGFrame *vgf)
1544 {
1545 free(vgf);
1546 }
1547