HDLRuby 2.10.5 → 2.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HDLRuby.gemspec +1 -0
- data/README.md +8 -4
- data/Rakefile +8 -0
- data/{lib/HDLRuby/sim/Makefile → ext/hruby_sim/Makefile_csim} +0 -0
- data/ext/hruby_sim/extconf.rb +13 -0
- data/ext/hruby_sim/hruby_rcsim_build.c +1190 -0
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim.h +255 -16
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_calc.c +311 -182
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_core.c +36 -18
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_list.c +0 -0
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_stack_calc.c +4 -1
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_stack_calc.c.sav +0 -0
- data/ext/hruby_sim/hruby_sim_tree_calc.c +375 -0
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_vcd.c +5 -5
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_sim_vizualize.c +2 -2
- data/{lib/HDLRuby/sim → ext/hruby_sim}/hruby_value_pool.c +8 -1
- data/lib/HDLRuby/hdr_samples/bstr_bench.rb +2 -0
- data/lib/HDLRuby/hdr_samples/case_bench.rb +2 -2
- data/lib/HDLRuby/hdr_samples/counter_bench.rb +0 -1
- data/lib/HDLRuby/hdr_samples/counter_dff_bench.rb +46 -0
- data/lib/HDLRuby/hdr_samples/dff_bench.rb +1 -1
- data/lib/HDLRuby/hdr_samples/print_bench.rb +62 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +5 -3
- data/lib/HDLRuby/hdr_samples/simple_counter_bench.rb +43 -0
- data/lib/HDLRuby/hdrcc.rb +54 -8
- data/lib/HDLRuby/hruby_bstr.rb +1175 -917
- data/lib/HDLRuby/hruby_high.rb +200 -90
- data/lib/HDLRuby/hruby_high_fullname.rb +82 -0
- data/lib/HDLRuby/hruby_low.rb +41 -23
- data/lib/HDLRuby/hruby_low2c.rb +7 -0
- data/lib/HDLRuby/hruby_rcsim.rb +978 -0
- data/lib/HDLRuby/hruby_rsim.rb +1134 -0
- data/lib/HDLRuby/hruby_rsim_vcd.rb +322 -0
- data/lib/HDLRuby/hruby_values.rb +362 -18
- data/lib/HDLRuby/hruby_verilog.rb +21 -3
- data/lib/HDLRuby/version.rb +1 -1
- metadata +24 -13
|
@@ -67,6 +67,7 @@ static int sim_end_flag = 0;
|
|
|
67
67
|
/** Adds a timed behavior for processing.
|
|
68
68
|
* @param behavior the timed behavior to register */
|
|
69
69
|
void register_timed_behavior(Behavior behavior) {
|
|
70
|
+
// printf("Registering timed behavior=%p\n",behavior);fflush(stdout);
|
|
70
71
|
if (num_timed_behaviors == cap_timed_behaviors) {
|
|
71
72
|
if (cap_timed_behaviors == 0) {
|
|
72
73
|
/* Need to create the array containing the timed behaviors. */
|
|
@@ -75,7 +76,8 @@ void register_timed_behavior(Behavior behavior) {
|
|
|
75
76
|
} else {
|
|
76
77
|
/* Need to increase the capacity. */
|
|
77
78
|
Behavior* behaviors = calloc(sizeof(Behavior),cap_timed_behaviors*2);
|
|
78
|
-
memcpy(timed_behaviors,
|
|
79
|
+
memcpy(behaviors,timed_behaviors,sizeof(Behavior)*cap_timed_behaviors);
|
|
80
|
+
timed_behaviors = behaviors;
|
|
79
81
|
cap_timed_behaviors *= 2;
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -100,7 +102,7 @@ void register_signal(SignalI signal) {
|
|
|
100
102
|
all_signals=new_signals;
|
|
101
103
|
}
|
|
102
104
|
}
|
|
103
|
-
/* Add the
|
|
105
|
+
/* Add the signal. */
|
|
104
106
|
all_signals[num_all_signals++] = signal;
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -108,15 +110,16 @@ void register_signal(SignalI signal) {
|
|
|
108
110
|
/** Recursively update the signals until no (untimed) behavior are
|
|
109
111
|
* activated. */
|
|
110
112
|
void hruby_sim_update_signals() {
|
|
111
|
-
|
|
113
|
+
// printf("hruby_sim_update_signals...\n");fflush(stdout);
|
|
112
114
|
/* As long as the list of touched signals is not empty go on computing. */
|
|
113
115
|
while(!empty_list(touched_signals) || !empty_list(touched_signals_seq)) {
|
|
114
|
-
// printf("## Checking touched signals.\n");
|
|
116
|
+
// printf("## Checking touched signals.\n");fflush(stdout);
|
|
115
117
|
/* Sets the new signals values and mark the signals as activating. */
|
|
116
118
|
/* For the case of the parallel execution model. */
|
|
117
119
|
while(!empty_list(touched_signals)) {
|
|
118
120
|
Elem e = remove_list(touched_signals);
|
|
119
121
|
SignalI sig = e->data;
|
|
122
|
+
// printf("sig=%p kind=%d\n",sig,sig->kind);fflush(stdout);
|
|
120
123
|
delete_element(e);
|
|
121
124
|
/* Is there a change? */
|
|
122
125
|
if (same_content_value(sig->c_value,sig->f_value)) continue;
|
|
@@ -124,7 +127,7 @@ void hruby_sim_update_signals() {
|
|
|
124
127
|
printer.print_signal(sig);
|
|
125
128
|
// printf("c_value="); printer.print_value(sig->c_value);
|
|
126
129
|
// printf("\nf_value="); printer.print_value(sig->f_value); printf("\n");
|
|
127
|
-
// printf("Touched signal: %p (%s)\n",sig,sig->name);
|
|
130
|
+
// printf("Touched signal: %p (%s)\n",sig,sig->name);fflush(stdout);
|
|
128
131
|
/* Update the current value of the signal. */
|
|
129
132
|
copy_value(sig->f_value,sig->c_value);
|
|
130
133
|
// /* Mark the signal as activated. */
|
|
@@ -148,11 +151,13 @@ void hruby_sim_update_signals() {
|
|
|
148
151
|
}
|
|
149
152
|
/* Positive edge activation. */
|
|
150
153
|
if (!zero_value(sig->c_value)) {
|
|
154
|
+
// printf("PAR: posedge for sig=%s with num_pos=%i\n",sig->name,sig->num_pos);
|
|
151
155
|
for(i=0; i<sig->num_pos; ++i) {
|
|
152
156
|
Object obj = sig->pos[i];
|
|
153
157
|
if (obj->kind == BEHAVIOR) {
|
|
154
158
|
/* Behavior case. */
|
|
155
159
|
Behavior beh = (Behavior)obj;
|
|
160
|
+
// printf("Activating beh=%p.\n",beh);
|
|
156
161
|
beh->activated = 1;
|
|
157
162
|
add_list(activate_codes,get_element(beh));
|
|
158
163
|
} else {
|
|
@@ -210,6 +215,7 @@ void hruby_sim_update_signals() {
|
|
|
210
215
|
}
|
|
211
216
|
/* Positive edge activation. */
|
|
212
217
|
if (!zero_value(sig->c_value)) {
|
|
218
|
+
// printf("SEQ: posedge for sig=%s with num_pos=%i\n",sig->name,sig->num_pos);
|
|
213
219
|
for(i=0; i<sig->num_pos; ++i) {
|
|
214
220
|
Object obj = sig->pos[i];
|
|
215
221
|
if (obj->kind == BEHAVIOR) {
|
|
@@ -253,10 +259,17 @@ void hruby_sim_update_signals() {
|
|
|
253
259
|
if (obj->kind == BEHAVIOR) {
|
|
254
260
|
/* Behavior case. */
|
|
255
261
|
Behavior beh = (Behavior)obj;
|
|
262
|
+
// printf("beh=%p\n",beh);
|
|
256
263
|
/* Is the code really enabled and activated? */
|
|
257
264
|
if (beh->enabled && beh->activated) {
|
|
258
265
|
/* Yes, execute it. */
|
|
266
|
+
#ifdef RCSIM
|
|
267
|
+
// printf("going to execute with beh=%p\n",beh);
|
|
268
|
+
// printf("going to execute: %p with kind=%d\n",beh->block,beh->block->kind);
|
|
269
|
+
execute_statement((Statement)(beh->block),0,beh);
|
|
270
|
+
#else
|
|
259
271
|
beh->block->function();
|
|
272
|
+
#endif
|
|
260
273
|
/* And deactivate it. */
|
|
261
274
|
beh->activated = 0;
|
|
262
275
|
}
|
|
@@ -284,9 +297,11 @@ void hruby_sim_advance_time() {
|
|
|
284
297
|
int i;
|
|
285
298
|
for(i=0; i<num_timed_behaviors; ++i) {
|
|
286
299
|
unsigned long long beh_time = timed_behaviors[i]->active_time;
|
|
300
|
+
// printf("beh_time=%llu\n",beh_time);
|
|
287
301
|
if (timed_behaviors[i]->timed == 1)
|
|
288
302
|
if (beh_time < next_time) next_time = beh_time;
|
|
289
303
|
}
|
|
304
|
+
// printf("hruby_sim_time=%llu next_time=%llu\n",hruby_sim_time,next_time);
|
|
290
305
|
/* Sets the new activation time. */
|
|
291
306
|
hruby_sim_time = next_time;
|
|
292
307
|
// println_time(hruby_sim_time);
|
|
@@ -294,7 +309,7 @@ void hruby_sim_advance_time() {
|
|
|
294
309
|
}
|
|
295
310
|
|
|
296
311
|
|
|
297
|
-
/** Sets the
|
|
312
|
+
/** Sets the enable status of the behaviors of a scope.
|
|
298
313
|
* @param scope the scope to process.
|
|
299
314
|
* @param status the enable status. */
|
|
300
315
|
static void set_enable_scope(Scope scope, int status) {
|
|
@@ -334,7 +349,6 @@ void activate_behavior(Behavior behavior) {
|
|
|
334
349
|
* time. */
|
|
335
350
|
void hruby_sim_activate_behaviors_on_time() {
|
|
336
351
|
int i;
|
|
337
|
-
// printf("$1\n");
|
|
338
352
|
pthread_mutex_lock(&hruby_sim_mutex);
|
|
339
353
|
/* Count the number of behaviors that will be activated. */
|
|
340
354
|
for(i=0; i<num_timed_behaviors; ++i) {
|
|
@@ -349,7 +363,6 @@ void hruby_sim_activate_behaviors_on_time() {
|
|
|
349
363
|
}
|
|
350
364
|
/* Activate the behaviors .*/
|
|
351
365
|
behaviors_can_run = 1;
|
|
352
|
-
// printf("$2\n");
|
|
353
366
|
// pthread_cond_signal(&compute_cond); /* No behaviors. */
|
|
354
367
|
// pthread_cond_signal(&hruby_beh_cond);
|
|
355
368
|
pthread_mutex_unlock(&hruby_sim_mutex);
|
|
@@ -361,14 +374,12 @@ void hruby_sim_activate_behaviors_on_time() {
|
|
|
361
374
|
void hruby_sim_wait_behaviors() {
|
|
362
375
|
pthread_mutex_lock(&hruby_sim_mutex);
|
|
363
376
|
while(num_active_behaviors > 0) {
|
|
364
|
-
// printf("$3\n");
|
|
365
377
|
// printf("num_active_behaviors = %d\n",num_active_behaviors);
|
|
366
378
|
// pthread_cond_wait(&active_behaviors_cond, &hruby_sim_mutex);
|
|
367
379
|
pthread_cond_wait(&hruby_sim_cond, &hruby_sim_mutex);
|
|
368
380
|
}
|
|
369
381
|
behaviors_can_run = 0;
|
|
370
382
|
pthread_mutex_unlock(&hruby_sim_mutex);
|
|
371
|
-
// printf("$4\n");
|
|
372
383
|
}
|
|
373
384
|
|
|
374
385
|
|
|
@@ -377,7 +388,6 @@ void hruby_sim_wait_behaviors() {
|
|
|
377
388
|
void* behavior_run(void* arg) {
|
|
378
389
|
Behavior behavior = (Behavior)arg;
|
|
379
390
|
/* First lock the behavior until the simulation engine starts. */
|
|
380
|
-
// printf("#1\n");
|
|
381
391
|
pthread_mutex_lock(&hruby_sim_mutex);
|
|
382
392
|
num_active_behaviors -= 1;
|
|
383
393
|
while(!behaviors_can_run) {
|
|
@@ -386,11 +396,16 @@ void* behavior_run(void* arg) {
|
|
|
386
396
|
pthread_cond_wait(&hruby_beh_cond, &hruby_sim_mutex);
|
|
387
397
|
}
|
|
388
398
|
pthread_mutex_unlock(&hruby_sim_mutex);
|
|
389
|
-
// printf("#2\n");
|
|
390
399
|
/* Now can start the execution of the behavior. */
|
|
391
|
-
if (behavior->enabled)
|
|
400
|
+
if (behavior->enabled) {
|
|
401
|
+
#ifdef RCSIM
|
|
402
|
+
// printf("going to execute with behavior=%p\n",behavior);
|
|
403
|
+
// printf("going to execute: %p with kind=%d\n",behavior->block,behavior->block->kind);
|
|
404
|
+
execute_statement((Statement)(behavior->block),0,behavior);
|
|
405
|
+
#else
|
|
392
406
|
behavior->block->function();
|
|
393
|
-
|
|
407
|
+
#endif
|
|
408
|
+
}
|
|
394
409
|
/* Now can start the execution of the behavior. */
|
|
395
410
|
/* Stops the behavior. */
|
|
396
411
|
pthread_mutex_lock(&hruby_sim_mutex);
|
|
@@ -410,6 +425,8 @@ void* behavior_run(void* arg) {
|
|
|
410
425
|
* @note create a thread per timed behavior. */
|
|
411
426
|
void hruby_sim_start_timed_behaviors() {
|
|
412
427
|
int i;
|
|
428
|
+
// printf("hruby_sim_start_timed_behaviors\n");fflush(stdout);
|
|
429
|
+
// printf("timed_behaviors=%p\n",timed_behaviors);fflush(stdout);
|
|
413
430
|
pthread_mutex_lock(&hruby_sim_mutex);
|
|
414
431
|
/* Sets the end flags to 0. */
|
|
415
432
|
sim_end_flag = 0;
|
|
@@ -418,12 +435,11 @@ void hruby_sim_start_timed_behaviors() {
|
|
|
418
435
|
/* Create and start the threads. */
|
|
419
436
|
for(i=0; i<num_timed_behaviors; ++i) {
|
|
420
437
|
num_run_behaviors += 1;
|
|
421
|
-
// ++num_active_behaviors;
|
|
422
|
-
// printf("0 num_run_behaviors = %d\n",num_run_behaviors);
|
|
423
438
|
pthread_create(&timed_behaviors[i]->thread,NULL,
|
|
424
439
|
&behavior_run,timed_behaviors[i]);
|
|
425
440
|
}
|
|
426
441
|
pthread_mutex_unlock(&hruby_sim_mutex);
|
|
442
|
+
// exit(0);
|
|
427
443
|
}
|
|
428
444
|
|
|
429
445
|
/** Ends waiting all the threads properly terminates. */
|
|
@@ -474,6 +490,7 @@ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
|
|
474
490
|
/* Initially touch all the signals. */
|
|
475
491
|
each_all_signal(&touch_signal);
|
|
476
492
|
}
|
|
493
|
+
// printf("num_run_behavior=%d\n",num_run_behaviors);
|
|
477
494
|
if (num_run_behaviors <= 0) break;
|
|
478
495
|
/* Advance time to next timestep. */
|
|
479
496
|
hruby_sim_advance_time();
|
|
@@ -499,7 +516,7 @@ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
|
|
499
516
|
|
|
500
517
|
|
|
501
518
|
/** Makes the behavior wait for a given time.
|
|
502
|
-
* @param delay the delay to wait in
|
|
519
|
+
* @param delay the delay to wait in ps.
|
|
503
520
|
* @param behavior the current behavior. */
|
|
504
521
|
void hw_wait(unsigned long long delay, Behavior behavior) {
|
|
505
522
|
/* Maybe the thread is to end immediatly. */
|
|
@@ -544,7 +561,6 @@ void touch_signal(SignalI signal) {
|
|
|
544
561
|
* @param value the value to transmit
|
|
545
562
|
* @param signal the signal to transmit the value to. */
|
|
546
563
|
void transmit_to_signal(Value value, SignalI signal) {
|
|
547
|
-
// printf("Tansmit to signal: %s(%p) with fading=%d\n",signal->name,signal,signal->fading);
|
|
548
564
|
/* Copy the content. */
|
|
549
565
|
if (signal->fading)
|
|
550
566
|
signal->f_value = copy_value(value,signal->f_value);
|
|
@@ -584,6 +600,7 @@ void transmit_to_signal_range(Value value, RefRangeS ref) {
|
|
|
584
600
|
* @param signal the signal to touch */
|
|
585
601
|
void touch_signal_seq(SignalI signal) {
|
|
586
602
|
// printf("touching signal seq: %p\n",signal);
|
|
603
|
+
// printf("signal->c_value=%p\n",signal->c_value);
|
|
587
604
|
/* Is there a difference between the present and future value? */
|
|
588
605
|
if (same_content_value(signal->c_value,signal->f_value)) return;
|
|
589
606
|
/* Yes, add the signal to the list of touched sequential ones and update
|
|
@@ -601,6 +618,7 @@ void touch_signal_seq(SignalI signal) {
|
|
|
601
618
|
* @param signal the signal to transmit the value to. */
|
|
602
619
|
void transmit_to_signal_seq(Value value, SignalI signal) {
|
|
603
620
|
// printf("Tansmit to signal seq: %s(%p)\n",signal->name,signal);
|
|
621
|
+
// printf("signal->f_value=%p\n",signal->f_value);
|
|
604
622
|
/* Copy the content. */
|
|
605
623
|
if (signal->fading)
|
|
606
624
|
copy_value(value,signal->f_value);
|
|
File without changes
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/* Not used for the C-Ruby hybrid simulator. */
|
|
2
|
+
#ifndef RCSIM
|
|
3
|
+
|
|
1
4
|
#include <stdio.h>
|
|
2
5
|
#include <stdarg.h>
|
|
3
6
|
#include <stdlib.h>
|
|
@@ -5,7 +8,6 @@
|
|
|
5
8
|
#include <limits.h>
|
|
6
9
|
#include "hruby_sim.h"
|
|
7
10
|
|
|
8
|
-
|
|
9
11
|
/**
|
|
10
12
|
* The HDLRuby simulation stack calculation engine, to be used with C code
|
|
11
13
|
* generated by hruby_low2c.
|
|
@@ -248,3 +250,4 @@ void transmitR_seq(RefRangeS ref) {
|
|
|
248
250
|
transmit_to_signal_range_seq(pop(),ref);
|
|
249
251
|
}
|
|
250
252
|
|
|
253
|
+
#endif
|
|
File without changes
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/* Used by the C-Ruby hybrid simulator only. */
|
|
2
|
+
#ifdef RCSIM
|
|
3
|
+
|
|
4
|
+
#include "extconf.h"
|
|
5
|
+
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <stdarg.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <string.h>
|
|
10
|
+
#include <limits.h>
|
|
11
|
+
#include "hruby_sim.h"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The HDLRuby simulation tree-based calculation engine.
|
|
16
|
+
**/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/** Calculates a tree expression.
|
|
21
|
+
* @param expr the expression to execute.
|
|
22
|
+
* @param res the expression where to write the result. */
|
|
23
|
+
Value calc_expression(Expression expr, Value res) {
|
|
24
|
+
// printf("calc_expression with kind=%d\n",expr->kind);
|
|
25
|
+
/* Depending on the kind of expression. */
|
|
26
|
+
switch(expr->kind) {
|
|
27
|
+
case VALUEE:
|
|
28
|
+
/* Assume it is a Value. */
|
|
29
|
+
// printf("value=%p type=%p\n",expr,((Value)expr)->type);
|
|
30
|
+
res = (Value)expr;
|
|
31
|
+
// res = copy_value((Value)expr,res);
|
|
32
|
+
break;
|
|
33
|
+
case UNARY:
|
|
34
|
+
{
|
|
35
|
+
Unary uexpr = (Unary)expr;
|
|
36
|
+
Value child = get_value();
|
|
37
|
+
child = calc_expression(uexpr->child,child);
|
|
38
|
+
res = uexpr->oper(child,res);
|
|
39
|
+
free_value();
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case BINARY:
|
|
43
|
+
{
|
|
44
|
+
Binary bexpr = (Binary)expr;
|
|
45
|
+
Value left = get_value();
|
|
46
|
+
Value right = get_value();
|
|
47
|
+
left = calc_expression(bexpr->left,left);
|
|
48
|
+
right = calc_expression(bexpr->right,right);
|
|
49
|
+
res = bexpr->oper(left,right,res);
|
|
50
|
+
free_value();
|
|
51
|
+
free_value();
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case CONCAT:
|
|
55
|
+
{
|
|
56
|
+
Concat cexpr = (Concat)expr;
|
|
57
|
+
/* Calculate the sub expressions. */
|
|
58
|
+
Value values[cexpr->num_exprs];
|
|
59
|
+
for(int i=0; i<cexpr->num_exprs; ++i) {
|
|
60
|
+
values[i] = get_value();
|
|
61
|
+
values[i] = calc_expression(cexpr->exprs[i],values[i]);
|
|
62
|
+
}
|
|
63
|
+
/* Use them for calculating the concat. */
|
|
64
|
+
res = concat_valueP(cexpr->num_exprs,cexpr->dir,res,values);
|
|
65
|
+
for(int i=0; i<cexpr->num_exprs; ++i) free_value();
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case CAST:
|
|
69
|
+
{
|
|
70
|
+
Cast cexpr = (Cast)expr;
|
|
71
|
+
Value child = get_value();
|
|
72
|
+
child = calc_expression(cexpr->child,child);
|
|
73
|
+
res = cast_value(child,cexpr->type,res);
|
|
74
|
+
free_value();
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case REF_OBJECT:
|
|
78
|
+
res = calc_expression((Expression)(((RefObject)expr)->object),res);
|
|
79
|
+
break;
|
|
80
|
+
case REF_INDEX:
|
|
81
|
+
{
|
|
82
|
+
RefIndex rexpr = (RefIndex)expr;
|
|
83
|
+
/* Compute the accessed value. */
|
|
84
|
+
Value value = get_value();
|
|
85
|
+
value = calc_expression((Expression)(rexpr->ref),value);
|
|
86
|
+
/* Compute the index. */
|
|
87
|
+
Value indexV = get_value();
|
|
88
|
+
indexV = calc_expression(rexpr->index,indexV);
|
|
89
|
+
/* Get its integer index. */
|
|
90
|
+
long long index = value2integer(indexV);
|
|
91
|
+
// printf("index=%llu\n",index);
|
|
92
|
+
free_value();
|
|
93
|
+
/* Performs the access. */
|
|
94
|
+
res = read_range(value,index,index,rexpr->type,res);
|
|
95
|
+
free_value();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case REF_RANGE:
|
|
99
|
+
{
|
|
100
|
+
RefRangeE rexpr = (RefRangeE)expr;
|
|
101
|
+
/* Compute the accessed value. */
|
|
102
|
+
Value value = get_value();
|
|
103
|
+
value = calc_expression((Expression)(rexpr->ref),value);
|
|
104
|
+
/* Compute the range. */
|
|
105
|
+
Value firstV = get_value();
|
|
106
|
+
firstV = calc_expression(rexpr->first,firstV);
|
|
107
|
+
Value lastV = get_value();
|
|
108
|
+
lastV = calc_expression(rexpr->last,lastV);
|
|
109
|
+
/* Get its integer range. */
|
|
110
|
+
long long first = value2integer(firstV);
|
|
111
|
+
long long last = value2integer(lastV);
|
|
112
|
+
free_value();
|
|
113
|
+
free_value();
|
|
114
|
+
// printf("first=%lli last=%lli\n",first,last);
|
|
115
|
+
/* Performs the access. */
|
|
116
|
+
TypeS base_type = { rexpr->type->base, 1, rexpr->type->flags };
|
|
117
|
+
res = read_range(value,first,last,&base_type,res);
|
|
118
|
+
free_value();
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case REF_CONCAT:
|
|
122
|
+
{
|
|
123
|
+
RefConcat rexpr = (RefConcat)expr;
|
|
124
|
+
/* Process like a simple concat. */
|
|
125
|
+
/* Calculate the sub expressions. */
|
|
126
|
+
Value values[rexpr->num_refs];
|
|
127
|
+
for(int i=0; i<rexpr->num_refs; ++i) {
|
|
128
|
+
values[i] = get_value();
|
|
129
|
+
values[i] = calc_expression((Expression)(rexpr->refs[i]),values[i]);
|
|
130
|
+
}
|
|
131
|
+
/* Use them for calculating the concat. */
|
|
132
|
+
res = concat_valueP(rexpr->num_refs,rexpr->dir,res,values);
|
|
133
|
+
for(int i=0; i<rexpr->num_refs; ++i) free_value();
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
case SIGNALI:
|
|
137
|
+
res = calc_expression((Expression)(((SignalI)expr)->c_value),res);
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
perror("Invalid expression kind.");
|
|
141
|
+
exit(1);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
return res;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
/** Executes a statement.
|
|
150
|
+
* @param stmnt the statement to execute.
|
|
151
|
+
* @param mode blocking mode: 0: par, 1:seq
|
|
152
|
+
* @param behavior the behavior in execution. */
|
|
153
|
+
void execute_statement(Statement stmnt, int mode, Behavior behavior) {
|
|
154
|
+
/* Depending on the kind of statement. */
|
|
155
|
+
// printf("Executing statement=%p with kind=%d\n",stmnt,stmnt->kind);fflush(stdout);
|
|
156
|
+
switch(stmnt->kind) {
|
|
157
|
+
case TRANSMIT:
|
|
158
|
+
{
|
|
159
|
+
Transmit trans = (Transmit)stmnt;
|
|
160
|
+
// printf("trans=%p trans->left=%p trans->left->kind=%d\n",trans,trans->left,trans->left->kind);
|
|
161
|
+
/* Compute the right value. */
|
|
162
|
+
// Value right = calc_expression(trans->right);
|
|
163
|
+
Value right = get_value();
|
|
164
|
+
right = calc_expression(trans->right,right);
|
|
165
|
+
/* Depending on the left value. */
|
|
166
|
+
switch (trans->left->kind) {
|
|
167
|
+
case SIGNALI:
|
|
168
|
+
// printf("left->name=%s\n",((SignalI)(trans->left))->name);
|
|
169
|
+
fflush(stdout);
|
|
170
|
+
/* Simple transmission. */
|
|
171
|
+
if (mode)
|
|
172
|
+
transmit_to_signal_seq(right,(SignalI)(trans->left));
|
|
173
|
+
else
|
|
174
|
+
transmit_to_signal(right,(SignalI)(trans->left));
|
|
175
|
+
break;
|
|
176
|
+
case REF_INDEX:
|
|
177
|
+
{
|
|
178
|
+
/* Transmission to sub element. */
|
|
179
|
+
RefIndex refi = (RefIndex)(trans->left);
|
|
180
|
+
/* Compute the index. */
|
|
181
|
+
// Value indexV = calc_expression(refi->index);
|
|
182
|
+
Value indexV = get_value();
|
|
183
|
+
indexV = calc_expression(refi->index,indexV);
|
|
184
|
+
long long index = value2integer(indexV);
|
|
185
|
+
free_value();
|
|
186
|
+
/* Generate the reference inside the left value. */
|
|
187
|
+
RefRangeS ref =
|
|
188
|
+
make_ref_rangeS((SignalI)(refi->ref),refi->type,
|
|
189
|
+
index,index);
|
|
190
|
+
/* Perform the transmit. */
|
|
191
|
+
if(mode)
|
|
192
|
+
transmit_to_signal_range_seq(right,ref);
|
|
193
|
+
else
|
|
194
|
+
transmit_to_signal_range(right,ref);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
case REF_RANGE:
|
|
198
|
+
{
|
|
199
|
+
/* Transmission to range of sub elements. */
|
|
200
|
+
RefRangeE refr = (RefRangeE)(trans->left);
|
|
201
|
+
/* Compute the range. */
|
|
202
|
+
// Value firstV = calc_expression(refr->first);
|
|
203
|
+
Value firstV = get_value();
|
|
204
|
+
firstV = calc_expression(refr->first,firstV);
|
|
205
|
+
long long first = value2integer(firstV);
|
|
206
|
+
free_value();
|
|
207
|
+
// Value lastV = calc_expression(refr->last);
|
|
208
|
+
Value lastV = get_value();
|
|
209
|
+
lastV = calc_expression(refr->last,lastV);
|
|
210
|
+
long long last = value2integer(lastV);
|
|
211
|
+
free_value();
|
|
212
|
+
/* Generate the reference inside the left value. */
|
|
213
|
+
RefRangeS ref =
|
|
214
|
+
make_ref_rangeS((SignalI)(refr->ref),refr->type,
|
|
215
|
+
first,last);
|
|
216
|
+
/* Perform the transmit. */
|
|
217
|
+
if(mode)
|
|
218
|
+
transmit_to_signal_range_seq(right,ref);
|
|
219
|
+
else
|
|
220
|
+
transmit_to_signal_range(right,ref);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case REF_CONCAT:
|
|
224
|
+
{
|
|
225
|
+
/* Transmit to each sub-reference. */
|
|
226
|
+
RefConcat refc = (RefConcat)(trans->left);
|
|
227
|
+
/* For that purpose use a temporary Transmit node. */
|
|
228
|
+
TransmitS subtrans = { TRANSMIT, NULL, NULL };
|
|
229
|
+
long long pos=0; /* The current position in the value
|
|
230
|
+
to assign */
|
|
231
|
+
/* For each sub reference. */
|
|
232
|
+
for(int i=0; i < refc->num_refs; ++i) {
|
|
233
|
+
/* Set up the transmit. */
|
|
234
|
+
subtrans.left = refc->refs[i];
|
|
235
|
+
long long size = type_width(subtrans.left->type);
|
|
236
|
+
subtrans.right = (Expression)get_value();
|
|
237
|
+
subtrans.right = (Expression)read_range(
|
|
238
|
+
right,pos,pos+size-1,
|
|
239
|
+
get_type_bit(),(Value)(subtrans.right));
|
|
240
|
+
/* Execute it. */
|
|
241
|
+
execute_statement((Statement)&subtrans,
|
|
242
|
+
mode,behavior);
|
|
243
|
+
/* Prepare the next step. */
|
|
244
|
+
free_value();
|
|
245
|
+
pos += size;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
default:
|
|
249
|
+
perror("Invalid kind for a reference.");
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case PRINT:
|
|
254
|
+
{
|
|
255
|
+
Print prt = (Print)stmnt;
|
|
256
|
+
/* Prints each argument. */
|
|
257
|
+
for(int i=0; i<prt->num_args; ++i) {
|
|
258
|
+
Expression arg=prt->args[i];
|
|
259
|
+
switch(arg->kind) {
|
|
260
|
+
case SYSTEMT:
|
|
261
|
+
case SYSTEMI:
|
|
262
|
+
printer.print_string_name((Object)arg);
|
|
263
|
+
break;
|
|
264
|
+
case STRINGE:
|
|
265
|
+
printer.print_string(((StringE)arg)->str);
|
|
266
|
+
break;
|
|
267
|
+
default:
|
|
268
|
+
{
|
|
269
|
+
Value res = get_value();
|
|
270
|
+
res = calc_expression(arg,res);
|
|
271
|
+
printer.print_string_value(res);
|
|
272
|
+
free_value();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case HIF:
|
|
279
|
+
{
|
|
280
|
+
HIf hif = (HIf)stmnt;
|
|
281
|
+
/* Calculation the condition. */
|
|
282
|
+
// Value condition = calc_expression(hif->condition);
|
|
283
|
+
Value condition = get_value();
|
|
284
|
+
condition = calc_expression(hif->condition,condition);
|
|
285
|
+
/* Is it true? */
|
|
286
|
+
if (is_defined_value(condition) && value2integer(condition)) {
|
|
287
|
+
/* Yes, execute the yes branch. */
|
|
288
|
+
execute_statement(hif->yes,mode,behavior);
|
|
289
|
+
} else {
|
|
290
|
+
/* No, maybe an alternate condition is met. */
|
|
291
|
+
int met = 0;/* Tell if an alternate condition has been met.*/
|
|
292
|
+
for(int i=0; i<hif->num_noifs; ++i) {
|
|
293
|
+
// Value subcond = calc_expression(hif->noconds[i]);
|
|
294
|
+
Value subcond = get_value();
|
|
295
|
+
subcond = calc_expression(hif->noconds[i],subcond);
|
|
296
|
+
if (is_defined_value(subcond) && value2integer(subcond)){
|
|
297
|
+
/* The subcondition is met, execute the corresponding
|
|
298
|
+
* substatement. */
|
|
299
|
+
execute_statement(hif->nostmnts[i],mode,behavior);
|
|
300
|
+
/* And remember it. */
|
|
301
|
+
met = 1;
|
|
302
|
+
free_value();
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
free_value();
|
|
306
|
+
}
|
|
307
|
+
/* Where there a sub condition met? */
|
|
308
|
+
if (!met) {
|
|
309
|
+
/* No, execute the no statement. */
|
|
310
|
+
execute_statement(hif->no,mode,behavior);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
free_value();
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
case HCASE:
|
|
317
|
+
{
|
|
318
|
+
HCase hcase = (HCase)stmnt;
|
|
319
|
+
/* Calculation the value to check. */
|
|
320
|
+
// Value value = calc_expression(hcase->value);
|
|
321
|
+
Value value = get_value();
|
|
322
|
+
value = calc_expression(hcase->value,value);
|
|
323
|
+
/* Tell if a case if matched. */
|
|
324
|
+
int met = 0;
|
|
325
|
+
/* Check each case. */
|
|
326
|
+
Value cmp = get_value();
|
|
327
|
+
for(int i=0; i<hcase->num_whens; ++i) {
|
|
328
|
+
// cmp = equal_value_c(value,calc_expression(hcase->matches[i]),
|
|
329
|
+
// cmp);
|
|
330
|
+
Value match = get_value();
|
|
331
|
+
match = calc_expression(hcase->matches[i],match);
|
|
332
|
+
cmp = equal_value_c(value,match,cmp);
|
|
333
|
+
if (is_defined_value(cmp) && value2integer(cmp)) {
|
|
334
|
+
/* Found the right case, execute the corresponding
|
|
335
|
+
* statement. */
|
|
336
|
+
execute_statement(hcase->stmnts[i],mode,behavior);
|
|
337
|
+
/* And remeber it. */
|
|
338
|
+
met = 1;
|
|
339
|
+
free_value();
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
free_value();
|
|
343
|
+
}
|
|
344
|
+
free_value();
|
|
345
|
+
free_value();
|
|
346
|
+
/* Was no case found and is there a default statement? */
|
|
347
|
+
if (!met && hcase->defolt) {
|
|
348
|
+
/* Yes, execute the default statement. */
|
|
349
|
+
execute_statement(hcase->defolt,mode,behavior);
|
|
350
|
+
}
|
|
351
|
+
break;
|
|
352
|
+
}
|
|
353
|
+
case TIME_WAIT:
|
|
354
|
+
{
|
|
355
|
+
/* Get the value of the delay. */
|
|
356
|
+
long long delay = ((TimeWait)stmnt)->delay;
|
|
357
|
+
/* Wait the given delay. */
|
|
358
|
+
hw_wait(delay,behavior);
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
case BLOCK:
|
|
362
|
+
{
|
|
363
|
+
Block block = (Block)stmnt;
|
|
364
|
+
/* Execute each statement of the block. */
|
|
365
|
+
for(int i=0; i<block->num_stmnts; ++i)
|
|
366
|
+
execute_statement(block->stmnts[i],block->mode,behavior);
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
default:
|
|
371
|
+
perror("Invalid kind for an expression.");
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
#endif
|
|
@@ -22,7 +22,7 @@ static unsigned long long vcd_timeunit = 1;
|
|
|
22
22
|
|
|
23
23
|
/** Prints to the vcd file.
|
|
24
24
|
* @param fmt the format for handling the variadic arguments. */
|
|
25
|
-
static int vcd_print(char* fmt, ...) {
|
|
25
|
+
static int vcd_print(const char* fmt, ...) {
|
|
26
26
|
int ret;
|
|
27
27
|
|
|
28
28
|
/* Declare a va_list type variable */
|
|
@@ -94,7 +94,7 @@ static void vcd_print_name(Object object) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
/** Prints the name of an object incluing its
|
|
97
|
+
/** Prints the name of an object incluing its hierarchy.
|
|
98
98
|
* @param object the object to print the name. */
|
|
99
99
|
static void vcd_print_full_name(Object object) {
|
|
100
100
|
/* Recurse on the owner if any. */
|
|
@@ -119,8 +119,8 @@ static void vcd_print_value(Value value) {
|
|
|
119
119
|
}
|
|
120
120
|
} else {
|
|
121
121
|
/* Display a bitstring value. */
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
unsigned long long i;
|
|
123
|
+
unsigned long long width = type_width(value->type);
|
|
124
124
|
char* data = value->data_str;
|
|
125
125
|
if (value->capacity == 0) {
|
|
126
126
|
/* The value is empty, therefore undefined. */
|
|
@@ -289,7 +289,6 @@ static void vcd_print_systemT_content(SystemT system) {
|
|
|
289
289
|
/** Prints the hierarchy of a system type.
|
|
290
290
|
* @param system the system to print. */
|
|
291
291
|
static void vcd_print_systemT(SystemT system) {
|
|
292
|
-
int i;
|
|
293
292
|
/* Declares the module. */
|
|
294
293
|
vcd_print("$scope module ");
|
|
295
294
|
vcd_print_name((Object)system);
|
|
@@ -346,6 +345,7 @@ static void vcd_print_header() {
|
|
|
346
345
|
|
|
347
346
|
/* The declaration of the hierarchy and the variables
|
|
348
347
|
* from the top system. */
|
|
348
|
+
// printf("top_system=%p\n",top_system);
|
|
349
349
|
vcd_print_systemT(top_system);
|
|
350
350
|
/* Ends the declarations. */
|
|
351
351
|
vcd_print("$enddefinitions $end\n");
|