HDLRuby 2.2.14 → 2.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|