origen 0.28.2 → 0.29.0

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/bin/origen +14 -2
  3. data/config/version.rb +2 -2
  4. data/lib/origen.rb +72 -45
  5. data/lib/origen/application.rb +29 -19
  6. data/lib/origen/application/deployer.rb +3 -1
  7. data/lib/origen/application/runner.rb +10 -8
  8. data/lib/origen/chip_mode.rb +1 -1
  9. data/lib/origen/commands.rb +24 -12
  10. data/lib/origen/commands/version.rb +1 -1
  11. data/lib/origen/commands_global.rb +32 -8
  12. data/lib/origen/core_ext.rb +1 -2
  13. data/lib/origen/core_ext/enumerable.rb +2 -2
  14. data/lib/origen/core_ext/integer.rb +85 -0
  15. data/lib/origen/core_ext/numeric.rb +28 -4
  16. data/lib/origen/global_app.rb +9 -0
  17. data/lib/origen/log.rb +1 -1
  18. data/lib/origen/model_initializer.rb +6 -1
  19. data/lib/origen/netlist/list.rb +2 -2
  20. data/lib/origen/org_file.rb +125 -0
  21. data/lib/origen/org_file/interceptable.rb +44 -0
  22. data/lib/origen/org_file/interceptor.rb +100 -0
  23. data/lib/origen/parameters/set.rb +1 -1
  24. data/lib/origen/pins.rb +4 -0
  25. data/lib/origen/pins/function_proxy.rb +8 -0
  26. data/lib/origen/pins/pin.rb +90 -38
  27. data/lib/origen/pins/pin_collection.rb +61 -21
  28. data/lib/origen/ports/port.rb +1 -1
  29. data/lib/origen/registers.rb +1 -1
  30. data/lib/origen/registers/reg.rb +1 -1
  31. data/lib/origen/remote_manager.rb +25 -15
  32. data/lib/origen/site_config.rb +140 -13
  33. data/lib/origen/specs/checkers.rb +2 -2
  34. data/lib/origen/sub_blocks.rb +6 -1
  35. data/lib/origen/value.rb +119 -0
  36. data/lib/origen/value/bin_str_val.rb +72 -0
  37. data/lib/origen/value/hex_str_val.rb +100 -0
  38. data/origen_site_config.yml +15 -8
  39. metadata +12 -6
  40. data/lib/origen/core_ext/bignum.rb +0 -38
  41. data/lib/origen/core_ext/fixnum.rb +0 -56
@@ -71,7 +71,7 @@ module Origen
71
71
  def drive(value = nil, options = {})
72
72
  value, options = nil, value if value.is_a?(Hash)
73
73
  if options[:index]
74
- if options[:index].is_a?(Fixnum)
74
+ if options[:index].is_a?(Integer)
75
75
  drive_values[options[:index]] = value ? value[0] : nil
76
76
  else
77
77
  options[:index].to_a.each do |i|
@@ -516,7 +516,7 @@ module Origen
516
516
  # Can also be used to define a new register if a block is supplied in which case
517
517
  # it is equivalent to calling add_reg with a block.
518
518
  def reg(*args, &block)
519
- if block_given? || (args[1].is_a?(Fixnum) && !try(:_initialized?))
519
+ if block_given? || (args[1].is_a?(Integer) && !try(:_initialized?))
520
520
  @reg_define_file = define_file(caller[0])
521
521
  add_reg(*args, &block)
522
522
  else
@@ -1095,7 +1095,7 @@ module Origen
1095
1095
  args.flatten!
1096
1096
  args.sort!
1097
1097
  args.each do |arg_item|
1098
- if arg_item.is_a?(Fixnum)
1098
+ if arg_item.is_a?(Integer)
1099
1099
  b = get_bits_with_constraint(arg_item, constraint)
1100
1100
  collection << b if b
1101
1101
  elsif arg_item.is_a?(Range)
@@ -22,9 +22,9 @@ module Origen
22
22
  Origen.log.info 'The following remotes need to be updated, this will now happen automatically:'
23
23
  dirty_remotes.each do |name, remote|
24
24
  if remote[:path]
