HDLRuby 2.3.8 → 2.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 164191b6cbfda40e60bc6b253c95a0ff511164007c83adf53c7f86383b404464
4
- data.tar.gz: 5344dd9f624089cab1488d9e10b67e542cb83639db81e397c0d2241c67a43527
3
+ metadata.gz: 65ef28718e6de9e9d1358073d2d7ae8bd914a3f942b48d6cd45c8f28f545a906
4
+ data.tar.gz: 0d469d886d79f65ebfc69a4c4f95d2d8f50c0ada6f4fdbf0349d3c9650fa4581
5
5
  SHA512:
6
- metadata.gz: 5e9b00b3fad458789078bcaca6d8d45e7ac5877ff14a3971ce2ddac186ed15a1ad2aa440d3c5619c66f324e9f6dbeda5c8bcf2aa5de3389aa12d631abbd780a4
7
- data.tar.gz: '08dc450e1e3807d85f8ffb22888c037b081bed44dab318fac5fb33611f706c58191a2b06379b0798b61bbf3578d0e058b144ee8995e4212250826366bd306e9e'
6
+ metadata.gz: 4d458fe640fd29e1e31470b1f395333c3fd344703903c0c7d126e780d9e6f93c419f18a4e4cbaadc91461d19ed0087388a249fe3ccd87b2ed29d731733ecbc5b
7
+ data.tar.gz: 1ff098b2ca9bff7758bff7a5bb5e20df7272f53f103944037f9575b55444e6179781129e5d87e301a4e29b885bee5cc82794918ad85ac8236894603759d66212
data/README.md CHANGED
@@ -50,6 +50,7 @@ Where:
50
50
  | `-s, --syntax` | Output the Ruby syntax tree |
51
51
  | `-C, --clang` | Output the C code of the simulator |
52
52
  | `-S, --sim` | Output the executable simulator and execute it |
53
+ | `--vcd` | Make the simulator generate a vcd file |
53
54
  | `-d, --directory` | Specify the base directory for loading the HDLRuby files |
54
55
  | `-D, --debug` | Set the HDLRuby debug mode |
55
56
  | `-t, --top system`| Specify the top system describing the circuit to compile |
