HDLRuby 2.9.0 → 2.10.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,592 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'fileutils'
4
+ require 'tempfile'
5
+ require 'HDLRuby'
6
+ require 'HDLRuby/hruby_check.rb'
7
+ # require 'ripper'
8
+ require 'HDLRuby/hruby_low2hdr'
9
+ require 'HDLRuby/hruby_low2c'
10
+ require 'HDLRuby/hruby_low2vhd'
11
+ require 'HDLRuby/hruby_low_fix_types'
12
+ # require 'HDLRuby/hruby_low_expand_types' # For now dormant
13
+ require 'HDLRuby/hruby_low_without_outread'
14
+ require 'HDLRuby/hruby_low_with_bool'
15
+ require 'HDLRuby/hruby_low_bool2select'
16
+ require 'HDLRuby/hruby_low_without_select'
17
+ require 'HDLRuby/hruby_low_without_namespace'
18
+ require 'HDLRuby/hruby_low_without_bit2vector'
19
+ require 'HDLRuby/hruby_low_with_port'
20
+ require 'HDLRuby/hruby_low_with_var'
21
+ require 'HDLRuby/hruby_low_without_concat'
22
+ require 'HDLRuby/hruby_low_without_connection'
23
+ require 'HDLRuby/hruby_low_casts_without_expression'
24
+ require 'hruby_low_without_parinseq'
25
+ require 'HDLRuby/hruby_low_cleanup'
26
+
27
+ require 'HDLRuby/hruby_verilog.rb'
28
+
29
+ require 'HDLRuby/backend/hruby_allocator'
30
+ require 'HDLRuby/backend/hruby_c_allocator'
31
+
32
+ require 'HDLRuby/version.rb'
33
+
34
+ ##
35
+ # HDLRuby compiler interface program
36
+ #####################################
37
+
38
+ module HDLRuby
39
+
40
+
41
+
42
+ # Class for loading HDLRuby files.
43
+ class HDRLoad
44
+
45
+ # TOP_NAME = "__hdr_top_instance__"
46
+ TOP_NAME = "__"
47
+
48
+ # The top instance, only accessible after parsing the files.
49
+ attr_reader :top_instance
50
+
51
+ # The required files.
52
+ attr_reader :requires
53
+
54
+ # Creates a new loader for a +top_system+ system in file +top_file_name+
55
+ # from directory +dir+ with generic parameters +params+.
56
+ #
57
+ # NOTE: +top_file+ can either be a file or a file name.
58
+ def initialize(top_system,top_file,dir,*params)
59
+ # Sets the top and the looking directory.
60
+ @top_system = top_system.to_s
61
+ # @top_file can either be a file or a string giving the file name.
62
+ if top_file.respond_to?(:path) then
63
+ @top_file = top_file
64
+ @top_file_name = top_file.path
65
+ else
66
+ @top_file = nil
67
+ @top_file_name = top_file.to_s
68
+ end
69
+ @dir = dir.to_s
70
+ @params = params
71
+
72
+ # The list of the standard library files to exclude for
73
+ # checking.
74
+ # Get the directory of the HDLRuby and Ruby standard libraries.
75
+ @std_dirs = $LOAD_PATH
76
+ # @std_dirs << File.dirname(__FILE__) + "/std"
77
+ # # Gather the files with their path to std.
78
+ # @std_files = Dir[@std_dir + "/*"]
79
+
80
+ # The list of required files.
81
+ @requires = []
82
+
83
+ # The list of the code texts (the first one should be the one
84
+ # containing the top system).
85
+ @texts = []
86
+
87
+ # The list of the code checkers.
88
+ @checks = []
89
+
90
+ # The name of the top instance
91
+ @top_name = TOP_NAME
92
+ end
93
+
94
+ # Loads a single +file+.
95
+ #
96
+ # NOTE: +file+ can either be a file or a file name.
97
+ def read(file)
98
+ # Resolve the file.
99
+ if file.respond_to?(:read) then
100
+ found = file
101
+ else
102
+ found = File.join(@dir,file)
103
+ unless File.exist?(found) then
104
+ founds = Dir.glob(@std_dirs.map do |path|
105
+ File.join(path,file)
106
+ end)
107
+ if founds.empty? then
108
+ # No standard file with this name, this is an error.
109
+ raise "Unknown required file: #{file}."
110
+ else
111
+ # A standard file is found, skip it since it does not
112
+ # need to be read.
113
+ # show? "Standard files: #{founds}"
114
+ return false
115
+ end
116
+ end
117
+ end
118
+ # Load the file.
119
+ @texts << File.read(found)
120
+ if found.respond_to?(:path) then
121
+ @checks << Checker.new(@texts[-1],found.path)
122
+ else
123
+ @checks << Checker.new(@texts[-1])
124
+ end
125
+ return true
126
+ end
127
+
128
+ # Loads all the files from +file+.
129
+ def read_all(file = nil)
130
+ unless file then
131
+ if @top_file then
132
+ file = @top_file
133
+ else
134
+ file = @top_file_name
135
+ end
136
+ end
137
+ # show? "read_all with file=#{file}"
138
+ # Read the file
139
+ # read(file)
140
+ unless read(file) then
141
+ # The file is to skip.
142
+ return
143
+ end
144
+ # Get its required files.
145
+ requires = @checks[-1].get_all_requires +
146
+ @checks[-1].get_all_require_relatives
147
+ requires.each do |file|
148
+ read_all(file)
149
+ end
150
+ @requires += requires
151
+ @requires.uniq!
152
+ end
153
+
154
+ # Checks the read files.
155
+ def check_all
156
+ @checks.each { |check| check.assign_check }
157
+ end
158
+
159
+ # Displays the syntax tree of all the files.
160
+ def show_all(outfile = $stdout)
161
+ # show? "@checks.size=#{@checks.size}"
162
+ @checks.each { |check| check.show(outfile) }
163
+ end
164
+
165
+ # Gets the (first) top system.
166
+ def get_top
167
+ # Get all the systems.
168
+ systems = @checks.reduce([]) {|ar,check| ar + check.get_all_systems}
169
+ # show? "First systems=#{systems}"
170
+ # Remove the systems that are instantiated or included
171
+ # (they cannot be tops)
172
+ @checks.each do |check|
173
+ # The instances
174
+ check.get_all_instances(systems).each do |instance|
175
+ systems.delete(check.get_instance_system(instance))
176
+ end
177
+ # The explicitly included systems
178
+ check.get_all_includes(systems).each do |included|
179
+ systems.delete(check.get_include_system(included))
180
+ end
181
+ # The system included when declaring (inheritance)
182
+ check.get_all_inherits(systems).each do |inherit|
183
+ systems -= check.get_inherit_systems(inherit)
184
+ end
185
+ end
186
+ # show? "Now systems=#{systems}"
187
+ # Return the first top of the list.
188
+ return systems[-1]
189
+ end
190
+
191
+
192
+ # Load the HDLRuby structure from an instance of the top module.
193
+ def parse
194
+ # Is there a top system specified yet?
195
+ if @top_system == "" then
196
+ # No, look for it.
197
+ @top_system = get_top
198
+ # show? "@top_system=#{@top_system}"
199
+ unless @top_system then
200
+ # Not found? Error.
201
+ # Maybe it is a parse error, look for it.
202
+ bind = TOPLEVEL_BINDING.clone
203
+ eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
204
+ eval(@texts[0],bind,@top_file_name,1)
205
+ # No parse error found.
206
+ raise "Cannot find a top system." unless @top_system
207
+ end
208
+ end
209
+ # Initialize the environment for processing the hdr file.
210
+ bind = TOPLEVEL_BINDING.clone
211
+ eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
212
+ # Process it.
213
+ eval(@texts[0],bind,@top_file_name,1)
214
+ # Get the resulting instance
215
+ if @params.empty? then
216
+ # There is no generic parameter
217
+ @top_instance =
218
+ eval("#{@top_system} :#{@top_name}\n#{@top_name}",bind)
219
+ else
220
+ # There are generic parameters
221
+ @top_instance =
222
+ # eval("#{@top_system} :#{@top_name},#{@params.join(",")}\n#{@top_name}",bind)
223
+ eval("#{@top_system}(#{@params.join(",")}).(:#{@top_name})\n#{@top_name}",bind)
224
+ end
225
+ end
226
+ end
227
+
228
+
229
+ # Extend the Code class with generation of file for the content.
230
+ class HDLRuby::Low::Code
231
+
232
+ ## Creates a file in +path+ containing the content of the code.
233
+ def to_file(path = "")
234
+ self.each_chunk do |chunk|
235
+ # Process the lumps of the chunk.
236
+ # NOTE: for now use the C code generation of Low2C
237
+ content = chunk.to_c
238
+ # Dump to a file.
239
+ if chunk.name != :sim then
240
+ # The chunk is to be dumbed to a file.
241
+ # show? "Outputing chunk:#{HDLRuby::Low::Low2C.obj_name(chunk)}"
242
+ outfile = File.open(path + "/" +
243
+ HDLRuby::Low::Low2C.obj_name(chunk) + "." +
244
+ chunk.name.to_s,"w")
245
+ outfile << content
246
+ outfile.close
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+
253
+ end
254
+
255
+ # Locate an executable from cmd.
256
+ def which(cmd)
257
+ # Get the possible exetensions (for windows case).
258
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
259
+ # Look for the command within the executable paths.
260
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
261
+ exts.each do |ext|
262
+ exe = File.join(path, "#{cmd}#{ext}")
263
+ return exe if File.executable?(exe) && !File.directory?(exe)
264
+ end
265
+ end
266
+ nil
267
+ end
268
+
269
+
270
+
271
+ if __FILE__ == $0 then
272
+ # From hdrcc.rb
273
+ $hdr_dir = File.dirname(__FILE__)
274
+ else
275
+ # Form hdrcc
276
+ $hdr_dir = File.dirname(Gem.bin_path("HDLRuby","hdrcc")).chomp("exe") +
277
+ "lib/HDLRuby"
278
+ end
279
+
280
+ include HDLRuby
281
+
282
+
283
+ def hdr_test
284
+ $top = "__test__"
285
+ tests = $options[:test]
286
+ if tests then
287
+ tests = tests.to_s.split(",")
288
+ tests.map! {|test| ":\"#{test}\"" }
289
+ tests = ", #{tests.join(",")}"
290
+ else
291
+ tests = ""
292
+ end
293
+ # Generate the unit test file.
294
+ $test_file = Tempfile.new('tester.rb',Dir.getwd)
295
+ $test_file.write("require 'std/hruby_unit.rb'\nrequire_relative '#{$input}'\n\n" +
296
+ "HDLRuby::Unit.test(:\"#{$top}\"#{tests})\n")
297
+ # $test_file.rewind
298
+ # show? $test_file.read
299
+ # exit
300
+ $test_file.rewind
301
+ # It is the new input file.
302
+ $input = $test_file
303
+ end
304
+
305
+ # Sets the options.
306
+ $options = {}
307
+
308
+ # Sets the default input name.
309
+ $input = "top_system"
310
+
311
+ # Open the output.
312
+ $output = "HDLRubyWorkspace"
313
+
314
+ def hdr_output(output = $output)
315
+ # Create a directory if necessary.
316
+ unless File.directory?($output)
317
+ FileUtils.mkdir_p($output)
318
+ end
319
+ end
320
+
321
+ hdr_output
322
+
323
+ # Read some files.
324
+ def hdr_load(input)
325
+ # loader = HDRLoad.new($top,input,"./",*params)
326
+ # loader.read_all
327
+ # loader.check_all
328
+ # # Not debug mode, use the error management.
329
+ # error_manager(loader.requires + [input]) { top_instance = loader.parse }
330
+ # $top_system = top_instance.to_low.systemT
331
+ # $top_intance = nil # Free as much memory as possible.
332
+ load(input)
333
+ end
334
+
335
+
336
+ # Process a system for generation.
337
+ def hdr_make(sys,params = [])
338
+ if sys.is_a?(SystemI) then
339
+ $top_system = sys.to_low.systemT
340
+ elsif params.empty? then
341
+ $top_system = sys.(HDLRuby.uniq_name).to_low.systemT
342
+ else
343
+ $top_system = sys.(*params).(HDLRuby.uniq_name).to_low.systemT
344
+ end
345
+ end
346
+
347
+ $non_hdlruby = []
348
+
349
+ def hdr_code
350
+ # Gather the non-HDLRuby code.
351
+ $top_system.each_systemT_deep do |systemT|
352
+ systemT.scope.each_scope_deep do |scope|
353
+ scope.each_code do |code|
354
+ non_hdlruby << code
355
+ end
356
+ end
357
+ end
358
+ # Generates its code.
359
+ $non_hdlruby.each {|code| code.to_file($output) }
360
+ end
361
+
362
+
363
+ def hdr_yaml
364
+ puts $top_system.to_yaml
365
+ end
366
+
367
+ def hdr_hdr
368
+ puts $top_system.to_hdr
369
+ end
370
+
371
+ def hdr_sim
372
+ $top_system.each_systemT_deep do |systemT|
373
+ HDLRuby.show "seq2seq step..."
374
+ # Coverts the par blocks in seq blocks to seq blocks to match
375
+ # the simulation engine.
376
+ systemT.par_in_seq2seq!
377
+ HDLRuby.show Time.now
378
+ HDLRuby.show "connections_to_behaviors step..."
379
+ # Converts the connections to behaviors.
380
+ systemT.connections_to_behaviors!
381
+ HDLRuby.show Time.now
382
+ # Break the RefConcat.
383
+ HDLRuby.show "concat_assigns step..."
384
+ systemT.break_concat_assigns!
385
+ HDLRuby.show Time.now
386
+ # Explicits the types.
387
+ HDLRuby.show "explicit_types step..."
388
+ systemT.explicit_types!
389
+ HDLRuby.show Time.now
390
+ end
391
+ # Generate the C.
392
+ # Get the base name of the input file, it will be used for
393
+ # generating the main name of the multiple result files.
394
+ $basename = File.basename($input,File.extname($input))
395
+ $basename = $output + "/" + $basename
396
+ # Multiple files generation mode.
397
+ # Generate the h file.
398
+ $hname = $output + "/hruby_sim_gen.h"
399
+ $hnames = [ File.basename($hname) ]
400
+ $outfile = File.open($hname,"w")
401
+ # Adds the generated globals
402
+ $top_system.each_systemT_deep do |systemT|
403
+ systemT.to_ch($outfile)
404
+ # # # Close the file.
405
+ # # output.close
406
+ # # # Clears the name.
407
+ # # hname = nil
408
+ end
409
+ # Adds the globals from the non-HDLRuby code
410
+ $non_hdlruby.each do |code|
411
+ code.each_chunk do |chunk|
412
+ if chunk.name == :sim then
413
+ $outfile << "extern "
414
+ $outfile << HDLRuby::Low::Low2C.prototype(chunk.to_c(""))
415
+ end
416
+ end
417
+ end
418
+ $outfile.close
419
+
420
+ # Prepare the initial name for the main file.
421
+ $name = $basename + ".c"
422
+ # Generate the code for it.
423
+ $main = File.open($name,"w")
424
+
425
+ # Select the vizualizer depending on the options.
426
+ init_visualizer = $options[:vcd] ? "init_vcd_visualizer" :
427
+ "init_default_visualizer"
428
+
429
+ # Gather the system to generate and sort them in the right order
430
+ # to ensure references are generated before being used.
431
+ # Base: reverse order of the tree.
432
+ # Then, multiple configuration of a system instance must be
433
+ # reverversed so that the base configuration is generated first.
434
+ c_systems = $top_system.each_systemT_deep_ref
435
+ # Generate the code of the main function.
436
+ # HDLRuby start code
437
+ $main << HDLRuby::Low::Low2C.main("hruby_simulator",
438
+ init_visualizer,
439
+ $top_system,
440
+ c_systems,
441
+ $hnames)
442
+ $main.close
443
+
444
+ $top_system.each_systemT_deep do |systemT|
445
+ # For the c file.
446
+ name = $output + "/" +
447
+ HDLRuby::Low::Low2C.c_name(systemT.name) +
448
+ ".c"
449
+ # show? "for systemT=#{systemT.name} generating: #{name}"
450
+ # Open the file for current systemT
451
+ outfile = File.open(name,"w")
452
+ # Generate the C code in to.
453
+ # outfile << systemT.to_c(0,*$hnames)
454
+ systemT.to_c(outfile,0,*$hnames)
455
+ # Close the file.
456
+ outfile.close
457
+ # Clears the name.
458
+ name = nil
459
+ end
460
+
461
+ # Simulation mode, compile and exectute.
462
+ # Path of the simulator core files.
463
+ $simdir = $hdr_dir + "/sim/"
464
+ # Generate and execute the simulation commands.
465
+ # Kernel.system("cp -n #{simdir}* #{$output}/; cd #{$output}/ ; make -s ; ./hruby_simulator")
466
+ Dir.entries($simdir).each do |filename|
467
+ if !File.directory?(filename) && /\.[ch]$/ === filename then
468
+ FileUtils.cp($simdir + "/" + filename,$output)
469
+ end
470
+ end
471
+ Dir.chdir($output)
472
+ # Find the compiler.
473
+ cc_cmd = which('cc')
474
+ unless cc_cmd then
475
+ cc_cmd = which('gcc')
476
+ end
477
+ unless cc_cmd then
478
+ raise "Could not find any compiler, please compile by hand as follows:\n" +
479
+ " In folder #{$output} execute:\n" +
480
+ " <my compiler> -o hruby_simulator *.c -lpthread\n" +
481
+ " Then execute:\n hruby_simulator"
482
+ end
483
+ # Use it.
484
+ Kernel.system("#{cc_cmd} -o3 -o hruby_simulator *.c -lpthread")
485
+ Kernel.system("./hruby_simulator")
486
+ Dir.chdir("..")
487
+ end
488
+
489
+ def hdr_verilog
490
+ # Make description compatible with verilog generation.
491
+ $top_system.each_systemT_deep do |systemT|
492
+ # HDLRuby.show "casts_without_expression! step..."
493
+ # systemT.casts_without_expression!
494
+ # HDLRuby.show Time.now
495
+ HDLRuby.show "to_upper_space! step..."
496
+ systemT.to_upper_space!
497
+ HDLRuby.show Time.now
498
+ end
499
+ HDLRuby.show "to_global_space! step (global)..."
500
+ $top_system.to_global_systemTs!
501
+ HDLRuby.show Time.now
502
+ $top_system.each_systemT_deep do |systemT|
503
+ ## systemT.break_types!
504
+ ## systemT.expand_types!
505
+ HDLRuby.show "par_in_seq2seq! step..."
506
+ systemT.par_in_seq2seq!
507
+ HDLRuby.show Time.now
508
+ HDLRuby.show "initial_concat_to_timed! step..."
509
+ systemT.initial_concat_to_timed!
510
+ HDLRuby.show Time.now
511
+ HDLRuby.show "with_port! step..."
512
+ systemT.with_port!
513
+ HDLRuby.show Time.now
514
+ end
515
+ # # Verilog generation
516
+ # $output << top_system.to_verilog
517
+ # Generate the Verilog.
518
+ # Get the base name of the input file, it will be used for
519
+ # generating the main name of the multiple result files.
520
+ $basename = File.basename($input,File.extname($input))
521
+ $basename = $output + "/" + $basename
522
+ # # File name counter.
523
+ # $namecount = 0
524
+ # Prepare the initial name for the main file.
525
+ $name = $basename + ".v"
526
+ # Multiple files generation mode.
527
+ $top_system.each_systemT_deep do |systemT|
528
+ # Generate the name if necessary.
529
+ unless $name
530
+ $name = $output + "/" +
531
+ HDLRuby::Verilog.name_to_verilog(systemT.name) +
532
+ ".v"
533
+ end
534
+ # Open the file for current systemT
535
+ outfile = File.open($name,"w")
536
+ # Generate the Verilog code in to.
537
+ outfile << systemT.to_verilog
538
+ # Close the file.
539
+ outfile.close
540
+ # Clears the name.
541
+ $name = nil
542
+ end
543
+ end
544
+
545
+ def hdr_vhdl
546
+ # top_system = $top_instance.to_low.systemT
547
+ # top_system = $top_system
548
+ # Make description compatible with vhdl generation.
549
+ $top_system.each_systemT_deep do |systemT|
550
+ systemT.outread2inner! unless $options[:vhdl08] || $options[:alliance]
551
+ systemT.with_boolean!
552
+ systemT.boolean_in_assign2select! unless $options[:alliance]
553
+ systemT.bit2vector2inner! unless $options[:vhdl08] || $options[:alliance]
554
+ systemT.select2case! # if $options[:alliance]
555
+ systemT.break_concat_assigns! # if $options[:alliance]
556
+ systemT.to_upper_space!
557
+ systemT.to_global_systemTs!
558
+ systemT.break_types!
559
+ systemT.with_port!
560
+ systemT.with_var!
561
+ systemT.cleanup!
562
+ end
563
+ # Generate the vhdl.
564
+ # Get the base name of the input file, it will be used for
565
+ # generating the main name of the multiple result files.
566
+ $basename = File.basename($input,File.extname($input))
567
+ $basename = $output + "/" + $basename
568
+ # # File name counter.
569
+ # $namecount = 0
570
+ # Prepare the initial name for the main file.
571
+ $name = $basename + ".vhd"
572
+ # Multiple files generation mode.
573
+ $top_system.each_systemT_deep do |systemT|
574
+ # Generate the name if necessary.
575
+ unless $name
576
+ $name = $output + "/" +
577
+ HDLRuby::Low::Low2VHDL.entity_name(systemT.name) +
578
+ ".vhd"
579
+ end
580
+ # Open the file for current systemT
581
+ outfile = File.open($name,"w")
582
+ # Generate the VHDL code in to.
583
+ outfile << systemT.to_vhdl
584
+ # Close the file.
585
+ outfile.close
586
+ # Clears the name.
587
+ $name = nil
588
+ end
589
+ end
590
+
591
+
592
+ configure_high