25
- Origen.log.info " #{name} - #{remote[:path]}".green
25
+ Origen.log.info " #{name} - #{remote[:path]} (included by #{remote[:importer].name})".green
26
26
  else
27
- Origen.log.info " #{name} - #{remote[:version]}".green
27
+ Origen.log.info " #{name} - #{remote[:version]} (included by #{remote[:importer].name})".green
28
28
  end
29
29
  end
30
30
  Origen.log.info ''
@@ -216,11 +216,13 @@ module Origen
216
216
  @remotes = {}
217
217
  top_level_remotes
218
218
  top_level_remotes.each do |remote|
219
+ remote[:importer] = Origen.app
219
220
  add_remote(remote)
220
221
  end
221
222
  # Add remotes from imports
222
223
  Origen.app.plugins.each do |plugin|
223
224
  plugin.config.remotes.each do |import_remote|
225
+ import_remote[:importer] = plugin
224
226
  add_remote(import_remote) unless import_remote[:development]
225
227
  end
226
228
  end
@@ -292,20 +294,28 @@ module Origen
292
294
  rc_url = remote[:rc_url] || remote[:vault]
293
295
  tag = Origen::VersionString.new(remote[:version])
294
296
  version_file = dir.to_s + '/.current_version'
295
- if File.exist?("#{dir}/.initial_populate_successful")
296
- FileUtils.rm_f(version_file) if File.exist?(version_file)
297
- rc = RevisionControl.new remote: rc_url, local: dir
298
- rc.checkout version: prefix_tag(tag), force: true
299
- File.open(version_file, 'w') do |f|
300
- f.write tag
301
- end
302
- else
303
- rc = RevisionControl.new remote: rc_url, local: dir
304
- rc.checkout version: prefix_tag(tag), force: true
305
- FileUtils.touch "#{dir}/.initial_populate_successful"
306
- File.open(version_file, 'w') do |f|
307
- f.write tag
297
+ begin
298
+ if File.exist?("#{dir}/.initial_populate_successful")
299
+ FileUtils.rm_f(version_file) if File.exist?(version_file)
300
+ rc = RevisionControl.new remote: rc_url, local: dir
301
+ rc.checkout version: prefix_tag(tag), force: true
302
+ File.open(version_file, 'w') do |f|
303
+ f.write tag
304
+ end
305
+ else
306
+ rc = RevisionControl.new remote: rc_url, local: dir
307
+ rc.checkout version: prefix_tag(tag), force: true
308
+ FileUtils.touch "#{dir}/.initial_populate_successful"
309
+ File.open(version_file, 'w') do |f|
310
+ f.write tag
311
+ end
308
312
  end
313
+ rescue Origen::GitError, Origen::DesignSyncError => e
314
+ # If Git failed in the remote, its usually easy to see what the problem is, but now *where* it is.
315
+ # This will prepend the failing remote along with the error from the revision control system,
316
+ # then rethrow the error
317
+ e.message.prepend "When updating remotes for #{remote[:importer].name}: "
318
+ raise e
309
319
  end
310
320
  end
311
321
  end
@@ -2,6 +2,7 @@ module Origen
2
2
  class SiteConfig
3
3
  require 'pathname'
4
4
  require 'yaml'
5
+ require 'etc'
5
6
 
6
7
  TRUE_VALUES = ['true', 'TRUE', '1', 1]
7
8
  FALSE_VALUES = ['false', 'FALSE', '0', 0]
@@ -10,13 +11,109 @@ module Origen
10
11
 
11
12
  # Gets the gem_intall_dir. This is either site_config.home_dir/gems or the site configs gem_install_dir
12
13
  def gem_install_dir
13
- return "#{tool_repo_install_dir}/gems" if gems_use_tool_repo && tool_repo_install_dir && !user_install_enable
14
- find_val('user_gem_dir') || find_val('gem_install_dir') || "#{find_val('home_dir')}/gems"
14
+ if gems_use_tool_repo && tool_repo_install_dir && !user_install_enable
15
+ path = eval_path(tool_repo_install_dir)
16
+ else
17
+ path = eval_path(find_val('user_gem_dir') || find_val('gem_install_dir') || home_dir)
18
+ end
19
+
20
+ append = find_val('append_gems')
21
+ append = 'gems' if append == true || append.nil?
22
+
23
+ if append
24
+ unless path.end_with?(append)
25
+ path = File.join(path, append)
26
+ end
27
+ end
28
+ path
15
29
  end