@@ -0,0 +1,290 @@
1
+ require "std/channel.rb"
2
+
3
+ include HDLRuby::High::Std
4
+
5
+ # Channel describing a buffered queue storing data of +typ+ type of +depth+,
6
+ # synchronized through clk and reset on +rst+.
7
+ channel(:queue) do |typ,depth,clk,rst|
8
+ # The inner buffer of the queue.
9
+ typ[-depth].inner :buffer
10
+ # The read and write pointers.
11
+ [depth.width].inner :rptr, :wptr
12
+ # The read and write command signals.
13
+ inner :rcmd, :wcmd
14
+ # The read and write ack signals.
15
+ inner :rack, :wack
16
+ # The ack check deactivator (for synchron accesses).
17
+ inner :hrack, :hwack
18
+ # The read/write data registers.
19
+ typ.inner :rdata, :wdata
20
+
21
+ # The process handling the decoupled access to the buffer.
22
+ par(clk.posedge) do
23
+ # rack <= 0
24
+ # wack <= 0
25
+ hif (~rcmd) { rack <= 0 }
26
+ hif (~wcmd) { wack <= 0 }
27
+ hif(rst) { rptr <= 0; wptr <= 0 }
28
+ hif(rcmd & (hrack|~rack) & (rptr != wptr)) do
29
+ rptr <= (rptr + 1) % depth
30
+ rack <= 1
31
+ end
32
+ hif(wcmd & (hwack|~wack) & (((wptr+1) % depth) != rptr)) do
33
+ buffer[wptr] <= wdata
34
+ # buffer[1] <= wdata
35
+ wptr <= (wptr + 1) % depth
36
+ wack <= 1
37
+ end
38
+ end
39
+ par { rdata <= buffer[rptr] }
40
+
41
+ reader_output :rcmd, :rptr, :hrack
42
+ reader_input :rdata, :rack
43
+
44
+ # The read primitive.
45
+ reader do |blk,target|
46
+ if (cur_behavior.on_event?(clk.posedge,clk.negedge)) then
47
+ # Same clk event, synchrone case: perform a direct access.
48
+ # Now perform the access.
49
+ top_block.unshift do
50
+ rcmd <= 0
51
+ hrack <= 1
52
+ end
53
+ seq do
54
+ rptr <= (rptr + 1) % depth
55
+ target <= rdata
56
+ blk.call if blk
57
+ end
58
+ else
59
+ # Different clk event, perform a decoupled access.
60
+ top_block.unshift do
61
+ rcmd <= 0
62
+ hrack <= 0
63
+ end
64
+ seq do
65
+ hif(rack) do
66
+ blk.call if blk
67
+ end
68
+ helse do
69
+ rcmd <= 1
70
+ target <= rdata
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ writer_output :wcmd, :wdata, :hwack
77
+ writer_input :wack
78
+
79
+ # The write primitive.
80
+ writer do |blk,target|
81
+ if (cur_behavior.on_event?(clk.negedge,clk.posedge)) then
82
+ # Same clk event, synchrone case: perform a direct access.
83
+ top_block.unshift do
84
+ wcmd <= 0
85
+ hwack <= 1
86
+ end
87
+ wcmd <= 1
88
+ wdata <= target
89
+ blk.call if blk
90
+ else
91
+ # Different clk event, asynchrone case: perform a decoupled access.
92
+ top_block.unshift do
93
+ wcmd <= 0
94
+ hwack <= 0
95
+ end
96
+ seq do
97
+ hif(wack) do
98
+ blk.call if blk
99
+ end
100
+ helse { wcmd <= 1 }
101
+ wdata <= target
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+
108
+ # Channel describing a register of +typ+ type.
109
+ channel(:register) do |typ|
110
+ # The register.
111
+ typ.inner :buffer
112
+
113
+ reader_input :buffer
114
+
115
+ # The read primitive.
116
+ reader do |blk,target|
117
+ target <= buffer
118
+ blk.call if blk
119
+ end
120
+
121
+ writer_output :buffer
122
+
123
+ # The read primitive.
124
+ writer do |blk,target|
125
+ buffer <= target
126
+ blk.call if blk
127
+ end
128
+ end
129
+
130
+
131
+
132
+ # Channel describing a handshake for transmitting data of +typ+ type, reset
133
+ # by +rst+
134
+ channel(:handshake) do |typ|
135
+ # The data signal.
136
+ typ.inner :data
137
+ # The request and acknowledge.
138
+ typ.inner :req, :ack
139
+
140
+ reader_input :ack, :data
141
+ reader_output :req
142
+
143
+ # The read primitive.
144
+ reader do |blk,target|
145
+ top_block.unshift do
146
+ req <= 0
147
+ end
148
+ hif(ack == 0) do
149
+ req <= 1
150
+ end
151
+ helsif(req) do
152
+ target <= data
153
+ req <= 0
154
+ blk.call if blk
155
+ end
156
+ end
157
+
158
+ writer_input :req
159
+ writer_output :ack, :data
160
+
161
+ # The read primitive.
162
+ writer do |blk,target|
163
+ top_block.unshift do
164
+ ack <= 0
165
+ end
166
+ hif(req) do
167
+ hif(~ack) do
168
+ data <= target
169
+ blk.call if blk
170
+ end
171
+ ack <= 1
172
+ end
173
+ end
174
+ end
175
+
176
+
177
+ $mode = :prodcons
178
+ # $mode = :sync
179
+ # $mode = :nsync
180
+ # $mode = :async
181
+ # $channel = :register
182
+ # $channel = :handshake
183
+ $channel = :queue
184
+
185
+ # Testing the queue channel.
186
+ system :test_queue do
187
+ inner :clk, :rst, :clk2, :clk3
188
+ [8].inner :idata, :odata
189
+ [4].inner :counter
190
+
191
+ if $channel == :register then
192
+ register(bit[8]).(:my_ch)
193
+ elsif $channel == :handshake then
194
+ handshake(bit[8],rst).(:my_ch)
195
+ elsif $channel == :queue then
196
+ queue(bit[8],5,clk,rst).(:my_ch)
197
+ end
198
+
199
+ ev = $mode == :sync ? clk.posedge :
200
+ $mode == :nsync ? clk.negedge : clk2.posedge
201
+
202
+ if $mode != :prodcons then
203
+ # Sync/Neg sync and async tests mode
204
+ par(ev) do
205
+ hif(rst) do
206
+ counter <= 0
207
+ idata <= 0
208
+ odata <= 0
209
+ end
210
+ helse do
211
+ hif (counter < 4) do
212
+ my_ch.write(idata) do
213
+ idata <= idata + 1
214
+ counter <= counter + 1
215
+ end
216
+ end
217
+ helsif ((counter > 10) & (counter < 15)) do
218
+ my_ch.read(odata) do
219
+ idata <= idata - odata
220
+ counter <= counter + 1
221
+ end
222
+ end
223
+ helse do
224
+ counter <= counter + 1
225
+ end
226
+ end
227
+ end
228
+ else
229
+ # Producter/consumer mode
230
+ # Producer
231
+ par(clk2.posedge) do
232
+ hif(rst) do
233
+ idata <= 0
234
+ end
235
+ helse do
236
+ my_ch.write(idata) do
237
+ idata <= idata + 1
238
+ end
239
+ end
240
+ end
241
+ # Consumer
242
+ par(clk3.posedge) do
243
+ hif(rst) do
244
+ counter <= 0
245
+ end
246
+ helse do
247
+ my_ch.read(odata) do
248
+ counter <= counter + 1
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ timed do
255
+ clk <= 0
256
+ clk2 <= 0
257
+ clk3 <= 0
258
+ rst <= 0
259
+ !10.ns
260
+ clk <= 1
261
+ !10.ns
262
+ clk <= 0
263
+ rst <= 1
264
+ !3.ns
265
+ clk2 <= 1
266
+ !1.ns
267
+ clk3 <= 1
268
+ !6.ns
269
+ clk <= 1
270
+ !10.ns
271
+ clk <= 0
272
+ rst <= 0
273
+ !3.ns
274
+ clk2 <= 0
275
+ !1.ns
276
+ clk3 <= 1
277
+ !6.ns
278
+ 64.times do
279
+ clk <= 1
280
+ !10.ns
281
+ clk <= 0
282
+ !3.ns
283
+ clk2 <= ~clk2
284
+ !1.ns
285
+ hif (clk2 == 0) { clk3 <= ~ clk3 }
286
+ !6.ns
287
+ end
288
+ end
289
+ end
290
+
@@ -269,6 +269,9 @@ $optparse = OptionParser.new do |opts|
269
269
  $options[:multiple] = v
