HDLRuby 2.4.27 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/HDLRuby/drivers/xcd.rb +79 -0
  3. data/lib/HDLRuby/drivers/xcd/dummy.xcd +4 -0
  4. data/lib/HDLRuby/hdr_samples/adder.rb +1 -1
  5. data/lib/HDLRuby/hdr_samples/adder_bench.rb +1 -1
  6. data/lib/HDLRuby/hdr_samples/adder_gen.rb +1 -1
  7. data/lib/HDLRuby/hdr_samples/constant_in_function.rb +27 -0
  8. data/lib/HDLRuby/hdr_samples/dff_properties.rb +19 -0
  9. data/lib/HDLRuby/hdr_samples/dff_unit.rb +54 -0
  10. data/lib/HDLRuby/hdr_samples/huge_rom.rb +25 -0
  11. data/lib/HDLRuby/hdr_samples/logic_bench.rb +21 -0
  12. data/lib/HDLRuby/hdr_samples/mei8_bench.rb +1 -1
  13. data/lib/HDLRuby/hdr_samples/music.rb +79 -0
  14. data/lib/HDLRuby/hdr_samples/named_sub.rb +42 -0
  15. data/lib/HDLRuby/hdr_samples/rom.rb +16 -0
  16. data/lib/HDLRuby/hdr_samples/seqpar_bench.rb +59 -0
  17. data/lib/HDLRuby/hdr_samples/with_function_generator.rb +25 -0
  18. data/lib/HDLRuby/hdrcc.rb +140 -24
  19. data/lib/HDLRuby/hruby_decorator.rb +250 -0
  20. data/lib/HDLRuby/hruby_high.rb +468 -91
  21. data/lib/HDLRuby/hruby_low.rb +913 -45
  22. data/lib/HDLRuby/hruby_low2c.rb +189 -168
  23. data/lib/HDLRuby/hruby_low2hdr.rb +738 -0
  24. data/lib/HDLRuby/hruby_low2high.rb +331 -549
  25. data/lib/HDLRuby/hruby_low2vhd.rb +39 -2
  26. data/lib/HDLRuby/hruby_low_bool2select.rb +29 -0
  27. data/lib/HDLRuby/hruby_low_casts_without_expression.rb +27 -0
  28. data/lib/HDLRuby/hruby_low_fix_types.rb +25 -0
  29. data/lib/HDLRuby/hruby_low_mutable.rb +70 -0
  30. data/lib/HDLRuby/hruby_low_resolve.rb +28 -0
  31. data/lib/HDLRuby/hruby_low_without_connection.rb +6 -3
  32. data/lib/HDLRuby/hruby_low_without_namespace.rb +7 -4
  33. data/lib/HDLRuby/hruby_low_without_parinseq.rb +151 -0
  34. data/lib/HDLRuby/hruby_low_without_select.rb +13 -0
  35. data/lib/HDLRuby/hruby_tools.rb +11 -1
  36. data/lib/HDLRuby/hruby_verilog.rb +1602 -1629
  37. data/lib/HDLRuby/sim/hruby_sim.h +25 -2
  38. data/lib/HDLRuby/sim/hruby_sim_calc.c +63 -6
  39. data/lib/HDLRuby/sim/hruby_sim_vcd.c +5 -1
  40. data/lib/HDLRuby/sim/hruby_sim_vizualize.c +22 -6
  41. data/lib/HDLRuby/std/fixpoint.rb +9 -0
  42. data/lib/HDLRuby/std/function_generator.rb +139 -0
  43. data/lib/HDLRuby/std/hruby_unit.rb +75 -0
  44. data/lib/HDLRuby/template_expander.rb +61 -0
  45. data/lib/HDLRuby/version.rb +1 -1
  46. metadata +22 -5
