HDLRuby 2.3.8 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
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