HDLRuby 2.2.14 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,850 @@
1
+ module HDLRuby::High::Std
2
+
3
+ ##
4
+ # Standard HDLRuby::High library: tasks
5
+ #
6
+ ########################################################################
7
+
8
+ ## Describes a high-level task type.
9
+ class TaskT
10
+
11
+ # The name of the task type.
12
+ attr_reader :name
13
+
14
+ # Creates a new task type with +name+ built whose
15
+ # instances are created from +ruby_block+.
16
+ def initialize(name,&ruby_block)
17
+ # Checks and sets the name.
18
+ @name = name.to_sym
19
+ # Sets the block for instantiating a task.
20
+ @ruby_block = ruby_block
21
+ # Sets the instantiation procedure if named.
22
+ return if @name.empty?
23
+ obj = self
24
+ HDLRuby::High.space_reg(@name) do |*args|
25
+ obj.instantiate(*args)
26
+ end
27
+ end
28
+
29
+ ## Intantiates a task
30
+ def instantiate(*args)
31
+ obj = self
32
+ # No argument, so not an instantiation but actually
33
+ # an access to the task type.
34
+ return obj if args.empty?
35
+ # Process the case of generic task.
36
+ if @ruby_block.arity > 0 then
37
+ # Actually the arguments are generic arguments,
38
+ # generates a new task type with these arguments
39
+ # fixed.
40
+ ruby_block = @ruby_block
41
+ return TaskT.new(:"") do
42
+ HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
43
+ end
44
+ end
45
+ # Generates the tasks.
46
+ taskI = nil
47
+ args.each do |nameI|
48
+ taskI = TaskI.new(name,&@ruby_block)
49
+ HDLRuby::High.space_reg(nameI) { taskI }
50
+ end
51
+ taskI
52
+ end
53
+
54
+ alias_method :call, :instantiate
55
+ end
56
+
57
+
58
+ ## Creates a new task type named +name+ whose instances are
59
+ # creating executing +ruby_block+.
60
+ def self.task(name,&ruby_block)
61
+ return TaskT.new(name,&ruby_block)
62
+ end
63
+
64
+ ## Creates a new task type named +name+ whose instances are
65
+ # creating executing +ruby_block+.
66
+ def task(name,&ruby_block)
67
+ HDLRuby::High::Std.task(name,&ruby_block)
68
+ end
69
+
70
+ ## Creates directly an instance of task named +name+ using
71
+ # +ruby_block+ built with +args+.
72
+ def self.task_instance(name,*args,&ruby_block)
73
+ # return TaskT.new(:"",&ruby_block).instantiate(name,*args)
74
+ return self.task(:"",&ruby_block).instantiate(name,*args)
75
+ end
76
+
77
+ ## Creates directly an instance of task named +name+ using
78
+ # +ruby_block+ built with +args+.
79
+ def task_instance(name,*args,&ruby_block)
80
+ HDLRuby::High::Std.task_instance(name,*args,&ruby_block)
81
+ end
82
+
83
+
84
+
85
+ # ##
86
+ # # Module for wrapping task ports.
87
+ # module TaskPortWrapping
88
+ # # Wrap with +args+ arguments.
89
+ # def wrap(*args)
90
+ # return TaskPortB.new(self,*args)
91
+ # end
92
+ # end
93
+
94
+
95
+ ##
96
+ # Describes a runner port to a task.
97
+ class TaskPortS
98
+ # include TaskPortWrapping
99
+
100
+ # Creates a new task runner running in +namespace+ and
101
+ # reading using +runner_proc+ and reseting using +reseter_proc+.
102
+ def initialize(namespace,runner_proc,reseter_proc = nil)
103
+ unless namespace.is_a?(Namespace)
104
+ raise "Invalid class for a namespace: #{namespace.class}"
105
+ end
106
+ @namespace = namespace
107
+ @runner_proc = runner_proc.to_proc
108
+ @rester_proc = reseter_proc ? reseter_proc.to_proc : proc {}
109
+ end
110
+
111
+ ## Performs a run on the task using +args+ and +ruby_block+
112
+ # as arguments.
113
+ def run(*args,&ruby_block)
114
+ # Gain access to the runner as local variable.
115
+ runner_proc = @runner_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,&runner_proc)
120
+ end
121
+ HDLRuby::High.space_pop
122
+ end
123
+
124
+ ## Performs a reset on the task using +args+ and +ruby_block+
125
+ # as arguments.
126
+ def reset(*args,&ruby_block)
127
+ # Gain access to the accesser as local variable.
128
+ reseter_proc = @reseter_proc
129
+ # Execute the code generating the accesser in context.
130
+ HDLRuby::High.space_push(@namespace)
131
+ HDLRuby::High.cur_block.open do
132
+ instance_exec(ruby_block,*args,&reseter_proc)
133
+ end
134
+ HDLRuby::High.space_pop
135
+ end
136
+ end
137
+
138
+
139
+ ##
140
+ # Describes an finisher port to a task.
141
+ class TaskPortA
142
+ # include TaskPortWrapping
143
+
144
+ # Creates a new task finisher running in +namespace+ and
145
+ # writing using +finisher_proc+ and reseting using +reseter_proc+.
146
+ def initialize(namespace,finisher_proc,reseter_proc = nil)
147
+ unless namespace.is_a?(Namespace)
148
+ raise "Invalid class for a namespace: #{namespace.class}"
149
+ end
150
+ @namespace = namespace
151
+ @finisher_proc = finisher_proc.to_proc
152
+ # @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
153
+ end
154
+
155
+ ## Performs a finish on the task using +args+ and +ruby_block+
156
+ # as arguments.
157
+ def finish(*args,&ruby_block)
158
+ # Gain access to the finisher as local variable.
159
+ finisher_proc = @finisher_proc
160
+ # Execute the code generating the accesser in context.
161
+ HDLRuby::High.space_push(@namespace)
162
+ HDLRuby::High.cur_block.open do
163
+ instance_exec(ruby_block,*args,&finisher_proc)
164
+ end
165
+ HDLRuby::High.space_pop
166
+ end
167
+
168
+ # ## Performs a reset on the task using +args+ and +ruby_block+
169
+ # # as arguments.
170
+ # def reset(*args,&ruby_block)
171
+ # # Gain access to the accesser as local variable.
172
+ # reseter_proc = @reseter_proc
173
+ # # Execute the code generating the accesser in context.
174
+ # HDLRuby::High.space_push(@namespace)
175
+ # HDLRuby::High.cur_block.open do
176
+ # instance_exec(ruby_block,*args,&reseter_proc)
177
+ # end
178
+ # HDLRuby::High.space_pop
179
+ # end
180
+ end
181
+
182
+
183
+ ##
184
+ # Describes an runner and finisher port to a task.
185
+ class TaskPortSA
186
+ # include TaskPortWrapping
187
+
188
+ # Creates a new task accesser running in +namespace+
189
+ # and reading using +runner_proc+, writing using +finisher_proc+,
190
+ # and reseting using +reseter_proc+.
191
+ def initialize(namespace,runner_proc,finisher_proc,reseter_proc = nil)
192
+ unless namespace.is_a?(Namespace)
193
+ raise "Invalid class for a namespace: #{namespace.class}"
194
+ end
195
+ @namespace = namespace
196
+ unless runner_proc || finisher_proc then
197
+ raise "An accesser must have at least a reading or a writing procedure."
198
+ end
199
+ @runner_proc = runner_proc ? runner_proc.to_proc : proc { }
200
+ @finisher_proc = finisher_proc ? finisher_proc.to_proc : proc { }
201
+ @reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
202
+ end
203
+
204
+ ## Performs a run on the task using +args+ and +ruby_block+
205
+ # as arguments.
206
+ def run(*args,&ruby_block)
207
+ # Gain access to the accesser as local variable.
208
+ runner_proc = @runner_proc
209
+ # Execute the code generating the accesser in context.
210
+ HDLRuby::High.space_push(@namespace)
211
+ HDLRuby::High.cur_block.open do
212
+ instance_exec(ruby_block,*args,&runner_proc)
213
+ end
214
+ HDLRuby::High.space_pop
215
+ end
216
+
217
+ ## Performs a finish on the task using +args+ and +ruby_block+
218
+ # as arguments.
219
+ def finish(*args,&ruby_block)
220
+ # Gain access to the accesser as local variable.
221
+ finisher_proc = @finisher_proc
222
+ # Execute the code generating the accesser in context.
223
+ HDLRuby::High.space_push(@namespace)
224
+ HDLRuby::High.cur_block.open do
225
+ instance_exec(ruby_block,*args,&finisher_proc)
226
+ end
227
+ HDLRuby::High.space_pop
228
+ end
229
+
230
+ ## Performs a reset on the task using +args+ and +ruby_block+
231
+ # as arguments.
232
+ def reset(*args,&ruby_block)
233
+ # Gain access to the accesser as local variable.
234
+ reseter_proc = @reseter_proc
235
+ # Execute the code generating the accesser in context.
236
+ HDLRuby::High.space_push(@namespace)
237
+ HDLRuby::High.cur_block.open do
238
+ instance_exec(ruby_block,*args,&reseter_proc)
239
+ end
240
+ HDLRuby::High.space_pop
241
+ end
242
+ end
243
+
244
+
245
+ # ##
246
+ # # Describes port wrapper (Box) for fixing arugments.
247
+ # class TaskPortB
248
+ # include TaskPortWrapping
249
+
250
+ # # Creates a new task box over task port +port+ fixing +args+
251
+ # # as arguments.
252
+ # # +args+ is a list of arguments to apply to all read, write
253
+ # # and access procedure, nil values meaning that the corresponding
254
+ # # argument is not overwritten.
255
+ # # It can also be three lists for seperate read, write and access
256
+ # # procedures using named arguments as:
257
+ # # read: <read arguments>, write: <write arguments>,
258
+ # # access: <access arguments>
259
+ # def initialize(port,*args)
260
+ # # Ensure port is a task port.
261
+ # unless port.is_a?(TaskPortS) || port.is_a?(TaskPortA) ||
262
+ # port.is_a?(TaskPortSA) || port.is_a?(TaskPortB)
263
+ # raise "Invalid class for a task port: #{port.class}"
264
+ # end
265
+ # @port = port
266
+ # # Process the arguments.
267
+ # if args.size == 1 && args[0].is_a?(Hash) then
268
+ # # Read, write and access are separated.
269
+ # @args_run = args[0][:run]
270
+ # @args_finish = args[0][:finish]
271
+ # else
272
+ # @args_run = args
273
+ # @args_finish = args.clone
274
+ # end
275
+ # end
276
+
277
+ # ## Performs a run on the task using +args+ and +ruby_block+
278
+ # # as arguments.
279
+ # def run(*args,&ruby_block)
280
+ # # Generate the final arguments: fills the nil with arguments
281
+ # # from args
282
+ # rargs = @args_run.clone
283
+ # rargs.map! { |arg| arg == nil ? args.shift : arg }
284
+ # # And add the remaining at the tail.
285
+ # rargs += args
286
+ # @port.run(*rargs,&ruby_block)
287
+ # end
288
+
289
+ # ## Performs a wait on a finish of the task using +args+ and +ruby_block+
290
+ # # as arguments.
291
+ # def finish(*args,&ruby_block)
292
+ # # Generate the final arguments: fills the nil with arguments
293
+ # # from args
294
+ # rargs = @args_finish.clone
295
+ # rargs.map! { |arg| arg == nil ? args.shift : arg }
296
+ # # And add the remaining at the tail.
297
+ # rargs += args
298
+ # @port.finish(*rargs,&ruby_block)
299
+ # end
300
+
301
+ # ## Performs a reset on the task using +args+ and +ruby_block+
302
+ # # as arguments.
303
+ # def reset(*args,&ruby_block)
304
+ # @port.reset(*@args,*args)
305
+ # end
306
+ # end
307
+
308
+
309
+
310
+ ##
311
+ # Describes a high-level task instance.
312
+ class TaskI
313
+ # include HDLRuby::High::HScope_missing
314
+ include HDLRuby::High::Hmissing
315
+
316
+ # The name of the task instance.
317
+ attr_reader :name
318
+
319
+ # The scope the task has been created in.
320
+ attr_reader :scope
321
+
322
+ # The namespace associated with the current execution when
323
+ # building a task.
324
+ attr_reader :namespace
325
+
326
+ ## Creates a new task instance with +name+ built from +ruby_block+.
327
+ def initialize(name,&ruby_block)
328
+ # Check and set the name of the task.
329
+ @name = name.to_sym
330
+ # Generate a name for the scope containing the signals of
331
+ # the task.
332
+ @scope_name = HDLRuby.uniq_name
333
+
334
+ # # Sets the scope.
335
+ # @scope = HDLRuby::High.cur_scope
336
+
337
+ # Keep access to self.
338
+ obj = self
339
+
340
+
341
+ # The runner input ports by name.
342
+ @runner_inputs = {}
343
+ # The runner output ports by name.
344
+ @runner_outputs = {}
345
+ # The runner inout ports by name.
346
+ @runner_inouts = {}
347
+
348
+ # # The stopper input ports by name.
349
+ # @stopper_inputs = {}
350
+ # # The stopper output ports by name.
351
+ # @stopper_outputs = {}
352
+ # # The stopper inout ports by name.
353
+ # @stopper_inouts = {}
354
+
355
+ # The finisher input ports by name.
356
+ @finisher_inputs = {}
357
+ # The finisher output ports by name.
358
+ @finisher_outputs = {}
359
+ # The finisher inout ports by name.
360
+ @finisher_inouts = {}
361
+
362
+ # Create the namespaces for building the task, its readers
363
+ # its writers and its accessers.
364
+
365
+ # Creates the namespace of the task.
366
+ @namespace = Namespace.new(self)
367
+ # Make it give access to the internal of the class.
368
+ @namespace.add_method(:runner_input, &method(:runner_input))
369
+ @namespace.add_method(:runner_output, &method(:runner_output))
370
+ @namespace.add_method(:runner_inout, &method(:runner_inout))
371
+ # @namespace.add_method(:stopper_input, &method(:stopper_input))
372
+ # @namespace.add_method(:stopper_output, &method(:stopper_output))
373
+ # @namespace.add_method(:stopper_inout, &method(:stopper_inout))
374
+ @namespace.add_method(:finisher_input, &method(:finisher_input))
375
+ @namespace.add_method(:finisher_output, &method(:finisher_output))
376
+ @namespace.add_method(:finisher_inout, &method(:finisher_inout))
377
+ @namespace.add_method(:runner, &method(:runner))
378
+ # @namespace.add_method(:stopper, &method(:stopper))
379
+ @namespace.add_method(:finisher, &method(:finisher))
380
+
381
+ # Creates the namespace of the runner.
382
+ @runner_namespace = Namespace.new(self)
383
+ # # Creates the namespace of the stopper.
384
+ # @stopper_namespace = Namespace.new(self)
385
+ # Creates the namespace of the finisher.
386
+ @finisher_namespace = Namespace.new(self)
387
+ @controller_namespace = Namespace.new(self)
388
+
389
+ # Builds the task within a new scope.
390
+ HDLRuby::High.space_push(@namespace)
391
+ # puts "top_user=#{HDLRuby::High.top_user}"
392
+ scope_name = @scope_name
393
+ scope = nil
394
+ HDLRuby::High.top_user.instance_eval do
395
+ sub(scope_name) do
396
+ # Generate the task code.
397
+ ruby_block.call
398
+ end
399
+ end
400
+ HDLRuby::High.space_pop
401
+
402
+ # Keep access to the scope containing the code of the task.
403
+ @scope = @namespace.send(scope_name)
404
+ # puts "@scope=#{@scope}"
405
+ # Adds the name space of the scope to the namespace of the
406
+ # task
407
+ @namespace.concat_namespace(@scope.namespace)
408
+
409
+ # Gives access to the task by registering its name.
410
+ obj = self
411
+ # HDLRuby::High.space_reg(@name) { self }
412
+ HDLRuby::High.space_reg(@name) { obj }
413
+ end
414
+
415
+ # The methods for defining the task
416
+
417
+ # For the task itself
418
+
419
+ # ## Defines new command +name+ to execute +ruby_block+ for the
420
+ # # task.
421
+ # def command(name,&ruby_block)
422
+ # # Ensures name is a symbol.
423
+ # name = name.to_sym
424
+ # res = nil
425
+ # # Sets the new command.
426
+ # self.define_singleton_method(name) do |*args|
427
+ # HDLRuby::High.space_push(@namespace)
428
+ # HDLRuby::High.cur_block.open do
429
+ # res = instance_exec(*args,&ruby_block)
430
+ # end
431
+ # HDLRuby::High.space_pop
432
+ # res
433
+ # end
434
+ # end
435
+
436
+ # For the runner the stopper and the finisher
437
+
438
+ ## Sets the signals accessible through +key+ to be run input port.
439
+ def runner_input(*keys)
440
+ # Registers each signal as run port
441
+ keys.each do |key|
442
+ # Ensure the key is a symbol.
443
+ key = key.to_sym
444
+ # Register it with the corresponding signal.
445
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
446
+ @runner_inputs[name] = send(key)
447
+ end
448
+ end
449
+
450
+ ## Sets the signals accessible through +key+ to be run output port.
451
+ def runner_output(*keys)
452
+ # Registers each signal as run port
453
+ keys.each do |key|
454
+ # Ensure the key is a symbol.
455
+ key = key.to_sym
456
+ # Register it with the corresponding signal.
457
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
458
+ @runner_outputs[name] = send(key)
459
+ end
460
+ end
461
+
462
+ ## Sets the signals accessible through +key+ to be run inout port.
463
+ def runner_inout(*keys)
464
+ # Registers each signal as run port
465
+ keys.each do |key|
466
+ # Ensure the key is a symbol.
467
+ key = key.to_sym
468
+ # Register it with the corresponding signal.
469
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
470
+ @runner_inouts[name] = send(key)
471
+ end
472
+ end
473
+
474
+ # ## Sets the signals accessible through +key+ to be stopper input port.
475
+ # def stopper_input(*keys)
476
+ # # Registers each signal as stopper port
477
+ # keys.each do |key|
478
+ # # Ensure the key is a symbol.
479
+ # key = key.to_sym
480
+ # # Register it with the corresponding signal.
481
+ # name = HDLRuby.uniq_name # The name of the signal is uniq.
482
+ # @stopper_inputs[name] = send(key)
483
+ # end
484
+ # end
485
+
486
+ # ## Sets the signals accessible through +key+ to be stopper output port.
487
+ # def stopper_output(*keys)
488
+ # # Registers each signal as stopper port
489
+ # keys.each do |key|
490
+ # # Ensure the key is a symbol.
491
+ # key = key.to_sym
492
+ # # Register it with the corresponding signal.
493
+ # name = HDLRuby.uniq_name # The name of the signal is uniq.
494
+ # @stopper_outputs[name] = send(key)
495
+ # end
496
+ # end
497
+
498
+ # ## Sets the signals accessible through +key+ to be stopper inout port.
499
+ # def stopper_inout(*keys)
500
+ # # Registers each signal as stopper port
501
+ # keys.each do |key|
502
+ # # Ensure the key is a symbol.
503
+ # key = key.to_sym
504
+ # # Register it with the corresponding signal.
505
+ # name = HDLRuby.uniq_name # The name of the signal is uniq.
506
+ # @stopper_inouts[name] = send(key)
507
+ # end
508
+ # end
509
+
510
+ ## Sets the signals accessible through +key+ to be finisher input port.
511
+ def finisher_input(*keys)
512
+ # Registers each signal as finisher port
513
+ keys.each do |key|
514
+ # Ensure the key is a symbol.
515
+ key = key.to_sym
516
+ # Register it with the corresponding signal.
517
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
518
+ @finisher_inputs[name] = send(key)
519
+ end
520
+ end
521
+
522
+ ## Sets the signals accessible through +key+ to be finisher output port.
523
+ def finisher_output(*keys)
524
+ # Registers each signal as finisher port
525
+ keys.each do |key|
526
+ # Ensure the key is a symbol.
527
+ key = key.to_sym
528
+ # Register it with the corresponding signal.
529
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
530
+ @finisher_outputs[name] = send(key)
531
+ end
532
+ end
533
+
534
+ ## Sets the signals accessible through +key+ to be finisher inout port.
535
+ def finisher_inout(*keys)
536
+ # Registers each signal as finisher port
537
+ keys.each do |key|
538
+ # Ensure the key is a symbol.
539
+ key = key.to_sym
540
+ # Register it with the corresponding signal.
541
+ name = HDLRuby.uniq_name # The name of the signal is uniq.
542
+ @finisher_inouts[name] = send(key)
543
+ end
544
+ end
545
+
546
+
547
+ ## Sets the read procedure to be +ruby_block+.
548
+ def runner(&ruby_block)
549
+ @runner_proc = ruby_block
550
+ end
551
+
552
+ # ## Sets the stopper procedure to be +ruby_block+.
553
+ # def stopper(&ruby_block)
554
+ # @stopper_proc = ruby_block
555
+ # end
556
+
557
+ ## Sets the finisher procedure to be +ruby_block+.
558
+ def finisher(&ruby_block)
559
+ @finisher_proc = ruby_block
560
+ end
561
+
562
+ ## Sets the reset to be +ruby_block+.
563
+ def reseter(&ruby_block)
564
+ @reseter_proc = ruby_block
565
+ end
566
+
567
+
568
+ # The methods for accessing the task
569
+ # Task side.
570
+
571
+ ## Gets the list of the signals of the task to be connected
572
+ # to the runner.
573
+ def runner_signals
574
+ return @runner_inputs.values + @runner_outputs.values +
575
+ @runner_inouts.values
576
+ end
577
+
578
+ # # ## Gets the list of the signals of the task to be connected
579
+ # # # to the stopper.
580
+ # # def stopper_signals
581
+ # # return @stopper_inputs.values + @stopper_outputs.values +
582
+ # # @stopper_inouts.values
583
+ # # end
584
+
585
+ ## Gets the list of the signals of the task to be connected
586
+ # to the finisher.
587
+ def finisher_signals
588
+ return @finisher_inputs.values + @finisher_outputs.values +
589
+ @finisher_inouts.values
590
+ end
591
+
592
+
593
+ ## Declares the ports for the runner and assigned them to +name+.
594
+ def input(name)
595
+ # Ensure name is a symbol.
596
+ name = name.to_sym
597
+ # Access the ports
598
+ loc_inputs = @runner_inputs
599
+ loc_outputs = @runner_outputs
600
+ loc_inouts = @runner_inouts
601
+ # The generated port with corresponding task port pairs.
602
+ port_pairs = []
603
+ # Add them to the current system.
604
+ HDLRuby::High.cur_system.open do
605
+ # The inputs
606
+ loc_inputs.each do |name,sig|
607
+ # puts "name=#{name} sig.name=#{sig.name}"
608
+ port_pairs << [sig, sig.type.input(name)]
609
+ end
610
+ # The outputs
611
+ loc_outputs.each do |name,sig|
612
+ port_pairs << [sig, sig.type.output(name)]
613
+ end
614
+ # The inouts
615
+ loc_inouts.each do |name,sig|
616
+ port_pairs << [sig, sig.type.inout(name)]
617
+ end
618
+ end
619
+ obj = self
620
+ # Make the connection of the instance.
621
+ HDLRuby::High.cur_system.on_instance do |inst|
622
+ obj.scope.open do
623
+ port_pairs.each do |sig, port|
624
+ RefObject.new(inst,port.to_ref) <= sig
625
+ end
626
+ end
627
+ end
628
+
629
+ # Fill the runner namespace with the access to the runner signals.
630
+ @runner_inputs.each do |name,sig|
631
+ @runner_namespace.add_method(sig.name) do
632
+ HDLRuby::High.top_user.send(name)
633
+ end
634
+ end
635
+ @runner_outputs.each do |name,sig|
636
+ @runner_namespace.add_method(sig.name) do
637
+ HDLRuby::High.top_user.send(name)
638
+ end
639
+ end
640
+ @runner_inouts.each do |name,sig|
641
+ @runner_namespace.add_method(sig.name) do
642
+ HDLRuby::High.top_user.send(name)
643
+ end
644
+ end
645
+
646
+ # Give access to the ports through name.
647
+ # NOTE: for now, simply associate the task to name.
648
+ tp = TaskPortS.new(@runner_namespace,@runner_proc,@reseter_proc)
649
+ HDLRuby::High.space_reg(name) { tp }
650
+ return tp
651
+ end
652
+
653
+ ## Declares the ports for the finisher and assigned them to +name+.
654
+ def output(name)
655
+ # Ensure name is a symbol.
656
+ name = name.to_sym
657
+ # Access the ports
658
+ loc_inputs = @finisher_inputs
659
+ loc_outputs = @finisher_outputs
660
+ loc_inouts = @finisher_inouts
661
+ # The generated port with corresponding task port pairs.
662
+ port_pairs = []
663
+ # Add them to the current system.
664
+ HDLRuby::High.cur_system.open do
665
+ # The inputs
666
+ loc_inputs.each do |name,sig|
667
+ port_pairs << [sig, sig.type.input(name)]
668
+ end
669
+ # The outputs
670
+ loc_outputs.each do |name,sig|
671
+ port_pairs << [sig, sig.type.output(name)]
672
+ end
673
+ # The inouts
674
+ loc_inouts.each do |name,sig|
675
+ port_pairs << [sig, sig.type.inout(name)]
676
+ end
677
+ end
678
+ obj = self
679
+ # Make the connection of the instance.
680
+ HDLRuby::High.cur_system.on_instance do |inst|
681
+ obj.scope.open do
682
+ port_pairs.each do |sig, port|
683
+ RefObject.new(inst,port.to_ref) <= sig
684
+ end
685
+ end
686
+ end
687
+
688
+ # Fill the finisher namespace with the access to the finisher signals.
689
+ @finisher_inputs.each do |name,sig|
690
+ @finisher_namespace.add_method(sig.name) do
691
+ HDLRuby::High.top_user.send(name)
692
+ end
693
+ end
694
+ @finisher_outputs.each do |name,sig|
695
+ @finisher_namespace.add_method(sig.name) do
696
+ HDLRuby::High.top_user.send(name)
697
+ end
698
+ end
699
+ @finisher_inouts.each do |name,sig|
700
+ @finisher_namespace.add_method(sig.name) do
701
+ HDLRuby::High.top_user.send(name)
702
+ end
703
+ end
704
+
705
+ # Give access to the ports through name.
706
+ # NOTE: for now, simply associate the task to name.
707
+ chp = TaskPortA.new(@finisher_namespace,@finisher_proc,@output_reseter_proc)
708
+ HDLRuby::High.space_reg(name) { chp }
709
+ return chp
710
+ end
711
+
712
+
713
+ ## Declares the ports for accessing the task as an inner component
714
+ # and assigned them to +name+.
715
+ def inner(name)
716
+ # Ensure name is a symbol.
717
+ name = name.to_sym
718
+ # Access the ports
719
+ loc_inputs = @runner_inputs.merge(@finisher_inputs)
720
+ loc_outputs = @runner_outputs.merge(@finisher_outputs)
721
+ loc_inouts = @runner_inouts.merge(@finisher_inouts)
722
+ locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
723
+ # The generated port with corresponding task port pairs.
724
+ port_pairs = []
725
+ # Add them to the current system.
726
+ HDLRuby::High.cur_system.open do
727
+ locs.each do |name,sig|
728
+ port_pairs << [sig, sig.type.inner(name)]
729
+ end
730
+ end
731
+ obj = self
732
+ # Make the inner connection
733
+ port_pairs.each do |sig, port|
734
+ sig.parent.open do
735
+ port.to_ref <= sig
736
+ end
737
+ end
738
+
739
+ # Set ups the controller's namespace
740
+ loc_inputs.each do |name,sig|
741
+ @controller_namespace.add_method(sig.name) do
742
+ HDLRuby::High.top_user.send(name)
743
+ end
744
+ end
745
+ loc_outputs.each do |name,sig|
746
+ @controller_namespace.add_method(sig.name) do
747
+ HDLRuby::High.top_user.send(name)
748
+ end
749
+ end
750
+ loc_inouts.each do |name,sig|
751
+ @controller_namespace.add_method(sig.name) do
752
+ HDLRuby::High.top_user.send(name)
753
+ end
754
+ end
755
+
756
+ # Give access to the ports through name.
757
+ # NOTE: for now, simply associate the task to name.
758
+ tp = TaskPortSA.new(@controller_namespace,@runner_proc,@finisher_proc,@reseter_proc)
759
+ HDLRuby::High.space_reg(name) { chp }
760
+ return tp
761
+ end
762
+
763
+
764
+ ## Runs the task using +args+ and +ruby_block+
765
+ # as arguments.
766
+ def run(*args,&ruby_block)
767
+ # Gain access to the runner as local variable.
768
+ runner_proc = @runner_proc
769
+ # # The context is the one of the reader.
770
+ # Execute the code generating the reader in context.
771
+ HDLRuby::High.space_push(@namespace)
772
+ HDLRuby::High.cur_block.open do
773
+ instance_exec(ruby_block,*args,&runner_proc)
774
+ end
775
+ HDLRuby::High.space_pop
776
+ end
777
+
778
+ ## Performs a wait from the end of the computation of the task using
779
+ # +args+ and +ruby_block+ as arguments.
780
+ def finish(*args,&ruby_block)
781
+ # Gain access to the finisher as local variable.
782
+ finisher_proc = @finisher_proc
783
+ # # The context is the one of the finisher.
784
+ # Execute the code generating the finisher in context.
785
+ HDLRuby::High.space_push(@namespace)
786
+ HDLRuby::High.cur_block.open do
787
+ instance_exec(ruby_block,*args,&finisher_proc)
788
+ end
789
+ HDLRuby::High.space_pop
790
+ end
791
+
792
+ ## Performs a reset on the task using +args+ and +ruby_block+
793
+ # as arguments.
794
+ def reset(*args,&ruby_block)
795
+ # Gain access to the writer as local variable.
796
+ reseter_proc = @inout_reseter_proc
797
+ # # The context is the one of the writer.
798
+ # Execute the code generating the writer in context.
799
+ HDLRuby::High.space_push(@namespace)
800
+ HDLRuby::High.cur_block.open do
801
+ instance_exec(ruby_block,*args,&reseter_proc)
802
+ end
803
+ HDLRuby::High.space_pop
804
+ end
805
+ end
806
+
807
+
808
+ ## Encapsulate a task for integrating a control with simple
809
+ # reset (+rst+), request and acknowledge (+ack+) signals,
810
+ # synchronised on +clk_e+.
811
+ # +port+ is assumed to return a TaskPortSA.
812
+ # If +clk_e+ is nil, work in asynchronous mode.
813
+ # If +rst+ is nil, no reset is handled.
814
+ def rst_req_ack(clk_e,rst,req,ack,port)
815
+ if clk_e then
816
+ # Ensures clk_e is an event.
817
+ clk_e = clk_e.posedge unless clk_e.is_a?(Event)
818
+ par(clk_e) do
819
+ # Handle the reset.
820
+ hif(rst) { port.reset } if rst
821
+ ack <= 0
822
+ # Control the start of the task.
823
+ hif(req) { port.run }
824
+ # Control the end of the task: set ack to 1.
825
+ port.finish { ack <= 1 }
826
+ end
827
+ else
828
+ par do
829
+ # Handle the reset
830
+ hif(rst) { port.reset } if rst
831
+ # Control the start of the task.
832
+ hif(req) { port.run }
833
+ ack <= 0
834
+ # Control the end of the task: set ack to 1.
835
+ port.finish { ack <= 1 }
836
+ end
837
+ end
838
+ end
839
+
840
+
841
+ ## Encapsulate a task for integrating a control with simple
842
+ # request and acknowledge (+ack+) signals,
843
+ # synchronised on +clk_e+.
844
+ # +port+ is assumed to return a TaskPortSA.
845
+ # If +clk_e+ is nil, work in asynchronous mode.
846
+ def req_ack(clk_e,req,ack,port)
847
+ rst_req_ack(clk_e,nil,req,ack,port)
848
+ end
849
+
850
+ end