HDLRuby 2.1.2 → 2.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/HDLRuby.gemspec +4 -2
- data/README.md +84 -25
- data/lib/HDLRuby/hdr_samples/mei8.rb +2 -2
- data/lib/HDLRuby/hdr_samples/mei8_bench.rb +2 -2
- data/lib/HDLRuby/hdr_samples/with_channel.rb +11 -13
- data/lib/HDLRuby/hdr_samples/with_memory.rb +123 -0
- data/lib/HDLRuby/hdrcc.rb +62 -55
- data/lib/HDLRuby/high_samples/with_top_unshift.rb +29 -0
- data/lib/HDLRuby/high_samples/with_unshift.rb +25 -0
- data/lib/HDLRuby/hruby_high.rb +120 -10
- data/lib/HDLRuby/hruby_low.rb +32 -0
- data/lib/HDLRuby/hruby_low2vhd.rb +5 -1
- data/lib/HDLRuby/hruby_verilog.rb +1 -1
- data/lib/HDLRuby/std/channel.rb +488 -111
- data/lib/HDLRuby/std/memory.rb +328 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +11 -8
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'HDLRuby'
|
2
|
+
|
3
|
+
configure_high
|
4
|
+
|
5
|
+
|
6
|
+
# A example of behavior with some unshifted statements in the top block
|
7
|
+
# of a behavior.
|
8
|
+
system :with_top_unshift do
|
9
|
+
[15..0].input :x,:y, :clk
|
10
|
+
[16..0].inner :w0,:w1
|
11
|
+
[16..0].output :o
|
12
|
+
|
13
|
+
seq(clk.posedge) do
|
14
|
+
w0 <= x + y
|
15
|
+
par do
|
16
|
+
w1 <= w0 * x
|
17
|
+
top_block.unshift { o <= w1 + y }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Instantiate it for checking.
|
23
|
+
with_top_unshift :with_top_unshiftI
|
24
|
+
|
25
|
+
# Generate the low level representation.
|
26
|
+
low = with_top_unshiftI.systemT.to_low
|
27
|
+
|
28
|
+
# Displays it
|
29
|
+
puts low.to_yaml
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'HDLRuby'
|
2
|
+
|
3
|
+
configure_high
|
4
|
+
|
5
|
+
|
6
|
+
# A example of behavior with some unshifted statements in a block.
|
7
|
+
system :with_unshift do
|
8
|
+
[15..0].input :x,:y, :clk
|
9
|
+
[16..0].inner :w
|
10
|
+
[16..0].output :o
|
11
|
+
|
12
|
+
seq(clk.posedge) do
|
13
|
+
w <= x + y
|
14
|
+
unshift { o <= w + y }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Instantiate it for checking.
|
19
|
+
with_unshift :with_unshiftI
|
20
|
+
|
21
|
+
# Generate the low level representation.
|
22
|
+
low = with_unshiftI.systemT.to_low
|
23
|
+
|
24
|
+
# Displays it
|
25
|
+
puts low.to_yaml
|
data/lib/HDLRuby/hruby_high.rb
CHANGED
@@ -1187,6 +1187,11 @@ module HDLRuby::High
|
|
1187
1187
|
end
|
1188
1188
|
|
1189
1189
|
|
1190
|
+
# Gets the current system.
|
1191
|
+
def cur_system
|
1192
|
+
return HDLRuby::High.cur_system
|
1193
|
+
end
|
1194
|
+
|
1190
1195
|
include Hmux
|
1191
1196
|
|
1192
1197
|
# Fills a low level scope with self's contents.
|
@@ -2321,6 +2326,41 @@ module HDLRuby::High
|
|
2321
2326
|
return Cast.new(type.to_type,self.to_expr)
|
2322
2327
|
end
|
2323
2328
|
|
2329
|
+
# Casts to a bit vector type.
|
2330
|
+
def to_bit
|
2331
|
+
return self.as(bit[self.width])
|
2332
|
+
end
|
2333
|
+
|
2334
|
+
# Casts to an unsigned bit vector type.
|
2335
|
+
def to_unsigned
|
2336
|
+
return self.as(unsigned[self.width])
|
2337
|
+
end
|
2338
|
+
|
2339
|
+
# Casts to a signed bit vector type.
|
2340
|
+
def to_unsigned
|
2341
|
+
return self.as(signed[self.width])
|
2342
|
+
end
|
2343
|
+
|
2344
|
+
# Extends on the left to +n+ bits filling with +v+ bit values.
|
2345
|
+
def ljust(n,v)
|
2346
|
+
return [(v.to_s * (n-self.width)).to_expr, self]
|
2347
|
+
end
|
2348
|
+
|
2349
|
+
# Extends on the right to +n+ bits filling with +v+ bit values.
|
2350
|
+
def rjust(n,v)
|
2351
|
+
return [self, (v.to_s * (n-self.width)).to_expr]
|
2352
|
+
end
|
2353
|
+
|
2354
|
+
# Extends on the left to +n+ bits filling with 0.
|
2355
|
+
def zext(n)
|
2356
|
+
return self.ljust(n,0)
|
2357
|
+
end
|
2358
|
+
|
2359
|
+
# Extends on the left to +n+ bits preserving the signe.
|
2360
|
+
def sext(n)
|
2361
|
+
return self.ljust(self[-1])
|
2362
|
+
end
|
2363
|
+
|
2324
2364
|
# Gets the origin method for operation +op+.
|
2325
2365
|
def self.orig_operator(op)
|
2326
2366
|
return (op.to_s + "_orig").to_sym
|
@@ -2342,6 +2382,26 @@ module HDLRuby::High
|
|
2342
2382
|
define_method(orig_operator(operator),&meth)
|
2343
2383
|
end
|
2344
2384
|
|
2385
|
+
# Left shift of +n+ bits.
|
2386
|
+
def ls(n)
|
2387
|
+
return self << n
|
2388
|
+
end
|
2389
|
+
|
2390
|
+
# Right shift of +n+ bits.
|
2391
|
+
def rs(n)
|
2392
|
+
return self >> n
|
2393
|
+
end
|
2394
|
+
|
2395
|
+
# Left rotate of +n+ bits.
|
2396
|
+
def lr(n)
|
2397
|
+
return [self[-(n+1)..0], self[-1..-(n)]]
|
2398
|
+
end
|
2399
|
+
|
2400
|
+
# Right rotate of +n+ bits.
|
2401
|
+
def rr(n)
|
2402
|
+
return [self[(n-1)..0], self[-1..n]]
|
2403
|
+
end
|
2404
|
+
|
2345
2405
|
# Coerce by forcing convertion of obj to expression.
|
2346
2406
|
def coerce(obj)
|
2347
2407
|
if obj.is_a?(HDLRuby::Low::Expression) then
|
@@ -2806,10 +2866,10 @@ module HDLRuby::High
|
|
2806
2866
|
return High.cur_behavior
|
2807
2867
|
end
|
2808
2868
|
|
2809
|
-
# Gets the enclosing block if any.
|
2810
|
-
def block
|
2811
|
-
|
2812
|
-
end
|
2869
|
+
# # Gets the enclosing block if any.
|
2870
|
+
# def block
|
2871
|
+
# return High.cur_block
|
2872
|
+
# end
|
2813
2873
|
|
2814
2874
|
# Converts the this reference to HDLRuby::Low.
|
2815
2875
|
def to_low
|
@@ -3182,13 +3242,50 @@ module HDLRuby::High
|
|
3182
3242
|
self.add_block(self.mode,name,&ruby_block)
|
3183
3243
|
end
|
3184
3244
|
|
3185
|
-
#
|
3186
|
-
|
3187
|
-
|
3188
|
-
|
3189
|
-
|
3245
|
+
# Adds statements at the top of the block.
|
3246
|
+
def unshift(&ruby_block)
|
3247
|
+
# Create a sub block for the statements.
|
3248
|
+
block = High.make_block(self.mode,:"",&ruby_block)
|
3249
|
+
# Unshifts it.
|
3250
|
+
self.unshift_statement(block)
|
3251
|
+
# Use its return value.
|
3252
|
+
return block.return_value
|
3190
3253
|
end
|
3191
3254
|
|
3255
|
+
# # Get the current mode of the block.
|
3256
|
+
# #
|
3257
|
+
# # NOTE: for name coherency purpose only.
|
3258
|
+
# def block
|
3259
|
+
# return self.mode
|
3260
|
+
# end
|
3261
|
+
|
3262
|
+
# Gets the current block.
|
3263
|
+
def cur_block
|
3264
|
+
return HDLRuby::High.cur_block
|
3265
|
+
end
|
3266
|
+
|
3267
|
+
# Gets the top block of the current behavior.
|
3268
|
+
def top_block
|
3269
|
+
return HDLRuby::High.top_block
|
3270
|
+
end
|
3271
|
+
|
3272
|
+
# Gets the current behavior.
|
3273
|
+
def cur_behavior
|
3274
|
+
return HDLRuby::High.cur_behavior
|
3275
|
+
end
|
3276
|
+
|
3277
|
+
# Gets the current scope.
|
3278
|
+
def cur_scope
|
3279
|
+
return HDLRuby::High.cur_scope
|
3280
|
+
end
|
3281
|
+
|
3282
|
+
# Gets the current system.
|
3283
|
+
def cur_system
|
3284
|
+
return HDLRuby::High.cur_system
|
3285
|
+
end
|
3286
|
+
|
3287
|
+
|
3288
|
+
|
3192
3289
|
# Need to be able to declare select operators
|
3193
3290
|
include Hmux
|
3194
3291
|
|
@@ -3624,7 +3721,6 @@ module HDLRuby::High
|
|
3624
3721
|
end
|
3625
3722
|
end
|
3626
3723
|
|
3627
|
-
|
3628
3724
|
# Gets the enclosing block if any.
|
3629
3725
|
#
|
3630
3726
|
# NOTE: +level+ allows to get an upper block of the currently enclosing
|
@@ -3640,6 +3736,20 @@ module HDLRuby::High
|
|
3640
3736
|
end
|
3641
3737
|
end
|
3642
3738
|
|
3739
|
+
# Gets the top enclosing block if any.
|
3740
|
+
def self.top_block(level = 0)
|
3741
|
+
blk = cur_block(level)
|
3742
|
+
unless blk.is_a?(Block)
|
3743
|
+
raise AnyError,
|
3744
|
+
"Not within a block: #{blk.user.class}"
|
3745
|
+
end
|
3746
|
+
if Namespaces[-1-level-1].user.is_a?(Scope) then
|
3747
|
+
return blk
|
3748
|
+
else
|
3749
|
+
return top_block(level+1)
|
3750
|
+
end
|
3751
|
+
end
|
3752
|
+
|
3643
3753
|
# Registers hardware referencing method +name+ to the current namespace.
|
3644
3754
|
def self.space_reg(name,&ruby_block)
|
3645
3755
|
# print "registering #{name} in #{Namespaces[-1]}\n"
|
data/lib/HDLRuby/hruby_low.rb
CHANGED
@@ -3495,6 +3495,24 @@ module HDLRuby::Low
|
|
3495
3495
|
statement
|
3496
3496
|
end
|
3497
3497
|
|
3498
|
+
# Adds a +statement+ and the begining of the block
|
3499
|
+
#
|
3500
|
+
# NOTE: TimeWait is not supported unless for TimeBlock objects.
|
3501
|
+
def unshift_statement(statement)
|
3502
|
+
unless statement.is_a?(Statement) then
|
3503
|
+
raise AnyError,
|
3504
|
+
"Invalid class for a statement: #{statement.class}"
|
3505
|
+
end
|
3506
|
+
if statement.is_a?(TimeWait) then
|
3507
|
+
raise AnyError,
|
3508
|
+
"Timed statements are not supported in common blocks."
|
3509
|
+
end
|
3510
|
+
@statements.unshift(statement)
|
3511
|
+
# And set its parent.
|
3512
|
+
statement.parent = self
|
3513
|
+
statement
|
3514
|
+
end
|
3515
|
+
|
3498
3516
|
# Gets the number of statements.
|
3499
3517
|
def num_statements
|
3500
3518
|
return @statements.size
|
@@ -3620,6 +3638,20 @@ module HDLRuby::Low
|
|
3620
3638
|
statement
|
3621
3639
|
end
|
3622
3640
|
|
3641
|
+
# Adds a +statement+ and the begining of the block
|
3642
|
+
#
|
3643
|
+
# NOTE: TimeWait is not supported unless for TimeBlock objects.
|
3644
|
+
def unshift_statement(statement)
|
3645
|
+
unless statement.is_a?(Statement) then
|
3646
|
+
raise AnyError,
|
3647
|
+
"Invalid class for a statement: #{statement.class}"
|
3648
|
+
end
|
3649
|
+
@statements.unshift(statement)
|
3650
|
+
# And set its parent.
|
3651
|
+
statement.parent = self
|
3652
|
+
statement
|
3653
|
+
end
|
3654
|
+
|
3623
3655
|
# Comparison for hash: structural comparison.
|
3624
3656
|
def eql?(obj)
|
3625
3657
|
return false unless obj.is_a?(TimeBlock)
|
@@ -1100,7 +1100,11 @@ module HDLRuby::Low
|
|
1100
1100
|
# when Numeric
|
1101
1101
|
# return self.content.to_s
|
1102
1102
|
when HDLRuby::BitString
|
1103
|
-
|
1103
|
+
# Compute the extension: in case of signed type, the extension
|
1104
|
+
# is the last bit. Otherwise it is 0 unless the last bit
|
1105
|
+
# is not defined (Z or X).
|
1106
|
+
sign = self.type.signed? ? self.content.to_s[-1] :
|
1107
|
+
/[01]/ =~ self.content[-1] ? "0" : self.content[-1]
|
1104
1108
|
return '"' + self.content.to_s.rjust(width,sign).upcase + '"'
|
1105
1109
|
else
|
1106
1110
|
sign = self.type.signed? ? (self.content>=0 ? "0" : "1") : "0"
|
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -18,7 +18,8 @@ module HDLRuby::High::Std
|
|
18
18
|
@name = name.to_sym
|
19
19
|
# Sets the block for instantiating a channel.
|
20
20
|
@ruby_block = ruby_block
|
21
|
-
# Sets the instantiation procedure.
|
21
|
+
# Sets the instantiation procedure if named.
|
22
|
+
return if @name.empty?
|
22
23
|
obj = self
|
23
24
|
HDLRuby::High.space_reg(@name) do |*args|
|
24
25
|
obj.instantiate(*args)
|
@@ -42,11 +43,12 @@ module HDLRuby::High::Std
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
# Generates the channels.
|
46
|
+
channelI = nil
|
45
47
|
args.each do |nameI|
|
46
48
|
channelI = ChannelI.new(name,&@ruby_block)
|
47
49
|
HDLRuby::High.space_reg(nameI) { channelI }
|
48
|
-
channelI
|
49
50
|
end
|
51
|
+
channelI
|
50
52
|
end
|
51
53
|
|
52
54
|
alias_method :call, :instantiate
|
@@ -55,11 +57,172 @@ module HDLRuby::High::Std
|
|
55
57
|
|
56
58
|
## Creates a new channel type named +name+ whose instances are
|
57
59
|
# creating executing +ruby_block+.
|
58
|
-
def channel(name,&ruby_block)
|
60
|
+
def self.channel(name,&ruby_block)
|
59
61
|
return ChannelT.new(name,&ruby_block)
|
60
62
|
end
|
61
63
|
|
64
|
+
## Creates a new channel type named +name+ whose instances are
|
65
|
+
# creating executing +ruby_block+.
|
66
|
+
def channel(name,&ruby_block)
|
67
|
+
HDLRuby::High::Std.channel(name,&ruby_block)
|
68
|
+
end
|
69
|
+
|
70
|
+
## Creates directly an instance of channel named +name+ using
|
71
|
+
# +ruby_block+ built with +args+.
|
72
|
+
def self.channel_instance(name,*args,&ruby_block)
|
73
|
+
return ChannelT.new(:"",&ruby_block).instantiate(name,*args)
|
74
|
+
end
|
75
|
+
|
76
|
+
## Creates directly an instance of channel named +name+ using
|
77
|
+
# +ruby_block+ built with +args+.
|
78
|
+
def channel_instance(name,*args,&ruby_block)
|
79
|
+
HDLRuby::High::Std.channel_instance(name,*args,&ruby_block)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
##
|
84
|
+
# Describes a read port to a channel.
|
85
|
+
class ChannelPortR
|
86
|
+
|
87
|
+
# Creates a new channel reader running in +namespace+ and
|
88
|
+
# reading using +reader_proc+ and reseting using +reseter_proc+.
|
89
|
+
def initialize(namespace,reader_proc,reseter_proc)
|
90
|
+
unless namespace.is_a?(Namespace)
|
91
|
+
raise "Invalid class for a namespace: #{namespace.class}"
|
92
|
+
end
|
93
|
+
@namespace = namespace
|
94
|
+
@reader_proc = reader_proc.to_proc
|
95
|
+
@rester_proc = reseter_proc.to_proc
|
96
|
+
end
|
97
|
+
|
98
|
+
## Performs a read on the channel using +args+ and +ruby_block+
|
99
|
+
# as arguments.
|
100
|
+
def read(*args,&ruby_block)
|
101
|
+
# Gain access to the reader as local variable.
|
102
|
+
reader_proc = @reader_proc
|
103
|
+
# Execute the code generating the accesser in context.
|
104
|
+
HDLRuby::High.space_push(@namespace)
|
105
|
+
HDLRuby::High.cur_block.open do
|
106
|
+
instance_exec(ruby_block,*args,&reader_proc)
|
107
|
+
end
|
108
|
+
HDLRuby::High.space_pop
|
109
|
+
end
|
110
|
+
|
111
|
+
## Performs a reset on the channel using +args+ and +ruby_block+
|
112
|
+
# as arguments.
|
113
|
+
def reset(*args,&ruby_block)
|
114
|
+
# Gain access to the accesser as local variable.
|
115
|
+
reseter_proc = @reseter_proc
|
116
|
+
# Execute the code generating the accesser in context.
|
117
|
+
HDLRuby::High.space_push(@namespace)
|
118
|
+
HDLRuby::High.cur_block.open do
|
119
|
+
instance_exec(ruby_block,*args,&reseter_proc)
|
120
|
+
end
|
121
|
+
HDLRuby::High.space_pop
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
##
|
127
|
+
# Describes a writer port to a channel.
|
128
|
+
class ChannelPortW
|
129
|
+
|
130
|
+
# Creates a new channel writer running in +namespace+ and
|
131
|
+
# writing using +writer_proc+ and reseting using +reseter_proc+.
|
132
|
+
def initialize(namespace,writer_proc,reseter_proc)
|
133
|
+
unless namespace.is_a?(Namespace)
|
134
|
+
raise "Invalid class for a namespace: #{namespace.class}"
|
135
|
+
end
|
136
|
+
@namespace = namespace
|
137
|
+
@writer_proc = writer_proc.to_proc
|
138
|
+
@reseter_proc = reseter_proc.to_proc
|
139
|
+
end
|
140
|
+
|
141
|
+
## Performs a write on the channel using +args+ and +ruby_block+
|
142
|
+
# as arguments.
|
143
|
+
def write(*args,&ruby_block)
|
144
|
+
# Gain access to the writer as local variable.
|
145
|
+
writer_proc = @writer_proc
|
146
|
+
# Execute the code generating the accesser in context.
|
147
|
+
HDLRuby::High.space_push(@namespace)
|
148
|
+
HDLRuby::High.cur_block.open do
|
149
|
+
instance_exec(ruby_block,*args,&writer_proc)
|
150
|
+
end
|
151
|
+
HDLRuby::High.space_pop
|
152
|
+
end
|
153
|
+
|
154
|
+
## Performs a reset on the channel using +args+ and +ruby_block+
|
155
|
+
# as arguments.
|
156
|
+
def reset(*args,&ruby_block)
|
157
|
+
# Gain access to the accesser as local variable.
|
158
|
+
reseter_proc = @reseter_proc
|
159
|
+
# Execute the code generating the accesser in context.
|
160
|
+
HDLRuby::High.space_push(@namespace)
|
161
|
+
HDLRuby::High.cur_block.open do
|
162
|
+
instance_exec(ruby_block,*args,&reseter_proc)
|
163
|
+
end
|
164
|
+
HDLRuby::High.space_pop
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
62
169
|
|
170
|
+
##
|
171
|
+
# Describes an access port to a channel.
|
172
|
+
class ChannelPortA
|
173
|
+
|
174
|
+
# Creates a new channel accesser running in +namespace+
|
175
|
+
# and reading using +reader_proc+, writing using +writer_proc+,
|
176
|
+
# and reseting using +reseter_proc+.
|
177
|
+
def initialize(namespace,reader_proc,writer_proc,reseter_proc)
|
178
|
+
unless namespace.is_a?(Namespace)
|
179
|
+
raise "Invalid class for a namespace: #{namespace.class}"
|
180
|
+
end
|
181
|
+
@namespace = namespace
|
182
|
+
@reader_proc = reader_proc.to_proc
|
183
|
+
@writer_proc = writer_proc.to_proc
|
184
|
+
@reseter_proc = reseter_proc.to_proc
|
185
|
+
end
|
186
|
+
|
187
|
+
## Performs a read on the channel using +args+ and +ruby_block+
|
188
|
+
# as arguments.
|
189
|
+
def read(*args,&ruby_block)
|
190
|
+
# Gain access to the accesser as local variable.
|
191
|
+
reader_proc = @reader_proc
|
192
|
+
# Execute the code generating the accesser in context.
|
193
|
+
HDLRuby::High.space_push(@namespace)
|
194
|
+
HDLRuby::High.cur_block.open do
|
195
|
+
instance_exec(ruby_block,*args,&reader_proc)
|
196
|
+
end
|
197
|
+
HDLRuby::High.space_pop
|
198
|
+
end
|
199
|
+
|
200
|
+
## Performs a write on the channel using +args+ and +ruby_block+
|
201
|
+
# as arguments.
|
202
|
+
def write(*args,&ruby_block)
|
203
|
+
# Gain access to the accesser as local variable.
|
204
|
+
writer_proc = @writer_proc
|
205
|
+
# Execute the code generating the accesser in context.
|
206
|
+
HDLRuby::High.space_push(@namespace)
|
207
|
+
HDLRuby::High.cur_block.open do
|
208
|
+
instance_exec(ruby_block,*args,&writer_proc)
|
209
|
+
end
|
210
|
+
HDLRuby::High.space_pop
|
211
|
+
end
|
212
|
+
|
213
|
+
## Performs a reset on the channel using +args+ and +ruby_block+
|
214
|
+
# as arguments.
|
215
|
+
def reset(*args,&ruby_block)
|
216
|
+
# Gain access to the accesser as local variable.
|
217
|
+
reseter_proc = @reseter_proc
|
218
|
+
# Execute the code generating the accesser in context.
|
219
|
+
HDLRuby::High.space_push(@namespace)
|
220
|
+
HDLRuby::High.cur_block.open do
|
221
|
+
instance_exec(ruby_block,*args,&reseter_proc)
|
222
|
+
end
|
223
|
+
HDLRuby::High.space_pop
|
224
|
+
end
|
225
|
+
end
|
63
226
|
|
64
227
|
|
65
228
|
##
|
@@ -75,16 +238,19 @@ module HDLRuby::High::Std
|
|
75
238
|
attr_reader :scope
|
76
239
|
|
77
240
|
# The namespace associated with the current execution when
|
78
|
-
# building a channel
|
241
|
+
# building a channel.
|
79
242
|
attr_reader :namespace
|
80
243
|
|
81
244
|
## Creates a new channel instance with +name+ built from +ruby_block+.
|
82
245
|
def initialize(name,&ruby_block)
|
83
|
-
# Check and set the name
|
246
|
+
# Check and set the name of the channel.
|
84
247
|
@name = name.to_sym
|
248
|
+
# Generate a name for the scope containing the signals of
|
249
|
+
# the channel.
|
250
|
+
@scope_name = HDLRuby.uniq_name
|
85
251
|
|
86
|
-
# Sets the scope.
|
87
|
-
@scope = HDLRuby::High.cur_scope
|
252
|
+
# # Sets the scope.
|
253
|
+
# @scope = HDLRuby::High.cur_scope
|
88
254
|
|
89
255
|
# Keep access to self.
|
90
256
|
obj = self
|
@@ -103,58 +269,93 @@ module HDLRuby::High::Std
|
|
103
269
|
# The writer inout ports by name.
|
104
270
|
@writer_inouts = {}
|
105
271
|
|
272
|
+
# The accesser input ports by name.
|
273
|
+
@accesser_inputs = {}
|
274
|
+
# The accesser output ports by name.
|
275
|
+
@accesser_outputs = {}
|
276
|
+
# The accesser inout ports by name.
|
277
|
+
@accesser_inouts = {}
|
278
|
+
|
279
|
+
# The default reset procedures (reseters), by default do nothing.
|
280
|
+
@input_reseter_proc = proc {}
|
281
|
+
@output_reseter_proc = proc {}
|
282
|
+
@inout_reseter_proc = proc {}
|
283
|
+
|
284
|
+
# The branch channels
|
285
|
+
@branches = {}
|
286
|
+
|
106
287
|
# Create the namespaces for building the channel, its readers
|
107
|
-
# and its
|
288
|
+
# its writers and its accessers.
|
108
289
|
|
109
290
|
# Creates the namespace of the channel.
|
110
|
-
@
|
291
|
+
@namespace = Namespace.new(self)
|
111
292
|
# Make it give access to the internal of the class.
|
112
|
-
@
|
113
|
-
@
|
114
|
-
@
|
115
|
-
@
|
116
|
-
@
|
117
|
-
@
|
118
|
-
@
|
119
|
-
@
|
293
|
+
@namespace.add_method(:reader_input, &method(:reader_input))
|
294
|
+
@namespace.add_method(:reader_output, &method(:reader_output))
|
295
|
+
@namespace.add_method(:reader_inout, &method(:reader_inout))
|
296
|
+
@namespace.add_method(:writer_input, &method(:writer_input))
|
297
|
+
@namespace.add_method(:writer_output, &method(:writer_output))
|
298
|
+
@namespace.add_method(:writer_inout, &method(:writer_inout))
|
299
|
+
@namespace.add_method(:accesser_input, &method(:accesser_input))
|
300
|
+
@namespace.add_method(:accesser_output,&method(:accesser_output))
|
301
|
+
@namespace.add_method(:accesser_inout, &method(:accesser_inout))
|
302
|
+
@namespace.add_method(:reader, &method(:reader))
|
303
|
+
@namespace.add_method(:writer, &method(:writer))
|
304
|
+
@namespace.add_method(:brancher, &method(:brancher))
|
120
305
|
|
121
306
|
# Creates the namespace of the reader.
|
122
307
|
@reader_namespace = Namespace.new(self)
|
123
308
|
# Creates the namespace of the writer.
|
124
309
|
@writer_namespace = Namespace.new(self)
|
310
|
+
# Creates the namespace of the accesser.
|
311
|
+
@accesser_namespace = Namespace.new(self)
|
125
312
|
|
126
|
-
#
|
127
|
-
@namespace = @channel_namespace
|
128
|
-
|
129
|
-
# Builds the channel.
|
313
|
+
# Builds the channel within a new scope.
|
130
314
|
HDLRuby::High.space_push(@namespace)
|
131
315
|
# puts "top_user=#{HDLRuby::High.top_user}"
|
132
|
-
|
316
|
+
scope_name = @scope_name
|
317
|
+
scope = nil
|
318
|
+
HDLRuby::High.top_user.instance_eval do
|
319
|
+
sub(scope_name) do
|
320
|
+
# Generate the channel code.
|
321
|
+
ruby_block.call
|
322
|
+
end
|
323
|
+
end
|
133
324
|
HDLRuby::High.space_pop
|
134
325
|
|
326
|
+
# Keep access to the scope containing the code of the channel.
|
327
|
+
@scope = @namespace.send(scope_name)
|
328
|
+
# puts "@scope=#{@scope}"
|
329
|
+
# Adds the name space of the scope to the namespace of the
|
330
|
+
# channel
|
331
|
+
@namespace.concat_namespace(@scope.namespace)
|
332
|
+
|
135
333
|
# Gives access to the channel by registering its name.
|
136
334
|
obj = self
|
137
|
-
HDLRuby::High.space_reg(@name) { self }
|
335
|
+
# HDLRuby::High.space_reg(@name) { self }
|
336
|
+
HDLRuby::High.space_reg(@name) { obj }
|
138
337
|
end
|
139
338
|
|
140
339
|
# The methods for defining the channel
|
141
340
|
|
142
341
|
# For the channel itself
|
143
342
|
|
144
|
-
## Defines new command +name+ to execute +ruby_block+ for the
|
145
|
-
# channel.
|
146
|
-
def command(name,&ruby_block)
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
343
|
+
# ## Defines new command +name+ to execute +ruby_block+ for the
|
344
|
+
# # channel.
|
345
|
+
# def command(name,&ruby_block)
|
346
|
+
# # Ensures name is a symbol.
|
347
|
+
# name = name.to_sym
|
348
|
+
# res = nil
|
349
|
+
# # Sets the new command.
|
350
|
+
# self.define_singleton_method(name) do |*args|
|
351
|
+
# HDLRuby::High.space_push(@namespace)
|
352
|
+
# HDLRuby::High.cur_block.open do
|
353
|
+
# res = instance_exec(*args,&ruby_block)
|
354
|
+
# end
|
355
|
+
# HDLRuby::High.space_pop
|
356
|
+
# res
|
357
|
+
# end
|
358
|
+
# end
|
158
359
|
|
159
360
|
# For the reader and the writer
|
160
361
|
|
@@ -230,18 +431,74 @@ module HDLRuby::High::Std
|
|
230
431
|
end
|
231
432
|
end
|
232
433
|
|
434
|
+
## Sets the signals accessible through +key+ to be accesser input port.
|
435
|
+
def accesser_input(*keys)
|
436
|
+
# Registers each signal as accesser port
|
437
|
+
keys.each do |key|
|
438
|
+
# Ensure the key is a symbol.
|
439
|
+
key = key.to_sym
|
440
|
+
# Register it with the corresponding signal.
|
441
|
+
name = HDLRuby.uniq_name # The name of the signal is uniq.
|
442
|
+
@accesser_inputs[name] = send(key)
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
## Sets the signals accessible through +key+ to be accesser output port.
|
447
|
+
def accesser_output(*keys)
|
448
|
+
# Registers each signal as accesser port
|
449
|
+
keys.each do |key|
|
450
|
+
# Ensure the key is a symbol.
|
451
|
+
key = key.to_sym
|
452
|
+
# Register it with the corresponding signal.
|
453
|
+
name = HDLRuby.uniq_name # The name of the signal is uniq.
|
454
|
+
@accesser_outputs[name] = send(key)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
## Sets the signals accessible through +key+ to be accesser inout port.
|
459
|
+
def accesser_inout(*keys)
|
460
|
+
# Registers each signal as accesser port
|
461
|
+
keys.each do |key|
|
462
|
+
# Ensure the key is a symbol.
|
463
|
+
key = key.to_sym
|
464
|
+
# Register it with the corresponding signal.
|
465
|
+
name = HDLRuby.uniq_name # The name of the signal is uniq.
|
466
|
+
@accesser_inouts[name] = send(key)
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
|
233
471
|
## Sets the read procedure to be +ruby_block+.
|
234
472
|
def reader(&ruby_block)
|
235
473
|
@reader_proc = ruby_block
|
236
474
|
end
|
237
475
|
|
238
|
-
## Sets the
|
476
|
+
## Sets the writer procedure to be +ruby_block+.
|
239
477
|
def writer(&ruby_block)
|
240
478
|
@writer_proc = ruby_block
|
241
479
|
end
|
242
480
|
|
243
|
-
#
|
481
|
+
# ## Sets the accesser procedure to be +ruby_block+.
|
482
|
+
# def accesser(&ruby_block)
|
483
|
+
# @accesser_proc = ruby_block
|
484
|
+
# end
|
485
|
+
|
486
|
+
## Sets the input port reset to be +ruby_block+.
|
487
|
+
def input_reseter(&ruby_block)
|
488
|
+
@input_reseter_proc = ruby_block
|
489
|
+
end
|
490
|
+
|
491
|
+
## Sets the output port reset to be +ruby_block+.
|
492
|
+
def output_reseter(&ruby_block)
|
493
|
+
@output_reseter_proc = ruby_block
|
494
|
+
end
|
495
|
+
|
496
|
+
## Sets the inout port reset to be +ruby_block+.
|
497
|
+
def inout_reseter(&ruby_block)
|
498
|
+
@inout_reseter_proc = ruby_block
|
499
|
+
end
|
244
500
|
|
501
|
+
# The methods for accessing the channel
|
245
502
|
# Channel side.
|
246
503
|
|
247
504
|
## Gets the list of the signals of the channel to be connected
|
@@ -258,22 +515,32 @@ module HDLRuby::High::Std
|
|
258
515
|
@writer_inouts.values
|
259
516
|
end
|
260
517
|
|
261
|
-
#
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
#
|
274
|
-
|
275
|
-
#
|
276
|
-
#
|
518
|
+
# Defines a branch in the channel named +name+ built executing
|
519
|
+
# +ruby_block+.
|
520
|
+
def brancher(name,*args,&ruby_block)
|
521
|
+
# Ensure name is a symbol.
|
522
|
+
name = name.to_s unless name.respond_to?(:to_sym)
|
523
|
+
name = name.to_sym
|
524
|
+
# Create the branch.
|
525
|
+
channelI = HDLRuby::High.channel_instance(name,*args,&ruby_block)
|
526
|
+
@branches[name] = channelI
|
527
|
+
end
|
528
|
+
|
529
|
+
|
530
|
+
# Methods used on the channel outside its definition.
|
531
|
+
|
532
|
+
# Gets branch channel +name+.
|
533
|
+
# NOTE: +name+ can be of any type on purpose.
|
534
|
+
def branch(name)
|
535
|
+
# Ensure name is a symbol.
|
536
|
+
name = name.to_s unless name.respond_to?(:to_sym)
|
537
|
+
name = name.to_sym
|
538
|
+
# Get the branch.
|
539
|
+
return @branches[name]
|
540
|
+
end
|
541
|
+
|
542
|
+
|
543
|
+
# Reader, writer and accesser side.
|
277
544
|
|
278
545
|
## Declares the ports for the reader and assigned them to +name+.
|
279
546
|
def input(name)
|
@@ -289,6 +556,7 @@ module HDLRuby::High::Std
|
|
289
556
|
HDLRuby::High.cur_system.open do
|
290
557
|
# The inputs
|
291
558
|
loc_inputs.each do |name,sig|
|
559
|
+
# puts "name=#{name} sig.name=#{sig.name}"
|
292
560
|
port_pairs << [sig, sig.type.input(name)]
|
293
561
|
end
|
294
562
|
# The outputs
|
@@ -309,28 +577,32 @@ module HDLRuby::High::Std
|
|
309
577
|
end
|
310
578
|
end
|
311
579
|
end
|
580
|
+
|
581
|
+
# Fill the reader namespace with the access to the reader signals.
|
582
|
+
@reader_inputs.each do |name,sig|
|
583
|
+
@reader_namespace.add_method(sig.name) do
|
584
|
+
HDLRuby::High.top_user.send(name)
|
585
|
+
end
|
586
|
+
end
|
587
|
+
@reader_outputs.each do |name,sig|
|
588
|
+
@reader_namespace.add_method(sig.name) do
|
589
|
+
HDLRuby::High.top_user.send(name)
|
590
|
+
end
|
591
|
+
end
|
592
|
+
@reader_inouts.each do |name,sig|
|
593
|
+
@reader_namespace.add_method(sig.name) do
|
594
|
+
HDLRuby::High.top_user.send(name)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
312
598
|
# Give access to the ports through name.
|
313
599
|
# NOTE: for now, simply associate the channel to name.
|
314
|
-
|
315
|
-
HDLRuby::High.space_reg(name) {
|
316
|
-
|
317
|
-
|
318
|
-
# ## Declares the ports for the writer.
|
319
|
-
# def writer_ports
|
320
|
-
# loc_inputs = @writer_inputs
|
321
|
-
# loc_outputs = @writer_outputs
|
322
|
-
# loc_inouts = @writer_inouts
|
323
|
-
# HDLRuby::High.cur_system.open do
|
324
|
-
# # The inputs
|
325
|
-
# loc_inputs.each { |name,sig| sig.type.input name }
|
326
|
-
# # The outputs
|
327
|
-
# loc_outputs.each { |name,sig| sig.type.output name }
|
328
|
-
# # The inouts
|
329
|
-
# loc_inouts.each { |name,sig| sig.type.inout name }
|
330
|
-
# end
|
331
|
-
# end
|
600
|
+
chp = ChannelPortR.new(@reader_namespace,@reader_proc,@input_reseter_proc)
|
601
|
+
HDLRuby::High.space_reg(name) { chp }
|
602
|
+
return chp
|
603
|
+
end
|
332
604
|
|
333
|
-
## Declares the ports for the
|
605
|
+
## Declares the ports for the writer and assigned them to +name+.
|
334
606
|
def output(name)
|
335
607
|
# Ensure name is a symbol.
|
336
608
|
name = name.to_sym
|
@@ -364,77 +636,182 @@ module HDLRuby::High::Std
|
|
364
636
|
end
|
365
637
|
end
|
366
638
|
end
|
639
|
+
|
640
|
+
# Fill the writer namespace with the access to the writer signals.
|
641
|
+
@writer_inputs.each do |name,sig|
|
642
|
+
@writer_namespace.add_method(sig.name) do
|
643
|
+
HDLRuby::High.top_user.send(name)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
@writer_outputs.each do |name,sig|
|
647
|
+
@writer_namespace.add_method(sig.name) do
|
648
|
+
HDLRuby::High.top_user.send(name)
|
649
|
+
end
|
650
|
+
end
|
651
|
+
@writer_inouts.each do |name,sig|
|
652
|
+
@writer_namespace.add_method(sig.name) do
|
653
|
+
HDLRuby::High.top_user.send(name)
|
654
|
+
end
|
655
|
+
end
|
656
|
+
|
367
657
|
# Give access to the ports through name.
|
368
658
|
# NOTE: for now, simply associate the channel to name.
|
369
|
-
|
370
|
-
HDLRuby::High.space_reg(name) {
|
659
|
+
chp = ChannelPortW.new(@writer_namespace,@writer_proc,@output_reseter_proc)
|
660
|
+
HDLRuby::High.space_reg(name) { chp }
|
661
|
+
return chp
|
371
662
|
end
|
372
663
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
#
|
378
|
-
@
|
379
|
-
|
664
|
+
## Declares the ports for the accesser and assigned them to +name+.
|
665
|
+
def inout(name)
|
666
|
+
# Ensure name is a symbol.
|
667
|
+
name = name.to_sym
|
668
|
+
# Access the ports
|
669
|
+
loc_inputs = @accesser_inputs
|
670
|
+
loc_outputs = @accesser_outputs
|
671
|
+
loc_inouts = @accesser_inouts
|
672
|
+
# The generated port with corresponding channel port pairs.
|
673
|
+
port_pairs = []
|
674
|
+
# Add them to the current system.
|
675
|
+
HDLRuby::High.cur_system.open do
|
676
|
+
# The inputs
|
677
|
+
loc_inputs.each do |name,sig|
|
678
|
+
port_pairs << [sig, sig.type.input(name)]
|
679
|
+
end
|
680
|
+
# The outputs
|
681
|
+
loc_outputs.each do |name,sig|
|
682
|
+
port_pairs << [sig, sig.type.output(name)]
|
683
|
+
end
|
684
|
+
# The inouts
|
685
|
+
loc_inouts.each do |name,sig|
|
686
|
+
port_pairs << [sig, sig.type.inout(name)]
|
687
|
+
end
|
688
|
+
end
|
689
|
+
obj = self
|
690
|
+
# Make the connection of the instance.
|
691
|
+
HDLRuby::High.cur_system.on_instance do |inst|
|
692
|
+
obj.scope.open do
|
693
|
+
port_pairs.each do |sig, port|
|
694
|
+
RefObject.new(inst,port.to_ref) <= sig
|
695
|
+
end
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
# Set ups the accesser's namespace
|
700
|
+
@accesser_inputs.each do |name,sig|
|
701
|
+
@accesser_namespace.add_method(sig.name) do
|
380
702
|
HDLRuby::High.top_user.send(name)
|
381
703
|
end
|
382
704
|
end
|
383
|
-
@
|
384
|
-
@
|
705
|
+
@accesser_outputs.each do |name,sig|
|
706
|
+
@accesser_namespace.add_method(sig.name) do
|
385
707
|
HDLRuby::High.top_user.send(name)
|
386
708
|
end
|
387
709
|
end
|
388
|
-
@
|
389
|
-
@
|
710
|
+
@accesser_inouts.each do |name,sig|
|
711
|
+
@accesser_namespace.add_method(sig.name) do
|
390
712
|
HDLRuby::High.top_user.send(name)
|
391
713
|
end
|
392
714
|
end
|
715
|
+
|
716
|
+
# Give access to the ports through name.
|
717
|
+
# NOTE: for now, simply associate the channel to name.
|
718
|
+
chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
|
719
|
+
HDLRuby::High.space_reg(name) { chp }
|
720
|
+
return chp
|
721
|
+
end
|
722
|
+
|
723
|
+
## Declares the ports for accessing the channel as an inner component
|
724
|
+
# and assigned them to +name+.
|
725
|
+
def inner(name)
|
726
|
+
# Ensure name is a symbol.
|
727
|
+
name = name.to_sym
|
728
|
+
# Access the ports
|
729
|
+
loc_inputs = @accesser_inputs.merge(@reader_inputs).
|
730
|
+
merge(@writer_inputs)
|
731
|
+
loc_outputs = @accesser_outputs.merge(@reader_outputs).
|
732
|
+
merge(@writer_outputs)
|
733
|
+
loc_inouts = @accesser_inouts.merge(@reader_inouts).
|
734
|
+
merge(@writer_inouts)
|
735
|
+
locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
|
736
|
+
# The generated port with corresponding channel port pairs.
|
737
|
+
port_pairs = []
|
738
|
+
# Add them to the current system.
|
739
|
+
HDLRuby::High.cur_system.open do
|
740
|
+
locs.each do |name,sig|
|
741
|
+
port_pairs << [sig, sig.type.inner(name)]
|
742
|
+
end
|
743
|
+
end
|
744
|
+
obj = self
|
745
|
+
# Make the inner connection
|
746
|
+
port_pairs.each do |sig, port|
|
747
|
+
port.to_ref <= sig
|
748
|
+
end
|
749
|
+
|
750
|
+
# Set ups the accesser's namespace
|
751
|
+
@accesser_inputs.each do |name,sig|
|
752
|
+
@accesser_namespace.add_method(sig.name) do
|
753
|
+
HDLRuby::High.top_user.send(name)
|
754
|
+
end
|
755
|
+
end
|
756
|
+
@accesser_outputs.each do |name,sig|
|
757
|
+
@accesser_namespace.add_method(sig.name) do
|
758
|
+
HDLRuby::High.top_user.send(name)
|
759
|
+
end
|
760
|
+
end
|
761
|
+
@accesser_inouts.each do |name,sig|
|
762
|
+
@accesser_namespace.add_method(sig.name) do
|
763
|
+
HDLRuby::High.top_user.send(name)
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
# Give access to the ports through name.
|
768
|
+
# NOTE: for now, simply associate the channel to name.
|
769
|
+
chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
|
770
|
+
HDLRuby::High.space_reg(name) { chp }
|
771
|
+
return chp
|
772
|
+
end
|
773
|
+
|
774
|
+
|
775
|
+
## Performs a read on the channel using +args+ and +ruby_block+
|
776
|
+
# as arguments.
|
777
|
+
def read(*args,&ruby_block)
|
393
778
|
# Gain access to the reader as local variable.
|
394
779
|
reader_proc = @reader_proc
|
395
|
-
# The context is the one of the reader.
|
396
|
-
@namespace = @reader_namespace
|
780
|
+
# # The context is the one of the reader.
|
397
781
|
# Execute the code generating the reader in context.
|
398
782
|
HDLRuby::High.space_push(@namespace)
|
399
783
|
HDLRuby::High.cur_block.open do
|
400
784
|
instance_exec(ruby_block,*args,&reader_proc)
|
401
785
|
end
|
402
786
|
HDLRuby::High.space_pop
|
403
|
-
# Restores the default context.
|
404
|
-
@namespace = @channel_namespace
|
405
787
|
end
|
406
788
|
|
407
789
|
## Performs a write on the channel using +args+ and +ruby_block+
|
408
790
|
# as arguments.
|
409
791
|
def write(*args,&ruby_block)
|
410
|
-
# Fill the writer namespace with the access to the writer signals.
|
411
|
-
@writer_inputs.each do |name,sig|
|
412
|
-
@writer_namespace.add_method(sig.name) do
|
413
|
-
HDLRuby::High.top_user.send(name)
|
414
|
-
end
|
415
|
-
end
|
416
|
-
@writer_outputs.each do |name,sig|
|
417
|
-
@writer_namespace.add_method(sig.name) do
|
418
|
-
HDLRuby::High.top_user.send(name)
|
419
|
-
end
|
420
|
-
end
|
421
|
-
@writer_inouts.each do |name,sig|
|
422
|
-
@writer_namespace.add_method(sig.name) do
|
423
|
-
HDLRuby::High.top_user.send(name)
|
424
|
-
end
|
425
|
-
end
|
426
792
|
# Gain access to the writer as local variable.
|
427
793
|
writer_proc = @writer_proc
|
428
|
-
# The context is the one of the writer.
|
429
|
-
@namespace = @writer_namespace
|
794
|
+
# # The context is the one of the writer.
|
430
795
|
# Execute the code generating the writer in context.
|
431
796
|
HDLRuby::High.space_push(@namespace)
|
432
797
|
HDLRuby::High.cur_block.open do
|
433
798
|
instance_exec(ruby_block,*args,&writer_proc)
|
434
799
|
end
|
435
800
|
HDLRuby::High.space_pop
|
436
|
-
|
437
|
-
|
801
|
+
end
|
802
|
+
|
803
|
+
## Performs a reset on the channel using +args+ and +ruby_block+
|
804
|
+
# as arguments.
|
805
|
+
def reset(*args,&ruby_block)
|
806
|
+
# Gain access to the writer as local variable.
|
807
|
+
reseter_proc = @inout_reseter_proc
|
808
|
+
# # The context is the one of the writer.
|
809
|
+
# Execute the code generating the writer in context.
|
810
|
+
HDLRuby::High.space_push(@namespace)
|
811
|
+
HDLRuby::High.cur_block.open do
|
812
|
+
instance_exec(ruby_block,*args,&reseter_proc)
|
813
|
+
end
|
814
|
+
HDLRuby::High.space_pop
|
438
815
|
end
|
439
816
|
end
|
440
817
|
|