@@ -0,0 +1,25 @@
1
+ require 'std/function_generator.rb'
2
+
3
+ include HDLRuby::High::Std
4
+
5
+ # System for testing the function generator standard library.
6
+ system :with_function_generator do
7
+ # signed[8].inner :x
8
+ # signed[32].inner :y
9
+ bit[8].inner :x
10
+ signed[8].inner :y
11
+
12
+ # function_generator(Math.method(:sin).to_proc,
13
+ # signed[8],signed[32],4,-Math::PI..Math::PI,-2..2).
14
+ function_generator(Math.method(:sin).to_proc,
15
+ bit[8],signed[8],4,-Math::PI..Math::PI,-2..2).
16
+ (:my_sin).(x,y)
17
+
18
+ timed do
19
+ # (-128..127).each do |i|
20
+ (0..255).each do |i|
21
+ x <= i
22
+ !10.ns
23
+ end
24
+ end
25
+ end
data/lib/HDLRuby/hdrcc.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
3
  require 'fileutils'
4
+ require 'tempfile'
4
5
  require 'HDLRuby'
5
6
  require 'HDLRuby/hruby_check.rb'
6
7
  # require 'ripper'
7
- require 'HDLRuby/hruby_low2high'
8
+ require 'HDLRuby/hruby_low2hdr'
8
9
  require 'HDLRuby/hruby_low2c'
9
10
  require 'HDLRuby/hruby_low2vhd'
10
11
  require 'HDLRuby/hruby_low_fix_types'
@@ -20,6 +21,7 @@ require 'HDLRuby/hruby_low_with_var'
20
21
  require 'HDLRuby/hruby_low_without_concat'
21
22
  require 'HDLRuby/hruby_low_without_connection'
22
23
  require 'HDLRuby/hruby_low_casts_without_expression'
24
+ require 'hruby_low_without_parinseq'
23
25
  require 'HDLRuby/hruby_low_cleanup'
24
26
 
25
27
  require 'HDLRuby/hruby_verilog.rb'
@@ -49,12 +51,21 @@ module HDLRuby
49
51
  # The required files.
50
52
  attr_reader :requires
51
53
 
52
- # Creates a new loader for a +top_system+ system in file +top_file+
54
+ # Creates a new loader for a +top_system+ system in file +top_file_name+
53
55
  # from directory +dir+ with generic parameters +params+.
56
+ #
57
+ # NOTE: +top_file+ can either be a file or a file name.
54
58
  def initialize(top_system,top_file,dir,*params)
55
59
  # Sets the top and the looking directory.
56
60
  @top_system = top_system.to_s
57
- @top_file = top_file.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
58
69
  @dir = dir.to_s
59
70
  @params = params
60
71
 
@@ -81,31 +92,48 @@ module HDLRuby
81
92
  end
82
93
 
83
94
  # Loads a single +file+.
95
+ #
96
+ # NOTE: +file+ can either be a file or a file name.
84
97
  def read(file)
85
98
  # Resolve the file.
86
- found = File.join(@dir,file)
87
- unless File.exist?(found) then
88
- founds = Dir.glob(@std_dirs.map {|path| File.join(path,file) })
89
- if founds.empty? then
90
- # No standard file with this name, this is an error.
91
- raise "Unknown required file: #{file}."
92
- else
93
- # A standard file is found, skip it since it does not
94
- # need to be read.
95
- # puts "Standard files: #{founds}"
96
- return false
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
+ # puts "Standard files: #{founds}"
114
+ return false
115
+ end
97
116
  end
98
117
  end
99
118
  # Load the file.
100
- # @texts << File.read(File.join(@dir,file) )
101
119
  @texts << File.read(found)