270
270
  $options[:sim] = v
271
271
  end
272
+ opts.on("--vcd", "The simulator will generate a vcd file") do |v|
273
+ $options[:vcd] = v
274
+ end
272
275
  opts.on("-v", "--verilog","Output in Verlog HDL format") do |v|
273
276
  $options[:verilog] = v
274
277
  $options[:multiple] = v
@@ -515,9 +518,15 @@ elsif $options[:clang] then
515
518
  # Generate the code for it.
516
519
  $main = File.open($name,"w")
517
520
 
521
+ # Select the vizualizer depending on the options.
522
+ init_visualizer = $options[:vcd] ? "init_vcd_visualizer" :
523
+ "init_default_visualizer"
524
+
518
525
  # Generate the code of the main function.
519
526
  # HDLRuby start code
520
- $main << HDLRuby::Low::Low2C.main($top_system,
527
+ $main << HDLRuby::Low::Low2C.main("hruby_simulator",
528
+ init_visualizer,
529
+ $top_system,
521
530
  $top_system.each_systemT_deep.to_a.reverse,$hnames)
522
531
  $main.close
523
532
 
@@ -2791,6 +2791,14 @@ module HDLRuby::High
2791
2791
  return RefObject.new(@base,@object)
2792
2792
  end
2793
2793
 
2794
+ # Comparison for hash: structural comparison.
2795
+ def eql?(obj)
2796
+ return false unless obj.is_a?(RefObject)
2797
+ return false unless @base.eql?(obj.base)
2798
+ return false unless @object.eql?(obj.object)
2799
+ return true
2800
+ end
2801
+
2794
2802
  # Converts the name reference to a HDLRuby::Low::RefName.
2795
2803
  def to_low
2796
2804
  # return HDLRuby::Low::RefName.new(@base.to_ref.to_low,@object.name)
@@ -1978,14 +1978,6 @@ module HDLRuby::Low
1978
1978
 
1979
1979
  include Hparent
1980
1980
 
1981
- # # Creates a new behavior.
1982
- # def initialize
1983
- # # Initialize the sensitivity list.
1984
- # @events = []
1985
- # # Initialize the block list.
1986
- # @blocks = []
1987
- # end
1988
-
1989
1981
  # The block executed by the behavior.
1990
1982
  attr_reader :block
1991
1983
 
@@ -2074,6 +2066,11 @@ module HDLRuby::Low
2074
2066
  return !@events.empty?
2075
2067
  end
2076
2068
 
2069
+ # Tells if it is activated on one of +events+.
2070
+ def on_event?(*events)
2071
+ @events.any? { |ev0| events.any? { |ev1| ev0.eql?(ev1) } }
2072
+ end
2073
+
2077
2074
  # Tells if there is a positive or negative edge event.
2078
2075
  def on_edge?
2079
2076
  @events.each do |event|
@@ -2619,6 +2616,15 @@ module HDLRuby::Low
2619
2616
  end
2620
2617
  end
2621
2618
 
2619
+ # Gets the behavior the statement is in.
2620
+ def behavior
2621
+ if self.parent.is_a?(Behavior) then
2622
+ return self.parent
2623
+ else
2624
+ return self.parent.behavior
2625
+ end
2626
+ end
2627
+
2622
2628
  # Gets the top block, i.e. the first block of the current behavior.
2623
2629
  def top_block
2624
2630
  return self.parent.is_a?(Behavior) ? self : self.parent.top_block
@@ -4368,7 +4374,7 @@ module HDLRuby::Low
4368
4374
  # Recurse on the select.
4369
4375
  return true if @select.use_name?(*names)
4370
4376
  # Recurse on the choices.
4371
- return @choices.include? { |choice| choice.use_name?(*names) }
4377
+ return @choices.any? { |choice| choice.use_name?(*names) }
4372
4378
  end
4373
4379
 
4374
4380
  # Clones the select (deeply)
@@ -4453,7 +4459,7 @@ module HDLRuby::Low
4453
4459
  # Tell if the expression includes a signal whose name is one of +names+.
4454
4460
  def use_name?(*names)
4455
4461
  # Recurse on the expressions.
4456
- return @expressions.include? { |expr| expr.use_name?(*names) }
4462
+ return @expressions.any? { |expr| expr.use_name?(*names) }
4457
4463
  end
4458
4464
 
4459
4465
  # Clones the concatenated expression (deeply)
@@ -4601,7 +4607,7 @@ module HDLRuby::Low
4601
4607
  # Tell if the expression includes a signal whose name is one of +names+.
4602
4608
  def use_name?(*names)
4603
4609
  # Recurse on the references.
4604
- return @refs.include? { |expr| expr.use_name?(*names) }
4610
+ return @refs.any? { |expr| expr.use_name?(*names) }
4605
4611
  end
4606
4612
 
4607
4613
  # Clones the concatenated references (deeply)
@@ -106,13 +106,13 @@ module HDLRuby::Low
106
106
 
107
107
  ## Generates the main for making the objects of +objs+ and
108
108
  # for starting the simulation and including the files from +hnames+
109
- def self.main(top,objs,hnames)
109
+ def self.main(name,init_visualizer,top,objs,hnames)
110
110
  res = Low2C.includes(*hnames)
111
111
  res << "int main(int argc, char* argv[]) {\n"
112
112
  # Build the objects.
113
113
  objs.each { |obj| res << " #{Low2C.make_name(obj)}();\n" }
114
114
  # Starts the simulation.
115
- res << " hruby_sim_core(-1);\n"
115
+ res<< " hruby_sim_core(\"#{name}\",#{init_visualizer},-1);\n"
116
116
  # Close the main.
117
117
  res << "}\n"
118
118
  return res
@@ -1612,7 +1612,9 @@ module HDLRuby::Low
1612
1612
  # return "equal_value(#{self.left.to_c(level)}," +
1613
1613
  # "#{self.right.to_c(level)})"
1614
1614
  # when :!= then
1615
- # return "not_equal_value(#{self.left.to_c(level)}," +
1615
+ # # return "not_equal_value(#{self.left.to_c(level)}," +
1616
+ # # "#{self.right.to_c(level)})"
1617
+ # return "xor_value(#{self.left.to_c(level)}," +
1616
1618
  # "#{self.right.to_c(level)})"
1617
1619
  # when :> then
1618
1620
  # return "greater_value(#{self.left.to_c(level)}," +
@@ -1681,9 +1683,12 @@ module HDLRuby::Low
1681
1683
  when :rr then
1682
1684
  res += "dst = rotate_right_value(src0,src1,dst);\n"
1683
1685
  when :== then
1684
- res += "dst = equal_value(src0,src1,dst);\n"
1686
+ res += "dst = equal_value(src0,src1,dst);\n" +
1687
+ "dst = reduce_or_value(dst,dst);"
1685
1688
  when :!= then
1686
- res += "dst = not_equal_value(src0,src1,dst);\n"
1689
+ # res += "dst = not_equal_value(src0,src1,dst);\n"
1690
+ res += "dst = xor_value(src0,src1,dst);\n" +
1691
+ "dst = reduce_or_value(dst,dst);"
1687
1692
  when :> then
1688
1693
  res += "dst = greater_value(src0,src1,dst);\n"
1689
1694
  when :< then
@@ -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)
@@ -31,6 +31,7 @@ module HDLRuby::Low
31
31
  outputs_blk = Block.new(:par)
