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