origen 0.28.2 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
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