HDLRuby 2.2.14 → 2.3.1

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