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 +4 -4
- data/README.md +1 -0
- data/lib/HDLRuby/hdr_samples/with_multi_channels.rb +290 -0
- data/lib/HDLRuby/hdrcc.rb +10 -1
- data/lib/HDLRuby/hruby_high.rb +8 -0
- data/lib/HDLRuby/hruby_low.rb +17 -11
- data/lib/HDLRuby/hruby_low2c.rb +10 -5
- data/lib/HDLRuby/hruby_low_resolve.rb +1 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +1 -0
- data/lib/HDLRuby/sim/hruby_sim.h +75 -37
- data/lib/HDLRuby/sim/hruby_sim_calc.c +69 -0
- data/lib/HDLRuby/sim/hruby_sim_core.c +29 -6
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +215 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +51 -12
- data/lib/HDLRuby/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65ef28718e6de9e9d1358073d2d7ae8bd914a3f942b48d6cd45c8f28f545a906
|
4
|
+
data.tar.gz: 0d469d886d79f65ebfc69a4c4f95d2d8f50c0ada6f4fdbf0349d3c9650fa4581
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
|
data/lib/HDLRuby/hdrcc.rb
CHANGED
@@ -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(
|
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
|
|
data/lib/HDLRuby/hruby_high.rb
CHANGED
@@ -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)
|
data/lib/HDLRuby/hruby_low.rb
CHANGED
@@ -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.
|
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.
|
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.
|
4610
|
+
return @refs.any? { |expr| expr.use_name?(*names) }
|
4605
4611
|
end
|
4606
4612
|
|
4607
4613
|
# Clones the concatenated references (deeply)
|
data/lib/HDLRuby/hruby_low2c.rb
CHANGED
@@ -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
|
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
|
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);
|
@@ -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
|
-
|
562
|
-
*
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
* @param
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
*
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
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(
|
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
|
-
|
123
|
-
// printf("
|
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(
|
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
|
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
|
-
* @
|
18
|
-
void
|
19
|
-
|
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
|
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
|
-
|
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
|
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
|
81
|
-
|
105
|
+
static void default_print_signal(SignalI signal) {
|
106
|
+
default_print_name((Object)signal);
|
82
107
|
printf(": ");
|
83
|
-
|
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
|
89
|
-
|
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
|
+
}
|
data/lib/HDLRuby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: HDLRuby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
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-
|
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
|