HDLRuby 2.4.27 → 2.6.2

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.
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