HDLRuby 2.1.2 → 2.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
- return High.cur_block
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
- # Get the current mode of the block.
3186
- #
3187
- # NOTE: for name coherency purpose only.
3188
- def block
3189
- return self.mode
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"
@@ -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
- sign = self.type.signed? ? self.content.to_s[-1] : "0"
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"
@@ -1796,7 +1796,7 @@ class SystemT
1796
1796
  ref = self.extract_port_assign!(systemI,inout)
1797
1797
  if ref then
1798
1798
  code << "." << name_to_verilog(inout.name) << "("
1799
- code << ref.to_vhdl(level)
1799
+ code << ref.to_verilog
1800
1800
  code << "),"
1801
1801
  end
1802
1802
  end
@@ -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, its reader or its writer.
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 writers.
288
+ # its writers and its accessers.
108
289
 
109
290
  # Creates the namespace of the channel.
110
- @channel_namespace = Namespace.new(self)
291
+ @namespace = Namespace.new(self)
111
292
  # Make it give access to the internal of the class.
112
- @channel_namespace.add_method(:reader_input, &method(:reader_input))
113
- @channel_namespace.add_method(:reader_output,&method(:reader_output))
114
- @channel_namespace.add_method(:reader_inout, &method(:reader_inout))
115
- @channel_namespace.add_method(:writer_input, &method(:writer_input))
116
- @channel_namespace.add_method(:writer_output,&method(:writer_output))
117
- @channel_namespace.add_method(:writer_inout, &method(:writer_inout))
118
- @channel_namespace.add_method(:reader, &method(:reader))
119
- @channel_namespace.add_method(:writer, &method(:writer))
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
- # By default the namespace is the one of the namespace
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
- HDLRuby::High.top_user.instance_eval(&ruby_block)
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
- # Ensures name is a symbol.
148
- name = name.to_sym
149
- # Sets the new command.
150
- self.define_singleton_method(name) do
151
- # Executes the command in the right environment.
152
- HDLRuby::High.space_push(@namespace)
153
- res = HDLRuby::High.top_user.instance_exec(&ruby_block)
154
- HDLRuby::High.space_pop
155
- res
156
- end
157
- end
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 writter procedure to be +ruby_block+.
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
- # The methods for accessing the channel
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
- # Reader an writer side.
262
-
263
- # ## Declares the ports for the reader.
264
- # def reader_ports
265
- # loc_inputs = @reader_inputs
266
- # loc_outputs = @reader_outputs
267
- # loc_inouts = @reader_inouts
268
- # HDLRuby::High.cur_system.open do
269
- # # The inputs
270
- # loc_inputs.each { |name,sig| sig.type.input name }
271
- # # The outputs
272
- # loc_outputs.each { |name,sig| sig.type.output name }
273
- # # The inouts
274
- # loc_inouts.each { |name,sig| sig.type.inout name }
275
- # end
276
- # end
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
- this = self
315
- HDLRuby::High.space_reg(name) { this }
316
- end
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 reader and assigned them to +name+.
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
- this = self
370
- HDLRuby::High.space_reg(name) { this }
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
- ## Performs a read on the channel using +args+ and +ruby_block+
375
- # as arguments.
376
- def read(*args,&ruby_block)
377
- # Fill the reader namespace with the access to the reader signals.
378
- @reader_inputs.each do |name,sig|
379
- @reader_namespace.add_method(sig.name) do
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
- @reader_outputs.each do |name,sig|
384
- @reader_namespace.add_method(sig.name) do
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
- @reader_inouts.each do |name,sig|
389
- @reader_namespace.add_method(sig.name) do
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
- # Restores the default context.
437
- @namespace = @channel_namespace
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