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.
- checksums.yaml +4 -4
- data/bin/origen +14 -2
- data/config/version.rb +2 -2
- data/lib/origen.rb +72 -45
- data/lib/origen/application.rb +29 -19
- data/lib/origen/application/deployer.rb +3 -1
- data/lib/origen/application/runner.rb +10 -8
- data/lib/origen/chip_mode.rb +1 -1
- data/lib/origen/commands.rb +24 -12
- data/lib/origen/commands/version.rb +1 -1
- data/lib/origen/commands_global.rb +32 -8
- data/lib/origen/core_ext.rb +1 -2
- data/lib/origen/core_ext/enumerable.rb +2 -2
- data/lib/origen/core_ext/integer.rb +85 -0
- data/lib/origen/core_ext/numeric.rb +28 -4
- data/lib/origen/global_app.rb +9 -0
- data/lib/origen/log.rb +1 -1
- data/lib/origen/model_initializer.rb +6 -1
- data/lib/origen/netlist/list.rb +2 -2
- data/lib/origen/org_file.rb +125 -0
- data/lib/origen/org_file/interceptable.rb +44 -0
- data/lib/origen/org_file/interceptor.rb +100 -0
- data/lib/origen/parameters/set.rb +1 -1
- data/lib/origen/pins.rb +4 -0
- data/lib/origen/pins/function_proxy.rb +8 -0
- data/lib/origen/pins/pin.rb +90 -38
- data/lib/origen/pins/pin_collection.rb +61 -21
- data/lib/origen/ports/port.rb +1 -1
- data/lib/origen/registers.rb +1 -1
- data/lib/origen/registers/reg.rb +1 -1
- data/lib/origen/remote_manager.rb +25 -15
- data/lib/origen/site_config.rb +140 -13
- data/lib/origen/specs/checkers.rb +2 -2
- data/lib/origen/sub_blocks.rb +6 -1
- data/lib/origen/value.rb +119 -0
- data/lib/origen/value/bin_str_val.rb +72 -0
- data/lib/origen/value/hex_str_val.rb +100 -0
- data/origen_site_config.yml +15 -8
- metadata +12 -6
- data/lib/origen/core_ext/bignum.rb +0 -38
- data/lib/origen/core_ext/fixnum.rb +0 -56
data/lib/origen/ports/port.rb
CHANGED
@@ -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?(
|
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|
|
data/lib/origen/registers.rb
CHANGED
@@ -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?(
|
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
|
data/lib/origen/registers/reg.rb
CHANGED
@@ -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?(
|
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
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
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
|
data/lib/origen/site_config.rb
CHANGED
@@ -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
|
-
|
14
|
-
|
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') ||
|
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
|
-
|
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
|
-
|
46
|
-
|
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 ||=
|
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
|
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
|
data/lib/origen/sub_blocks.rb
CHANGED
@@ -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 ==
|
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
|
data/lib/origen/value.rb
ADDED
@@ -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
|