HDLRuby 2.2.14 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +14 -8
- data/lib/HDLRuby/hdr_samples/linear_test.rb +235 -0
- data/lib/HDLRuby/hdr_samples/rom.rb +2 -2
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +3 -2
- data/lib/HDLRuby/hdr_samples/with_linear.rb +166 -0
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hdrcc.rb +1 -1
- data/lib/HDLRuby/hruby_high.rb +12 -4
- data/lib/HDLRuby/hruby_low.rb +25 -28
- data/lib/HDLRuby/hruby_low2c.rb +10 -5
- data/lib/HDLRuby/hruby_low2high.rb +1 -1
- data/lib/HDLRuby/hruby_low2vhd.rb +63 -48
- data/lib/HDLRuby/hruby_low_fix_types.rb +6 -2
- data/lib/HDLRuby/hruby_low_mutable.rb +2 -1
- data/lib/HDLRuby/hruby_low_resolve.rb +7 -4
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/hruby_verilog.rb +9 -1
- data/lib/HDLRuby/sim/hruby_sim.h +21 -0
- data/lib/HDLRuby/sim/hruby_sim_calc.c +254 -18
- data/lib/HDLRuby/std/channel.rb +103 -32
- data/lib/HDLRuby/std/fixpoint.rb +15 -6
- data/lib/HDLRuby/std/linear.rb +317 -0
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1000 -30
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +9 -2
@@ -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
|