32
32
  timed_blk = TimeBlock.new(:seq)
33
33
  scope.each_connection do |connection|
34
+ # puts "For connection: #{connection}"
34
35
  # Check the left and right of the connection
35
36
  # for input or output port.
36
37
  left = connection.left
@@ -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 or
189
- * @param src1 the second source value of the or
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 addition
196
- * @param src1 the second source value of the addition
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 addition
203
- * @param src1 the second source value of the addition
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 addition
210
- * @param src1 the second source value of the addition
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 addition
217
- * @param src1 the second source value of the addition
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 addition
224
- * @param src1 the second source value of the addition
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);
@@ -555,39 +561,71 @@ extern unsigned long long make_delay(int value, Unit unit);
555
561
 
556
562
 
557
563
 
564
+ /* Iterate over all the signals.
565
+ * @param func function to applie on each signal. */
566
+ extern void each_all_signal(void (*func)(SignalI));
558
567
 
559
568
  /* Interface to the visualization engine. */
560
569
 
561
- /** Prints the time.
562
- * @param time the time to show. */
563
- extern void print_time(unsigned long long time);
564
-
565
- /** Prints the time and goes to the next line.
566
- * @param time the time to show. */
567
- extern void println_time(unsigned long long time);
568
-
569
- /** Prints the name of an object.
570
- * @param object the object to print the name. */
571
- extern void print_name(Object object);
572
-
573
- /** Prints a value.
574
- * @param value the value to print */
575
- extern void print_value(Value value);
576
-
577
- /** Prints a signal.
578
- * @param signal the signal to show */
579
- extern void print_signal(SignalI signal);
580
-
581
- /** Prints a signal and goes to the next line.
582
- * @param signal the signal to show */
583
- extern void println_signal(SignalI signal);
584
-
570
+ typedef struct {
571
+ void (*print_time)(unsigned long long);
572
+ void (*print_name)(Object);
573
+ void (*print_value)(Value);
574
+ void (*print_signal)(SignalI);
575
+ } PrinterS;
576
+
577
+ PrinterS printer;
578
+
579
+ /** Initializes the visualization printer engine.
580
+ * @param print_time the time printer
581
+ * @param print_name the name printer
582
+ * @param print_value the value printer
583
+ * @param print_signal the signal state printer. */
584
+ void init_visualizer(void (*print_time)(unsigned long long),
585
+ void (*print_name)(Object),
586
+ void (*print_value)(Value),
587
+ void (*print_signal)(SignalI));
588
+
589
+ // /** Prints the time.
590
+ // * @param time the time to show. */
591
+ // extern void print_time(unsigned long long time);
592
+ //
593
+ // // /** Prints the time and goes to the next line.
594
+ // // * @param time the time to show. */
595
+ // // extern void println_time(unsigned long long time);
596
+ //
597
+ // /** Prints the name of an object.
598
+ // * @param object the object to print the name. */
599
+ // extern void print_name(Object object);
600
+ //
601
+ // /** Prints a value.
602
+ // * @param value the value to print */
603
+ // extern void print_value(Value value);
604
+ //
605
+ // /** Prints a signal.
606
+ // * @param signal the signal to show */
607
+ // extern void print_signal(SignalI signal);
608
+ //
609
+ // // /** Prints a signal and goes to the next line.
610
+ // // * @param signal the signal to show */
611
+ // // extern void println_signal(SignalI signal);
612
+
613
+ /** Sets up the default vizualization engine.
614
+ * @param name the name of the vizualization. */
615
+ extern void init_default_visualizer(char* name);
616
+
617
+ /** Sets up the vcd vizualization engine.
618
+ * @param name the name of the vizualization. */
619
+ extern void init_vcd_visualizer(char* name);
585
620
 