30
+ alias_method :user_gem_dir, :gem_install_dir
16
31
 
17
32
  # Gets the user_install_dir. Like gem_install_dir, this default to somewhere home_dir, unless overridden
18
33
  def user_install_dir
19
- find_val('user_install_dir') || find_val('home_dir')
34
+ eval_path(find_val('user_install_dir') || home_dir)
35
+ end
36
+
37
+ def home_dir
38
+ eval_path(find_val('home_dir') || '~/')
39
+ end
40
+
41
+ def eval_path(path, options = {})
42
+ # Expand the first path. This will take care of replacing any leading ~/ with the home directory.
43
+ if path.start_with?('\\')
44
+ path[0] = ''
45
+ else
46
+ path = File.expand_path(path)
47
+ end
48
+
49
+ # Gsub the remaining ~ that aren't escaped.
50
+ # If it was escaped, eat the escape character
51
+ path.gsub!(/(?<!\\|\A)~/, "#{Etc.getlogin}")
52
+ path.gsub!(/\\(?=~)/, '')
53
+
54
+ append = find_val('append_dot_origen')
55
+ append = '.origen' if append == true || append.nil?
56
+
57
+ if append
58
+ unless path.end_with?(append)
59
+ path = File.join(path, append)
60
+ end
61
+ end
62
+ path
63
+ end
64
+
65
+ # Dynamically remove the highest instance of :var
66
+ def remove_highest(var)
67
+ @configs.each do |c|
68
+ if c.key?(var)
69
+ return c.delete(var)
70
+ end
71
+ end
72
+
73
+ # return nil if we haven't returned a value yet
74
+ nil
75
+ end
76
+
77
+ # Dynamically remove all the instances of :var
78
+ def remove_all_instances(var)
79
+ # Iterate though all the site configs, removing every instance of :var
80
+ # Return an array containing the value of :var at each config,
81
+ # from lowest priority to highest.
82
+ # If [] is returned, it implies that there was no instancs of :var to be removed.
83
+ ret = []
84
+ @configs.each do |c|
85
+ if c.key?(var)
86
+ ret << c.delete(var)
87
+ end
88
+ end
89
+ ret
90
+ end
91
+ alias_method :purge, :remove_all_instances
92
+
93
+ # Dynamically add a new site variable at the highest priority.
94
+ def add_as_highest(var, value)
95
+ # Don't want to override anything, so just shift in a dummy site config instance at the highest level and
96
+ # set the value there.
97
+ configs.prepend(var.to_s => value)
98
+ end
99
+ alias_method :[]=, :add_as_highest
100
+
101
+ # Dynamically add a new site variable at the lowest priority.
102
+ # Essentially, this sets a new default value.
103
+ def add_as_lowest(var, value)
104
+ # Don't want to override anything, so just shift in a dummy site config at the lowest level and
105
+ # set the value there.
106
+ configs.append(var.to_s => value)
107
+ end
108
+
109
+ # Adds a new site config file as the highest priority
110
+ def add_site_config_as_highest(site_config_file)
111
+ configs.prepend YAML.load_file(File.expand_path('../../../origen_site_config.yml', __FILE__))
112
+ end
113
+
114
+ # Adds a new site config file as the highest priority
115
+ def add_site_config_as_lowest(site_config_file)
116
+ configs.append YAML.load_file(File.expand_path('../../../origen_site_config.yml', __FILE__))
20
117
  end
21
118
 
22
119
  def method_missing(method, *args, &block)
@@ -32,31 +129,61 @@ module Origen
32
129
  fail 'Missing site_config value!'
33
130
  end
34
131
  define_singleton_method(method) do
35
- val
132
+ find_val(method)
36
133
  end
37
134
  val
38
135
  end
39
136
 
