HDLRuby 2.11.4 → 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/ext/hruby_sim/hruby_rcsim_build.c +3 -0
- data/ext/hruby_sim/hruby_sim.h +2 -0
- data/ext/hruby_sim/hruby_sim_core.c +84 -50
- data/ext/hruby_sim/hruby_sim_vcd.c +23 -9
- data/lib/HDLRuby/hruby_low2c.rb +5 -0
- data/lib/HDLRuby/hruby_rsim.rb +144 -78
- data/lib/HDLRuby/hruby_rsim_vcd.rb +166 -10
- data/lib/HDLRuby/version.rb +1 -1
- metadata +2 -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
|
@@ -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;
|
data/ext/hruby_sim/hruby_sim.h
CHANGED
@@ -524,6 +524,8 @@ typedef struct SignalIS_ {
|
|
524
524
|
Object* pos; /* The objects actvated on pos edge. */
|
525
525
|
int num_neg; /* The number of behavior activated on neg edge. */
|
526
526
|
Object* neg; /* The objects actvated on neg edge. */
|
527
|
+
|
528
|
+
size_t id; /* The identity of the signal. */
|
527
529
|
} SignalIS;
|
528
530
|
|
529
531
|
|
@@ -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
|
|
@@ -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
|
}
|
data/lib/HDLRuby/hruby_low2c.rb
CHANGED
@@ -843,6 +843,9 @@ module HDLRuby::Low
|
|
843
843
|
## Extends the SignalI class with generation of C text.
|
844
844
|
class SignalI
|
845
845
|
|
846
|
+
# The id of a signal in the simulator.
|
847
|
+
@@signal_id = 0
|
848
|
+
|
846
849
|
## Generates the C text for an access to the signal.
|
847
850
|
# +level+ is the hierachical level of the object.
|
848
851
|
# def to_c_signal(level = 0)
|
@@ -881,6 +884,8 @@ module HDLRuby::Low
|
|
881
884
|
res << "SignalI signalI = malloc(sizeof(SignalIS));\n"
|
882
885
|
res << " " * (level+1)*3
|
883
886
|
res << "signalI->kind = SIGNALI;\n";
|
887
|
+
res << "signalI->id = #{@@signal_id};\n"
|
888
|
+
@@signal_id = @@signal_id+1;
|
884
889
|
|
885
890
|
# Sets the global variable of the signal.
|
886
891
|
res << "\n"
|
data/lib/HDLRuby/hruby_rsim.rb
CHANGED
@@ -16,6 +16,9 @@ module HDLRuby::High
|
|
16
16
|
# Enhance a system type with Ruby simulation.
|
17
17
|
class SystemT
|
18
18
|
|
19
|
+
# Tell if the simulation is in multithread mode or not.
|
20
|
+
attr_reader :multithread
|
21
|
+
|
19
22
|
## Add timed behavior +beh+.
|
20
23
|
# Returns the id of the timed behavior.
|
21
24
|
def add_timed_behavior(beh)
|
@@ -36,6 +39,50 @@ module HDLRuby::High
|
|
36
39
|
@sig_active << sig
|
37
40
|
end
|
38
41
|
|
42
|
+
## Advance the global simulator.
|
43
|
+
def advance
|
44
|
+
# Display the time
|
45
|
+
self.show_time
|
46
|
+
shown_values = {}
|
47
|
+
# Get the behaviors waiting on activated signals.
|
48
|
+
until @sig_active.empty? do
|
49
|
+
# # Update the signals.
|
50
|
+
# @sig_active.each { |sig| sig.c_value = sig.f_value }
|
51
|
+
# puts "sig_active.size=#{@sig_active.size}"
|
52
|
+
# Look for the behavior sensitive to the signals.
|
53
|
+
@sig_active.each do |sig|
|
54
|
+
sig.each_anyedge { |beh| @sig_exec << beh }
|
55
|
+
if (sig.c_value.zero? && !sig.f_value.zero?) then
|
56
|
+
# puts "sig.c_value=#{sig.c_value.content}"
|
57
|
+
sig.each_posedge { |beh| @sig_exec << beh }
|
58
|
+
elsif (!sig.c_value.zero? && sig.f_value.zero?) then
|
59
|
+
sig.each_negedge { |beh| @sig_exec << beh }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# Update the signals.
|
63
|
+
@sig_active.each { |sig| sig.c_value = sig.f_value }
|
64
|
+
# puts "first @sig_exec.size=#{@sig_exec.size}"
|
65
|
+
@sig_exec.uniq! {|beh| beh.object_id }
|
66
|
+
# Display the activated signals.
|
67
|
+
@sig_active.each do |sig|
|
68
|
+
if !shown_values[sig].eql?(sig.f_value) then
|
69
|
+
self.show_signal(sig)
|
70
|
+
shown_values[sig] = sig.f_value
|
71
|
+
end
|
72
|
+
end
|
73
|
+
# Clear the list of active signals.
|
74
|
+
@sig_active.clear
|
75
|
+
# puts "sig_exec.size=#{@sig_exec.size}"
|
76
|
+
# Execute the relevant behaviors and connections.
|
77
|
+
@sig_exec.each { |obj| obj.execute(:par) }
|
78
|
+
@sig_exec.clear
|
79
|
+
@sig_active.uniq! {|sig| sig.object_id }
|
80
|
+
# puts "@sig_active.size=#{@sig_active.size}"
|
81
|
+
# Advance time.
|
82
|
+
@time = (@timed_behaviors.min {|b0,b1| b0.time <=> b1.time }).time
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
39
86
|
## Run the simulation from the current systemT and outputs the resuts
|
40
87
|
# on simout.
|
41
88
|
def sim(simout)
|
@@ -43,15 +90,6 @@ module HDLRuby::High
|
|
43
90
|
HDLRuby.show "#{Time.now}#{show_mem}"
|
44
91
|
# Merge the included.
|
45
92
|
self.merge_included!
|
46
|
-
# Initializes the run mutex and the conditions.
|
47
|
-
@mutex = Mutex.new
|
48
|
-
@master = ConditionVariable.new
|
49
|
-
@master_flag = 0
|
50
|
-
@slave = ConditionVariable.new
|
51
|
-
@slave_flags_not = 0
|
52
|
-
@num_done = 0
|
53
|
-
# @lock = 0
|
54
|
-
# @runs = 0
|
55
93
|
# Initializes the time.
|
56
94
|
@time = 0
|
57
95
|
# Initializes the time and signals execution buffers.
|
@@ -68,72 +106,93 @@ module HDLRuby::High
|
|
68
106
|
self.init_sim(self)
|
69
107
|
# Initialize the displayer.
|
70
108
|
self.show_init(simout)
|
71
|
-
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
#
|
110
|
-
|
111
|
-
#
|
112
|
-
@sig_active.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
109
|
+
|
110
|
+
# Is there more than one timed behavior.
|
111
|
+
if @total_timed_behaviors <= 1 then
|
112
|
+
# No, no need of multithreading.
|
113
|
+
@multithread = false
|
114
|
+
# Simple execute the block of the behavior.
|
115
|
+
@timed_behaviors[0].block.execute(:seq)
|
116
|
+
else
|
117
|
+
# Yes, need of multithreading.
|
118
|
+
@multithread = true
|
119
|
+
# Initializes the run mutex and the conditions.
|
120
|
+
@mutex = Mutex.new
|
121
|
+
@master = ConditionVariable.new
|
122
|
+
@master_flag = 0
|
123
|
+
@slave = ConditionVariable.new
|
124
|
+
@slave_flags_not = 0
|
125
|
+
@num_done = 0
|
126
|
+
|
127
|
+
# First all the timed behaviors are to be executed.
|
128
|
+
@timed_behaviors.each {|beh| @tim_exec << beh }
|
129
|
+
# But starts locked.
|
130
|
+
@slave_flags_not = 2**@timed_behaviors.size - 1
|
131
|
+
# Starts the threads.
|
132
|
+
@timed_behaviors.each {|beh| beh.make_thread }
|
133
|
+
|
134
|
+
HDLRuby.show "Starting Ruby-level simulator..."
|
135
|
+
HDLRuby.show "#{Time.now}#{show_mem}"
|
136
|
+
# Run the simulation.
|
137
|
+
self.run_init do
|
138
|
+
# # Wake the behaviors.
|
139
|
+
# @timed_behaviors.each {|beh| beh.run }
|
140
|
+
until @tim_exec.empty? do
|
141
|
+
# Execute the time behaviors that are ready.
|
142
|
+
self.run_ack
|
143
|
+
self.run_wait
|
144
|
+
# Advance the global simulator.
|
145
|
+
self.advance
|
146
|
+
# # Display the time
|
147
|
+
# self.show_time
|
148
|
+
# shown_values = {}
|
149
|
+
# # Get the behaviors waiting on activated signals.
|
150
|
+
# until @sig_active.empty? do
|
151
|
+
# # # Update the signals.
|
152
|
+
# # @sig_active.each { |sig| sig.c_value = sig.f_value }
|
153
|
+
# # puts "sig_active.size=#{@sig_active.size}"
|
154
|
+
# # Look for the behavior sensitive to the signals.
|
155
|
+
# @sig_active.each do |sig|
|
156
|
+
# sig.each_anyedge { |beh| @sig_exec << beh }
|
157
|
+
# if (sig.c_value.zero? && !sig.f_value.zero?) then
|
158
|
+
# # puts "sig.c_value=#{sig.c_value.content}"
|
159
|
+
# sig.each_posedge { |beh| @sig_exec << beh }
|
160
|
+
# elsif (!sig.c_value.zero? && sig.f_value.zero?) then
|
161
|
+
# sig.each_negedge { |beh| @sig_exec << beh }
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
# # Update the signals.
|
165
|
+
# @sig_active.each { |sig| sig.c_value = sig.f_value }
|
166
|
+
# # puts "first @sig_exec.size=#{@sig_exec.size}"
|
167
|
+
# @sig_exec.uniq! {|beh| beh.object_id }
|
168
|
+
# # Display the activated signals.
|
169
|
+
# @sig_active.each do |sig|
|
170
|
+
# if !shown_values[sig].eql?(sig.f_value) then
|
171
|
+
# self.show_signal(sig)
|
172
|
+
# shown_values[sig] = sig.f_value
|
173
|
+
# end
|
174
|
+
# end
|
175
|
+
# # Clear the list of active signals.
|
176
|
+
# @sig_active.clear
|
177
|
+
# # puts "sig_exec.size=#{@sig_exec.size}"
|
178
|
+
# # Execute the relevant behaviors and connections.
|
179
|
+
# @sig_exec.each { |obj| obj.execute(:par) }
|
180
|
+
# @sig_exec.clear
|
181
|
+
# @sig_active.uniq! {|sig| sig.object_id }
|
182
|
+
# # puts "@sig_active.size=#{@sig_active.size}"
|
183
|
+
# end
|
184
|
+
|
185
|
+
# # Advance time.
|
186
|
+
# @time = (@timed_behaviors.min {|b0,b1| b0.time <=> b1.time }).time
|
187
|
+
break if @timed_behaviors.empty?
|
188
|
+
# Schedule the next timed behavior to execute.
|
189
|
+
@tim_exec = []
|
190
|
+
@timed_behaviors.each do |beh|
|
191
|
+
@tim_exec << beh if beh.time == @time
|
117
192
|
end
|
118
|
-
#
|
119
|
-
@
|
120
|
-
# puts "sig_exec.size=#{@sig_exec.size}"
|
121
|
-
# Execute the relevant behaviors and connections.
|
122
|
-
@sig_exec.each { |obj| obj.execute(:par) }
|
123
|
-
@sig_exec.clear
|
124
|
-
@sig_active.uniq! {|sig| sig.object_id }
|
125
|
-
# puts "@sig_active.size=#{@sig_active.size}"
|
126
|
-
end
|
127
|
-
break if @timed_behaviors.empty?
|
128
|
-
# Advance time.
|
129
|
-
@time = (@timed_behaviors.min {|b0,b1| b0.time <=> b1.time }).time
|
130
|
-
# Schedule the next timed behavior to execute.
|
131
|
-
@tim_exec = []
|
132
|
-
@timed_behaviors.each do |beh|
|
133
|
-
@tim_exec << beh if beh.time == @time
|
193
|
+
# puts "@tim_exec.size=#{@tim_exec.size}"
|
194
|
+
# puts "@timed_bevaviors.size=#{@timed_behaviors.size}"
|
134
195
|
end
|
135
|
-
# puts "@tim_exec.size=#{@tim_exec.size}"
|
136
|
-
# puts "@timed_bevaviors.size=#{@timed_behaviors.size}"
|
137
196
|
end
|
138
197
|
end
|
139
198
|
end
|
@@ -358,7 +417,8 @@ module HDLRuby::High
|
|
358
417
|
begin
|
359
418
|
# puts "Starting thread"
|
360
419
|
systemT.run_req(@id)
|
361
|
-
self.block.execute(:par)
|
420
|
+
# self.block.execute(:par)
|
421
|
+
self.block.execute(:seq)
|
362
422
|
# puts "Ending thread"
|
363
423
|
rescue => e
|
364
424
|
puts "Got exception: #{e.full_message}"
|
@@ -690,10 +750,16 @@ module HDLRuby::High
|
|
690
750
|
def execute(mode)
|
691
751
|
@behavior ||= self.behavior
|
692
752
|
@behavior.time += self.delay.time_ps
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
753
|
+
if @sim.multithread then
|
754
|
+
# Multi thread mode: synchronize.
|
755
|
+
# puts "Stopping #{@behavior.object_id} (@behavior.time=#{@behavior.time})..."
|
756
|
+
@sim.run_done(@behavior.id)
|
757
|
+
# puts "Rerunning #{@behavior.object_id} (@behavior.time=#{@behavior.time})..."
|
758
|
+
@sim.run_req(@behavior.id)
|
759
|
+
else
|
760
|
+
# No thread mode, need to advance the global simulator.
|
761
|
+
@sim.advance
|
762
|
+
end
|
697
763
|
end
|
698
764
|
end
|
699
765
|
|
@@ -11,6 +11,35 @@ module HDLRuby::High
|
|
11
11
|
return name.to_s.gsub(/[^a-zA-Z0-9_$]/,"$")
|
12
12
|
end
|
13
13
|
|
14
|
+
## Converts a bit string to a vcd format.
|
15
|
+
def self.vcd_bitstr(str)
|
16
|
+
if str.length > 1 then
|
17
|
+
return "b" + str + " "
|
18
|
+
else
|
19
|
+
return str
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
## Converts a HDLRuby object to a VCD id string.
|
24
|
+
@@rsim_object_idstr = { }
|
25
|
+
@@rsim_object_idstr_count = 0
|
26
|
+
def self.vcd_idstr(obj)
|
27
|
+
idstr = @@rsim_object_idstr[obj]
|
28
|
+
unless idstr then
|
29
|
+
# Must generate a new id string.
|
30
|
+
chars = []
|
31
|
+
id = @@rsim_object_idstr_count
|
32
|
+
@@rsim_object_idstr_count += 1
|
33
|
+
loop do
|
34
|
+
chars << ((id % (127-33)) + 33).chr
|
35
|
+
break if ((id=id/(127-33)) == 0)
|
36
|
+
end
|
37
|
+
idstr = chars.join
|
38
|
+
@@rsim_object_idstr[obj] = idstr
|
39
|
+
end
|
40
|
+
return idstr
|
41
|
+
end
|
42
|
+
|
14
43
|
##
|
15
44
|
# Enhance the system type class with VCD support.
|
16
45
|
class SystemT
|
@@ -40,14 +69,24 @@ module HDLRuby::High
|
|
40
69
|
# Closes the header.
|
41
70
|
@vcdout << "$enddefinitions $end\n"
|
42
71
|
# Initializes the variables with their name.
|
43
|
-
@vars_with_fullname = self.get_vars_with_fullname
|
72
|
+
# @vars_with_fullname = self.get_vars_with_fullname
|
73
|
+
@vars_with_idstr = self.get_vars_with_idstr
|
44
74
|
@vcdout << "$dumpvars\n"
|
45
|
-
@vars_with_fullname.each_pair do |sig,fullname|
|
75
|
+
# @vars_with_fullname.each_pair do |sig,fullname|
|
76
|
+
# if sig.f_value then
|
77
|
+
# @vcdout << " b#{sig.f_value.to_vstr} #{fullname}\n"
|
78
|
+
# else
|
79
|
+
# @vcdout << " b#{"x"} #{fullname}\n"
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
@vars_with_idstr.each_pair do |sig,idstr|
|
46
83
|
if sig.f_value then
|
47
|
-
@vcdout << " b#{sig.f_value.to_vstr} #{
|
84
|
+
# @vcdout << " b#{sig.f_value.to_vstr} #{idstr}\n"
|
85
|
+
@vcdout << HDLRuby::High.vcd_bitstr(sig.f_value.to_vstr) <<
|
86
|
+
idstr << "\n"
|
48
87
|
else
|
49
|
-
# @vcdout << " b#{"x"
|
50
|
-
@vcdout << "
|
88
|
+
# @vcdout << " b#{"x"} #{idstr}\n"
|
89
|
+
@vcdout << HDLRuby::High.vcd_bitstr("x") << idstr << "\n"
|
51
90
|
end
|
52
91
|
end
|
53
92
|
@vcdout << "$end\n"
|
@@ -63,6 +102,16 @@ module HDLRuby::High
|
|
63
102
|
return self.scope.get_vars_with_fullname(vars_with_fullname)
|
64
103
|
end
|
65
104
|
|
105
|
+
## Gets the VCD variables with their id string.
|
106
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
107
|
+
# Adds the signals of the interface of the system.
|
108
|
+
self.each_signal do |sig|
|
109
|
+
vars_with_idstr[sig] = HDLRuby::High.vcd_idstr(sig)
|
110
|
+
end
|
111
|
+
# Recurse on the scope.
|
112
|
+
return self.scope.get_vars_with_idstr(vars_with_idstr)
|
113
|
+
end
|
114
|
+
|
66
115
|
## Shows the hierarchy of the variables.
|
67
116
|
def show_hierarchy(vcdout)
|
68
117
|
# puts "show_hierarchy for module #{self} (#{self.name})"
|
@@ -72,7 +121,8 @@ module HDLRuby::High
|
|
72
121
|
self.each_signal do |sig|
|
73
122
|
# puts "showing signal #{HDLRuby::High.vcd_name(sig.fullname)}"
|
74
123
|
vcdout << "$var wire #{sig.type.width} "
|
75
|
-
vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
124
|
+
# vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
125
|
+
vcdout << "#{HDLRuby::High.vcd_idstr(sig)} "
|
76
126
|
vcdout << "#{HDLRuby::High.vcd_name(sig.name)} $end\n"
|
77
127
|
end
|
78
128
|
# Recurse on the scope.
|
@@ -88,8 +138,9 @@ module HDLRuby::High
|
|
88
138
|
|
89
139
|
## Displays the value of signal +sig+.
|
90
140
|
def show_signal(sig)
|
91
|
-
@vcdout << "b#{sig.f_value.to_vstr} "
|
92
|
-
@vcdout <<
|
141
|
+
# @vcdout << "b#{sig.f_value.to_vstr} "
|
142
|
+
@vcdout << HDLRuby::High.vcd_bitstr(sig.f_value.to_vstr)
|
143
|
+
@vcdout << "#{@vars_with_idstr[sig]}\n"
|
93
144
|
end
|
94
145
|
|
95
146
|
## Displays value +val+.
|
@@ -121,7 +172,8 @@ module HDLRuby::High
|
|
121
172
|
self.each_inner do |sig|
|
122
173
|
# puts "showing inner signal #{HDLRuby::High.vcd_name(sig.fullname)}"
|
123
174
|
vcdout << "$var wire #{sig.type.width} "
|
124
|
-
vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
175
|
+
# vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
176
|
+
vcdout << "#{HDLRuby::High.vcd_idstr(sig)} "
|
125
177
|
vcdout << "#{HDLRuby::High.vcd_name(sig.name)} $end\n"
|
126
178
|
end
|
127
179
|
# Recurse on the behaviors' blocks
|
@@ -162,6 +214,27 @@ module HDLRuby::High
|
|
162
214
|
end
|
163
215
|
return vars_with_fullname
|
164
216
|
end
|
217
|
+
|
218
|
+
## Gets the VCD variables with their id string.
|
219
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
220
|
+
# Adds the inner signals.
|
221
|
+
self.each_inner do |sig|
|
222
|
+
vars_with_idstr[sig] = HDLRuby::High.vcd_idstr(sig)
|
223
|
+
end
|
224
|
+
# Recurse on the behaviors' blocks
|
225
|
+
self.each_behavior do |beh|
|
226
|
+
beh.block.get_vars_with_idstr(vars_with_idstr)
|
227
|
+
end
|
228
|
+
# Recurse on the systemI's Eigen system.
|
229
|
+
self.each_systemI do |sys|
|
230
|
+
sys.systemT.get_vars_with_idstr(vars_with_idstr)
|
231
|
+
end
|
232
|
+
# Recurse on the subscopes.
|
233
|
+
self.each_scope do |scope|
|
234
|
+
scope.get_vars_with_idstr(vars_with_idstr)
|
235
|
+
end
|
236
|
+
return vars_with_idstr
|
237
|
+
end
|
165
238
|
end
|
166
239
|
|
167
240
|
|
@@ -177,6 +250,11 @@ module HDLRuby::High
|
|
177
250
|
def get_vars_with_fullname(vars_with_fullname = {})
|
178
251
|
# By default: nothing to do
|
179
252
|
end
|
253
|
+
|
254
|
+
## Gets the VCD variables with their id string.
|
255
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
256
|
+
# By default: nothing to do
|
257
|
+
end
|
180
258
|
end
|
181
259
|
|
182
260
|
##
|
@@ -192,6 +270,11 @@ module HDLRuby::High
|
|
192
270
|
def get_vars_with_fullname(vars_with_fullname = {})
|
193
271
|
# By default: nothing to do
|
194
272
|
end
|
273
|
+
|
274
|
+
## Gets the VCD variables with their idstr.
|
275
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
276
|
+
# By default: nothing to do
|
277
|
+
end
|
195
278
|
end
|
196
279
|
|
197
280
|
##
|
@@ -206,6 +289,11 @@ module HDLRuby::High
|
|
206
289
|
def get_vars_with_fullname(vars_with_fullname = {})
|
207
290
|
# By default: nothing to do
|
208
291
|
end
|
292
|
+
|
293
|
+
## Gets the VCD variables with their id string.
|
294
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
295
|
+
# By default: nothing to do
|
296
|
+
end
|
209
297
|
end
|
210
298
|
|
211
299
|
##
|
@@ -220,6 +308,11 @@ module HDLRuby::High
|
|
220
308
|
def get_vars_with_fullname(vars_with_fullname = {})
|
221
309
|
# By default: nothing to do
|
222
310
|
end
|
311
|
+
|
312
|
+
## Gets the VCD variables with their id string.
|
313
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
314
|
+
# By default: nothing to do
|
315
|
+
end
|
223
316
|
end
|
224
317
|
|
225
318
|
|
@@ -238,7 +331,8 @@ module HDLRuby::High
|
|
238
331
|
self.each_inner do |sig|
|
239
332
|
# puts "showing inner signal #{HDLRuby::High.vcd_name(sig.fullname)}"
|
240
333
|
vcdout << "$var wire #{sig.type.width} "
|
241
|
-
vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
334
|
+
# vcdout << "#{HDLRuby::High.vcd_name(sig.fullname)} "
|
335
|
+
vcdout << "#{HDLRuby::High.vcd_idstr(sig)} "
|
242
336
|
vcdout << "#{HDLRuby::High.vcd_name(sig.name)} $end\n"
|
243
337
|
end
|
244
338
|
# Recurse on the statements
|
@@ -263,6 +357,19 @@ module HDLRuby::High
|
|
263
357
|
end
|
264
358
|
return vars_with_fullname
|
265
359
|
end
|
360
|
+
|
361
|
+
## Gets the VCD variables with their id string.
|
362
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
363
|
+
# Adds the inner signals.
|
364
|
+
self.each_inner do |sig|
|
365
|
+
vars_with_idstr[sig] = HDLRuby::High.vcd_idstr(sig)
|
366
|
+
end
|
367
|
+
# Recurse on the statements.
|
368
|
+
self.each_statement do |stmnt|
|
369
|
+
stmnt.get_vars_with_idstr(vars_with_idstr)
|
370
|
+
end
|
371
|
+
return vars_with_idstr
|
372
|
+
end
|
266
373
|
end
|
267
374
|
|
268
375
|
|
@@ -307,6 +414,19 @@ module HDLRuby::High
|
|
307
414
|
self.no.get_vars_with_fullname(vars_with_fullname) if self.no
|
308
415
|
return vars_with_fullname
|
309
416
|
end
|
417
|
+
|
418
|
+
## Gets the VCD variables with their id string.
|
419
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
420
|
+
# Recurse on the yes.
|
421
|
+
self.yes.get_vars_with_idstr(vars_with_idstr)
|
422
|
+
# Recurse on the noifs.
|
423
|
+
self.each_noif do |cond,stmnt|
|
424
|
+
stmnt.get_vars_with_idstr(vars_with_idstr)
|
425
|
+
end
|
426
|
+
# Recure on the no if any.
|
427
|
+
self.no.get_vars_with_idstr(vars_with_idstr) if self.no
|
428
|
+
return vars_with_idstr
|
429
|
+
end
|
310
430
|
end
|
311
431
|
|
312
432
|
|
@@ -333,5 +453,41 @@ module HDLRuby::High
|
|
333
453
|
self.default.get_vars_with_fullname(vars_with_fullname)
|
334
454
|
return vars_with_fullname
|
335
455
|
end
|
456
|
+
|
457
|
+
## Gets the VCD variables with their id string.
|
458
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
459
|
+
# Recurse on each when.
|
460
|
+
self.each_when do |w|
|
461
|
+
w.statement.get_vars_with_idstr(vars_with_idstr)
|
462
|
+
end
|
463
|
+
# Recurse on the default if any.
|
464
|
+
self.default.get_vars_with_idstr(vars_with_idstr)
|
465
|
+
return vars_with_idstr
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
##
|
470
|
+
# Enhance the TimeRepeat class with VCD support.
|
471
|
+
class TimeRepeat
|
472
|
+
## Shows the hierarchy of the variables.
|
473
|
+
def show_hierarchy(vcdout)
|
474
|
+
# Recurse on the statement.
|
475
|
+
self.statement.show_hierarchy(vcdout)
|
476
|
+
end
|
477
|
+
|
478
|
+
## Gets the VCD variables with their long name.
|
479
|
+
def get_vars_with_fullname(vars_with_fullname = {})
|
480
|
+
# Recurse on the statement.
|
481
|
+
self.statement.get_vars_with_fullname(vars_with_fullname)
|
482
|
+
return vars_with_fullname
|
483
|
+
end
|
484
|
+
|
485
|
+
## Gets the VCD variables with their id string.
|
486
|
+
def get_vars_with_idstr(vars_with_idstr = {})
|
487
|
+
# Recurse on the statement.
|
488
|
+
self.statement.get_vars_with_idstr(vars_with_idstr)
|
489
|
+
return vars_with_idstr
|
490
|
+
end
|
336
491
|
end
|
492
|
+
|
337
493
|
end
|
data/lib/HDLRuby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: HDLRuby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.11.
|
4
|
+
version: 2.11.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lovic Gauthier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|