586
621
  /* The interface to the simulator core. */
587
622
 
588
623
  /** The simulation core function.
624
+ * @param name the name of the simulation.
625
+ * @param init_vizualizer the vizualizer engine initializer.
589
626
  * @param limit the time limit in fs. */
590
- extern void hruby_sim_core(unsigned long long limit);
627
+ extern void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
628
+ unsigned long long limit);
591
629
 
592
630
 
593
631
 
@@ -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
@@ -118,9 +118,10 @@ void hruby_sim_update_signals() {
118
118
  /* Is there a change? */
119
119
  if (same_content_value(sig->c_value,sig->f_value)) continue;
120
120
  /* Yes, process the signal. */
121
- println_signal(sig);
122
- // printf("c_value="); print_value(sig->c_value);
123
- // printf("\nf_value="); print_value(sig->f_value); printf("\n");
121
+ // println_signal(sig);
122
+ printer.print_signal(sig);
123
+ // printf("c_value="); printer.print_value(sig->c_value);
124
+ // printf("\nf_value="); printer.print_value(sig->f_value); printf("\n");
124
125
  // printf("Touched signal: %p (%s)\n",sig,sig->name);
125
126
  /* Update the current value of the signal. */
126
127
  copy_value(sig->f_value,sig->c_value);
@@ -185,7 +186,8 @@ void hruby_sim_update_signals() {
185
186
  SignalI sig = e->data;
186
187
  delete_element(e);
187
188
  /* Yes, process the signal. */
188
- println_signal(sig);
189
+ // println_signal(sig);
190
+ printer.print_signal(sig);
189
191
  /* Update the current value of the signal. */
190
192
  /* Mark the corresponding code as activated. */
191
193
  /* Any edge activation. */
@@ -284,7 +286,8 @@ void hruby_sim_advance_time() {
284
286
  }
285
287
  /* Sets the new activation time. */
286
288
  hruby_sim_time = next_time;
287
- println_time(hruby_sim_time);
289
+ // println_time(hruby_sim_time);
290
+ printer.print_time(hruby_sim_time);
288
291
  }
289
292
 
290
293
 
@@ -393,9 +396,18 @@ void hruby_sim_end_timed_behaviors() {
393
396
 
394
397
 
395
398
 
399
+ // /** The simulation core function.
400
+ // * @param limit the time limit in fs. */
401
+ // void hruby_sim_core(unsigned long long limit) {
396
402
  /** The simulation core function.
403
+ * @param name the name of the simulation.
404
+ * @param vizualizer the vizualizer engine initializer.
397
405
  * @param limit the time limit in fs. */
398
- void hruby_sim_core(unsigned long long limit) {
406
+ void hruby_sim_core(char* name, void (*init_vizualizer)(char*),
407
+ unsigned long long limit) {
408
+ /* Initilize the vizualizer. */
409
+ init_vizualizer(name);
410
+
399
411
  /* Initialize the time to 0. */
400
412
  hruby_sim_time = 0;
401
413
 
@@ -597,3 +609,14 @@ unsigned long long make_delay(int value, Unit unit) {
597
609
  return -1;
598
610
  }
599
611
 
612
+
613
+
614
+
615
+ /* Iterate over all the signals.
616
+ * @param func function to applie on each signal. */
617
+ void each_all_signal(void (*func)(SignalI)) {
618
+ int i;
619
+ for(i = 0; i<num_all_signals; ++i) {
620
+ func(all_signals[i]);
621
+ }
622
+ }
@@ -0,0 +1,215 @@
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.
68
+ * @param object the object to print the name. */
69
+ static void vcd_print_name(Object object) {
70
+ /* Recurse on the owner if any. */
71
+ // printf("owner=%p\n",object->owner);
72
+ if (object->owner != NULL) {
73
+ vcd_print_name(object->owner);
74
+ vcd_print("$");
75
+ }
76
+ /* Depending on the kind of object. */
77
+ switch(object->kind) {
78
+ case SYSTEMT:
79
+ case SIGNALI:
80
+ case SCOPE:
81
+ case SYSTEMI:
82
+ /* Print the name if name. */
83
+ /* Trick: SystemT, SignalI, Scope and SystemI have the
84
+ * field name at the same place. */
85
+ if (((SystemI)object)->name != NULL) {
86
+ char name[256];
87
+ strncpy(name,((SystemI)object)->name,256);
88
+ replace_char(name,':','$');
89
+ vcd_print("%s",name);
90
+ }
91
+ default: /* Nothing to do */
92
+ break;
93
+ }
94
+ }
95
+
96
+ /** Prints a value.
97
+ * @param value the value to print */
98
+ static void vcd_print_value(Value value) {
99
+ vcd_print("b");
100
+ if (value->numeric) {
101
+ unsigned long long width = type_width(value->type);
102
+ unsigned long long mask = 1ULL << (width-1);
103
+ for(; mask > 0; mask >>= 1) {
104
+ vcd_print("%d",(value->data_int & mask) != 0);
105
+ }
106
+ } else {
107
+ /* Display a bitstring value. */
108
+ int i;
109
+ int width = type_width(value->type);
110
+ char* data = value->data_str;
111
+ if (value->capacity == 0) {
112
+ /* The value is empty, therefore undefined. */
113
+ for(i=width; i>0; --i) {
114
+ vcd_print("u");
115
+ }
116
+ }
117
+ else {
118
+ /* The value is not empty. */
119
+ for(i=width; i>0; --i) {
120
+ vcd_print("%c",data[i-1]);
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ /** Prints a signal declaration.
127
+ * @param signal the signal to declare */
128
+ static void vcd_print_var(SignalI signal) {
129
+ vcd_print("$var wire %d ",type_width(signal->type));
130
+ vcd_print_name((Object)signal);
131
+ vcd_print(" ");
132
+ vcd_print_name((Object)signal);
133
+ vcd_print(" $end\n");
134
+ }
135
+
136
+
137
+ /** Prints a signal.
138
+ * @param signal the signal to show */
139
+ static void vcd_print_signal(SignalI signal) {
140
+ vcd_print_value(signal->f_value);
141
+ vcd_print(" ");
142
+ vcd_print_name((Object)signal);
143
+ vcd_print("\n");
144
+ }
145
+
146
+
147
+
148
+
149
+ /* high-end print functions. */
150
+
151
+ /** Prints the header of the vcd file. */
152
+ static void vcd_print_header() {
153
+ /* The date section. */
154
+ vcd_print("$date\n");
155
+ {
156
+ char text[100];
157
+ time_t now = time(NULL);
158
+ struct tm *t = localtime(&now);
159
+ strftime(text, sizeof(text), "%d %m %Y %H:%M", t);
160
+ vcd_print(" %s\n", text);
161
+ }
162
+ vcd_print("$end\n");
163
+
164
+ /* The version section. */
165
+ vcd_print("$version\n");
166
+ vcd_print(" Generated from HDLRuby simulator\n");
167
+ vcd_print("$end");
168
+
169
+ /* The comment section. */
170
+ vcd_print("$comment\n");
171
+ vcd_print(" Is it an easter egg?\n");
172
+ vcd_print("$end\n");
173
+
174
+ /* The time scale section: for now 1ps only. */
175
+ vcd_print("$timescale 1ps $end\n");
176
+
177
+ /* The scope section: nothing specific. */
178
+ vcd_print("$scope module logic $end\n");
179
+
180
+ /* The variables declaration. */
181
+ each_all_signal(&vcd_print_var);
182
+
183
+ /* Ends the declarations. */
184
+ vcd_print("$upscope $end\n");
185
+ vcd_print("$enddefinitions $end\n");
186
+
187
+ /* Display the initializations. */
188
+ vcd_print("$dumpvars\n");
189
+ // Maybe nothing to do.
190
+ // each_all_init_signal(&vcd_print_signal);
191
+ vcd_print("$end\n");
192
+ }
193
+
194
+
195
+ /* The configuration and initialization of the vcd vizualizer. */
196
+
197
+
198
+ /** Sets up the vcd vizualization engine.
199
+ * @param name the name of the vizualization. */
200
+ extern void init_vcd_visualizer(char* name) {
201
+ /* Open the resulting file with name: <name>.vcd */
202
+ char filename[256];
203
+ strncpy(filename,name,256);
204
+ strncat(filename,".vcd",256);
205
+ vcd_file = fopen(filename,"w");
206
+
207
+ /* Initialize the vizualizer printer engine. */
208
+ init_visualizer(&vcd_print_time,
209
+ &vcd_print_name,
210
+ &vcd_print_value,
211
+ &vcd_print_signal);
212
+
213
+ /* Prints the header of the vcd file. */
214
+ vcd_print_header();
215
+ }
@@ -7,26 +7,51 @@
7
7
  * generated by hruby_low2c.
8
8
  **/
9
9
 
10
+ /* The print function pointers. */
11
+
12
+ PrinterS printer;
13
+
14
+
15
+ /** Initializes the visualization printer engine.
16
+ * @param print_time the time printer
17
+ * @param print_name the name printer
18
+ * @param print_value the value printer
19
+ * @param print_signal the signal state printer. */
20
+ void init_visualizer(void (*print_time)(unsigned long long),
21
+ void (*print_name)(Object),
22
+ void (*print_value)(Value),
23
+ void (*print_signal)(SignalI)) {
24
+ printer.print_time = print_time;
25
+ printer.print_name = print_name;
26
+ printer.print_value = print_value;
27
+ printer.print_signal = print_signal;
28
+ }
29
+
30
+
31
+
32
+
33
+ /* The default printing functions. */
34
+
10
35
  /** Prints the time.
11
36
  * @param time the time to show. */
12
- void print_time(unsigned long long time) {
37
+ static void default_print_time(unsigned long long time) {
13
38
  printf("# %llups",time);
14
39
  }
15
40
 
16
41
  /** Prints the time and goes to the next line.
17
- * @param time the time to show. */
18
- void println_time(unsigned long long time) {
19
- print_time(time);
42
+ * @par1am time the time to show. */
43
+ static void default_println_time(unsigned long long time) {
44
+ default_print_time(time);
20
45
  printf("\n");
21
46
  }
22
47
 
23
48
  /** Prints the name of an object.
24
49
  * @param object the object to print the name. */
25
- void print_name(Object object) {
50
+ static void default_print_name(Object object) {
26
51
  /* Recurse on the owner if any. */
27
52
  // printf("owner=%p\n",object->owner);
28
53
  if (object->owner != NULL) {
29
- print_name(object->owner);
54
+ default_print_name(object->owner);
30
55
  printf("::");
31
56
  }
32
57
  /* Depending on the kind of object. */
@@ -48,7 +73,7 @@ void print_name(Object object) {
48
73
 
49
74
  /** Prints a value.
50
75
  * @param value the value to print */
51
- void print_value(Value value) {
76
+ static void default_print_value(Value value) {
52
77
  if (value->numeric) {
53
78
  unsigned long long width = type_width(value->type);
54
79
  unsigned long long mask = 1ULL << (width-1);
@@ -77,15 +102,29 @@ void print_value(Value value) {
77
102
 
78
103
  /** Prints a signal.
79
104
  * @param signal the signal to show */
80
- void print_signal(SignalI signal) {
81
- print_name((Object)signal);
105
+ static void default_print_signal(SignalI signal) {
106
+ default_print_name((Object)signal);
82
107
  printf(": ");
83
- print_value(signal->f_value);
108
+ default_print_value(signal->f_value);
84
109
  }
85
110
 
86
111
  /** Prints a signal and goes to the next line.
87
112
  * @param signal the signal to show */
88
- void println_signal(SignalI signal) {
89
- print_signal(signal);
113
+ static void default_println_signal(SignalI signal) {
114
+ default_print_signal(signal);
90
115
  printf("\n");
91
116
  }
117
+
118
+
119
+
120
+ /* Set up the visualizer. */
121
+
122
+ /** Set up the default vizualization engine.
123
+ * @param name the name of the vizualization. */
124
+ void init_default_visualizer(char* name) {
125
+ /* Initialize the vizualizer printer engine. */
126
+ init_visualizer(&default_println_time,
127
+ &default_print_name,
128
+ &default_print_value,
129
+ &default_println_signal);
130
+ }
@@ -1,3 +1,3 @@
1
1
  module HDLRuby
2
- VERSION = "2.3.8"
2
+ VERSION = "2.4.1"
3
3
  end
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.3.8
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lovic Gauthier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-18 00:00:00.000000000 Z
11
+ date: 2020-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -123,6 +123,7 @@ files:
123
123
  - lib/HDLRuby/hdr_samples/with_linear.rb
124
124
  - lib/HDLRuby/hdr_samples/with_loop.rb
125
125
  - lib/HDLRuby/hdr_samples/with_memory.rb
126
+ - lib/HDLRuby/hdr_samples/with_multi_channels.rb
126
127
  - lib/HDLRuby/hdr_samples/with_reconf.rb
127
128
  - lib/HDLRuby/hdrcc.rb
128
129
  - lib/HDLRuby/high_samples/_adder_fault.rb
@@ -262,6 +263,7 @@ files:
262
263
  - lib/HDLRuby/sim/hruby_sim_calc.c
263
264
  - lib/HDLRuby/sim/hruby_sim_core.c
264
265
  - lib/HDLRuby/sim/hruby_sim_list.c
266
+ - lib/HDLRuby/sim/hruby_sim_vcd.c
265
267
  - lib/HDLRuby/sim/hruby_sim_vizualize.c
266
268
  - lib/HDLRuby/sim/hruby_value_pool.c
267
269
  - lib/HDLRuby/std/channel.rb