HDLRuby 2.3.5 → 2.4.6
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 +1 -0
- data/lib/HDLRuby/hdr_samples/bstr_bench.rb +14 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +9 -0
- data/lib/HDLRuby/hdr_samples/with_linear.rb +3 -15
- data/lib/HDLRuby/hdr_samples/with_multi_channels.rb +300 -0
- data/lib/HDLRuby/hdrcc.rb +10 -1
- data/lib/HDLRuby/hruby_bstr.rb +5 -2
- data/lib/HDLRuby/hruby_high.rb +8 -0
- data/lib/HDLRuby/hruby_low.rb +107 -8
- data/lib/HDLRuby/hruby_low2c.rb +24 -7
- data/lib/HDLRuby/hruby_low_mutable.rb +90 -2
- data/lib/HDLRuby/hruby_low_resolve.rb +1 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +14 -0
- data/lib/HDLRuby/sim/hruby_sim.h +79 -37
- data/lib/HDLRuby/sim/hruby_sim_calc.c +69 -0
- data/lib/HDLRuby/sim/hruby_sim_core.c +32 -6
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +380 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +51 -12
- data/lib/HDLRuby/std/channel.rb +302 -60
- data/lib/HDLRuby/std/linear.rb +16 -8
- data/lib/HDLRuby/version.rb +1 -1
- metadata +5 -2
@@ -145,6 +145,7 @@ module HDLRuby::Low
|
|
145
145
|
# puts "Resolve with #{self} and name=#{self.name}"
|
146
146
|
# First resolve the sub reference if possible.
|
147
147
|
if self.ref.is_a?(RefName) then
|
148
|
+
# puts "ref name=#{self.ref.name}"
|
148
149
|
obj = self.ref.resolve
|
149
150
|
# Look into the object for the name.
|
150
151
|
return obj.get_by_name(self.name)
|
@@ -29,7 +29,9 @@ module HDLRuby::Low
|
|
29
29
|
if scope.each_connection.to_a.any? then
|
30
30
|
inputs_blk = Block.new(:par)
|
31
31
|
outputs_blk = Block.new(:par)
|
32
|
+
timed_blk = TimeBlock.new(:seq)
|
32
33
|
scope.each_connection do |connection|
|
34
|
+
# puts "For connection: #{connection}"
|
33
35
|
# Check the left and right of the connection
|
34
36
|
# for input or output port.
|
35
37
|
left = connection.left
|
@@ -40,6 +42,15 @@ module HDLRuby::Low
|
|
40
42
|
right_r = right.resolve if right.respond_to?(:resolve)
|
41
43
|
# puts "right_r=#{right_r.name}" if right_r
|
42
44
|
# puts "right_r.parent=#{right_r.parent.name}" if right_r && right_r.parent
|
45
|
+
if right.is_a?(Value) then
|
46
|
+
# Right is value, the new transmit is to add
|
47
|
+
# to the timed block.
|
48
|
+
timed_blk.add_statement(
|
49
|
+
Transmit.new(left.clone,right.clone))
|
50
|
+
# No more process for this connection.
|
51
|
+
next
|
52
|
+
end
|
53
|
+
|
43
54
|
# Check if left is an input or an output.
|
44
55
|
left_is_i = left_is_o = false
|
45
56
|
if left_r && left_r.parent.is_a?(SystemT) then
|
@@ -118,6 +129,9 @@ module HDLRuby::Low
|
|
118
129
|
if outputs_blk.each_statement.any? then
|
119
130
|
scope.add_behavior(Behavior.new(outputs_blk))
|
120
131
|
end
|
132
|
+
if timed_blk.each_statement.any? then
|
133
|
+
scope.add_behavior(TimeBehavior.new(timed_blk))
|
134
|
+
end
|
121
135
|
end
|
122
136
|
end
|
123
137
|
end
|
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -170,6 +170,12 @@ extern Value mod_value(Value src0, Value src1, Value dst);
|
|
170
170
|
* @return dst */
|
171
171
|
extern Value not_value(Value src, Value dst);
|
172
172
|
|
173
|
+
/** Compute the or of the bits a a value.
|
174
|
+
* @param src the source value
|
175
|
+
* @param dst the destination value
|
176
|
+
* @return dst */
|
177
|
+
extern Value reduce_or_value(Value src, Value dst);
|
178
|
+
|
173
179
|
/** Computes the AND of two values.
|
174
180
|
* @param src0 the first source value of the and
|
175
181
|
* @param src1 the second source value of the and
|
@@ -185,43 +191,43 @@ extern Value and_value(Value src0, Value src1, Value dst);
|
|
185
191
|
extern Value or_value(Value src0, Value src1, Value dst);
|
186
192
|
|
187
193
|
/** Computes the XOR of two values.
|
188
|
-
* @param src0 the first source value of the
|
189
|
-
* @param src1 the second source value of the
|
194
|
+
* @param src0 the first source value of the xor
|
195
|
+
* @param src1 the second source value of the xor
|
190
196
|
* @param dst the destination value
|
191
197
|
* @return dst */
|
192
198
|
extern Value xor_value(Value src0, Value src1, Value dst);
|
193
199
|
|
194
200
|
/** Computes the left shift of two general values.
|
195
|
-
* @param src0 the first source value of the
|
196
|
-
* @param src1 the second source value of the
|
201
|
+
* @param src0 the first source value of the shift
|
202
|
+
* @param src1 the second source value of the shift
|
197
203
|
* @param dst the destination
|
198
204
|
* @return dst */
|
199
205
|
Value shift_left_value(Value src0, Value src1, Value dst);
|
200
206
|
|
201
207
|
/** Computes the right shift of two general values.
|
202
|
-
* @param src0 the first source value of the
|
203
|
-
* @param src1 the second source value of the
|
208
|
+
* @param src0 the first source value of the shift
|
209
|
+
* @param src1 the second source value of the shift
|
204
210
|
* @param dst the destination
|
205
211
|
* @return dst */
|
206
212
|
Value shift_right_value(Value src0, Value src1, Value dst);
|
207
213
|
|
208
214
|
/** Computes the equal (NXOR) of two values.
|
209
|
-
* @param src0 the first source value of the
|
210
|
-
* @param src1 the second source value of the
|
215
|
+
* @param src0 the first source value of the comparison
|
216
|
+
* @param src1 the second source value of the comparison
|
211
217
|
* @param dst the destination value
|
212
218
|
* @return dst */
|
213
219
|
extern Value equal_value(Value src0, Value src1, Value dst);
|
214
220
|
|
215
221
|
/** Computes the lesser comparision of two values.
|
216
|
-
* @param src0 the first source value of the
|
217
|
-
* @param src1 the second source value of the
|
222
|
+
* @param src0 the first source value of the comparison
|
223
|
+
* @param src1 the second source value of the comparison
|
218
224
|
* @param dst the destination value
|
219
225
|
* @return dst */
|
220
226
|
extern Value lesser_value(Value src0, Value src1, Value dst);
|
221
227
|
|
222
228
|
/** Computes the greater comparision of two values.
|
223
|
-
* @param src0 the first source value of the
|
224
|
-
* @param src1 the second source value of the
|
229
|
+
* @param src0 the first source value of the comparison
|
230
|
+
* @param src1 the second source value of the comparison
|
225
231
|
* @param dst the destination value
|
226
232
|
* @return dst */
|
227
233
|
extern Value greater_value(Value src0, Value src1, Value dst);
|
@@ -468,6 +474,7 @@ typedef struct BlockS_ {
|
|
468
474
|
Kind kind; /* The kind of object. */
|
469
475
|
Object owner; /* The owner if any. */
|
470
476
|
|
477
|
+
char* name; /* The name of the block. */
|
471
478
|
int num_inners; /* The number of inners. */
|
472
479
|
SignalI* inners; /* The inners of the scope. */
|
473
480
|
void (*function)(); /* The function to execute for the block. */
|
@@ -490,6 +497,9 @@ typedef struct EventS_ {
|
|
490
497
|
/* The time units. */
|
491
498
|
typedef enum { S, MS, US, NS, PS, FS } Unit;
|
492
499
|
|
500
|
+
/** The top system. */
|
501
|
+
extern SystemT top_system;
|
502
|
+
|
493
503
|
/** Adds a timed behavior for processing.
|
494
504
|
* @param behavior the timed behavior to register */
|
495
505
|
extern void register_timed_behavior(Behavior behavior);
|
@@ -555,39 +565,71 @@ extern unsigned long long make_delay(int value, Unit unit);
|
|
555
565
|
|
556
566
|
|
557
567
|
|
568
|
+
/* Iterate over all the signals.
|
569
|
+
* @param func function to applie on each signal. */
|
570
|
+
extern void each_all_signal(void (*func)(SignalI));
|
558
571
|
|
559
572
|
/* Interface to the visualization engine. */
|
560
573
|
|
561
|
-
|
562
|
-
*
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
* @param
|
575
|
-
extern void
|
576
|
-
|
577
|
-
|
578
|
-
*
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
574
|
+
typedef struct {
|
575
|
+
void (*print_time)(unsigned long long);
|
576
|
+
void (*print_name)(Object);
|
577
|
+
void (*print_value)(Value);
|
578
|
+
void (*print_signal)(SignalI);
|
579
|
+
} PrinterS;
|
580
|
+
|
581
|
+
extern PrinterS printer;
|
582
|
+
|
583
|
+
/** Initializes the visualization printer engine.
|
584
|
+
* @param print_time the time printer
|
585
|
+
* @param print_name the name printer
|
586
|
+
* @param print_value the value printer
|
587
|
+
* @param print_signal the signal state printer. */
|
588
|
+
extern void init_visualizer(void (*print_time)(unsigned long long),
|
589
|
+
void (*print_name)(Object),
|
590
|
+
void (*print_value)(Value),
|
591
|
+
void (*print_signal)(SignalI));
|
592
|
+
|
593
|
+
// /** Prints the time.
|
594
|
+
// * @param time the time to show. */
|
595
|
+
// extern void print_time(unsigned long long time);
|
596
|
+
//
|
597
|
+
// // /** Prints the time and goes to the next line.
|
598
|
+
// // * @param time the time to show. */
|
599
|
+
// // extern void println_time(unsigned long long time);
|
600
|
+
//
|
601
|
+
// /** Prints the name of an object.
|
602
|
+
// * @param object the object to print the name. */
|
603
|
+
// extern void print_name(Object object);
|
604
|
+
//
|
605
|
+
// /** Prints a value.
|
606
|
+
// * @param value the value to print */
|
607
|
+
// extern void print_value(Value value);
|
608
|
+
//
|
609
|
+
// /** Prints a signal.
|
610
|
+
// * @param signal the signal to show */
|
611
|
+
// extern void print_signal(SignalI signal);
|
612
|
+
//
|
613
|
+
// // /** Prints a signal and goes to the next line.
|
614
|
+
// // * @param signal the signal to show */
|
615
|
+
// // extern void println_signal(SignalI signal);
|
616
|
+
|
617
|
+
/** Sets up the default vizualization engine.
|
618
|
+
* @param name the name of the vizualization. */
|
619
|
+
extern void init_default_visualizer(char* name);
|
620
|
+
|
621
|
+
/** Sets up the vcd vizualization engine.
|
622
|
+
* @param name the name of the vizualization. */
|
623
|
+
extern void init_vcd_visualizer(char* name);
|
585
624
|
|
586
625
|
/* The interface to the simulator core. */
|
587
626
|
|
588
627
|
/** The simulation core function.
|
628
|
+
* @param name the name of the simulation.
|
629
|
+
* @param init_vizualizer the vizualizer engine initializer.
|
589
630
|
* @param limit the time limit in fs. */
|
590
|
-
extern void hruby_sim_core(
|
631
|
+
extern void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
632
|
+
unsigned long long limit);
|
591
633
|
|
592
634
|
|
593
635
|
|
@@ -714,6 +714,45 @@ static Value not_value_bitstring(Value src, Value dst) {
|
|
714
714
|
return dst;
|
715
715
|
}
|
716
716
|
|
717
|
+
/** Compute the or of the bits a bitstring value.
|
718
|
+
* @param src the source value
|
719
|
+
* @param dst the destination value
|
720
|
+
* @return dst */
|
721
|
+
Value reduce_or_value_bitstring(Value src, Value dst) {
|
722
|
+
/* Compute the width of the result in bits. */
|
723
|
+
unsigned long long width = type_width(src->type);
|
724
|
+
|
725
|
+
/* Update the destination capacity if required. */
|
726
|
+
resize_value(dst,width);
|
727
|
+
/* Set the type and size of the destination from the type of the source.*/
|
728
|
+
dst->type = src->type;
|
729
|
+
dst->numeric = 0;
|
730
|
+
|
731
|
+
/* Get access to the source and destination data. */
|
732
|
+
char* src_data = src->data_str;
|
733
|
+
char* dst_data = dst->data_str;
|
734
|
+
|
735
|
+
/* Performs the reduce or. */
|
736
|
+
unsigned long long count;
|
737
|
+
char res;
|
738
|
+
for(count = 0; count < width; ++count) {
|
739
|
+
/* Performs the reduce or. */
|
740
|
+
char d = src_data[count] - '0'; /* Get and convert to bit. */
|
741
|
+
if ((d == (d&1)) && (res != 'x'-'0')) { /* d is defined. */
|
742
|
+
res |= d;
|
743
|
+
} else {
|
744
|
+
/* res is undefined. */
|
745
|
+
res = 'x' - '0';
|
746
|
+
}
|
747
|
+
/* Apart for the first bit, there are only 0, still we are in
|
748
|
+
* the loop, set it. */
|
749
|
+
dst_data[count] = '0';
|
750
|
+
}
|
751
|
+
dst_data[0] = res + '0';
|
752
|
+
/* Return the destination. */
|
753
|
+
return dst;
|
754
|
+
}
|
755
|
+
|
717
756
|
|
718
757
|
/** Computes the and of two bitstring values.
|
719
758
|
* @param src0 the first source value of the and
|
@@ -1575,6 +1614,21 @@ static Value not_value_numeric(Value src, Value dst) {
|
|
1575
1614
|
}
|
1576
1615
|
|
1577
1616
|
|
1617
|
+
/** Compute the or of the bits a numeric value.
|
1618
|
+
* @param src the source value
|
1619
|
+
* @param dst the destination value
|
1620
|
+
* @return dst */
|
1621
|
+
Value reduce_or_value_numeric(Value src, Value dst) {
|
1622
|
+
/* Sets state of the destination using the first source. */
|
1623
|
+
dst->type = src->type;
|
1624
|
+
dst->numeric = 1;
|
1625
|
+
|
1626
|
+
/* Perform the reduce or. */
|
1627
|
+
dst->data_int = fix_numeric_type(dst->type, src->data_int != 0);
|
1628
|
+
return dst;
|
1629
|
+
}
|
1630
|
+
|
1631
|
+
|
1578
1632
|
/** Computes the AND of two numeric values.
|
1579
1633
|
* @param src0 the first source value of the addition
|
1580
1634
|
* @param src1 the second source value of the addition
|
@@ -2093,6 +2147,21 @@ Value not_value(Value src, Value dst) {
|
|
2093
2147
|
}
|
2094
2148
|
|
2095
2149
|
|
2150
|
+
/** Compute the or of the bits a value.
|
2151
|
+
* @param src the source value
|
2152
|
+
* @param dst the destination value
|
2153
|
+
* @return dst */
|
2154
|
+
Value reduce_or_value(Value src, Value dst) {
|
2155
|
+
if (src->numeric) {
|
2156
|
+
/* The source is numeric. */
|
2157
|
+
return reduce_or_value_numeric(src,dst);
|
2158
|
+
} else {
|
2159
|
+
/* The source cannot be numeric, compute bitsitrings. */
|
2160
|
+
return reduce_or_value_bitstring(src,dst);
|
2161
|
+
}
|
2162
|
+
}
|
2163
|
+
|
2164
|
+
|
2096
2165
|
/** Computes the AND of two general values.
|
2097
2166
|
* @param src0 the first source value of the addition
|
2098
2167
|
* @param src1 the second source value of the addition
|
@@ -12,6 +12,9 @@
|
|
12
12
|
* hruby_low2c.
|
13
13
|
* */
|
14
14
|
|
15
|
+
/** The top system. */
|
16
|
+
SystemT top_system;
|
17
|
+
|
15
18
|
/** The number of all the signals. */
|
16
19
|
static int num_all_signals = 0;
|
17
20
|
/** The capacity of the set of signals. */
|
@@ -118,9 +121,10 @@ void hruby_sim_update_signals() {
|
|
118
121
|
/* Is there a change? */
|
119
122
|
if (same_content_value(sig->c_value,sig->f_value)) continue;
|
120
123
|
/* Yes, process the signal. */
|
121
|
-
println_signal(sig);
|
122
|
-
|
123
|
-
// printf("
|
124
|
+
// println_signal(sig);
|
125
|
+
printer.print_signal(sig);
|
126
|
+
// printf("c_value="); printer.print_value(sig->c_value);
|
127
|
+
// printf("\nf_value="); printer.print_value(sig->f_value); printf("\n");
|
124
128
|
// printf("Touched signal: %p (%s)\n",sig,sig->name);
|
125
129
|
/* Update the current value of the signal. */
|
126
130
|
copy_value(sig->f_value,sig->c_value);
|
@@ -185,7 +189,8 @@ void hruby_sim_update_signals() {
|
|
185
189
|
SignalI sig = e->data;
|
186
190
|
delete_element(e);
|
187
191
|
/* Yes, process the signal. */
|
188
|
-
println_signal(sig);
|
192
|
+
// println_signal(sig);
|
193
|
+
printer.print_signal(sig);
|
189
194
|
/* Update the current value of the signal. */
|
190
195
|
/* Mark the corresponding code as activated. */
|
191
196
|
/* Any edge activation. */
|
@@ -284,7 +289,8 @@ void hruby_sim_advance_time() {
|
|
284
289
|
}
|
285
290
|
/* Sets the new activation time. */
|
286
291
|
hruby_sim_time = next_time;
|
287
|
-
println_time(hruby_sim_time);
|
292
|
+
// println_time(hruby_sim_time);
|
293
|
+
printer.print_time(hruby_sim_time);
|
288
294
|
}
|
289
295
|
|
290
296
|
|
@@ -393,9 +399,18 @@ void hruby_sim_end_timed_behaviors() {
|
|
393
399
|
|
394
400
|
|
395
401
|
|
402
|
+
// /** The simulation core function.
|
403
|
+
// * @param limit the time limit in fs. */
|
404
|
+
// void hruby_sim_core(unsigned long long limit) {
|
396
405
|
/** The simulation core function.
|
406
|
+
* @param name the name of the simulation.
|
407
|
+
* @param vizualizer the vizualizer engine initializer.
|
397
408
|
* @param limit the time limit in fs. */
|
398
|
-
void hruby_sim_core(
|
409
|
+
void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
|
410
|
+
unsigned long long limit) {
|
411
|
+
/* Initilize the vizualizer. */
|
412
|
+
init_vizualizer(name);
|
413
|
+
|
399
414
|
/* Initialize the time to 0. */
|
400
415
|
hruby_sim_time = 0;
|
401
416
|
|
@@ -597,3 +612,14 @@ unsigned long long make_delay(int value, Unit unit) {
|
|
597
612
|
return -1;
|
598
613
|
}
|
599
614
|
|
615
|
+
|
616
|
+
|
617
|
+
|
618
|
+
/* Iterate over all the signals.
|
619
|
+
* @param func function to applie on each signal. */
|
620
|
+
void each_all_signal(void (*func)(SignalI)) {
|
621
|
+
int i;
|
622
|
+
for(i = 0; i<num_all_signals; ++i) {
|
623
|
+
func(all_signals[i]);
|
624
|
+
}
|
625
|
+
}
|
@@ -0,0 +1,380 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <time.h>
|
4
|
+
#include <stdarg.h>
|
5
|
+
#include "hruby_sim.h"
|
6
|
+
|
7
|
+
|
8
|
+
/**
|
9
|
+
* The HDLRuby simulation vcd format genertion engine, to be used with C code
|
10
|
+
* generated by hruby_low2c.
|
11
|
+
**/
|
12
|
+
|
13
|
+
/* Global variables storing the configuration of the vcd generation. */
|
14
|
+
|
15
|
+
/* The target file. */
|
16
|
+
static FILE* vcd_file;
|
17
|
+
|
18
|
+
/* The time scale unit in the ps. */
|
19
|
+
static unsigned long long vcd_timeunit = 1;
|
20
|
+
|
21
|
+
/* Accessing target file. */
|
22
|
+
|
23
|
+
/** Prints to the vcd file.
|
24
|
+
* @param fmt the format for handling the variadic arguments. */
|
25
|
+
static int vcd_print(char* fmt, ...) {
|
26
|
+
int ret;
|
27
|
+
|
28
|
+
/* Declare a va_list type variable */
|
29
|
+
va_list myargs;
|
30
|
+
|
31
|
+
/* Initialise the va_list variable with the ... after fmt */
|
32
|
+
va_start(myargs, fmt);
|
33
|
+
|
34
|
+
/* Forward the '...' to vprintf */
|
35
|
+
ret = vfprintf(vcd_file, fmt, myargs);
|
36
|
+
|
37
|
+
/* Clean up the va_list */
|
38
|
+
va_end(myargs);
|
39
|
+
|
40
|
+
return ret;
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
/* Utility functions for printing in vcd format. */
|
45
|
+
|
46
|
+
/* Replace all the occurences of a character with another.
|
47
|
+
* CREDIT: Superlokkus */
|
48
|
+
static char* replace_char(char* str, char find, char replace){
|
49
|
+
char *current_pos = strchr(str,find);
|
50
|
+
while (current_pos){
|
51
|
+
*current_pos = replace;
|
52
|
+
current_pos = strchr(current_pos+1,find);
|
53
|
+
}
|
54
|
+
return str;
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
/* Low-end print functions. */
|
59
|
+
|
60
|
+
/** Prints the time.
|
61
|
+
* @param time the time to show (given in ps). */
|
62
|
+
static void vcd_print_time(unsigned long long time) {
|
63
|
+
vcd_print("#%llu\n",time/vcd_timeunit);
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
/** Prints the name of an object without its hierarchy.
|
68
|
+
* @param object the object to print the name. */
|
69
|
+
static void vcd_print_name(Object object) {
|
70
|
+
/* Depending on the kind of object. */
|
71
|
+
switch(object->kind) {
|
72
|
+
case SYSTEMT:
|
73
|
+
case SIGNALI:
|
74
|
+
case SCOPE:
|
75
|
+
case SYSTEMI:
|
76
|
+
case BLOCK:
|
77
|
+
/* Print the name if name. */
|
78
|
+
/* Trick: SystemT, SignalI, Scope and SystemI have the
|
79
|
+
* field name at the same place. */
|
80
|
+
if ((((Block)object)->name != NULL) &&
|
81
|
+
strlen(((Block)object)->name)>0) {
|
82
|
+
char name[256];
|
83
|
+
strncpy(name,((Block)object)->name,256);
|
84
|
+
replace_char(name,':','$');
|
85
|
+
vcd_print("%s",name);
|
86
|
+
} else {
|
87
|
+
/* No name, use the address of the object as name generator.*/
|
88
|
+
vcd_print("$%p",(void*)object);
|
89
|
+
}
|
90
|
+
break;
|
91
|
+
default: /* Nothing to do */
|
92
|
+
break;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
/** Prints the name of an object incluing its heirarchy.
|
98
|
+
* @param object the object to print the name. */
|
99
|
+
static void vcd_print_full_name(Object object) {
|
100
|
+
/* Recurse on the owner if any. */
|
101
|
+
// printf("owner=%p\n",object->owner);
|
102
|
+
if (object->owner != NULL) {
|
103
|
+
vcd_print_full_name(object->owner);
|
104
|
+
vcd_print("$");
|
105
|
+
}
|
106
|
+
/* Print the name of the object. */
|
107
|
+
vcd_print_name(object);
|
108
|
+
}
|
109
|
+
|
110
|
+
/** Prints a value.
|
111
|
+
* @param value the value to print */
|
112
|
+
static void vcd_print_value(Value value) {
|
113
|
+
vcd_print("b");
|
114
|
+
if (value->numeric) {
|
115
|
+
unsigned long long width = type_width(value->type);
|
116
|
+
unsigned long long mask = 1ULL << (width-1);
|
117
|
+
for(; mask > 0; mask >>= 1) {
|
118
|
+
vcd_print("%d",(value->data_int & mask) != 0);
|
119
|
+
}
|
120
|
+
} else {
|
121
|
+
/* Display a bitstring value. */
|
122
|
+
int i;
|
123
|
+
int width = type_width(value->type);
|
124
|
+
char* data = value->data_str;
|
125
|
+
if (value->capacity == 0) {
|
126
|
+
/* The value is empty, therefore undefined. */
|
127
|
+
for(i=width; i>0; --i) {
|
128
|
+
vcd_print("u");
|
129
|
+
}
|
130
|
+
}
|
131
|
+
else {
|
132
|
+
/* The value is not empty. */
|
133
|
+
for(i=width; i>0; --i) {
|
134
|
+
vcd_print("%c",data[i-1]);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
/** Prints a signal declaration.
|
141
|
+
* @param signal the signal to declare */
|
142
|
+
static void vcd_print_var(SignalI signal) {
|
143
|
+
vcd_print("$var wire %d ",type_width(signal->type));
|
144
|
+
vcd_print_full_name((Object)signal);
|
145
|
+
vcd_print(" ");
|
146
|
+
vcd_print_name((Object)signal);
|
147
|
+
vcd_print(" $end\n");
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
/** Prints a signal with its future value if any.
|
152
|
+
* @param signal the signal to show */
|
153
|
+
static void vcd_print_signal_fvalue(SignalI signal) {
|
154
|
+
if (signal->f_value) {
|
155
|
+
vcd_print_value(signal->f_value);
|
156
|
+
vcd_print(" ");
|
157
|
+
vcd_print_full_name((Object)signal);
|
158
|
+
vcd_print("\n");
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
|
163
|
+
/** Prints a signal with its current value if any
|
164
|
+
* @param signal the signal to show */
|
165
|
+
static void vcd_print_signal_cvalue(SignalI signal) {
|
166
|
+
if (signal->c_value) {
|
167
|
+
vcd_print_value(signal->c_value);
|
168
|
+
vcd_print(" ");
|
169
|
+
vcd_print_full_name((Object)signal);
|
170
|
+
vcd_print("\n");
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
/** Prints the hierarchy content of a system type.
|
176
|
+
* @param system the system to print. */
|
177
|
+
static void vcd_print_systemT_content(SystemT system);
|
178
|
+
|
179
|
+
/** Prints the hierarchy of a scope.
|
180
|
+
* @param scope the scope to print. */
|
181
|
+
static void vcd_print_scope(Scope scope);
|
182
|
+
|
183
|
+
|
184
|
+
/** Prints the hierarchy of a block.
|
185
|
+
* @param block the block to print. */
|
186
|
+
static void vcd_print_block(Block block) {
|
187
|
+
int i;
|
188
|
+
/* Do not print block with no declaration. */
|
189
|
+
if (block->num_inners == 0) return;
|
190
|
+
|
191
|
+
/* Declares the block if named. */
|
192
|
+
vcd_print("$scope module ");
|
193
|
+
vcd_print_name((Object)block);
|
194
|
+
vcd_print(" $end\n");
|
195
|
+
|
196
|
+
/* Declare the inners of the systems. */
|
197
|
+
for(i=0; i<block->num_inners; ++i) {
|
198
|
+
vcd_print_var(block->inners[i]);
|
199
|
+
}
|
200
|
+
|
201
|
+
/* Close the hierarchy. */
|
202
|
+
vcd_print("$upscope $end\n");
|
203
|
+
}
|
204
|
+
|
205
|
+
|
206
|
+
/** Prints the hierarchy of a system instances.
|
207
|
+
* @param scope the scope to print. */
|
208
|
+
static void vcd_print_systemI(SystemI systemI) {
|
209
|
+
/* Declares the systemI. */
|
210
|
+
vcd_print("$scope module ");
|
211
|
+
vcd_print_name((Object)systemI);
|
212
|
+
vcd_print(" $end\n");
|
213
|
+
|
214
|
+
/* Declares its content. */
|
215
|
+
vcd_print_systemT_content(systemI->system);
|
216
|
+
|
217
|
+
/* Close the hierarchy. */
|
218
|
+
vcd_print("$upscope $end\n");
|
219
|
+
}
|
220
|
+
|
221
|
+
|
222
|
+
/** Prints the hierarchy inside a scope.
|
223
|
+
* @param scope the scope to print the inside. */
|
224
|
+
static void vcd_print_scope_content(Scope scope) {
|
225
|
+
int i;
|
226
|
+
|
227
|
+
/* Declare the inners of the systems. */
|
228
|
+
for(i=0; i<scope->num_inners; ++i) {
|
229
|
+
vcd_print_var(scope->inners[i]);
|
230
|
+
}
|
231
|
+
|
232
|
+
/* Recurse on the system instances. */
|
233
|
+
for(i=0; i<scope->num_systemIs; ++i) {
|
234
|
+
vcd_print_systemI(scope->systemIs[i]);
|
235
|
+
}
|
236
|
+
|
237
|
+
/* Recurse on the sub scopes. */
|
238
|
+
for(i=0; i<scope->num_scopes; ++i) {
|
239
|
+
vcd_print_scope(scope->scopes[i]);
|
240
|
+
}
|
241
|
+
|
242
|
+
/* Recurse on the behaviors. */
|
243
|
+
for(i=0; i<scope->num_behaviors; ++i) {
|
244
|
+
vcd_print_block(scope->behaviors[i]->block);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
|
249
|
+
/** Prints the hierarchy of a scope.
|
250
|
+
* @param scope the scope to print. */
|
251
|
+
static void vcd_print_scope(Scope scope) {
|
252
|
+
/* Do not print block with no declaration. */
|
253
|
+
if (scope->num_inners == 0 && scope->num_scopes == 0 && scope->num_behaviors == 0) return;
|
254
|
+
/* Declares the scope. */
|
255
|
+
vcd_print("$scope module ");
|
256
|
+
vcd_print_name((Object)scope);
|
257
|
+
vcd_print(" $end\n");
|
258
|
+
|
259
|
+
/* Declares its content. */
|
260
|
+
vcd_print_scope_content(scope);
|
261
|
+
|
262
|
+
/* Close the hierarchy. */
|
263
|
+
vcd_print("$upscope $end\n");
|
264
|
+
}
|
265
|
+
|
266
|
+
|
267
|
+
/** Prints the hierarchy content of a system type.
|
268
|
+
* @param system the system to print. */
|
269
|
+
static void vcd_print_systemT_content(SystemT system) {
|
270
|
+
int i;
|
271
|
+
|
272
|
+
/* Declare the inputs of the systems. */
|
273
|
+
for(i = 0; i<system->num_inputs; ++i) {
|
274
|
+
vcd_print_var(system->inputs[i]);
|
275
|
+
}
|
276
|
+
/* Declare the outputs of the systems. */
|
277
|
+
for(i = 0; i<system->num_outputs; ++i) {
|
278
|
+
vcd_print_var(system->outputs[i]);
|
279
|
+
}
|
280
|
+
/* Declare the inouts of the systems. */
|
281
|
+
for(i = 0; i<system->num_inouts; ++i) {
|
282
|
+
vcd_print_var(system->inouts[i]);
|
283
|
+
}
|
284
|
+
/* Recurse on the content of the scope (the scope header is the system).*/
|
285
|
+
vcd_print_scope_content(system->scope);
|
286
|
+
}
|
287
|
+
|
288
|
+
|
289
|
+
/** Prints the hierarchy of a system type.
|
290
|
+
* @param system the system to print. */
|
291
|
+
static void vcd_print_systemT(SystemT system) {
|
292
|
+
int i;
|
293
|
+
/* Declares the module. */
|
294
|
+
vcd_print("$scope module ");
|
295
|
+
vcd_print_name((Object)system);
|
296
|
+
vcd_print(" $end\n");
|
297
|
+
|
298
|
+
/* Declares the content. */
|
299
|
+
vcd_print_systemT_content(system);
|
300
|
+
|
301
|
+
/* Close the hierarchy. */
|
302
|
+
vcd_print("$upscope $end\n");
|
303
|
+
}
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
/* high-end print functions. */
|
310
|
+
|
311
|
+
/** Prints the header of the vcd file. */
|
312
|
+
static void vcd_print_header() {
|
313
|
+
/* The date section. */
|
314
|
+
vcd_print("$date\n");
|
315
|
+
{
|
316
|
+
char text[100];
|
317
|
+
time_t now = time(NULL);
|
318
|
+
struct tm *t = localtime(&now);
|
319
|
+
strftime(text, sizeof(text), "%d %m %Y %H:%M", t);
|
320
|
+
vcd_print(" %s\n", text);
|
321
|
+
}
|
322
|
+
vcd_print("$end\n");
|
323
|
+
|
324
|
+
/* The version section. */
|
325
|
+
vcd_print("$version\n");
|
326
|
+
vcd_print(" Generated from HDLRuby simulator\n");
|
327
|
+
vcd_print("$end\n");
|
328
|
+
|
329
|
+
/* The comment section. */
|
330
|
+
vcd_print("$comment\n");
|
331
|
+
vcd_print(" Is it an easter egg?\n");
|
332
|
+
vcd_print("$end\n");
|
333
|
+
|
334
|
+
/* The time scale section: for now 1ps only. */
|
335
|
+
vcd_print("$timescale 1ps $end\n");
|
336
|
+
|
337
|
+
// /* The scope section: nothing specific. */
|
338
|
+
// vcd_print("$scope module logic $end\n");
|
339
|
+
|
340
|
+
// /* The variables declaration. */
|
341
|
+
// each_all_signal(&vcd_print_var);
|
342
|
+
|
343
|
+
// /* Ends the declarations. */
|
344
|
+
// vcd_print("$upscope $end\n");
|
345
|
+
// vcd_print("$enddefinitions $end\n");
|
346
|
+
|
347
|
+
/* The declaration of the hierarchy and the variables
|
348
|
+
* from the top system. */
|
349
|
+
vcd_print_systemT(top_system);
|
350
|
+
/* Ends the declarations. */
|
351
|
+
vcd_print("$enddefinitions $end\n");
|
352
|
+
|
353
|
+
/* Display the initializations. */
|
354
|
+
vcd_print("$dumpvars\n");
|
355
|
+
each_all_signal(&vcd_print_signal_cvalue);
|
356
|
+
vcd_print("$end\n");
|
357
|
+
}
|
358
|
+
|
359
|
+
|
360
|
+
/* The configuration and initialization of the vcd vizualizer. */
|
361
|
+
|
362
|
+
|
363
|
+
/** Sets up the vcd vizualization engine.
|
364
|
+
* @param name the name of the vizualization. */
|
365
|
+
extern void init_vcd_visualizer(char* name) {
|
366
|
+
/* Open the resulting file with name: <name>.vcd */
|
367
|
+
char filename[256];
|
368
|
+
strncpy(filename,name,256);
|
369
|
+
strncat(filename,".vcd",256);
|
370
|
+
vcd_file = fopen(filename,"w");
|
371
|
+
|
372
|
+
/* Initialize the vizualizer printer engine. */
|
373
|
+
init_visualizer(&vcd_print_time,
|
374
|
+
&vcd_print_full_name,
|
375
|
+
&vcd_print_value,
|
376
|
+
&vcd_print_signal_fvalue);
|
377
|
+
|
378
|
+
/* Prints the header of the vcd file. */
|
379
|
+
vcd_print_header();
|
380
|
+
}
|