HDLRuby 2.2.14 → 2.2.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/HDLRuby/hdr_samples/linear_test.rb +207 -0
- data/lib/HDLRuby/hdr_samples/with_linear.rb +163 -0
- data/lib/HDLRuby/hruby_low.rb +1 -19
- data/lib/HDLRuby/hruby_low_mutable.rb +2 -1
- data/lib/HDLRuby/sim/hruby_sim.h +14 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +172 -13
- data/lib/HDLRuby/std/channel.rb +66 -18
- data/lib/HDLRuby/std/linear.rb +197 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cac7290729b07ecdbbd73528b0807e601c8ba0f04e6d2476bbd075d5c4dbb648
|
4
|
+
data.tar.gz: b2d244a59dcff8b363e6d1cdd66ff22cca81ffa24b666b97eb46b7b142047787
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '093bfbd1c000b0d7a4e039d51a8a27da09483ac1b61f0d19d78a3999d9231abe6df0611b720e4d47409b8c9769a31e7f3770f8bd6fa0246b8854ea15f56d1648'
|
7
|
+
data.tar.gz: fb97205d4d7f542efb02e4951c696783c8d3f99b7f6def0f3a2cfbae27c7ff3d5e72459ba8aa899c6e93241d92302958177be0ee47472f329272f0c5fa2afd09
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'std/memory.rb'
|
2
|
+
require 'std/linear.rb'
|
3
|
+
|
4
|
+
include HDLRuby::High::Std
|
5
|
+
|
6
|
+
# Tries for matrix-vector product.
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
# Sample code for testing the linear library.
|
13
|
+
|
14
|
+
system :linear_test do
|
15
|
+
|
16
|
+
# Clock and reset.
|
17
|
+
inner :clk,:rst
|
18
|
+
|
19
|
+
# Request and acknoledge signals.
|
20
|
+
inner :req
|
21
|
+
[8].inner :ack
|
22
|
+
|
23
|
+
|
24
|
+
# Circuit for testing the scaling.
|
25
|
+
|
26
|
+
# Input memory
|
27
|
+
mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_scale_in)
|
28
|
+
# Output memory
|
29
|
+
mem_file([8],8,clk,rst, winc: :rst).(:mem_scale_out)
|
30
|
+
# Access ports.
|
31
|
+
mem_scale_in.branch(:anum).inner :mem_scale_inP
|
32
|
+
mem_scale_inPs = 8.times.map { |i| mem_scale_inP.wrap(i) }
|
33
|
+
mem_scale_out.branch(:anum).inner :mem_scale_outP
|
34
|
+
mem_scale_outPs = 8.times.map { |i| mem_scale_outP.wrap(i) }
|
35
|
+
|
36
|
+
# Build the scaler.
|
37
|
+
scale([8],clk.posedge,req,ack[0],channel_port(3),
|
38
|
+
mem_scale_inPs,mem_scale_outPs)
|
39
|
+
|
40
|
+
|
41
|
+
# Circuit for testing the parallel addition.
|
42
|
+
|
43
|
+
# Input memories
|
44
|
+
mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_left_in)
|
45
|
+
mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_addn_right_in)
|
46
|
+
# Output memory
|
47
|
+
mem_file([8],8,clk,rst, winc: :rst).(:mem_addn_out)
|
48
|
+
# Access ports.
|
49
|
+
mem_addn_left_in.branch(:anum).inner :mem_addn_left_inP
|
50
|
+
mem_addn_left_inPs = 8.times.map { |i| mem_addn_left_inP.wrap(i) }
|
51
|
+
mem_addn_right_in.branch(:anum).inner :mem_addn_right_inP
|
52
|
+
mem_addn_right_inPs = 8.times.map { |i| mem_addn_right_inP.wrap(i) }
|
53
|
+
mem_addn_out.branch(:anum).inner :mem_addn_outP
|
54
|
+
mem_addn_outPs = 8.times.map { |i| mem_addn_outP.wrap(i) }
|
55
|
+
|
56
|
+
# Build the adder.
|
57
|
+
add_n([8],clk.posedge,ack[0],ack[1],mem_addn_left_inPs,
|
58
|
+
mem_addn_right_inPs,mem_addn_outPs)
|
59
|
+
|
60
|
+
|
61
|
+
# Circuit for testing the parallel multiplication.
|
62
|
+
|
63
|
+
# Input memories
|
64
|
+
mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_left_in)
|
65
|
+
mem_file([8],8,clk,rst, rinc: :rst, winc: :rst).(:mem_muln_right_in)
|
66
|
+
# Output memory
|
67
|
+
mem_file([8],8,clk,rst, winc: :rst).(:mem_muln_out)
|
68
|
+
# Access ports.
|
69
|
+
mem_muln_left_in.branch(:anum).inner :mem_muln_left_inP
|
70
|
+
mem_muln_left_inPs = 8.times.map { |i| mem_muln_left_inP.wrap(i) }
|
71
|
+
mem_muln_right_in.branch(:anum).inner :mem_muln_right_inP
|
72
|
+
mem_muln_right_inPs = 8.times.map { |i| mem_muln_right_inP.wrap(i) }
|
73
|
+
mem_muln_out.branch(:anum).inner :mem_muln_outP
|
74
|
+
mem_muln_outPs = 8.times.map { |i| mem_muln_outP.wrap(i) }
|
75
|
+
|
76
|
+
# Build the multer.
|
77
|
+
mul_n([8],clk.posedge,ack[1],ack[2],mem_muln_left_inPs,
|
78
|
+
mem_muln_right_inPs,mem_muln_outPs)
|
79
|
+
|
80
|
+
|
81
|
+
# Circuit for testing the mac
|
82
|
+
# Output signal.
|
83
|
+
[8].inner :acc
|
84
|
+
|
85
|
+
# Build the mac.
|
86
|
+
mac([8],clk.posedge,ack[2],ack[3],channel_port(5), channel_port(6),
|
87
|
+
channel_port(acc))
|
88
|
+
|
89
|
+
|
90
|
+
# Circuit for testing the parallel mac.
|
91
|
+
# Input memory
|
92
|
+
mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_left_in)
|
93
|
+
# Output memory
|
94
|
+
mem_file([8],8,clk,rst, winc: :rst).(:mem_macn1_out)
|
95
|
+
# Access ports.
|
96
|
+
mem_macn1_left_in.branch(:anum).inner :mem_macn1_left_inP
|
97
|
+
mem_macn1_left_inPs = 8.times.map { |i| mem_macn1_left_inP.wrap(i) }
|
98
|
+
mem_macn1_out.branch(:anum).inner :mem_macn1_outP
|
99
|
+
mem_macn1_outPs = 8.times.map { |i| mem_macn1_outP.wrap(i) }
|
100
|
+
|
101
|
+
# Build the mac.
|
102
|
+
mac_n1([8],clk.posedge,ack[3],ack[4], mem_macn1_left_inPs,
|
103
|
+
channel_port(5), mem_macn1_outPs)
|
104
|
+
|
105
|
+
|
106
|
+
# The memory initializer.
|
107
|
+
# Writing ports
|
108
|
+
mem_scale_in.branch(:winc).inner :mem_scale_in_writeP
|
109
|
+
mem_addn_left_in.branch(:winc).inner :mem_addn_left_in_writeP
|
110
|
+
mem_addn_right_in.branch(:winc).inner :mem_addn_right_in_writeP
|
111
|
+
mem_muln_left_in.branch(:winc).inner :mem_muln_left_in_writeP
|
112
|
+
mem_muln_right_in.branch(:winc).inner :mem_muln_right_in_writeP
|
113
|
+
mem_macn1_left_in.branch(:winc).inner :mem_macn1_left_in_writeP
|
114
|
+
# Filling index
|
115
|
+
[8].inner :idx
|
116
|
+
# Filling counter
|
117
|
+
[3].inner :cnt
|
118
|
+
# Filling value
|
119
|
+
[8].inner :val
|
120
|
+
|
121
|
+
# Start flag
|
122
|
+
inner :start
|
123
|
+
|
124
|
+
# The execution process
|
125
|
+
par(clk.posedge) do
|
126
|
+
hif(rst) { cnt <= 0; val <= 0 }
|
127
|
+
helse do
|
128
|
+
# Step index processing.
|
129
|
+
hif(cnt == 7) do
|
130
|
+
hif(idx < 6) { idx <= idx + 1 }
|
131
|
+
end
|
132
|
+
# Memory filling steps.
|
133
|
+
hcase(idx)
|
134
|
+
hwhen(0) do
|
135
|
+
mem_scale_in_writeP.write(val) do
|
136
|
+
cnt <= cnt + 1; val <= val + 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
hwhen(1) do
|
140
|
+
mem_addn_left_in_writeP.write(val) do
|
141
|
+
cnt <= cnt + 1; val <= val + 1
|
142
|
+
end
|
143
|
+
end
|
144
|
+
hwhen(2) do
|
145
|
+
mem_addn_right_in_writeP.write(val) do
|
146
|
+
cnt <= cnt + 1; val <= val + 1
|
147
|
+
end
|
148
|
+
end
|
149
|
+
hwhen(3) do
|
150
|
+
mem_muln_left_in_writeP.write(val-24) do
|
151
|
+
cnt <= cnt + 1; val <= val + 1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
hwhen(4) do
|
155
|
+
mem_muln_right_in_writeP.write(val-24) do
|
156
|
+
cnt <= cnt + 1; val <= val + 1
|
157
|
+
end
|
158
|
+
end
|
159
|
+
hwhen(5) do
|
160
|
+
mem_macn1_left_in_writeP.write(val-32) do
|
161
|
+
cnt <= cnt + 1; val <= val + 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
# Computation steps.
|
165
|
+
helse do
|
166
|
+
hif(start) do
|
167
|
+
req <= 1
|
168
|
+
start <= 0
|
169
|
+
end
|
170
|
+
helse { req <= 0 }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# The test bench.
|
177
|
+
timed do
|
178
|
+
req <= 0
|
179
|
+
ack <= 0
|
180
|
+
clk <= 0
|
181
|
+
rst <= 0
|
182
|
+
cnt <= 0
|
183
|
+
idx <= 0
|
184
|
+
val <= 0
|
185
|
+
start <= 0
|
186
|
+
!10.ns
|
187
|
+
clk <= 1
|
188
|
+
!10.ns
|
189
|
+
# Reset
|
190
|
+
clk <= 0
|
191
|
+
rst <= 1
|
192
|
+
!10.ns
|
193
|
+
clk <= 1
|
194
|
+
!10.ns
|
195
|
+
clk <= 0
|
196
|
+
rst <= 0
|
197
|
+
start <= 1
|
198
|
+
!10.ns
|
199
|
+
# Run
|
200
|
+
64.times do
|
201
|
+
clk <= 1
|
202
|
+
!10.ns
|
203
|
+
clk <= 0
|
204
|
+
!10.ns
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'std/memory.rb'
|
2
|
+
require 'std/linear.rb'
|
3
|
+
|
4
|
+
include HDLRuby::High::Std
|
5
|
+
|
6
|
+
# Tries for matrix-vector product.
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
# Testing.
|
13
|
+
system :testmat do
|
14
|
+
|
15
|
+
inner :clk,:rst, :req
|
16
|
+
|
17
|
+
# Input memories
|
18
|
+
mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL0)
|
19
|
+
mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL1)
|
20
|
+
mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memR)
|
21
|
+
# Access ports.
|
22
|
+
memL0.branch(:rinc).inner :readL0
|
23
|
+
memL1.branch(:rinc).inner :readL1
|
24
|
+
memR.branch(:rinc).inner :readR
|
25
|
+
|
26
|
+
# Prepares the left and acc arrays.
|
27
|
+
lefts = [readL0, readL1]
|
28
|
+
|
29
|
+
# Accumulators memory.
|
30
|
+
mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
|
31
|
+
memAcc.branch(:anum).inner :accs
|
32
|
+
accs_out = [accs.wrap(0), accs.wrap(1)]
|
33
|
+
|
34
|
+
# Layer 0 ack.
|
35
|
+
inner :ack0
|
36
|
+
|
37
|
+
# Instantiate the matrix product.
|
38
|
+
mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
|
39
|
+
|
40
|
+
# Translation.
|
41
|
+
# Translation memory.
|
42
|
+
mem_file([8],2,clk,rst,winc: :rst).(:memT)
|
43
|
+
# Tarnslation result
|
44
|
+
mem_file([8],2,clk,rst,rinc: :rst).(:memF)
|
45
|
+
# Access ports.
|
46
|
+
memT.branch(:anum).inner :readT
|
47
|
+
memF.branch(:anum).inner :writeF
|
48
|
+
regRs = [ readT.wrap(0), readT.wrap(1) ]
|
49
|
+
regLs = [ accs.wrap(0), accs.wrap(1) ]
|
50
|
+
regs = [ writeF.wrap(0), writeF.wrap(1) ]
|
51
|
+
|
52
|
+
# Translater ack.
|
53
|
+
inner :ackT
|
54
|
+
|
55
|
+
# Instantiate the translater.
|
56
|
+
add_n([8],clk,ack0,ackT,regLs,regRs,regs)
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
# Second layer.
|
61
|
+
# Input memories.
|
62
|
+
mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
|
63
|
+
# Access ports.
|
64
|
+
mem2L0.branch(:rinc).inner :read2L0
|
65
|
+
# memAcc.branch(:rinc).inner :accsR
|
66
|
+
memF.branch(:rinc).inner :readF
|
67
|
+
|
68
|
+
# Second layer ack.
|
69
|
+
inner :ack1
|
70
|
+
|
71
|
+
# Result.
|
72
|
+
[8].inner :res
|
73
|
+
|
74
|
+
sub do
|
75
|
+
# Instantiate the second matrix product.
|
76
|
+
# mac([8],clk,req,read2L0,accsR,res)
|
77
|
+
mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
# The memory initializer.
|
83
|
+
memL0.branch(:winc).inner :writeL0
|
84
|
+
memL1.branch(:winc).inner :writeL1
|
85
|
+
memR.branch(:winc).inner :writeR
|
86
|
+
memT.branch(:winc).inner :writeT
|
87
|
+
mem2L0.branch(:winc).inner :write2L0
|
88
|
+
inner :fill, :fill2
|
89
|
+
[8].inner :val
|
90
|
+
par(clk.posedge) do
|
91
|
+
hif(fill) do
|
92
|
+
writeL0.write(val)
|
93
|
+
writeL1.write(val+1)
|
94
|
+
writeR.write(val+1)
|
95
|
+
end
|
96
|
+
hif(fill2) do
|
97
|
+
write2L0.write(val+2)
|
98
|
+
writeT.write(val+2)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
timed do
|
103
|
+
req <= 0
|
104
|
+
clk <= 0
|
105
|
+
rst <= 0
|
106
|
+
fill <= 0
|
107
|
+
fill2 <= 0
|
108
|
+
val <= 0
|
109
|
+
!10.ns
|
110
|
+
# Reset the memories.
|
111
|
+
rst <= 1
|
112
|
+
!10.ns
|
113
|
+
clk <= 1
|
114
|
+
!10.ns
|
115
|
+
# Fill the memories.
|
116
|
+
# First layer
|
117
|
+
clk <= 0
|
118
|
+
rst <= 0
|
119
|
+
fill <= 1
|
120
|
+
!10.ns
|
121
|
+
256.times do |i|
|
122
|
+
clk <= 1
|
123
|
+
!10.ns
|
124
|
+
clk <= 0
|
125
|
+
val <= val + 1
|
126
|
+
!10.ns
|
127
|
+
end
|
128
|
+
fill <= 0
|
129
|
+
clk <= 1
|
130
|
+
!10.ns
|
131
|
+
# Second layer
|
132
|
+
clk <= 0
|
133
|
+
rst <= 0
|
134
|
+
fill2 <= 1
|
135
|
+
!10.ns
|
136
|
+
2.times do |i|
|
137
|
+
clk <= 1
|
138
|
+
!10.ns
|
139
|
+
clk <= 0
|
140
|
+
val <= val + 1
|
141
|
+
!10.ns
|
142
|
+
end
|
143
|
+
fill2 <= 0
|
144
|
+
clk <= 1
|
145
|
+
!10.ns
|
146
|
+
clk <= 0
|
147
|
+
!10.ns
|
148
|
+
clk <= 1
|
149
|
+
!10.ns
|
150
|
+
clk <= 0
|
151
|
+
!10.ns
|
152
|
+
# Launch the computation
|
153
|
+
clk <= 0
|
154
|
+
req <= 1
|
155
|
+
!10.ns
|
156
|
+
300.times do
|
157
|
+
clk <= 1
|
158
|
+
!10.ns
|
159
|
+
clk <= 0
|
160
|
+
!10.ns
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/lib/HDLRuby/hruby_low.rb
CHANGED
@@ -3059,24 +3059,6 @@ module HDLRuby::Low
|
|
3059
3059
|
return [@value,@whens,@default].hash
|
3060
3060
|
end
|
3061
3061
|
|
3062
|
-
# # Adds a possible +match+ for the case's value that lead to the
|
3063
|
-
# # execution of +statement+.
|
3064
|
-
# def add_when(match,statement)
|
3065
|
-
# # Checks the match.
|
3066
|
-
# unless match.is_a?(Expression)
|
3067
|
-
# raise AnyError, "Invalid class for a case match: #{match.class}"
|
3068
|
-
# end
|
3069
|
-
# # Checks statement.
|
3070
|
-
# unless statement.is_a?(Statement)
|
3071
|
-
# raise AnyError, "Invalid class for a statement: #{statement.class}"
|
3072
|
-
# end
|
3073
|
-
# # Add the case.
|
3074
|
-
# @whens << [match,statement]
|
3075
|
-
# # And set their parents.
|
3076
|
-
# match.parent = statement.parent = self
|
3077
|
-
# [match,statement]
|
3078
|
-
# end
|
3079
|
-
|
3080
3062
|
# Adds possible when case +w+.
|
3081
3063
|
def add_when(w)
|
3082
3064
|
# Check +w+.
|
@@ -3178,7 +3160,7 @@ module HDLRuby::Low
|
|
3178
3160
|
# Clones the Case (deeply)
|
3179
3161
|
def clone
|
3180
3162
|
# Clone the default if any.
|
3181
|
-
|
3163
|
+
default = @default ? @default.clone : nil
|
3182
3164
|
# Clone the case.
|
3183
3165
|
return Case.new(@value.clone,default,(@whens.map do |w|
|
3184
3166
|
w.clone
|
@@ -1069,7 +1069,8 @@ module HDLRuby::Low
|
|
1069
1069
|
node2rep = node2reassign.map {|n,r| [n,r[0]] }.to_h
|
1070
1070
|
|
1071
1071
|
# First recurse on the sub blocks.
|
1072
|
-
self.each_block { |block| block.reassign_expressions!(node2rep) }
|
1072
|
+
# self.each_block { |block| block.reassign_expressions!(node2rep) }
|
1073
|
+
self.each_block { |block| block.reassign_expressions!(node2reassign) }
|
1073
1074
|
|
1074
1075
|
# Now work on the block.
|
1075
1076
|
# Replace on the statements.
|
data/lib/HDLRuby/sim/hruby_sim.h
CHANGED
@@ -205,6 +205,20 @@ Value shift_right_value(Value src0, Value src1, Value dst);
|
|
205
205
|
* @return dst */
|
206
206
|
extern Value equal_value(Value src0, Value src1, Value dst);
|
207
207
|
|
208
|
+
/** Computes the lesser comparision of two values.
|
209
|
+
* @param src0 the first source value of the addition
|
210
|
+
* @param src1 the second source value of the addition
|
211
|
+
* @param dst the destination value
|
212
|
+
* @return dst */
|
213
|
+
extern Value lesser_value(Value src0, Value src1, Value dst);
|
214
|
+
|
215
|
+
/** Computes the greater comparision of two values.
|
216
|
+
* @param src0 the first source value of the addition
|
217
|
+
* @param src1 the second source value of the addition
|
218
|
+
* @param dst the destination value
|
219
|
+
* @return dst */
|
220
|
+
extern Value greater_value(Value src0, Value src1, Value dst);
|
221
|
+
|
208
222
|
/** Selects a value depending on a condition.
|
209
223
|
* @param cond the condition to use for selecting a value
|
210
224
|
* @param dst the destination value
|
@@ -284,6 +284,11 @@ Value make_set_value(Type type, int numeric, void* data) {
|
|
284
284
|
// }
|
285
285
|
// }
|
286
286
|
|
287
|
+
/* Defined after.*/
|
288
|
+
static unsigned long long
|
289
|
+
fix_numeric_type(Type type, unsigned long long val);
|
290
|
+
|
291
|
+
|
287
292
|
/** Copies a value to another, the type of the destination is preserved.
|
288
293
|
* @param src the source value
|
289
294
|
* @param dst the destination value
|
@@ -296,7 +301,7 @@ Value copy_value(Value src, Value dst) {
|
|
296
301
|
/* Copy the data. */
|
297
302
|
if (src->numeric) {
|
298
303
|
/* Numeric copy. */
|
299
|
-
dst->data_int = src->data_int;
|
304
|
+
dst->data_int = fix_numeric_type(dst->type,src->data_int);
|
300
305
|
} else {
|
301
306
|
/* Resize the destination if required. */
|
302
307
|
resize_value(dst,type_width(dst->type));
|
@@ -617,6 +622,38 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
|
617
622
|
}
|
618
623
|
|
619
624
|
|
625
|
+
/** Computes the lesser comparision of two defined bitstring values.
|
626
|
+
* @param src0 the first source value of the addition
|
627
|
+
* @param src1 the second source value of the addition
|
628
|
+
* @param dst the destination value
|
629
|
+
* @return dst */
|
630
|
+
static Value lesser_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
631
|
+
/* Sets state of the destination using the first source. */
|
632
|
+
dst->type = src0->type;
|
633
|
+
dst->numeric = 1;
|
634
|
+
|
635
|
+
/* Perform the comparison. */
|
636
|
+
dst->data_int = (value2integer(src0) < value2integer(src1));
|
637
|
+
return dst;
|
638
|
+
}
|
639
|
+
|
640
|
+
|
641
|
+
/** Computes the greater comparision of two defined bitstring values.
|
642
|
+
* @param src0 the first source value of the addition
|
643
|
+
* @param src1 the second source value of the addition
|
644
|
+
* @param dst the destination value
|
645
|
+
* @return dst */
|
646
|
+
static Value greater_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
647
|
+
/* Sets state of the destination using the first source. */
|
648
|
+
dst->type = src0->type;
|
649
|
+
dst->numeric = 1;
|
650
|
+
|
651
|
+
/* Perform the comparison. */
|
652
|
+
dst->data_int = (value2integer(src0) > value2integer(src1));
|
653
|
+
return dst;
|
654
|
+
}
|
655
|
+
|
656
|
+
|
620
657
|
/** Computes the NOT of a bitstring value.
|
621
658
|
* @param src the source value of the not
|
622
659
|
* @param dst the destination value
|
@@ -1364,6 +1401,37 @@ Value write_range_bitstring_no_z(Value src, long long first, long long last,
|
|
1364
1401
|
|
1365
1402
|
/* ############# Start of the computation of numeric values. ############## */
|
1366
1403
|
|
1404
|
+
/** Fix the content of a numeric value according to its type so that
|
1405
|
+
* it can be used for C numeric computation.
|
1406
|
+
* @param type the type to fix the value to
|
1407
|
+
* @param val the value to fix
|
1408
|
+
* @return the rsulting value */
|
1409
|
+
static unsigned long long
|
1410
|
+
fix_numeric_type(Type type, unsigned long long val) {
|
1411
|
+
/* Get the width of the type. */
|
1412
|
+
int width = type_width(type);
|
1413
|
+
/* Compute the base mask. */
|
1414
|
+
unsigned long long mask = ((unsigned long long)(-1)) << width;
|
1415
|
+
// printf("width=%i val=%llu mask=%llx\n",width,val,mask);
|
1416
|
+
|
1417
|
+
/* Is the type signed? */
|
1418
|
+
if (type->flags.sign) {
|
1419
|
+
/* Yes, perform sign extension. */
|
1420
|
+
int is_neg = (val >> (width-1)) & 1;
|
1421
|
+
// printf("is_neg=%i\n",is_neg);
|
1422
|
+
if (is_neg) {
|
1423
|
+
/* Negative sign extension. */
|
1424
|
+
return val | mask;
|
1425
|
+
} else {
|
1426
|
+
/* Positive sign extension. */
|
1427
|
+
return val & ~mask;
|
1428
|
+
}
|
1429
|
+
} else {
|
1430
|
+
/* No, perform a zero extension. */
|
1431
|
+
return val & ~mask;
|
1432
|
+
}
|
1433
|
+
}
|
1434
|
+
|
1367
1435
|
|
1368
1436
|
/** Computes the neg of a numeric value.
|
1369
1437
|
* @param src the source value of the not
|
@@ -1375,7 +1443,7 @@ static Value neg_value_numeric(Value src, Value dst) {
|
|
1375
1443
|
dst->numeric = 1;
|
1376
1444
|
|
1377
1445
|
/* Perform the negation. */
|
1378
|
-
dst->data_int =
|
1446
|
+
dst->data_int = fix_numeric_type(dst->type,-src->data_int);
|
1379
1447
|
return dst;
|
1380
1448
|
}
|
1381
1449
|
|
@@ -1391,7 +1459,7 @@ static Value add_value_numeric(Value src0, Value src1, Value dst) {
|
|
1391
1459
|
dst->numeric = 1;
|
1392
1460
|
|
1393
1461
|
/* Perform the addition. */
|
1394
|
-
dst->data_int = src0->data_int + src1->data_int;
|
1462
|
+
dst->data_int = fix_numeric_type(dst->type,src0->data_int + src1->data_int);
|
1395
1463
|
return dst;
|
1396
1464
|
}
|
1397
1465
|
|
@@ -1407,7 +1475,7 @@ static Value sub_value_numeric(Value src0, Value src1, Value dst) {
|
|
1407
1475
|
dst->numeric = 1;
|
1408
1476
|
|
1409
1477
|
/* Perform the subtraction. */
|
1410
|
-
dst->data_int = src0->data_int - src1->data_int;
|
1478
|
+
dst->data_int = fix_numeric_type(dst->type,src0->data_int - src1->data_int);
|
1411
1479
|
return dst;
|
1412
1480
|
}
|
1413
1481
|
|
@@ -1422,8 +1490,8 @@ static Value mul_value_numeric(Value src0, Value src1, Value dst) {
|
|
1422
1490
|
dst->type = src0->type;
|
1423
1491
|
dst->numeric = 1;
|
1424
1492
|
|
1425
|
-
/* Perform the
|
1426
|
-
dst->data_int = src0->data_int * src1->data_int;
|
1493
|
+
/* Perform the multiplication. */
|
1494
|
+
dst->data_int = fix_numeric_type(dst->type, src0->data_int * src1->data_int);
|
1427
1495
|
return dst;
|
1428
1496
|
}
|
1429
1497
|
|
@@ -1438,8 +1506,8 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
|
|
1438
1506
|
dst->type = src0->type;
|
1439
1507
|
dst->numeric = 1;
|
1440
1508
|
|
1441
|
-
/* Perform the
|
1442
|
-
dst->data_int = src0->data_int / src1->data_int;
|
1509
|
+
/* Perform the division. */
|
1510
|
+
dst->data_int = fix_numeric_type(dst->type, src0->data_int / src1->data_int);
|
1443
1511
|
return dst;
|
1444
1512
|
}
|
1445
1513
|
|
@@ -1454,7 +1522,7 @@ static Value not_value_numeric(Value src, Value dst) {
|
|
1454
1522
|
dst->numeric = 1;
|
1455
1523
|
|
1456
1524
|
/* Perform the not. */
|
1457
|
-
dst->data_int =
|
1525
|
+
dst->data_int = fix_numeric_type(dst->type,!src->data_int);
|
1458
1526
|
return dst;
|
1459
1527
|
}
|
1460
1528
|
|
@@ -1518,7 +1586,7 @@ static Value shift_left_value_numeric(Value src0, Value src1, Value dst) {
|
|
1518
1586
|
dst->numeric = 1;
|
1519
1587
|
|
1520
1588
|
/* Perform the left shift. */
|
1521
|
-
dst->data_int = src0->data_int << src1->data_int;
|
1589
|
+
dst->data_int = fix_numeric_type(dst->type,src0->data_int << src1->data_int);
|
1522
1590
|
return dst;
|
1523
1591
|
}
|
1524
1592
|
|
@@ -1534,7 +1602,7 @@ static Value shift_right_value_numeric(Value src0, Value src1, Value dst) {
|
|
1534
1602
|
dst->numeric = 1;
|
1535
1603
|
|
1536
1604
|
/* Perform the right shift. */
|
1537
|
-
dst->data_int = src0->data_int >> src1->data_int;
|
1605
|
+
dst->data_int = fix_numeric_type(dst->type,src0->data_int >> src1->data_int);
|
1538
1606
|
return dst;
|
1539
1607
|
}
|
1540
1608
|
|
@@ -1555,6 +1623,37 @@ static Value equal_value_numeric(Value src0, Value src1, Value dst) {
|
|
1555
1623
|
}
|
1556
1624
|
|
1557
1625
|
|
1626
|
+
/** Computes the lesser comparision of two numeric values.
|
1627
|
+
* @param src0 the first source value of the addition
|
1628
|
+
* @param src1 the second source value of the addition
|
1629
|
+
* @param dst the destination value
|
1630
|
+
* @return the destination value */
|
1631
|
+
static Value lesser_value_numeric(Value src0, Value src1, Value dst) {
|
1632
|
+
/* Sets state of the destination using the first source. */
|
1633
|
+
dst->type = src0->type;
|
1634
|
+
dst->numeric = 1;
|
1635
|
+
|
1636
|
+
/* Perform the lesser. */
|
1637
|
+
dst->data_int = (src0->data_int < src1->data_int);
|
1638
|
+
return dst;
|
1639
|
+
}
|
1640
|
+
|
1641
|
+
/** Computes the greater comparision of two numeric values.
|
1642
|
+
* @param src0 the first source value of the addition
|
1643
|
+
* @param src1 the second source value of the addition
|
1644
|
+
* @param dst the destination value
|
1645
|
+
* @return the destination value */
|
1646
|
+
static Value greater_value_numeric(Value src0, Value src1, Value dst) {
|
1647
|
+
/* Sets state of the destination using the first source. */
|
1648
|
+
dst->type = src0->type;
|
1649
|
+
dst->numeric = 1;
|
1650
|
+
|
1651
|
+
/* Perform the lesser. */
|
1652
|
+
dst->data_int = (src0->data_int > src1->data_int);
|
1653
|
+
return dst;
|
1654
|
+
}
|
1655
|
+
|
1656
|
+
|
1558
1657
|
/** Selects a value depending on a numeric condition.
|
1559
1658
|
* @param cond the condition to use for selecting a value
|
1560
1659
|
* @param dst the destination value (used only if new value is created).
|
@@ -1719,6 +1818,7 @@ Value read_range_numeric(Value value, long long first, long long last,
|
|
1719
1818
|
* @return dst */
|
1720
1819
|
Value write_range_numeric(Value src, long long first, long long last,
|
1721
1820
|
Value dst) {
|
1821
|
+
// printf("write_range_numeric\n");
|
1722
1822
|
/* Ensure first is the smaller. */
|
1723
1823
|
if (first > last) {
|
1724
1824
|
long long tmp = last;
|
@@ -1730,6 +1830,7 @@ Value write_range_numeric(Value src, long long first, long long last,
|
|
1730
1830
|
unsigned long long dst_width = type_width(dst->type);
|
1731
1831
|
/* scale the range according to the base type of the destination. */
|
1732
1832
|
unsigned long long bw = dst->type->base;
|
1833
|
+
// printf("src_width=%llu dst_wdith=%llu bw=%llu\n",src_width,dst_width,bw);
|
1733
1834
|
first *= bw;
|
1734
1835
|
last *= bw;
|
1735
1836
|
/* If first is too large, end here. */
|
@@ -1737,11 +1838,13 @@ Value write_range_numeric(Value src, long long first, long long last,
|
|
1737
1838
|
/* Adjust the last to fit the source and destination range. */
|
1738
1839
|
if (last >= dst_width) last = dst_width-1;
|
1739
1840
|
if (last-first >= src_width) last = src_width + first - 1;
|
1841
|
+
// printf("first=%lld last=%lld\n",first,last);
|
1740
1842
|
/* Copy from the source. */
|
1741
|
-
unsigned long long src_data = src->data_int & ~((-1LL) << (last-first));
|
1843
|
+
unsigned long long src_data = src->data_int & ~((-1LL) << (last-first+1));
|
1742
1844
|
/* Cleans the destination where to place the data. */
|
1743
|
-
unsigned long long mask = ((-1LL) << first) & ~((-1LL) << last);
|
1845
|
+
unsigned long long mask = ~(((-1LL) << first) & ~((-1LL) << (last+1)));
|
1744
1846
|
unsigned long long dst_data = dst->data_int & mask;
|
1847
|
+
// printf("src_data=%llx mask=%llx dst_data=%llx\n",src_data,mask,dst_data);
|
1745
1848
|
/* Write the data. */
|
1746
1849
|
dst_data |= src_data << first;
|
1747
1850
|
dst->data_int = dst_data;
|
@@ -2111,6 +2214,60 @@ Value equal_value(Value src0, Value src1, Value dst) {
|
|
2111
2214
|
}
|
2112
2215
|
|
2113
2216
|
|
2217
|
+
/** Computes the lesser comparision of two general values.
|
2218
|
+
* @param src0 the first source value of the addition
|
2219
|
+
* @param src1 the second source value of the addition
|
2220
|
+
* @param dst the destination value
|
2221
|
+
* @return dst */
|
2222
|
+
Value lesser_value(Value src0, Value src1, Value dst) {
|
2223
|
+
/* Might allocate a new value so save the current pool state. */
|
2224
|
+
unsigned int pos = get_value_pos();
|
2225
|
+
/* Do a numeric computation if possible, otherwise fallback to bitstring
|
2226
|
+
* computation. */
|
2227
|
+
if (src0->numeric && src1->numeric) {
|
2228
|
+
/* Both sources are numeric. */
|
2229
|
+
return lesser_value_numeric(src0,src1,dst);
|
2230
|
+
} else if (is_defined_value(src0) && is_defined_value(src1)) {
|
2231
|
+
/* Both sources can be converted to numeric values. */
|
2232
|
+
return lesser_value_defined_bitstring(src0,src1,dst);
|
2233
|
+
} else {
|
2234
|
+
/* Cannot compute (for now), simply undefines the destination. */
|
2235
|
+
/* First ensure dst has the right shape. */
|
2236
|
+
copy_value(src0,dst);
|
2237
|
+
/* Then make it undefined. */
|
2238
|
+
set_undefined_bitstring(dst);
|
2239
|
+
}
|
2240
|
+
return dst;
|
2241
|
+
}
|
2242
|
+
|
2243
|
+
|
2244
|
+
/** Computes the greater comparision of two general values.
|
2245
|
+
* @param src0 the first source value of the addition
|
2246
|
+
* @param src1 the second source value of the addition
|
2247
|
+
* @param dst the destination value
|
2248
|
+
* @return dst */
|
2249
|
+
Value greater_value(Value src0, Value src1, Value dst) {
|
2250
|
+
/* Might allocate a new value so save the current pool state. */
|
2251
|
+
unsigned int pos = get_value_pos();
|
2252
|
+
/* Do a numeric computation if possible, otherwise fallback to bitstring
|
2253
|
+
* computation. */
|
2254
|
+
if (src0->numeric && src1->numeric) {
|
2255
|
+
/* Both sources are numeric. */
|
2256
|
+
return greater_value_numeric(src0,src1,dst);
|
2257
|
+
} else if (is_defined_value(src0) && is_defined_value(src1)) {
|
2258
|
+
/* Both sources can be converted to numeric values. */
|
2259
|
+
return greater_value_defined_bitstring(src0,src1,dst);
|
2260
|
+
} else {
|
2261
|
+
/* Cannot compute (for now), simply undefines the destination. */
|
2262
|
+
/* First ensure dst has the right shape. */
|
2263
|
+
copy_value(src0,dst);
|
2264
|
+
/* Then make it undefined. */
|
2265
|
+
set_undefined_bitstring(dst);
|
2266
|
+
}
|
2267
|
+
return dst;
|
2268
|
+
}
|
2269
|
+
|
2270
|
+
|
2114
2271
|
/** Selects a value depending on a general condition.
|
2115
2272
|
* @param cond the condition to use for selecting a value
|
2116
2273
|
* @param dst the destination value (used only if new value is created).
|
@@ -2460,6 +2617,7 @@ Value read_range(Value value, long long first, long long last, Type base,
|
|
2460
2617
|
* @param dst the destination value
|
2461
2618
|
* @return dst */
|
2462
2619
|
Value write_range(Value src, long long first, long long last, Value dst) {
|
2620
|
+
// printf("write_range\n");
|
2463
2621
|
/* Is the value numeric? */
|
2464
2622
|
if ((src->numeric) && (dst->numeric)) {
|
2465
2623
|
/* Yes, do a numeric range read. */
|
@@ -2485,6 +2643,7 @@ Value write_range(Value src, long long first, long long last, Value dst) {
|
|
2485
2643
|
* @param dst the destination value
|
2486
2644
|
* @return dst */
|
2487
2645
|
Value write_range_no_z(Value src, long long first, long long last, Value dst) {
|
2646
|
+
// printf("write_range_no_z\n");
|
2488
2647
|
/* Is the value numeric? */
|
2489
2648
|
if ((src->numeric) && (dst->numeric)) {
|
2490
2649
|
/* Yes, do a numeric range read. */
|
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -901,29 +901,77 @@ module HDLRuby::High::Std
|
|
901
901
|
end
|
902
902
|
|
903
903
|
|
904
|
-
|
905
|
-
|
904
|
+
# Wrapper to make an object run like a channel port.
|
905
|
+
class ChannelPortObject
|
906
|
+
# Create a new object wrapper for +obj+.
|
907
|
+
def initialize(obj)
|
908
|
+
@obj = obj
|
909
|
+
end
|
906
910
|
|
907
|
-
|
911
|
+
# Port read with arguments +args+ executing +ruby_block+ in
|
912
|
+
# case of success.
|
913
|
+
def read(*args,&ruby_block)
|
914
|
+
# Get the target from the arguments.
|
915
|
+
target = args.pop
|
916
|
+
# Is there any argument left?
|
917
|
+
unless (args.empty?) then
|
918
|
+
# There are arguments left, perform an array access.
|
919
|
+
target <= @obj[*args]
|
920
|
+
else
|
921
|
+
# There are no argument left, perform a direct access.
|
922
|
+
target <= @obj
|
923
|
+
end
|
924
|
+
# Execute the ruby_block if any.
|
925
|
+
ruby_block.call if ruby_block
|
926
|
+
end
|
908
927
|
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
928
|
+
# Port write with argumnet +Args+ executing +ruby_block+ in
|
929
|
+
# case of success.
|
930
|
+
def write(*args,&ruby_block)
|
931
|
+
# Get the value to write from the arguments.
|
932
|
+
value = args.pop
|
933
|
+
# Is there any argument left?
|
934
|
+
unless (args.empty?) then
|
935
|
+
# There are arguments left, perform an array access.
|
936
|
+
@obj[*args] <= value
|
937
|
+
else
|
938
|
+
# There are no argument left, perform a direct access.
|
939
|
+
@obj <= value
|
940
|
+
end
|
941
|
+
# Execute the ruby_block if any.
|
942
|
+
ruby_block.call if ruby_block
|
916
943
|
end
|
944
|
+
|
917
945
|
end
|
918
946
|
|
919
947
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
# any.
|
924
|
-
def write(target,&ruby_block)
|
925
|
-
self <= target
|
926
|
-
ruby_block.call if ruby_block
|
927
|
-
end
|
948
|
+
# Wrap object +obj+ to act like a channel port.
|
949
|
+
def channel_port(obj)
|
950
|
+
return ChannelPortObject.new(obj)
|
928
951
|
end
|
929
952
|
end
|
953
|
+
|
954
|
+
|
955
|
+
# module HDLRuby::High
|
956
|
+
#
|
957
|
+
# ## Enhance expressions with possibility to act like a reading branch.
|
958
|
+
# module HExpression
|
959
|
+
# ## Transmits the expression to +target+ and execute +ruby_block+ if
|
960
|
+
# # any.
|
961
|
+
# def read(target,&ruby_block)
|
962
|
+
# target <= self
|
963
|
+
# ruby_block.call if ruby_block
|
964
|
+
# end
|
965
|
+
# end
|
966
|
+
#
|
967
|
+
#
|
968
|
+
# ## Enhance references with possibility to act like a writing branch.
|
969
|
+
# module HRef
|
970
|
+
# ## Transmits +target+ to the reference and execute +ruby_block+ if
|
971
|
+
# # any.
|
972
|
+
# def write(target,&ruby_block)
|
973
|
+
# self <= target
|
974
|
+
# ruby_block.call if ruby_block
|
975
|
+
# end
|
976
|
+
# end
|
977
|
+
# end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
module HDLRuby::High::Std
|
2
|
+
|
3
|
+
|
4
|
+
##
|
5
|
+
# Standard HDLRuby::High library: linear algebra functions.
|
6
|
+
#
|
7
|
+
# NOTE: require channel-like interface.
|
8
|
+
#
|
9
|
+
########################################################################
|
10
|
+
|
11
|
+
|
12
|
+
# Delcares a vector product by a scalar value.
|
13
|
+
#
|
14
|
+
# Can be used for scaling a vector.
|
15
|
+
function :scale do |typ,ev,req,ack,left,rights,prods,
|
16
|
+
mul = proc { |x,y| x*y }|
|
17
|
+
# Ensure ev is really an event.
|
18
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
19
|
+
# Ensures rights and prods are arrays.
|
20
|
+
rights = rights.to_a
|
21
|
+
prods = prods.to_a
|
22
|
+
# Left value (the scale) and right value.
|
23
|
+
typ.inner :lv
|
24
|
+
rvs = rights.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
|
25
|
+
# lv and rv are valid.
|
26
|
+
inner :lvok
|
27
|
+
rvoks = rights.each_with_index.map { |left,i| inner :"rvok#{i}" }
|
28
|
+
# Run flag
|
29
|
+
inner :run
|
30
|
+
par(ev) do
|
31
|
+
ack <= 0
|
32
|
+
run <= 0
|
33
|
+
hif(req | run) do
|
34
|
+
run <= 1
|
35
|
+
# Computation request.
|
36
|
+
left.read(lv) { lvok <= 1 }
|
37
|
+
rights.each_with_index do |right,i|
|
38
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
39
|
+
hif(lvok & rvoks[i]) do
|
40
|
+
ack <= 1
|
41
|
+
run <= 0
|
42
|
+
prods[i].write(mul.(lv,rvs[i]))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
helse do
|
47
|
+
lvok <= 0
|
48
|
+
rights.each_with_index do |right,i|
|
49
|
+
rvoks[i] <= 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# Declares a 1-dimension vector adder.
|
57
|
+
#
|
58
|
+
# Can be used for the sum of two vectors.
|
59
|
+
function :add_n do |typ,ev,req,ack,lefts, rights, sums,
|
60
|
+
add = proc { |x,y| x+y }|
|
61
|
+
# Ensure ev is really an event.
|
62
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
63
|
+
# Ensures lefts and rights and sums are arrays.
|
64
|
+
lefts = lefts.to_a
|
65
|
+
rights = rights.to_a
|
66
|
+
sums = sums.to_a
|
67
|
+
# Left value and right value.
|
68
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
69
|
+
rvs = lefts.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
|
70
|
+
# lv and rv are valid.
|
71
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
72
|
+
rvoks = lefts.each_with_index.map { |left,i| inner :"rvok#{i}" }
|
73
|
+
# Run flag.
|
74
|
+
inner :run
|
75
|
+
par(ev) do
|
76
|
+
ack <= 0
|
77
|
+
run <= 0
|
78
|
+
hif(req | run) do
|
79
|
+
run <= 1
|
80
|
+
# Computation request.
|
81
|
+
lefts.zip(rights).each_with_index do |(left,right),i|
|
82
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
83
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
84
|
+
hif(lvoks[i] & rvoks[i]) do
|
85
|
+
run <= 0
|
86
|
+
ack <= 1
|
87
|
+
sums[i].write(add.(lvs[i],rvs[i]))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
helse do
|
92
|
+
lefts.each_with_index do |left,i|
|
93
|
+
lvoks[i] <= 0
|
94
|
+
rvoks[i] <= 0
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Declares a 1-dimension vector element-wise multiplier.
|
101
|
+
function :mul_n do |typ,ev,req,ack,lefts, rights, prods,
|
102
|
+
mul = proc { |x,y| x*y }|
|
103
|
+
add_n(typ,ev,req,ack,lefts,rights,prods,mul)
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# Declares a simple multiplier accumulator.
|
108
|
+
#
|
109
|
+
# Can be used for the scalar product of two vectors.
|
110
|
+
function :mac do |typ,ev,req,ack,left, right, acc,
|
111
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
112
|
+
# Ensure ev is really an event.
|
113
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
114
|
+
# Left value and right value.
|
115
|
+
typ.inner :lv, :rv, :av
|
116
|
+
# lv and rv are valid.
|
117
|
+
inner :lvok, :rvok
|
118
|
+
# Run flag
|
119
|
+
inner :run
|
120
|
+
par(ev) do
|
121
|
+
ack <= 0
|
122
|
+
run <= 0
|
123
|
+
hif(req | run) do
|
124
|
+
run <= 1
|
125
|
+
# Computation request.
|
126
|
+
left.read(lv) { lvok <= 1 }
|
127
|
+
right.read(rv) { rvok <= 1 }
|
128
|
+
# ( acc <= add.(acc,mul.(lv,rv)) ).hif(lvok & rvok)
|
129
|
+
acc.read(av)
|
130
|
+
hif(lvok & rvok) do
|
131
|
+
ack <= 1
|
132
|
+
run <= 0
|
133
|
+
acc.write(add.(av,mul.(lv,rv)))
|
134
|
+
end
|
135
|
+
end
|
136
|
+
helse do
|
137
|
+
lvok <= 0
|
138
|
+
rvok <= 0
|
139
|
+
acc.write(0)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
# Declares a simple multiple mac with single right data.
|
146
|
+
#
|
147
|
+
# Can be used for the product of a martix-vector product.
|
148
|
+
function :mac_n1 do |typ,ev,req,ack,lefts, right, accs,
|
149
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
150
|
+
# Ensure ev is really an event.
|
151
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
152
|
+
# Ensures lefts is an array.
|
153
|
+
lefts = lefts.to_a
|
154
|
+
# Ensures accs is an array.
|
155
|
+
accs = accs.to_a
|
156
|
+
# Left value and right value.
|
157
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
158
|
+
# Accumutated values.
|
159
|
+
avs = lefts.each_with_index.map { |left,i| typ.inner :"av#{i}" }
|
160
|
+
typ.inner :rv
|
161
|
+
# lv and rv are valid.
|
162
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
163
|
+
inner :rvok
|
164
|
+
# Run flag
|
165
|
+
inner :run
|
166
|
+
par(ev) do
|
167
|
+
ack <= 0
|
168
|
+
run <= 0
|
169
|
+
hif(req | run) do
|
170
|
+
run <= 1
|
171
|
+
# Computation request.
|
172
|
+
right.read(rv) { rvok <= 1 }
|
173
|
+
lefts.each_with_index do |left,i|
|
174
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
175
|
+
# accs.read(i,avs[i])
|
176
|
+
accs[i].read(avs[i])
|
177
|
+
hif(lvoks[i] & rvok) do
|
178
|
+
ack <= 1
|
179
|
+
run <= 0
|
180
|
+
# accs.write(i,add.(avs[i],mul.(lvs[i],rv)))
|
181
|
+
accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
helse do
|
186
|
+
rvok <= 0
|
187
|
+
lefts.each_with_index do |left,i|
|
188
|
+
lvoks[i] <= 0
|
189
|
+
# accs.write(i,0)
|
190
|
+
accs[i].write(0)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
end
|
data/lib/HDLRuby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: HDLRuby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.15
|
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-03-
|
11
|
+
date: 2020-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- lib/HDLRuby/hdr_samples/dff_counter.rb
|
83
83
|
- lib/HDLRuby/hdr_samples/include.rb
|
84
84
|
- lib/HDLRuby/hdr_samples/instance_open.rb
|
85
|
+
- lib/HDLRuby/hdr_samples/linear_test.rb
|
85
86
|
- lib/HDLRuby/hdr_samples/mei8.rb
|
86
87
|
- lib/HDLRuby/hdr_samples/mei8_bench.rb
|
87
88
|
- lib/HDLRuby/hdr_samples/memory_test.rb
|
@@ -118,6 +119,7 @@ files:
|
|
118
119
|
- lib/HDLRuby/hdr_samples/with_decoder.rb
|
119
120
|
- lib/HDLRuby/hdr_samples/with_fixpoint.rb
|
120
121
|
- lib/HDLRuby/hdr_samples/with_fsm.rb
|
122
|
+
- lib/HDLRuby/hdr_samples/with_linear.rb
|
121
123
|
- lib/HDLRuby/hdr_samples/with_memory.rb
|
122
124
|
- lib/HDLRuby/hdr_samples/with_reconf.rb
|
123
125
|
- lib/HDLRuby/hdrcc.rb
|
@@ -266,6 +268,7 @@ files:
|
|
266
268
|
- lib/HDLRuby/std/decoder.rb
|
267
269
|
- lib/HDLRuby/std/fixpoint.rb
|
268
270
|
- lib/HDLRuby/std/fsm.rb
|
271
|
+
- lib/HDLRuby/std/linear.rb
|
269
272
|
- lib/HDLRuby/std/memory.rb
|
270
273
|
- lib/HDLRuby/std/pipeline.rb
|
271
274
|
- lib/HDLRuby/std/reconf.rb
|