137
+ def get(val)
138
+ find_val(val)
139
+ end
140
+ alias_method :[], :get
141
+
142
+ def get_all(val)
143
+ ret = []
144
+ @configs.each do |c|
145
+ if c.key?(val)
146
+ ret << c[val]
147
+ end
148
+ end
149
+ ret
150
+ end
151
+
152
+ def clear
153
+ @configs.clear
154
+ end
155
+
156
+ def rebuild!
157
+ configs!
158
+ end
159
+
40
160
  private
41
161
 
42
162
  def find_val(val, options = {})
43
163
  env = "ORIGEN_#{val.upcase}"
44
164
  if ENV.key?(env)
45
- val = ENV[env]
46
- if TRUE_VALUES.include?(val)
47
- return true
48
- elsif FALSE_VALUES.include?(val)
49
- return false
50
- end
51
- val
165
+ value = ENV[env]
166
+ value
52
167
  else
53
168
  config = configs.find { |c| c.key?(val) }
54
- config ? config[val] : nil
169
+ value = config ? config[val] : nil
170
+ end
171
+
172
+ if TRUE_VALUES.include?(value)
173
+ return true
174
+ elsif FALSE_VALUES.include?(value)
175
+ return false
55
176
  end
177
+ value
56
178
  end
57
179
 
58
180
  def configs
59
- @configs ||= begin
181
+ @configs ||= configs!
182
+ end
183
+
184
+ # Forces a reparse of the site configs.
185
+ def configs!
186
+ @configs = begin
60
187
  # This global is set when Origen is first required, it generally means that what is considered
61
188
  # to be the pwd for the purposes of looking for a site_config file is the place from where the
62
189
  # user invoked Origen. Otherwise if the running app switches the PWD it can lead to confusing
@@ -72,7 +72,7 @@ module Origen
72
72
  end
73
73
 
74
74
  def evaluate_limit(limit)
75
- return limit if [Fixnum, Float, Numeric].include? limit.class
75
+ return limit if limit.is_a?(Numeric)
76
76
  return nil if limit.nil?
77
77
  limit = limit.to_s if [Nokogiri::XML::NodeSet, Nokogiri::XML::Text, Nokogiri::XML::Element].include? limit.class
78
78
  if limit.is_a? Symbol
@@ -132,7 +132,7 @@ module Origen
132
132
  begin
133
133
  result = eval(limit)
134
134
  return result.round(4) if result.is_a? Numeric
135
- rescue SyntaxError, NameError, TypeError
135
+ rescue ::SyntaxError, ::NameError, ::TypeError
136
136
  Origen.log.debug "Limit '#{limit}' had to be rescued, storing it as a #{limit.class}"
137
137
  if limit.is_a? Symbol
138
138
  return limit
@@ -314,9 +314,14 @@ module Origen
314
314
  @attributes = @attributes.merge(attrs)
315
315
  end
316
316
 
317
+ # Make this appear like a sub-block to any application code
318
+ def class
319
+ klass
320
+ end
321
+
317
322
  # Make this appear like a sub-block to any application code
318
323
  def is_a?(klass)
319
- klass == self.klass || klass == self.class
324
+ klass == self.klass || klass == Placeholder
320
325
  end
321
326
 
322
327
  # Make it look like a sub-block in the console to avoid confusion
