HDLRuby 2.11.3 → 2.11.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/ext/hruby_sim/hruby_rcsim_build.c +36 -11
- data/ext/hruby_sim/hruby_sim.h +13 -1
- data/ext/hruby_sim/hruby_sim_core.c +84 -50
- data/ext/hruby_sim/hruby_sim_tree_calc.c +14 -0
- data/ext/hruby_sim/hruby_sim_vcd.c +23 -9
- data/lib/HDLRuby/hdr_samples/repeat_bench.rb +48 -0
- data/lib/HDLRuby/hruby_high.rb +11 -6
- data/lib/HDLRuby/hruby_low.rb +27 -17
- data/lib/HDLRuby/hruby_low2c.rb +31 -7
- data/lib/HDLRuby/hruby_rcsim.rb +16 -2
- data/lib/HDLRuby/hruby_rsim.rb +154 -79
- data/lib/HDLRuby/hruby_rsim_vcd.rb +181 -10
- data/lib/HDLRuby/hruby_verilog.rb +71 -58
- data/lib/HDLRuby/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 450d4465eb4fb71c70d61bdadf5bd0d944b5b8c7f7f9f3d02f847d670eb74f76
|
4
|
+
data.tar.gz: b3cf3b934d8a50f6d85ffc74f3a34b0cfd2f074d472d2f6a8b93b4324cc2e5bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 667da8c2f678834407374f739ea4d0094803e82145b1485aa2b53bcef54f04b368668ad62996aaa67ae48b0e80fb9c9c9f731131e3eeb6c69c5c23363b2242e7
|
7
|
+
data.tar.gz: 39ae4cea2c84140063b601b5c3f171462db40a41b01739894daa95b90cec6dd8c87780cc86f65ff269a0d7fb4478412d06c114d4c3a921ade691c6c3d9868110
|
data/README.md
CHANGED
@@ -1949,15 +1949,19 @@ There are two kinds of such statements:
|
|
1949
1949
|
!10.ns
|
1950
1950
|
```
|
1951
1951
|
|
1952
|
-
- The `repeat` statements: such a statement takes as argument a
|
1952
|
+
- The `repeat` statements: such a statement takes as argument a number of iteration and a block. The execution of the block is repeated the given number times. For example, the following code executes 10 times the inversion of the `clk` signal every 10 nanoseconds:
|
1953
1953
|
|
1954
1954
|
```ruby
|
1955
|
-
repeat(10
|
1955
|
+
repeat(10) do
|
1956
1956
|
!10.ns
|
1957
1957
|
clk <= ~clk
|
1958
1958
|
end
|
1959
1959
|
```
|
1960
1960
|
|
1961
|
+
__Note:__
|
1962
|
+
|
1963
|
+
This statement is not synthesizable and therefore can only be used in timed behaviors.
|
1964
|
+
|
1961
1965
|
### Parallel and sequential execution
|
1962
1966
|
|
1963
1967
|
Time behaviors are by default sequential, but they can include both parallel and
|
@@ -299,11 +299,14 @@ VALUE rcsim_make_event(VALUE mod, VALUE typeV, VALUE sigV) {
|
|
299
299
|
}
|
300
300
|
|
301
301
|
|
302
|
+
static size_t last_signal_id = 0;
|
303
|
+
|
302
304
|
/* Creating a signal C object. */
|
303
305
|
VALUE rcsim_make_signal(VALUE mod, VALUE name, VALUE type) {
|
304
306
|
// printf("rcsim_make_signal\n");
|
305
307
|
/* Allocates the signal. */
|
306
308
|
SignalI signal = (SignalI)malloc(sizeof(SignalIS));
|
309
|
+
signal->id = last_signal_id++;
|
307
310
|
// printf("signal=%p\n",signal);
|
308
311
|
/* Set it up. */
|
309
312
|
signal->kind = SIGNALI;
|
@@ -430,6 +433,27 @@ VALUE rcsim_make_timeWait(VALUE mod, VALUE unitV, VALUE delayV) {
|
|
430
433
|
return res;
|
431
434
|
}
|
432
435
|
|
436
|
+
/* Creating a time repeat C object. */
|
437
|
+
VALUE rcsim_make_timeRepeat(VALUE mod, VALUE numberV, VALUE statementV) {
|
438
|
+
// printf("rcsim_make_timeRepeat\n"); fflush(stdout);
|
439
|
+
/* Allocates the time repeat. */
|
440
|
+
TimeRepeat timeRepeat = (TimeRepeat)malloc(sizeof(TimeRepeatS));
|
441
|
+
// printf("timeRepeat=%p\n",timeRepeat); fflush(stdout);
|
442
|
+
/* Set it up. */
|
443
|
+
timeRepeat->kind = TIME_REPEAT;
|
444
|
+
/* Get and set the number of repeatition. */
|
445
|
+
long long number;
|
446
|
+
number = NUM2LL(numberV);
|
447
|
+
// printf("number=%lld\n",number); fflush(stdout);
|
448
|
+
timeRepeat->number = number;
|
449
|
+
/* Get and set the statement. */
|
450
|
+
value_to_rcsim(StatementS,statementV,timeRepeat->statement);
|
451
|
+
/* Returns the C time wait embedded into a ruby VALUE. */
|
452
|
+
VALUE res;
|
453
|
+
rcsim_to_value(TimeRepeatS,timeRepeat,res);
|
454
|
+
return res;
|
455
|
+
}
|
456
|
+
|
433
457
|
|
434
458
|
/* Creating a time terminate C object. */
|
435
459
|
VALUE rcsim_make_timeTerminate(VALUE mod) {
|
@@ -447,19 +471,19 @@ VALUE rcsim_make_timeTerminate(VALUE mod) {
|
|
447
471
|
|
448
472
|
|
449
473
|
/* Creating a hardware if C object. */
|
450
|
-
VALUE rcsim_make_hif(VALUE mod, VALUE
|
474
|
+
VALUE rcsim_make_hif(VALUE mod, VALUE conditionV, VALUE yesV, VALUE noV) {
|
451
475
|
// printf("rcsim_make_hif\n");
|
452
476
|
/* Allocates the hardware if. */
|
453
477
|
HIf hif = (HIf)malloc(sizeof(HIfS));
|
454
478
|
// printf("hif=%p\n",hif);
|
455
479
|
/* Set it up. */
|
456
480
|
hif->kind = HIF;
|
457
|
-
value_to_rcsim(ExpressionS,
|
458
|
-
value_to_rcsim(StatementS,
|
459
|
-
if (TYPE(
|
481
|
+
value_to_rcsim(ExpressionS,conditionV,hif->condition);
|
482
|
+
value_to_rcsim(StatementS,yesV,hif->yes);
|
483
|
+
if (TYPE(noV) == T_NIL)
|
460
484
|
hif->no = NULL;
|
461
485
|
else
|
462
|
-
value_to_rcsim(StatementS,
|
486
|
+
value_to_rcsim(StatementS,noV,hif->no);
|
463
487
|
hif->num_noifs = 0;
|
464
488
|
hif->noconds = NULL;
|
465
489
|
hif->nostmnts = NULL;
|
@@ -471,21 +495,21 @@ VALUE rcsim_make_hif(VALUE mod, VALUE condition, VALUE yes, VALUE no) {
|
|
471
495
|
|
472
496
|
|
473
497
|
/* Creating a hardware case C object. */
|
474
|
-
VALUE rcsim_make_hcase(VALUE mod, VALUE
|
498
|
+
VALUE rcsim_make_hcase(VALUE mod, VALUE valueV, VALUE defoltV) {
|
475
499
|
// printf("rcsim_make_hcase\n");
|
476
500
|
/* Allocates the hardware case. */
|
477
501
|
HCase hcase = (HCase)malloc(sizeof(HCaseS));
|
478
502
|
// printf("hcase=%p\n",hcase);
|
479
503
|
/* Set it up. */
|
480
504
|
hcase->kind = HCASE;
|
481
|
-
value_to_rcsim(ExpressionS,
|
505
|
+
value_to_rcsim(ExpressionS,valueV,hcase->value);
|
482
506
|
hcase->num_whens = 0;
|
483
507
|
hcase->matches = NULL;
|
484
508
|
hcase->stmnts = NULL;
|
485
|
-
if (TYPE(
|
509
|
+
if (TYPE(defoltV) == T_NIL)
|
486
510
|
hcase->defolt = NULL;
|
487
511
|
else
|
488
|
-
value_to_rcsim(StatementS,
|
512
|
+
value_to_rcsim(StatementS,defoltV,hcase->defolt);
|
489
513
|
/* Returns the C hardware case embedded into a ruby VALUE. */
|
490
514
|
VALUE res;
|
491
515
|
rcsim_to_value(HCaseS,hcase,res);
|
@@ -494,7 +518,7 @@ VALUE rcsim_make_hcase(VALUE mod, VALUE value, VALUE defolt) {
|
|
494
518
|
|
495
519
|
|
496
520
|
/* Creating a block C object. */
|
497
|
-
VALUE rcsim_make_block(VALUE mod, VALUE
|
521
|
+
VALUE rcsim_make_block(VALUE mod, VALUE modeV) {
|
498
522
|
// printf("rcsim_make_block\n");
|
499
523
|
/* Allocates the block. */
|
500
524
|
Block block = (Block)malloc(sizeof(BlockS));
|
@@ -507,7 +531,7 @@ VALUE rcsim_make_block(VALUE mod, VALUE mode) {
|
|
507
531
|
block->inners = NULL;
|
508
532
|
block->num_stmnts = 0;
|
509
533
|
block->stmnts = NULL;
|
510
|
-
block->mode = SYM2ID(
|
534
|
+
block->mode = SYM2ID(modeV) == id_PAR ? PAR : SEQ;
|
511
535
|
/* Returns the C block embedded into a ruby VALUE. */
|
512
536
|
VALUE res;
|
513
537
|
rcsim_to_value(BlockS,block,res);
|
@@ -1373,6 +1397,7 @@ void Init_hruby_sim() {
|
|
1373
1397
|
rb_define_singleton_method(mod,"rcsim_make_transmit",rcsim_make_transmit,2);
|
1374
1398
|
rb_define_singleton_method(mod,"rcsim_make_print",rcsim_make_print,0);
|
1375
1399
|
rb_define_singleton_method(mod,"rcsim_make_timeWait",rcsim_make_timeWait,2);
|
1400
|
+
rb_define_singleton_method(mod,"rcsim_make_timeRepeat",rcsim_make_timeRepeat,2);
|
1376
1401
|
rb_define_singleton_method(mod,"rcsim_make_timeTerminate",rcsim_make_timeTerminate,0);
|
1377
1402
|
rb_define_singleton_method(mod,"rcsim_make_hif",rcsim_make_hif,3);
|
1378
1403
|
rb_define_singleton_method(mod,"rcsim_make_hcase",rcsim_make_hcase,2);
|
data/ext/hruby_sim/hruby_sim.h
CHANGED
@@ -28,6 +28,7 @@ typedef struct PrintS_ PrintS;
|
|
28
28
|
typedef struct HIfS_ HIfS;
|
29
29
|
typedef struct HCaseS_ HCaseS;
|
30
30
|
typedef struct TimeWaitS_ TimeWaitS;
|
31
|
+
typedef struct TimeRepeatS_ TimeRepeatS;
|
31
32
|
typedef struct TimeTerminateS_ TimeTerminateS;
|
32
33
|
typedef struct ExpressionS_ ExpressionS;
|
33
34
|
typedef struct UnaryS_ UnaryS;
|
@@ -63,6 +64,7 @@ typedef struct PrintS_* Print;
|
|
63
64
|
typedef struct HIfS_* HIf;
|
64
65
|
typedef struct HCaseS_* HCase;
|
65
66
|
typedef struct TimeWaitS_* TimeWait;
|
67
|
+
typedef struct TimeRepeatS_* TimeRepeat;
|
66
68
|
typedef struct TimeTerminateS_* TimeTerminate;
|
67
69
|
typedef struct ExpressionS_* Expression;
|
68
70
|
typedef struct UnaryS_* Unary;
|
@@ -89,7 +91,8 @@ typedef enum {
|
|
89
91
|
#endif
|
90
92
|
OBJECT, SYSTEMT, SIGNALI, SCOPE, BEHAVIOR, SYSTEMI, CODE, BLOCK, EVENT,
|
91
93
|
#ifdef RCSIM
|
92
|
-
/* Statements */ TRANSMIT, PRINT, HIF, HCASE,
|
94
|
+
/* Statements */ TRANSMIT, PRINT, HIF, HCASE,
|
95
|
+
TIME_WAIT, TIME_REPEAT, TIME_TERMINATE,
|
93
96
|
/* Expressions */ UNARY, BINARY, SELECT, CONCAT, CAST,
|
94
97
|
/* References */ REF_OBJECT, REF_INDEX, REF_RANGE, REF_CONCAT,
|
95
98
|
/* Non-hardware*/ STRINGE,
|
@@ -521,6 +524,8 @@ typedef struct SignalIS_ {
|
|
521
524
|
Object* pos; /* The objects actvated on pos edge. */
|
522
525
|
int num_neg; /* The number of behavior activated on neg edge. */
|
523
526
|
Object* neg; /* The objects actvated on neg edge. */
|
527
|
+
|
528
|
+
size_t id; /* The identity of the signal. */
|
524
529
|
} SignalIS;
|
525
530
|
|
526
531
|
|
@@ -670,6 +675,13 @@ typedef struct TimeWaitS_ {
|
|
670
675
|
unsigned long long delay; /* The delay to wait in pico seconds. */
|
671
676
|
} TimeWaitS;
|
672
677
|
|
678
|
+
/** The C model of a time repeat statement. */
|
679
|
+
typedef struct TimeRepeatS_ {
|
680
|
+
Kind kind; /* The kind of object. */
|
681
|
+
long long number; /* The number of interations, negative means infinity. */
|
682
|
+
Statement statement;/* The statement to execute in loop. */
|
683
|
+
} TimeRepeatS;
|
684
|
+
|
673
685
|
/** The C model of a time terminate statement. */
|
674
686
|
typedef struct TimeTerminateS_ {
|
675
687
|
Kind kind; /* The kind of object. */
|
@@ -62,7 +62,8 @@ static pthread_cond_t hruby_beh_cond = PTHREAD_COND_INITIALIZER;
|
|
62
62
|
static pthread_cond_t hruby_sim_cond = PTHREAD_COND_INITIALIZER;
|
63
63
|
|
64
64
|
/** Flags for the simulation. */
|
65
|
-
static int
|
65
|
+
static int sim_single_flag = 0; /* Run in single timed behavior mode. */
|
66
|
+
static int sim_end_flag = 0; /* Ending the simulation. */
|
66
67
|
|
67
68
|
/** Adds a timed behavior for processing.
|
68
69
|
* @param behavior the timed behavior to register */
|
@@ -422,6 +423,21 @@ void* behavior_run(void* arg) {
|
|
422
423
|
pthread_exit(NULL);
|
423
424
|
}
|
424
425
|
|
426
|
+
/** Starts a signle timed behavior to run without the multi-threaded engine. */
|
427
|
+
void hruby_sim_start_single_timed_behavior() {
|
428
|
+
int i;
|
429
|
+
// printf("hruby_sim_start_single_timed_behaviors\n");fflush(stdout);
|
430
|
+
/* Set in mono-thread mode. */
|
431
|
+
sim_single_flag = 1;
|
432
|
+
Behavior behavior = timed_behaviors[0];
|
433
|
+
/* Simply run the timed behavior. */
|
434
|
+
#ifdef RCSIM
|
435
|
+
execute_statement((Statement)(behavior->block),0,behavior);
|
436
|
+
#else
|
437
|
+
behavior->block->function();
|
438
|
+
#endif
|
439
|
+
}
|
440
|
+
|
425
441
|
|
426
442
|
/** Starts the timed behaviors.
|
427
443
|
* @note create a thread per timed behavior. */
|
@@ -473,37 +489,46 @@ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
|
473
489
|
/* Initialize the time to 0. */
|
474
490
|
hruby_sim_time = 0;
|
475
491
|
|
476
|
-
|
477
|
-
|
478
|
-
// /* Activate the timed behavior that are on time. */
|
479
|
-
// hruby_sim_activate_behaviors_on_time();
|
480
|
-
|
481
|
-
/* Run while there are active behaviors and the time limit is not
|
482
|
-
* reached */
|
483
|
-
while(hruby_sim_time<limit) {
|
484
|
-
int i;
|
485
|
-
// printf("num_active_behaviors = %d\n",num_active_behaviors);
|
486
|
-
/* Wait for the active timed behaviors to perform their computations. */
|
487
|
-
hruby_sim_wait_behaviors();
|
488
|
-
/* Update the signal values (recursively executing blocks locked
|
489
|
-
* on the signals). */
|
492
|
+
if (num_timed_behaviors == 1) {
|
493
|
+
/* Initialize and touch all the signals. */
|
490
494
|
hruby_sim_update_signals();
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
495
|
+
each_all_signal(&touch_signal);
|
496
|
+
/* Only one timed behavior, no need of the multi-threaded engine. */
|
497
|
+
hruby_sim_start_single_timed_behavior();
|
498
|
+
} else {
|
499
|
+
/* Use the multi-threaded engine. */
|
500
|
+
/* Start all the timed behaviors. */
|
501
|
+
hruby_sim_start_timed_behaviors();
|
502
|
+
// /* Activate the timed behavior that are on time. */
|
503
|
+
// hruby_sim_activate_behaviors_on_time();
|
504
|
+
|
505
|
+
/* Run while there are active behaviors and the time limit is not
|
506
|
+
* reached */
|
507
|
+
while(hruby_sim_time<limit) {
|
508
|
+
int i;
|
509
|
+
// printf("num_active_behaviors = %d\n",num_active_behaviors);
|
510
|
+
/* Wait for the active timed behaviors to perform their computations. */
|
511
|
+
hruby_sim_wait_behaviors();
|
512
|
+
/* Update the signal values (recursively executing blocks locked
|
513
|
+
* on the signals). */
|
514
|
+
hruby_sim_update_signals();
|
515
|
+
if (hruby_sim_time == 0) {
|
516
|
+
/* Initially touch all the signals. */
|
517
|
+
each_all_signal(&touch_signal);
|
518
|
+
}
|
519
|
+
// printf("num_run_behavior=%d\n",num_run_behaviors);
|
520
|
+
if (num_run_behaviors <= 0) break;
|
521
|
+
/* Advance time to next timestep. */
|
522
|
+
hruby_sim_advance_time();
|
523
|
+
|
524
|
+
/* Mark the signals as fading. */
|
525
|
+
for(i=0; i<num_all_signals; ++i) {
|
526
|
+
all_signals[i]->fading = 1;
|
527
|
+
}
|
499
528
|
|
500
|
-
|
501
|
-
|
502
|
-
all_signals[i]->fading = 1;
|
529
|
+
/* Activate the timed behavior that are on time. */
|
530
|
+
hruby_sim_activate_behaviors_on_time();
|
503
531
|
}
|
504
|
-
|
505
|
-
/* Activate the timed behavior that are on time. */
|
506
|
-
hruby_sim_activate_behaviors_on_time();
|
507
532
|
}
|
508
533
|
}
|
509
534
|
|
@@ -521,29 +546,38 @@ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
|
521
546
|
* @param delay the delay to wait in ps.
|
522
547
|
* @param behavior the current behavior. */
|
523
548
|
void hw_wait(unsigned long long delay, Behavior behavior) {
|
524
|
-
/*
|
525
|
-
if (
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
pthread_cond_signal(&hruby_sim_cond);
|
537
|
-
/* Wait for being reactivated. */
|
538
|
-
while(behavior->active_time > hruby_sim_time) {
|
549
|
+
/* Is it in single timed behavior mode? */
|
550
|
+
if (sim_single_flag) {
|
551
|
+
/* Yes, simply update signals and advance time. */
|
552
|
+
behavior->active_time += delay;
|
553
|
+
hruby_sim_update_signals();
|
554
|
+
hruby_sim_advance_time();
|
555
|
+
} else {
|
556
|
+
/* No, handle the multi-threading. */
|
557
|
+
/* Maybe the thread is to end immediatly. */
|
558
|
+
if (sim_end_flag)
|
559
|
+
pthread_exit(NULL);
|
560
|
+
/* No go on with the wait procedure. */
|
539
561
|
pthread_mutex_lock(&hruby_sim_mutex);
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
562
|
+
/* Indicate the behavior finished current execution. */
|
563
|
+
num_active_behaviors -= 1;
|
564
|
+
// printf("!!num_active_behaviors=%d\n",num_active_behaviors);
|
565
|
+
// pthread_cond_signal(&hruby_sim_cond);
|
566
|
+
/* Update the behavior's time. */
|
567
|
+
behavior->active_time += delay;
|
546
568
|
pthread_mutex_unlock(&hruby_sim_mutex);
|
569
|
+
pthread_cond_signal(&hruby_sim_cond);
|
570
|
+
/* Wait for being reactivated. */
|
571
|
+
while(behavior->active_time > hruby_sim_time) {
|
572
|
+
pthread_mutex_lock(&hruby_sim_mutex);
|
573
|
+
while(!behaviors_can_run) {
|
574
|
+
// printf("!1\n");
|
575
|
+
// pthread_cond_wait(&compute_cond, &hruby_sim_mutex);
|
576
|
+
pthread_cond_wait(&hruby_beh_cond, &hruby_sim_mutex);
|
577
|
+
// printf("!2\n");
|
578
|
+
}
|
579
|
+
pthread_mutex_unlock(&hruby_sim_mutex);
|
580
|
+
}
|
547
581
|
}
|
548
582
|
}
|
549
583
|
|
@@ -358,6 +358,20 @@ void execute_statement(Statement stmnt, int mode, Behavior behavior) {
|
|
358
358
|
hw_wait(delay,behavior);
|
359
359
|
break;
|
360
360
|
}
|
361
|
+
case TIME_REPEAT:
|
362
|
+
{
|
363
|
+
TimeRepeat rep = (TimeRepeat)stmnt;
|
364
|
+
if (rep->number>=0) {
|
365
|
+
for(long long i=0; i<rep->number; ++i) {
|
366
|
+
execute_statement(rep->statement,mode,behavior);
|
367
|
+
}
|
368
|
+
} else {
|
369
|
+
for(;;) {
|
370
|
+
execute_statement(rep->statement,mode,behavior);
|
371
|
+
}
|
372
|
+
}
|
373
|
+
break;
|
374
|
+
}
|
361
375
|
case BLOCK:
|
362
376
|
{
|
363
377
|
Block block = (Block)stmnt;
|
@@ -98,7 +98,6 @@ static void vcd_print_name(Object object) {
|
|
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. */
|
101
|
-
// printf("owner=%p\n",object->owner);
|
102
101
|
if (object->owner != NULL) {
|
103
102
|
vcd_print_full_name(object->owner);
|
104
103
|
vcd_print("$");
|
@@ -107,12 +106,23 @@ static void vcd_print_full_name(Object object) {
|
|
107
106
|
vcd_print_name(object);
|
108
107
|
}
|
109
108
|
|
109
|
+
/** Prints the id of a signal in vcd indentifier format.
|
110
|
+
* @param signal the signal to print the id. */
|
111
|
+
static void vcd_print_signal_id(SignalI signal) {
|
112
|
+
size_t id = signal->id;
|
113
|
+
do {
|
114
|
+
vcd_print("%c",(id % (127-33)) + 33);
|
115
|
+
id = id / (127-33);
|
116
|
+
} while (id > 0);
|
117
|
+
}
|
118
|
+
|
110
119
|
/** Prints a value.
|
111
120
|
* @param value the value to print */
|
112
121
|
static void vcd_print_value(Value value) {
|
113
|
-
|
122
|
+
unsigned long long width = type_width(value->type);
|
123
|
+
if (width > 1) vcd_print("b");
|
114
124
|
if (value->numeric) {
|
115
|
-
unsigned long long width = type_width(value->type);
|
125
|
+
// unsigned long long width = type_width(value->type);
|
116
126
|
unsigned long long mask = 1ULL << (width-1);
|
117
127
|
for(; mask > 0; mask >>= 1) {
|
118
128
|
vcd_print("%d",(value->data_int & mask) != 0);
|
@@ -120,7 +130,7 @@ static void vcd_print_value(Value value) {
|
|
120
130
|
} else {
|
121
131
|
/* Display a bitstring value. */
|
122
132
|
unsigned long long i;
|
123
|
-
unsigned long long width = type_width(value->type);
|
133
|
+
// unsigned long long width = type_width(value->type);
|
124
134
|
char* data = value->data_str;
|
125
135
|
if (value->capacity == 0) {
|
126
136
|
/* The value is empty, therefore undefined. */
|
@@ -135,13 +145,15 @@ static void vcd_print_value(Value value) {
|
|
135
145
|
}
|
136
146
|
}
|
137
147
|
}
|
148
|
+
if (width > 1) vcd_print(" ");
|
138
149
|
}
|
139
150
|
|
140
151
|
/** Prints a signal declaration.
|
141
152
|
* @param signal the signal to declare */
|
142
153
|
static void vcd_print_var(SignalI signal) {
|
143
154
|
vcd_print("$var wire %d ",type_width(signal->type));
|
144
|
-
vcd_print_full_name((Object)signal);
|
155
|
+
// vcd_print_full_name((Object)signal);
|
156
|
+
vcd_print_signal_id(signal);
|
145
157
|
vcd_print(" ");
|
146
158
|
vcd_print_name((Object)signal);
|
147
159
|
vcd_print(" $end\n");
|
@@ -153,8 +165,9 @@ static void vcd_print_var(SignalI signal) {
|
|
153
165
|
static void vcd_print_signal_fvalue(SignalI signal) {
|
154
166
|
if (signal->f_value) {
|
155
167
|
vcd_print_value(signal->f_value);
|
156
|
-
vcd_print(" ");
|
157
|
-
vcd_print_full_name((Object)signal);
|
168
|
+
// vcd_print(" ");
|
169
|
+
// vcd_print_full_name((Object)signal);
|
170
|
+
vcd_print_signal_id(signal);
|
158
171
|
vcd_print("\n");
|
159
172
|
}
|
160
173
|
}
|
@@ -165,8 +178,9 @@ static void vcd_print_signal_fvalue(SignalI signal) {
|
|
165
178
|
static void vcd_print_signal_cvalue(SignalI signal) {
|
166
179
|
if (signal->c_value) {
|
167
180
|
vcd_print_value(signal->c_value);
|
168
|
-
vcd_print(" ");
|
169
|
-
vcd_print_full_name((Object)signal);
|
181
|
+
// vcd_print(" ");
|
182
|
+
// vcd_print_full_name((Object)signal);
|
183
|
+
vcd_print_signal_id(signal);
|
170
184
|
vcd_print("\n");
|
171
185
|
}
|
172
186
|
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# A simple D-FF
|
2
|
+
system :dff do
|
3
|
+
input :d, :clk, :rst
|
4
|
+
output :q
|
5
|
+
|
6
|
+
(q <= d & ~rst).at(clk.posedge)
|
7
|
+
end
|
8
|
+
|
9
|
+
# A benchmark for the dff using repeat.
|
10
|
+
system :dff_bench do
|
11
|
+
inner :d, :clk, :rst
|
12
|
+
inner :q
|
13
|
+
|
14
|
+
dff(:my_dff).(d,clk,rst,q)
|
15
|
+
|
16
|
+
timed do
|
17
|
+
clk <= 0
|
18
|
+
rst <= 0
|
19
|
+
d <= _z
|
20
|
+
!10.ns
|
21
|
+
clk <= 1
|
22
|
+
rst <= 0
|
23
|
+
d <= _z
|
24
|
+
!10.ns
|
25
|
+
clk <= 0
|
26
|
+
rst <= 1
|
27
|
+
d <= _z
|
28
|
+
!10.ns
|
29
|
+
clk <= 1
|
30
|
+
rst <= 1
|
31
|
+
d <= _z
|
32
|
+
!10.ns
|
33
|
+
clk <= 0
|
34
|
+
rst <= 0
|
35
|
+
d <= 1
|
36
|
+
!10.ns
|
37
|
+
clk <= 1
|
38
|
+
rst <= 0
|
39
|
+
!10.ns
|
40
|
+
repeat(100) do
|
41
|
+
clk <= 0
|
42
|
+
d <= ~d
|
43
|
+
!10.ns
|
44
|
+
clk <= 1
|
45
|
+
!10.ns
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/HDLRuby/hruby_high.rb
CHANGED
@@ -2682,10 +2682,10 @@ module HDLRuby::High
|
|
2682
2682
|
|
2683
2683
|
# Converts the repeat statement to HDLRuby::Low.
|
2684
2684
|
def to_low
|
2685
|
-
#
|
2685
|
+
# timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.statement.to_low,
|
2686
2686
|
# self.delay.to_low)
|
2687
|
-
timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.
|
2688
|
-
|
2687
|
+
timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.number,
|
2688
|
+
self.statement.to_low)
|
2689
2689
|
# # For debugging: set the source high object
|
2690
2690
|
# timeRepeatL.properties[:low2high] = self.hdr_id
|
2691
2691
|
# self.properties[:high2low] = timeRepeatL
|
@@ -4233,15 +4233,20 @@ module HDLRuby::High
|
|
4233
4233
|
self.add_statement(TimeWait.new(delay))
|
4234
4234
|
end
|
4235
4235
|
|
4236
|
-
# Adds a loop until +delay+ statement in the block in +mode+ whose
|
4236
|
+
# # Adds a loop until +delay+ statement in the block in +mode+ whose
|
4237
|
+
# # loop content is built using +ruby_block+.
|
4238
|
+
# def repeat(delay, mode = nil, &ruby_block)
|
4239
|
+
# Adds a +number+ times loop statement in the block in +mode+ whose
|
4237
4240
|
# loop content is built using +ruby_block+.
|
4238
|
-
|
4241
|
+
# NOTE: if +number+ is negative, the number of iteration is infinite.
|
4242
|
+
def repeat(number = -1, mode = nil, &ruby_block)
|
4239
4243
|
# Ensure there is a block.
|
4240
4244
|
ruby_block = proc {} unless block_given?
|
4241
4245
|
# Build the content block.
|
4242
4246
|
content = High.make_block(mode,&ruby_block)
|
4243
4247
|
# Create and add the statement.
|
4244
|
-
self.add_statement(TimeRepeat.new(content,delay))
|
4248
|
+
# self.add_statement(TimeRepeat.new(content,delay))
|
4249
|
+
self.add_statement(TimeRepeat.new(number,content))
|
4245
4250
|
end
|
4246
4251
|
|
4247
4252
|
# Converts the time block to HDLRuby::Low.
|
data/lib/HDLRuby/hruby_low.rb
CHANGED
@@ -4042,15 +4042,20 @@ module HDLRuby::Low
|
|
4042
4042
|
##
|
4043
4043
|
# Describes a timed loop statement: not synthesizable!
|
4044
4044
|
class TimeRepeat < Statement
|
4045
|
-
# The delay until the loop is repeated
|
4046
|
-
attr_reader :delay
|
4045
|
+
# # The delay until the loop is repeated
|
4046
|
+
# attr_reader :delay
|
4047
|
+
# The number of interrations.
|
4048
|
+
attr_reader :number
|
4047
4049
|
|
4048
4050
|
# The statement to execute.
|
4049
4051
|
attr_reader :statement
|
4050
4052
|
|
4051
|
-
# Creates a new timed loop statement execute in a loop +statement+ until
|
4052
|
-
# +delay+ has passed.
|
4053
|
-
def initialize(statement,delay)
|
4053
|
+
# # Creates a new timed loop statement execute in a loop +statement+ until
|
4054
|
+
# # +delay+ has passed.
|
4055
|
+
# def initialize(statement,delay)
|
4056
|
+
# Creates a new timed loop statement execute in a loop +statement+
|
4057
|
+
# +number+ times (negative means inifinity).
|
4058
|
+
def initialize(number,statement)
|
4054
4059
|
# Check and set the statement.
|
4055
4060
|
unless statement.is_a?(Statement)
|
4056
4061
|
raise AnyError,
|
@@ -4061,13 +4066,15 @@ module HDLRuby::Low
|
|
4061
4066
|
# And set its parent.
|
4062
4067
|
statement.parent = self
|
4063
4068
|
|
4064
|
-
# Check and set the delay.
|
4065
|
-
unless delay.is_a?(Delay)
|
4066
|
-
|
4067
|
-
end
|
4068
|
-
@delay = delay
|
4069
|
-
#
|
4070
|
-
|
4069
|
+
# # Check and set the delay.
|
4070
|
+
# unless delay.is_a?(Delay)
|
4071
|
+
# raise AnyError, "Invalid class for a delay: #{delay.class}."
|
4072
|
+
# end
|
4073
|
+
# @delay = delay
|
4074
|
+
# Check and set the number.
|
4075
|
+
@number = number.to_i
|
4076
|
+
# # And set its parent.
|
4077
|
+
# delay.parent = self
|
4071
4078
|
end
|
4072
4079
|
|
4073
4080
|
# Iterates over each object deeply.
|
@@ -4080,26 +4087,29 @@ module HDLRuby::Low
|
|
4080
4087
|
ruby_block.call(self)
|
4081
4088
|
# Then apply on the statement.
|
4082
4089
|
self.statement.each_deep(&ruby_block)
|
4083
|
-
# Then apply on the delay.
|
4084
|
-
self.delay.each_deep(&ruby_block)
|
4090
|
+
# # Then apply on the delay.
|
4091
|
+
# self.delay.each_deep(&ruby_block)
|
4085
4092
|
end
|
4086
4093
|
|
4087
4094
|
# Comparison for hash: structural comparison.
|
4088
4095
|
def eql?(obj)
|
4089
4096
|
return false unless obj.is_a?(TimeRepeat)
|
4090
|
-
return false unless @delay.eql?(obj.delay)
|
4097
|
+
# return false unless @delay.eql?(obj.delay)
|
4098
|
+
return false unless @number.eql?(obj.number)
|
4091
4099
|
return false unless @statement.eql?(obj.statement)
|
4092
4100
|
return true
|
4093
4101
|
end
|
4094
4102
|
|
4095
4103
|
# Hash function.
|
4096
4104
|
def hash
|
4097
|
-
return [@delay,@statement].hash
|
4105
|
+
# return [@delay,@statement].hash
|
4106
|
+
return [@number,@statement].hash
|
4098
4107
|
end
|
4099
4108
|
|
4100
4109
|
# Clones the TimeRepeat (deeply)
|
4101
4110
|
def clone
|
4102
|
-
return TimeRepeat.new(@statement.clone,@delay.clone)
|
4111
|
+
# return TimeRepeat.new(@statement.clone,@delay.clone)
|
4112
|
+
return TimeRepeat.new(@statement.clone,@number)
|
4103
4113
|
end
|
4104
4114
|
|
4105
4115
|
# Iterates over the expression children if any.
|