102
- # @checks << Checker.new(@texts[-1],file)
103
- @checks << Checker.new(@texts[-1],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
104
125
  return true
105
126
  end
106
127
 
107
128
  # Loads all the files from +file+.
108
- def read_all(file = @top_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
109
137
  # puts "read_all with file=#{file}"
110
138
  # Read the file
111
139
  # read(file)
@@ -173,7 +201,7 @@ module HDLRuby
173
201
  # Maybe it is a parse error, look for it.
174
202
  bind = TOPLEVEL_BINDING.clone
175
203
  eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
176
- eval(@texts[0],bind,@top_file,1)
204
+ eval(@texts[0],bind,@top_file_name,1)
177
205
  # No parse error found.
178
206
  raise "Cannot find a top system." unless @top_system
179
207
  end
@@ -182,7 +210,7 @@ module HDLRuby
182
210
  bind = TOPLEVEL_BINDING.clone
183
211
  eval("require 'HDLRuby'\n\nconfigure_high\n\n",bind)
184
212
  # Process it.
185
- eval(@texts[0],bind,@top_file,1)
213
+ eval(@texts[0],bind,@top_file_name,1)
186
214
  # Get the resulting instance
187
215
  if @params.empty? then
188
216
  # There is no generic parameter
@@ -309,14 +337,24 @@ $optparse = OptionParser.new do |opts|
309
337
  opts.on("-D", "--debug","Set the HDLRuby debug mode") do |d|
310
338
  $options[:debug] = d
311
339
  end
340
+ opts.on("-T","--test t0,t1,t2","Compile the unit tests named t0,t1,...") do |t|
341
+ $options[:test] = t
342
+ end
343
+ opts.on("--testall","Compile all the available unit tests.") do |t|
344
+ $options[:testall] = t
345
+ end
312
346
  opts.on("-t", "--top system", "Specify the top system to process") do|t|
313
347
  $options[:top] = t
314
348
  end
315
349
  opts.on("-p", "--param x,y,z", "Specify the generic parameters") do |p|
316
350
  $options[:param] = p
317
351
  end
318
- opts.on("--version", "Print the version number, then exit") do
319
- puts "hdrcc: HDLRuby #{HDLRuby::VERSION} compiler"
352
+ opts.on("--dump","Dump all the properties to yaml files") do |v|
353
+ $options[:dump] = v
354
+ $options[:multiple] = v
355
+ end
356
+ opts.on("--version", "Shows the version of HDLRuby.") do |v|
357
+ puts VERSION
320
358
  exit
321
359
  end
322
360
  # opts.on_tail("-h", "--help", "Show this message") do
@@ -369,6 +407,28 @@ if $input == nil then
369
407
  exit
370
408
  end
371
409
 
410
+ if ($options[:test] || $options[:testall]) then
411
+ $top = "__test__"
412
+ tests = $options[:test]
413
+ if tests then
414
+ tests = tests.to_s.split(",")
415
+ tests.map! {|test| ":\"#{test}\"" }
416
+ tests = ", #{tests.join(",")}"
417
+ else
418
+ tests = ""
419
+ end
420
+ # Generate the unit test file.
421
+ $test_file = Tempfile.new('tester.rb',Dir.getwd)
422
+ $test_file.write("require 'std/hruby_unit.rb'\nrequire_relative '#{$input}'\n\n" +
423
+ "HDLRuby::Unit.test(:\"#{$top}\"#{tests})\n")
424
+ # $test_file.rewind
425
+ # puts $test_file.read
426
+ # exit
427
+ $test_file.rewind
428
+ # It is the new input file.
429
+ $input = $test_file
430
+ end
431
+
372
432
  # Open the output.
373
433
  if $output then
374
434
  if $options[:multiple] then
@@ -381,7 +441,7 @@ if $output then
381
441
  $output = File.open($output,"w")
382
442
  end
383
443
  else
384
- if $option[:multiple] then
444
+ if $options[:multiple] then
385
445
  raise "Need a target directory in multiple files generation mode."
386
446
  end
387
447
  $output = $stdout
@@ -393,6 +453,12 @@ $loader = HDRLoad.new($top,$input,$options[:directory].to_s,*$params)
393
453
  $loader.read_all
394
454
  $loader.check_all
395
455
 
456
+ # Remove the test file if any, it is not needed any longer.
457
+ if $test_file then
458
+ $test_file.close
459
+ $test_file.unlink
460
+ end
461
+
396
462
  if $options[:syntax] then
397
463
  if $options[:multiple] then
398
464
  raise "Multiple files generation mode not supported for syntax tree output."
@@ -413,6 +479,24 @@ end
413
479
  # Get the top systemT.
414
480
  $top_system = $top_instance.to_low.systemT
415
481
 
482
+
483
+ # Apply the pre drivers if any.
484
+ Hdecorator.each_with_property(:pre_driver) do |obj, value|
485
+ unless value.is_a?(Array) && value.size == 2 then
486
+ raise "pre_driver requires a driver file name command name."
487
+ end
488
+ # Load the driver.
489
+ require_relative(value[0].to_s)
490
+ # Ensure obj is the low version.
491
+ if obj.properties.key?(:high2low) then
492
+ # obj is high, get the corresponding low.
493
+ obj = obj.properties[:high2low][0]
494
+ end
495
+ # Execute it.
496
+ send(value[1].to_sym,obj,*value[2..-1])
497
+ end
498
+
499
+
416
500
  # Gather the non-HDLRuby code.
417
501
  $non_hdlruby = []
418
502
  $top_system.each_systemT_deep do |systemT|
@@ -454,12 +538,15 @@ elsif $options[:hdr] then
454
538
  # $output << systemT.to_high
455
539
  # end
456
540
  # $output << $top_instance.to_low.systemT.to_high
457
- $output << $top_system.to_high
541
+ $output << $top_system.to_hdr
458
542
  elsif $options[:clang] then
459
543
  # top_system = $top_instance.to_low.systemT
460
544
  # top_system = $top_system
461
545
  # Preprocess the HW description for valid C generation.
462
546
  $top_system.each_systemT_deep do |systemT|
547
+ # Coverts the par blocks in seq blocks to seq blocks to match
548
+ # the simulation engine.
549
+ systemT.par_in_seq2seq!
463
550
  # Converts the connections to behaviors.
464
551
  systemT.connections_to_behaviors!
465
552
  # Break the RefConcat.
@@ -583,6 +670,7 @@ elsif $options[:verilog] then
583
670
  systemT.to_global_systemTs!
584
671
  # systemT.break_types!
585
672
  # systemT.expand_types!
673
+ systemT.par_in_seq2seq!
586
674
  systemT.initial_concat_to_timed!
587
675
  systemT.with_port!
588
676
  end
@@ -673,3 +761,31 @@ elsif $options[:vhdl] then
673
761
  end
674
762
  end
675
763
  end
764
+
765
+ # Apply the post drivers if any.
766
+ Hdecorator.each_with_property(:post_driver) do |obj, value|
767
+ # Load the driver.
768
+ require_relative(value[0].to_s)
769
+ # Execute it.
770
+ send(value[1].to_sym,obj,$output)
771
+ end
772
+
773
+ # Dump the properties
774
+ if $options[:dump] then
775
+ # Decorate with the parent ids.
776
+ Hdecorator.decorate_parent_id
777
+
778
+ # Generate the directory for the properties
779
+ property_dir = $output + "/properties"
780
+ unless File.directory?(property_dir)
781
+ FileUtils.mkdir_p(property_dir)
782
+ end
783
+
784
+ # Dump to one file per key
785
+ Properties.each_key do |key|
786
+ File.open(property_dir + "/#{key}.yaml", "w") do |f|
787
+ Hdecorator.dump(key,f)
788
+ end
789
+ end
790
+
791
+ end
@@ -0,0 +1,250 @@
1
+ require 'yaml'
2
+ require 'set'
3
+
4
+ module HDLRuby
5
+
6
+ ##
7
+ # Library for describing a decorator used for adding properties to
8
+ # HDLRuby objects that are persistent and can be used for back annotation
9
+ ########################################################################
10
+
11
+ ##
12
+ # Gives a decorator the HDLRuby object.
13
+ module Hdecorator
14
+ # The decorator requires that each HDLRuby object has a uniq
15
+ # persistent id
16
+
17
+ # The id
18
+ attr_reader :hdr_id
19
+
20
+ # The id to object table
21
+ @@id_map = {}
22
+
23
+ # Generate the ID
24
+ @@id_gen = 0
25
+
26
+ # Ensures the ID is generated when object is initialized
27
+ def self.included(base) # built-in Ruby hook for modules
28
+ base.class_eval do
29
+ original_method = instance_method(:initialize)
30
+ define_method(:initialize) do |*args, &block|
31
+ original_method.bind(self).call(*args, &block)
32
+ # Generate the id.
33
+ @hdr_id = @@id_gen
34
+ @@id_gen += 1
35
+ # Update the id to object table
36
+ @@id_map[@hdr_id] = self
37
+ end
38
+ end
39
+ end
40
+
41
+ # Get an object by id.
42
+ def self.get(id)
43
+ return @@id_map[id]
44
+ end
45
+
46
+ # Iterate over all the id with their object.
47
+ #
48
+ # Returns an enumerator if no ruby block is given.
49
+ #
50
+ # NOTE: converts the hash to an array to allow on-the-fly modification.
51
+ def self.each(&ruby_block)
52
+ # No ruby block? Return an enumerator.
53
+ return to_enum(:each) unless ruby_block
54
+ # A ruby block? Apply it on each object.
55
+ @@id_map.to_a.each(&ruby_block)
56
+ end
57
+
58
+ # The decorator also need to add properties to the HDLRuby objects.
59
+
60
+ # Access the set of properties
61
+ def properties
62
+ # Create the properties if not present.
63
+ unless @properties then
64
+ @properties = Properties.new(self)
65
+ end
66
+ return @properties
67
+ end
68
+
69
+ # Iterate over all the objects from +top+ with +prop+ property.
70
+ #
71
+ # Returns an enumerator if no ruby block is given.
72
+ # NOTE: if +top+ is not given, iterate over all the objects.
73
+ def self.each_with_property(prop, top = nil, &ruby_block)
74
+ # No ruby block? Return an enumerator.
75
+ return to_enum(:each_with_property) unless ruby_block
76
+ # A ruby block? Apply the ruby_block...
77
+ if (top) then
78
+ # A top... on each object from it.
79
+ top.each_deep do |obj|
80
+ if (obj.properties.key?(prop)) then
81
+ ruby_block.call(obj, *obj.properties[prop])
82
+ end
83
+ end
84
+ else
85
+ # No top... on all the objects.
86
+ self.each do |id,obj|
87
+ if (obj.properties.key?(prop)) then
88
+ ruby_block.call(obj, *obj.properties[prop])
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ # # Access the set of properties and the inherited properties from
95
+ # # the high objects.
96
+ # def all_properties
97
+ # high_id = self.properties[:low2high]
98
+ # if high_id && high_id >= 0 then
99
+ # return properties.merge(Hdecorator.get(high_id))
100
+ # else
101
+ # return properties.clone
102
+ # end
103
+ # end
104
+
105
+ # Saves properties +key+ of all the object associated with
106
+ # their id to +target+.
107
+ def self.dump(key, target = "")
108
+ # Build the table to dump
109
+ tbl = {}
110
+ self.each do |id,obj|
111
+ value = obj.properties[key]
112
+ if value.any? then
113
+ tbl[id] = value
114
+ end
115
+ end
116
+ # Dump the table.
117
+ target << YAML.dump(tbl)
118
+ return target
119
+ end
120
+
121
+ # Loads properties to +key+ for all objects from +source+.
122
+ def self.load(source,key)
123
+ # Load the id to property table.
124
+ tbl = YAML.load(source)
125
+ # Adds the property of each object according to tbl
126
+ tbl.each do |id,value|
127
+ @@id_map[id].properties[key] = value
128
+ end
129
+ end
130
+
131
+ # Some predefined properties to set.
132
+
133
+ def self.decorate_parent_id
134
+ @@id_map.each do |id, obj|
135
+ parent = obj.parent
136
+ if parent then
137
+ obj.properties[:parent_id] = obj.parent.hdr_id
138
+ else
139
+ obj.properties[:parent_id] = -1
140
+ end
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+
147
+ ## A HDLRuby set of properties
148
+ class Properties
149
+
150
+ # The set of all the property keys
151
+ @@property_keys = Set.new
152
+
153
+ # The HDLRuby object owning of the set of properties
154
+ attr_reader :owner
155
+
156
+ # Create a new set of properties and attach it to HDLRuby object
157
+ # +owner+.
158
+ def initialize(owner)
159
+ # Attach the owner.
160
+ @owner = owner
161
+ # Create the set.
162
+ @content = {}
163
+ end
164
+
165
+ # Clones the properties: also clone the contents.
166
+ def clone
167
+ result = Properties.new(owner)
168
+ @contents.each do |k,vals|
169
+ vals.each { |v| result[k] = v }
170
+ end
171
+ return result
172
+ end
173
+
174
+ # Create a new set of properties by merging with +prop+
175
+ def merge(prop)
176
+ result = self.clone
177
+ prop.each do |k,vals|
178
+ vals.each { |v| result[k] = v }
179
+ end
180
+ return result
181
+ end
182
+
183
+ # Tells if +key+ is present.
184
+ def key?(key)
185
+ @content.key?(key)
186
+ end
187
+
188
+ # Add a property
189
+ def []=(key,value)
190
+ @@property_keys << key
191
+ # Add an entry if not present.
192
+ @content[key] = [] unless @content.key?(key)
193
+ # Add the value to the entry.
194
+ @content[key] << value
195
+ end
196
+
197
+ # Get a property
198
+ def [](key)
199
+ return @content[key]
200
+ end
201
+
202
+ # Iterate over each value associated with +key+.
203
+ def each_with_key(key,&ruby_block)
204
+ return unless @content.key?(key)
205
+ @content[key].each(&ruby_block)
206
+ end
207
+
208
+ # Iterate over the properties of the current set.
209
+ #
210
+ # Returns an enumerator if no ruby block is given.
211
+ def each(&ruby_block)
212
+ # No ruby block? Return an enumerator.
213
+ return to_enum(:each) unless ruby_block
214
+ # A ruby block? Apply it on each input signal instance.
215
+ @content.each(&ruby_block)
216
+ end
217
+
218
+ # Iterator over all the property keys
219
+ #
220
+ # Returns an enumerator if no ruby block is given.
221
+ def self.each_key(&ruby_block)
222
+ # No ruby block? Return an enumerator.
223
+ return to_enum(:each_key) unless ruby_block
224
+ # A ruby block? Apply it on each input signal instance.
225
+ @@property_keys.each(&ruby_block)
226
+ end
227
+
228
+ # # Iterate over the property set of all the objects from current owner.
229
+ # #
230
+ # # Returns an enumerator if no ruby block is given.
231
+ # def each_properties(&ruby_block)
232
+ # # No ruby block? Return an enumerator.
233
+ # return to_enum(:each_properties) unless ruby_block
234
+ # # A ruby block? Apply it.
235
+ # # On current property set
236
+ # ruby_block.call(self)
237
+ # # And on the properties set of sub objects of the owner.
238
+ # self.owner.instance_variables.each do |var|
239
+ # obj = owner.instance_variable_get(var)
240
+ # if (obj.is_a?(Hproperties)) then
241
+ # # obj has properties, recurse on them.
242
+ # obj.properties.each_properties(&ruby_block)
243
+ # end
244
+ # end
245
+ # end
246
+
247
+ end
248
+
249
+
250
+ end