@@ -0,0 +1,119 @@
1
+ module Origen
2
+ # This class wraps various different class which handle number representation in
3
+ # various formats.
4
+ #
5
+ # The user should never instantiate those directly and should always instantiate an
6
+ # Origen::Value instance, thereby ensuring a common API regardless of the internal
7
+ # representation and handling of the value
8
+ class Value
9
+ autoload :HexStrVal, 'origen/value/hex_str_val'
10
+ autoload :BinStrVal, 'origen/value/bin_str_val'
11
+
12
+ # Represents a single bit value of 'X'
13
+ class X
14
+ def z?
15
+ false
16
+ end
17
+ alias_method :hi_z?, :z?
18
+
19
+ def x?
20
+ true
21
+ end
22
+ alias_method :undefined?, :x?
23
+
24
+ def x_or_z?
25
+ true
26
+ end
27
+ alias_method :z_or_x?, :x_or_z?
28
+ end
29
+
30
+ # Represents a single bit value of 'Y'
31
+ class Z
32
+ def z?
33
+ true
34
+ end
35
+ alias_method :hi_z?, :z?
36
+
37
+ def x?
38
+ false
39
+ end
40
+ alias_method :undefined?, :x?
41
+
42
+ def x_or_z?
43
+ true
44
+ end
45
+ alias_method :z_or_x?, :x_or_z?
46
+ end
47
+
48
+ def initialize(val, options = {})
49
+ if val.is_a?(Integer)
50
+ @val = val
51
+ else
52
+ val = val.to_s
53
+ case val[0].downcase
54
+ when 'b'
55
+ @val = BinStrVal.new(val, options)
56
+ when 'h'
57
+ @val = HexStrVal.new(val, options)
58
+ when 'd'
59
+ @val = val.to_s[1..-1].to_i
60
+ else
61
+ if val =~ /^[0-9]+$/
62
+ @val = val.to_i
63
+ else
64
+ fail 'Unsupported value syntax'
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ # Returns true if all bits have a numeric value - i.e. no X or Z
71
+ def numeric?
72
+ val.numeric?
73
+ end
74
+
75
+ def value?
76
+ true
77
+ end
78
+
79
+ # Converts to an integer, returns nil if the value contains non-numeric bits
80
+ def to_i
81
+ val.to_i
82
+ end
83
+
84
+ # Converts to a string, the format of it depends on the underlying value type
85
+ def to_s
86
+ val.to_s
87
+ end
88
+
89
+ # Returns the size of the value in bits
90
+ def size
91
+ val.size
92
+ end
93
+ alias_method :bits, :size
94
+ alias_method :number_of_bits, :size
95
+
96
+ def hex_str_val?
97
+ val.is_a?(HexStrVal)
98
+ end
99
+ alias_method :hex_str_value?, :hex_str_val?
100
+
101
+ def bin_str_val?
102
+ val.is_a?(BinStrVal)
103
+ end
104
+ alias_method :bin_str_value?, :bin_str_val?
105
+
106
+ def [](index)
107
+ if index.is_a?(Range)
108
+ fail 'Currently, only single bit extraction from a Value object is supported'
109
+ end
110
+ val[index]
111
+ end
112
+
113
+ private
114
+
115
+ def val
116
+ @val
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,72 @@
1
+ module Origen
2
+ class Value
3
+ # Handles a value represented by a string of bin character(s) [0, 1, x, z]
4
+ #
5
+ # Capital X/Z will be accepted when defining the value, but they will be converted
6
+ # to lower case
7
+ class BinStrVal
8
+ attr_reader :val, :size
9
+
10
+ def initialize(value, options)
11
+ @val = clean(value)
12
+ if options[:size]
13
+ @size = options[:size]
14
+ # Trim any bits that are out of range...
15
+ @val = val.split(//).last(size).join
16
+ else
17
+ @size = val.size
18
+ end
19
+ end
20
+
21
+ def numeric?
22
+ !!(val =~ /^[01]+$/)
23
+ end
24
+
25
+ def to_i
26
+ if numeric?
27
+ val.to_i(2) & size.bit_mask
28
+ end
29
+ end
30
+
31
+ def to_s
32
+ "b#{val}"
33
+ end
34
+
35
+ # Returns the value of the given bit.
36
+ # Return nil if out of range, otherwise 0, 1 or an X or Z object
37
+ def [](index)
38
+ unless index > (size - 1)
39
+ if numeric?
40
+ to_i[index]
41
+ else
42
+ char = val[val.size - 1 - index]
43
+ if char == 'x'
44
+ X.new
45
+ elsif char == 'z'
46
+ Z.new
47
+ else
48
+ char.to_i
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def clean(val)
57
+ val = val.to_s.strip.to_s[1..-1]
58
+ if valid?(val)
59
+ val.gsub('_', '').downcase
60
+ end
61
+ end
62
+
63
+ def valid?(val)
64
+ if val =~ /^[01_xXzZ]+$/
65
+ true
66
+ else
67
+ fail Origen::SyntaxError, 'Binary string values can only contain: 0, 1, _, x, X, z, Z'
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end