HDLRuby 2.11.3 → 2.11.5
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/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.
|