HDLRuby 2.11.4 → 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/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
|