HDLRuby 2.2.14 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -8
- data/lib/HDLRuby/hdr_samples/linear_test.rb +235 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +2 -2
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +3 -2
- data/lib/HDLRuby/hdr_samples/with_linear.rb +166 -0
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hdrcc.rb +1 -1
- data/lib/HDLRuby/hruby_high.rb +12 -4
- data/lib/HDLRuby/hruby_low.rb +25 -28
- data/lib/HDLRuby/hruby_low2c.rb +10 -5
- data/lib/HDLRuby/hruby_low2high.rb +1 -1
- data/lib/HDLRuby/hruby_low2vhd.rb +63 -48
- data/lib/HDLRuby/hruby_low_fix_types.rb +6 -2
- data/lib/HDLRuby/hruby_low_mutable.rb +2 -1
- data/lib/HDLRuby/hruby_low_resolve.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/hruby_verilog.rb +9 -1
- data/lib/HDLRuby/sim/hruby_sim.h +21 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +254 -18
- data/lib/HDLRuby/std/channel.rb +103 -32
- data/lib/HDLRuby/std/fixpoint.rb +15 -6
- data/lib/HDLRuby/std/linear.rb +317 -0
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1000 -30
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +9 -2
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -81,9 +81,17 @@ module HDLRuby::High::Std
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
-
##
|
85
|
-
# Module for wrapping channel ports.
|
86
|
-
module ChannelPortWrapping
|
84
|
+
# ##
|
85
|
+
# # Module for wrapping channel ports.
|
86
|
+
# module ChannelPortWrapping
|
87
|
+
# # Wrap with +args+ arguments.
|
88
|
+
# def wrap(*args)
|
89
|
+
# return ChannelPortB.new(self,*args)
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
|
93
|
+
## Describes a channel port.
|
94
|
+
class ChannelPort
|
87
95
|
# Wrap with +args+ arguments.
|
88
96
|
def wrap(*args)
|
89
97
|
return ChannelPortB.new(self,*args)
|
@@ -93,8 +101,8 @@ module HDLRuby::High::Std
|
|
93
101
|
|
94
102
|
##
|
95
103
|
# Describes a read port to a channel.
|
96
|
-
class ChannelPortR
|
97
|
-
include ChannelPortWrapping
|
104
|
+
class ChannelPortR < ChannelPort
|
105
|
+
# include ChannelPortWrapping
|
98
106
|
|
99
107
|
# Creates a new channel reader running in +namespace+ and
|
100
108
|
# reading using +reader_proc+ and reseting using +reseter_proc+.
|
@@ -137,8 +145,8 @@ module HDLRuby::High::Std
|
|
137
145
|
|
138
146
|
##
|
139
147
|
# Describes a writer port to a channel.
|
140
|
-
class ChannelPortW
|
141
|
-
include ChannelPortWrapping
|
148
|
+
class ChannelPortW < ChannelPort
|
149
|
+
# include ChannelPortWrapping
|
142
150
|
|
143
151
|
# Creates a new channel writer running in +namespace+ and
|
144
152
|
# writing using +writer_proc+ and reseting using +reseter_proc+.
|
@@ -181,8 +189,8 @@ module HDLRuby::High::Std
|
|
181
189
|
|
182
190
|
##
|
183
191
|
# Describes an access port to a channel.
|
184
|
-
class ChannelPortA
|
185
|
-
include ChannelPortWrapping
|
192
|
+
class ChannelPortA < ChannelPort
|
193
|
+
# include ChannelPortWrapping
|
186
194
|
|
187
195
|
# Creates a new channel accesser running in +namespace+
|
188
196
|
# and reading using +reader_proc+, writing using +writer_proc+,
|
@@ -243,8 +251,8 @@ module HDLRuby::High::Std
|
|
243
251
|
|
244
252
|
##
|
245
253
|
# Describes port wrapper (Box) for fixing arugments.
|
246
|
-
class ChannelPortB
|
247
|
-
include ChannelPortWrapping
|
254
|
+
class ChannelPortB < ChannelPort
|
255
|
+
# include ChannelPortWrapping
|
248
256
|
|
249
257
|
# Creates a new channel box over channel port +port+ fixing +args+
|
250
258
|
# as arguments.
|
@@ -600,13 +608,23 @@ module HDLRuby::High::Std
|
|
600
608
|
|
601
609
|
# Defines a branch in the channel named +name+ built executing
|
602
610
|
# +ruby_block+.
|
603
|
-
|
611
|
+
# Alternatively, a ready channel instance can be passed as argument
|
612
|
+
# as +channelI+.
|
613
|
+
def brancher(name,channelI = nil,&ruby_block)
|
604
614
|
# Ensure name is a symbol.
|
605
615
|
name = name.to_s unless name.respond_to?(:to_sym)
|
606
616
|
name = name.to_sym
|
607
|
-
#
|
608
|
-
channelI
|
617
|
+
# Is there a ready channel instance.
|
618
|
+
if channelI then
|
619
|
+
# Yes, use it directly.
|
620
|
+
@branches[name] = channelI
|
621
|
+
return self
|
622
|
+
end
|
623
|
+
# No, create the branch.
|
624
|
+
# channelI = HDLRuby::High.channel_instance(name, &ruby_block)
|
625
|
+
channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
|
609
626
|
@branches[name] = channelI
|
627
|
+
return self
|
610
628
|
end
|
611
629
|
|
612
630
|
|
@@ -619,6 +637,7 @@ module HDLRuby::High::Std
|
|
619
637
|
name = name.to_s unless name.respond_to?(:to_sym)
|
620
638
|
name = name.to_sym
|
621
639
|
# Get the branch.
|
640
|
+
channelI = @branches[name]
|
622
641
|
return @branches[name]
|
623
642
|
end
|
624
643
|
|
@@ -901,29 +920,81 @@ module HDLRuby::High::Std
|
|
901
920
|
end
|
902
921
|
|
903
922
|
|
904
|
-
|
905
|
-
|
923
|
+
# Wrapper to make an object run like a channel port.
|
924
|
+
class ChannelPortObject < ChannelPort
|
925
|
+
# Create a new object wrapper for +obj+.
|
926
|
+
def initialize(obj)
|
927
|
+
@obj = obj
|
928
|
+
end
|
906
929
|
|
907
|
-
|
930
|
+
# Port read with arguments +args+ executing +ruby_block+ in
|
931
|
+
# case of success.
|
932
|
+
def read(*args,&ruby_block)
|
933
|
+
# Get the target from the arguments.
|
934
|
+
target = args.pop
|
935
|
+
# Is there any argument left?
|
936
|
+
unless (args.empty?) then
|
937
|
+
# There are arguments left, perform an array access.
|
938
|
+
target <= @obj[*args]
|
939
|
+
else
|
940
|
+
# There are no argument left, perform a direct access.
|
941
|
+
target <= @obj
|
942
|
+
end
|
943
|
+
# Execute the ruby_block if any.
|
944
|
+
ruby_block.call if ruby_block
|
945
|
+
end
|
908
946
|
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
947
|
+
# Port write with argumnet +Args+ executing +ruby_block+ in
|
948
|
+
# case of success.
|
949
|
+
def write(*args,&ruby_block)
|
950
|
+
# Get the value to write from the arguments.
|
951
|
+
value = args.pop
|
952
|
+
# Is there any argument left?
|
953
|
+
unless (args.empty?) then
|
954
|
+
# There are arguments left, perform an array access.
|
955
|
+
@obj[*args] <= value
|
956
|
+
else
|
957
|
+
# There are no argument left, perform a direct access.
|
958
|
+
@obj <= value
|
959
|
+
end
|
960
|
+
# Execute the ruby_block if any.
|
961
|
+
ruby_block.call if ruby_block
|
916
962
|
end
|
963
|
+
|
917
964
|
end
|
918
965
|
|
919
966
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
end
|
967
|
+
# Wrap object +obj+ to act like a channel port.
|
968
|
+
def self.channel_port(obj)
|
969
|
+
return obj if obj.is_a?(ChannelPort) # No need to wrap.
|
970
|
+
return ChannelPortObject.new(obj)
|
971
|
+
end
|
972
|
+
def channel_port(obj)
|
973
|
+
return HDLRuby::High::Std.channel_port(obj)
|
928
974
|
end
|
929
975
|
end
|
976
|
+
|
977
|
+
|
978
|
+
# module HDLRuby::High
|
979
|
+
#
|
980
|
+
# ## Enhance expressions with possibility to act like a reading branch.
|
981
|
+
# module HExpression
|
982
|
+
# ## Transmits the expression to +target+ and execute +ruby_block+ if
|
983
|
+
# # any.
|
984
|
+
# def read(target,&ruby_block)
|
985
|
+
# target <= self
|
986
|
+
# ruby_block.call if ruby_block
|
987
|
+
# end
|
988
|
+
# end
|
989
|
+
#
|
990
|
+
#
|
991
|
+
# ## Enhance references with possibility to act like a writing branch.
|
992
|
+
# module HRef
|
993
|
+
# ## Transmits +target+ to the reference and execute +ruby_block+ if
|
994
|
+
# # any.
|
995
|
+
# def write(target,&ruby_block)
|
996
|
+
# self <= target
|
997
|
+
# ruby_block.call if ruby_block
|
998
|
+
# end
|
999
|
+
# end
|
1000
|
+
# end
|
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -26,17 +26,18 @@ module HDLRuby::High::Std
|
|
26
26
|
if args.size == 1 then
|
27
27
|
return self.send(:"_[]_fixpoint",*args)
|
28
28
|
else
|
29
|
-
# Handle the arguments.
|
29
|
+
# Handle the arguments and compute the fix point sizes.
|
30
30
|
arg0,arg1 = *args
|
31
31
|
if arg0.respond_to?(:to_i) then
|
32
|
-
|
32
|
+
isize = arg0
|
33
|
+
else
|
34
|
+
isize = (arg0.first-arg0.last).abs+1
|
33
35
|
end
|
34
36
|
if arg1.respond_to?(:to_i) then
|
35
|
-
|
37
|
+
fsize = arg1
|
38
|
+
else
|
39
|
+
fsize = (arg1.first-arg1.last).abs+1
|
36
40
|
end
|
37
|
-
# Compute the fix point sizes.
|
38
|
-
isize = (arg0.first-arg0.last).abs+1
|
39
|
-
fsize = (arg1.first-arg1.last).abs+1
|
40
41
|
# Build the type.
|
41
42
|
case(self.name)
|
42
43
|
when :bit
|
@@ -62,6 +63,14 @@ module HDLRuby::High::Std
|
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
66
|
+
# Extends the Numeric class for conversion to fixed point litteral.
|
67
|
+
class ::Numeric
|
68
|
+
# Convert to fixed point value with +dec+ digits after the decimal
|
69
|
+
# point.
|
70
|
+
def to_fix(dec)
|
71
|
+
return (self * (2**dec.to_i)).to_i
|
72
|
+
end
|
73
|
+
end
|
65
74
|
|
66
75
|
|
67
76
|
end
|
@@ -0,0 +1,317 @@
|
|
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
|
+
# Controller of the linear operator.
|
12
|
+
# - +num+: the number of computation cycles.
|
13
|
+
# - +ev+: event to synchronize the controller on.
|
14
|
+
# - +req+: the request to start the linear computation.
|
15
|
+
# - +ack+: the ack signal that is set to 1 when the computation completes.
|
16
|
+
# - +ruby_block+: the code of the linear computation kernel, it takes
|
17
|
+
# as argument +ev+, and its own req and ack signals
|
18
|
+
# (resp. +req_ker+ +ack_ker+).
|
19
|
+
function :linearun do |num,ev,req,ack,ruby_block|
|
20
|
+
# Ensure ev is really an event.
|
21
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
22
|
+
|
23
|
+
# Creates the kernel.
|
24
|
+
inner :req_ker, :ack_ker
|
25
|
+
|
26
|
+
HDLRuby::High.top_user.instance_exec(ev,req_ker,ack_ker,&ruby_block)
|
27
|
+
|
28
|
+
# The computation counter.
|
29
|
+
[num.width].inner :count
|
30
|
+
# Run flag
|
31
|
+
inner :run
|
32
|
+
par(ev) do
|
33
|
+
req_ker <= 0
|
34
|
+
ack <= 0
|
35
|
+
count <= 1
|
36
|
+
run <= 0
|
37
|
+
hif(req | run) do
|
38
|
+
run <= 1
|
39
|
+
req_ker <= 1
|
40
|
+
# Is one linear computation completed?
|
41
|
+
hif(ack_ker) do
|
42
|
+
# Yes.
|
43
|
+
count <= count + 1
|
44
|
+
end
|
45
|
+
# Is the full computation completed?
|
46
|
+
hif(count == num) do
|
47
|
+
# Yes.
|
48
|
+
ack <= 1
|
49
|
+
run <= 0
|
50
|
+
req_ker <= 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Delcares a vector product by a scalar value.
|
58
|
+
#
|
59
|
+
# Can be used for scaling a vector.
|
60
|
+
function :scale do |typ,ev,req,ack,left,rights,prods,
|
61
|
+
mul = proc { |x,y| x*y }|
|
62
|
+
# Ensure ev is really an event.
|
63
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
64
|
+
# Ensures rights and prods are arrays.
|
65
|
+
rights = rights.to_a
|
66
|
+
prods = prods.to_a
|
67
|
+
# Left value (the scale) and right value.
|
68
|
+
typ.inner :lv
|
69
|
+
rvs = rights.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
|
70
|
+
# lv and rv are valid.
|
71
|
+
inner :lvok
|
72
|
+
rvoks = rights.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
|
+
left.read(lv) { lvok <= 1 }
|
82
|
+
rights.each_with_index do |right,i|
|
83
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
84
|
+
hif(lvok & rvoks[i]) do
|
85
|
+
ack <= 1
|
86
|
+
run <= 0
|
87
|
+
prods[i].write(mul.(lv,rvs[i]))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
helse do
|
92
|
+
lvok <= 0
|
93
|
+
rights.each_with_index do |right,i|
|
94
|
+
rvoks[i] <= 0
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Declares a 1-dimension vector adder.
|
102
|
+
#
|
103
|
+
# Can be used for the sum of two vectors.
|
104
|
+
function :add_n do |typ,ev,req,ack,lefts, rights, sums,
|
105
|
+
add = proc { |x,y| x+y }|
|
106
|
+
# Ensure ev is really an event.
|
107
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
108
|
+
# Ensures lefts and rights and sums are arrays.
|
109
|
+
lefts = lefts.to_a
|
110
|
+
rights = rights.to_a
|
111
|
+
sums = sums.to_a
|
112
|
+
# Left value and right value.
|
113
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
114
|
+
rvs = lefts.each_with_index.map { |left,i| typ.inner :"rv#{i}" }
|
115
|
+
# lv and rv are valid.
|
116
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
117
|
+
rvoks = lefts.each_with_index.map { |left,i| inner :"rvok#{i}" }
|
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
|
+
lefts.zip(rights).each_with_index do |(left,right),i|
|
127
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
128
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
129
|
+
hif(lvoks[i] & rvoks[i]) do
|
130
|
+
run <= 0
|
131
|
+
ack <= 1
|
132
|
+
sums[i].write(add.(lvs[i],rvs[i]))
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
helse do
|
137
|
+
lefts.each_with_index do |left,i|
|
138
|
+
lvoks[i] <= 0
|
139
|
+
rvoks[i] <= 0
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Declares a 1-dimension vector element-wise multiplier.
|
146
|
+
function :mul_n do |typ,ev,req,ack,lefts, rights, prods,
|
147
|
+
mul = proc { |x,y| x*y }|
|
148
|
+
add_n(typ,ev,req,ack,lefts,rights,prods,mul)
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
# Declares a simple multiplier accumulator.
|
153
|
+
#
|
154
|
+
# Can be used for the scalar product of two vectors.
|
155
|
+
function :mac do |typ,ev,req,ack,left, right, acc,
|
156
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
157
|
+
# Ensure ev is really an event.
|
158
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
159
|
+
# Left value, right value and computation temp value.
|
160
|
+
typ.inner :lv, :rv, :av
|
161
|
+
# lv and rv are valid.
|
162
|
+
inner :lvok, :rvok
|
163
|
+
# Run flag
|
164
|
+
inner :run
|
165
|
+
par(ev) do
|
166
|
+
ack <= 0
|
167
|
+
run <= 0
|
168
|
+
hif(req | run) do
|
169
|
+
run <= 1
|
170
|
+
# Computation request.
|
171
|
+
left.read(lv) { lvok <= 1 }
|
172
|
+
right.read(rv) { rvok <= 1 }
|
173
|
+
hif(lvok & rvok) do
|
174
|
+
ack <= 1
|
175
|
+
run <= 0
|
176
|
+
# acc.write(add.(av,mul.(lv,rv)))
|
177
|
+
seq do
|
178
|
+
av <= add.(av,mul.(lv,rv))
|
179
|
+
acc.write(av)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
helse do
|
184
|
+
lvok <= 0
|
185
|
+
rvok <= 0
|
186
|
+
# acc.write(0)
|
187
|
+
av <= 0
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
# Declares a simple multiple mac with single right data.
|
194
|
+
#
|
195
|
+
# Can be used for the product of a martix-vector product.
|
196
|
+
function :mac_n1 do |typ,ev,req,ack,lefts, right, accs,
|
197
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
198
|
+
# Ensure ev is really an event.
|
199
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
200
|
+
# Ensures lefts is an array.
|
201
|
+
lefts = lefts.to_a
|
202
|
+
# Ensures accs is an array.
|
203
|
+
accs = accs.to_a
|
204
|
+
# Left value and right value.
|
205
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
206
|
+
# Accumutated values.
|
207
|
+
avs = lefts.each_with_index.map { |left,i| typ.inner :"av#{i}" }
|
208
|
+
typ.inner :rv
|
209
|
+
# lv and rv are valid.
|
210
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
211
|
+
inner :rvok
|
212
|
+
# Run flag
|
213
|
+
inner :run
|
214
|
+
par(ev) do
|
215
|
+
ack <= 0
|
216
|
+
run <= 0
|
217
|
+
hif(req | run) do
|
218
|
+
run <= 1
|
219
|
+
# Computation request.
|
220
|
+
right.read(rv) { rvok <= 1 }
|
221
|
+
lefts.each_with_index do |left,i|
|
222
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
223
|
+
# accs[i].read(avs[i])
|
224
|
+
hif(lvoks[i] & rvok) do
|
225
|
+
ack <= 1
|
226
|
+
run <= 0
|
227
|
+
# accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
|
228
|
+
seq do
|
229
|
+
avs[i] <= add.(avs[i],mul.(lvs[i],rv))
|
230
|
+
accs[i].write(avs[i])
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
helse do
|
236
|
+
rvok <= 0
|
237
|
+
lefts.each_with_index do |left,i|
|
238
|
+
lvoks[i] <= 0
|
239
|
+
# accs[i].write(0)
|
240
|
+
avs[i] <= 0
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
# Declares a simple pipelined multiple mac with single right data.
|
248
|
+
#
|
249
|
+
# Can be used for the product of a martix-vector product.
|
250
|
+
function :mac_np do |typ,ev,req,ack,lefts, rights, last,
|
251
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
252
|
+
# Ensure ev is really an event.
|
253
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
254
|
+
# Ensures lefts is an array.
|
255
|
+
lefts = lefts.to_a
|
256
|
+
# Ensures rights is an array.
|
257
|
+
rights = rights.to_a
|
258
|
+
# Get the size of the pipeline and ensure lefts and rights have the
|
259
|
+
# same.
|
260
|
+
size = lefts.size
|
261
|
+
if (rights.size != size) then
|
262
|
+
raise "Incompatible lefts and rights sizes: lefts size is #{size} and rights size is #{rights.size}"
|
263
|
+
end
|
264
|
+
# Declares the accumulators.
|
265
|
+
accs = size.times.map { |i| typ.inner :"acc#{i}" }
|
266
|
+
# Left value and right value.
|
267
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
268
|
+
rvs = rights.each_with_index.map { |right,i| typ.inner :"rv#{i}" }
|
269
|
+
# typ.inner :rv
|
270
|
+
# lv and rv are valid.
|
271
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
272
|
+
# inner :rvok
|
273
|
+
rvoks = rights.each_with_index.map { |right,i| inner :"rvok#{i}" }
|
274
|
+
# Run flag
|
275
|
+
inner :run
|
276
|
+
par(ev) do
|
277
|
+
ack <= 0
|
278
|
+
run <= 0
|
279
|
+
hif(req | run) do
|
280
|
+
run <= 1
|
281
|
+
# Computation request.
|
282
|
+
lefts.zip(rights).each_with_index do |(left,right),i|
|
283
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
284
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
285
|
+
hif(lvoks[i] & rvoks[i]) do
|
286
|
+
ack <= 1
|
287
|
+
run <= 0
|
288
|
+
if (i < lefts.size-1) then
|
289
|
+
if (i>0) then
|
290
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i])) +
|
291
|
+
accs[i-1]
|
292
|
+
else
|
293
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
294
|
+
end
|
295
|
+
else
|
296
|
+
# The last is reached
|
297
|
+
seq do
|
298
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
299
|
+
last.write(accs[i])
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
helse do
|
306
|
+
lefts.each_with_index do |left,i|
|
307
|
+
lvoks[i] <= 0
|
308
|
+
rvoks[i] <= 0
|
309
|
+
accs[i] <= 0
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
end
|