origen 0.31.0 → 0.32.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/config/version.rb +1 -1
- data/lib/origen/application/runner.rb +1 -0
- data/lib/origen/clocks/clock.rb +63 -44
- data/lib/origen/commands/web.rb +5 -1
- data/lib/origen/file_handler.rb +3 -2
- data/lib/origen/generator/pattern.rb +16 -5
- data/lib/origen/limits/limit.rb +126 -0
- data/lib/origen/limits/limit_set.rb +120 -0
- data/lib/origen/limits.rb +37 -0
- data/lib/origen/model/exporter.rb +36 -22
- data/lib/origen/model.rb +6 -0
- data/lib/origen/parameters.rb +12 -0
- data/lib/origen/registers/bit_collection.rb +16 -3
- data/lib/origen/remote_manager.rb +48 -5
- data/lib/origen/revision_control/base.rb +9 -0
- data/lib/origen/revision_control/perforce.rb +110 -0
- data/lib/origen/revision_control.rb +3 -0
- data/lib/origen/specs/checkers.rb +0 -3
- data/lib/origen/sub_blocks.rb +3 -1
- data/lib/origen/tests/test.rb +3 -0
- data/lib/origen.rb +2 -0
- data/templates/git/gitignore.erb +3 -0
- data/vendor/lib/models/origen/export1/block1.rb +1 -1
- data/vendor/lib/models/origen/export1.rb +3 -1
- metadata +27 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b636bd97c227eecf2344ccbdc17e29712953325
|
4
|
+
data.tar.gz: cd69d451f85313509d2a2c4a31887cbf81fb57c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e104a65bd531b7e52ec7f9f74d002b822d004fb0c46556e412392c3b874101a8be06c27fd83bb05e35acad5fa3b2c62251d9ba729a5de08dc472004ffd11b57
|
7
|
+
data.tar.gz: dc29b4f3a4567780af525fc9b023bae374af3d71ed96f241e294ae35aba9d241009f4496d4c7f25c112dca0a8d3978b3f6223b378488b8dc967bbabff6501af6
|
data/config/version.rb
CHANGED
@@ -79,6 +79,7 @@ module Origen
|
|
79
79
|
else
|
80
80
|
if options[:action] == :program
|
81
81
|
Origen.generator.generate_program(expand_lists_and_directories(options[:files], options), options)
|
82
|
+
Origen.app.listeners_for(:program_generated).each(&:program_generated)
|
82
83
|
else
|
83
84
|
temporary_plugin_from_options = options[:current_plugin]
|
84
85
|
expand_lists_and_directories(options[:files], options).each do |file|
|
data/lib/origen/clocks/clock.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
module Origen
|
2
2
|
module Clocks
|
3
3
|
class Clock
|
4
|
-
attr_accessor :id, :owner, :users, :
|
4
|
+
attr_accessor :id, :owner, :users, :freq_target, :freq_range, :setpoint, :instantiate_users
|
5
5
|
|
6
6
|
def initialize(id, owner, options = {}, &block)
|
7
7
|
@id = id
|
8
8
|
@owner = owner
|
9
9
|
@id = @id.symbolize unless id.is_a? Symbol
|
10
|
+
@instantiate_users = true
|
10
11
|
options.each { |k, v| instance_variable_set("@#{k}", v) }
|
11
12
|
(block.arity < 1 ? (instance_eval(&block)) : block.call(self)) if block_given?
|
12
13
|
@users = [@users] unless @users.is_a? Array
|
13
|
-
instantiate_users
|
14
|
+
add_users_sub_blocks if @instantiate_users
|
15
|
+
@setpoint = @freq_target
|
14
16
|
end
|
15
17
|
|
16
18
|
def name
|
@@ -21,29 +23,30 @@ module Origen
|
|
21
23
|
def users
|
22
24
|
@users
|
23
25
|
end
|
24
|
-
alias_method :ips, :users
|
25
|
-
alias_method :sub_blocks, :users
|
26
26
|
|
27
27
|
def setpoint=(val)
|
28
|
-
|
29
|
-
|
28
|
+
if val == :gated || val == 'gated'
|
29
|
+
@setpoint = :gated
|
30
|
+
else
|
31
|
+
setpoint_ok?(val) # This just warns if the clock is set out of range
|
32
|
+
@setpoint = val
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def setpoint_ok?(val = nil)
|
33
|
-
|
34
|
-
if freq_range == :fixed
|
35
|
-
if val
|
37
|
+
val = @setpoint if val.nil?
|
38
|
+
if @freq_range == :fixed
|
39
|
+
if val == @freq_target
|
36
40
|
return true
|
37
41
|
else
|
38
|
-
Origen.log.warn("Clock '#{id}' is a fixed clock with a
|
42
|
+
Origen.log.warn("Clock '#{id}' is a fixed clock with a target frequency of #{@freq_target.as_Hz}")
|
39
43
|
return false
|
40
44
|
end
|
41
45
|
else
|
42
|
-
|
43
|
-
if freq_range.include?(val)
|
46
|
+
if @freq_range.include?(val)
|
44
47
|
return true
|
45
48
|
else
|
46
|
-
Origen.log.warn("Setpoint (#{setpoint_string(val)}) for clock '#{id}' is not within the frequency range (#{freq_range_string})
|
49
|
+
Origen.log.warn("Setpoint (#{setpoint_string(val)}) for clock '#{id}' is not within the frequency range (#{freq_range_string})")
|
47
50
|
return false
|
48
51
|
end
|
49
52
|
end
|
@@ -51,17 +54,10 @@ module Origen
|
|
51
54
|
alias_method :value_ok?, :setpoint_ok?
|
52
55
|
alias_method :val_ok?, :setpoint_ok?
|
53
56
|
|
54
|
-
# Set the clock to the
|
55
|
-
def
|
56
|
-
@setpoint =
|
57
|
-
end
|
58
|
-
|
59
|
-
# Nominal frequency
|
60
|
-
def nominal_frequency
|
61
|
-
@nominal_frequency
|
57
|
+
# Set the clock to the target frequency
|
58
|
+
def setpoint_to_target
|
59
|
+
@setpoint = @freq_target
|
62
60
|
end
|
63
|
-
alias_method :nominal, :nominal_frequency
|
64
|
-
alias_method :nom, :nominal_frequency
|
65
61
|
|
66
62
|
# Current setpoint, defaults top nil on init
|
67
63
|
def setpoint
|
@@ -71,11 +67,34 @@ module Origen
|
|
71
67
|
alias_method :value, :setpoint
|
72
68
|
|
73
69
|
# Acceptable frequency range
|
74
|
-
def
|
75
|
-
@
|
70
|
+
def freq_range
|
71
|
+
@freq_range
|
72
|
+
end
|
73
|
+
alias_method :range, :freq_range
|
74
|
+
|
75
|
+
# Acceptable frequency range
|
76
|
+
def freq_target
|
77
|
+
@freq_target
|
78
|
+
end
|
79
|
+
alias_method :target, :freq_target
|
80
|
+
|
81
|
+
# min method
|
82
|
+
def min
|
83
|
+
if @freq_range == :fixed
|
84
|
+
@freq_target
|
85
|
+
else
|
86
|
+
@freq_range.first
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# max method
|
91
|
+
def max
|
92
|
+
if @freq_range == :fixed
|
93
|
+
@freq_target
|
94
|
+
else
|
95
|
+
@freq_range.last
|
96
|
+
end
|
76
97
|
end
|
77
|
-
alias_method :freq_range, :frequency_range
|
78
|
-
alias_method :range, :frequency_range
|
79
98
|
|
80
99
|
# Check if the clock users are defined anywhere in the DUT
|
81
100
|
def users_defined?
|
@@ -108,12 +127,12 @@ module Origen
|
|
108
127
|
private
|
109
128
|
|
110
129
|
# Instantiate and IP/users that use/access the clock
|
111
|
-
def
|
112
|
-
users.each do |ip|
|
113
|
-
if owner.respond_to? ip
|
130
|
+
def add_users_sub_blocks
|
131
|
+
@users.each do |ip|
|
132
|
+
if @owner.respond_to? ip
|
114
133
|
next
|
115
134
|
else
|
116
|
-
owner.sub_block ip
|
135
|
+
@owner.sub_block ip
|
117
136
|
end
|
118
137
|
end
|
119
138
|
end
|
@@ -130,20 +149,20 @@ module Origen
|
|
130
149
|
end
|
131
150
|
|
132
151
|
def frequencies_ok?
|
133
|
-
if
|
152
|
+
if @freq_target.nil?
|
134
153
|
false
|
135
|
-
elsif
|
154
|
+
elsif @freq_range.nil?
|
136
155
|
Origen.log.error("Missing frequency range for clock '#{name}'!")
|
137
156
|
false
|
138
|
-
elsif
|
139
|
-
if
|
157
|
+
elsif freq_range.is_a? Range
|
158
|
+
if freq_range.include?(@freq_target)
|
140
159
|
true
|
141
160
|
else
|
142
|
-
Origen.log.error("PPEKit:
|
161
|
+
Origen.log.error("PPEKit: Frequency target #{@freq_target} is not inbetween the frequency range #{freq_range} for clock '#{name}'!")
|
143
162
|
false
|
144
163
|
end
|
145
164
|
else
|
146
|
-
Origen.log.error("Clock attribute '
|
165
|
+
Origen.log.error("Clock attribute 'freq_range' must be a Range!")
|
147
166
|
return_value = false
|
148
167
|
end
|
149
168
|
end
|
@@ -157,24 +176,24 @@ module Origen
|
|
157
176
|
end
|
158
177
|
|
159
178
|
def freq_range_string
|
160
|
-
start_freq = freq_range.first
|
161
|
-
end_freq = freq_range.last
|
179
|
+
start_freq = @freq_range.first
|
180
|
+
end_freq = @freq_range.last
|
162
181
|
"#{start_freq.as_Hz}\.\.#{end_freq.as_Hz}"
|
163
182
|
end
|
164
183
|
|
165
184
|
def clock_freqs_ok?
|
166
|
-
if
|
185
|
+
if @freq_target.nil?
|
167
186
|
false
|
168
|
-
elsif freq_range == :fixed
|
187
|
+
elsif @freq_range == :fixed
|
169
188
|
true
|
170
189
|
else
|
171
|
-
if freq_range.nil?
|
190
|
+
if @freq_range.nil?
|
172
191
|
Origen.log.error("PPEKit: Missing frequency target or range for clock '#{id}'!")
|
173
192
|
false
|
174
|
-
elsif freq_range.include?(
|
193
|
+
elsif @freq_range.include?(@freq_target)
|
175
194
|
true
|
176
195
|
else
|
177
|
-
Origen.log.error("PPEKit: Frequency target #{
|
196
|
+
Origen.log.error("PPEKit: Frequency target #{@freq_target} is not inbetween the freq range #{@freq_range} for clock '#{id}'!")
|
178
197
|
false
|
179
198
|
end
|
180
199
|
end
|
data/lib/origen/commands/web.rb
CHANGED
@@ -92,7 +92,11 @@ The following options are available:
|
|
92
92
|
server.close
|
93
93
|
# Start the server
|
94
94
|
puts ''
|
95
|
-
|
95
|
+
if host.include? domain
|
96
|
+
puts "Point your browser to this address: http://#{host}:#{port}"
|
97
|
+
else
|
98
|
+
puts "Point your browser to this address: http://#{host}#{domain.empty? ? '' : '.' + domain}:#{port}"
|
99
|
+
end
|
96
100
|
puts ''
|
97
101
|
puts 'To shut down the server use CTRL-C'
|
98
102
|
puts ''
|
data/lib/origen/file_handler.rb
CHANGED
@@ -210,9 +210,10 @@ module Origen
|
|
210
210
|
file = inject_import_path(file, type: :template)
|
211
211
|
file = add_underscore_to(file)
|
212
212
|
file = add_extension_to(file)
|
213
|
+
web_file = file =~ /\.(html|md)(\.|$)/
|
213
214
|
begin
|
214
215
|
# Allow relative references to templates/web when compiling a web template
|
215
|
-
if Origen.lsf.current_command == 'web'
|
216
|
+
if Origen.lsf.current_command == 'web' || web_file
|
216
217
|
clean_path_to(file, load_paths: "#{Origen.root}/templates/web")
|
217
218
|
else
|
218
219
|
clean_path_to(file)
|
@@ -220,7 +221,7 @@ module Origen
|
|
220
221
|
rescue
|
221
222
|
# Try again without .erb
|
222
223
|
file = file.gsub('.erb', '')
|
223
|
-
if Origen.lsf.current_command == 'web'
|
224
|
+
if Origen.lsf.current_command == 'web' || web_file
|
224
225
|
clean_path_to(file, load_paths: "#{Origen.root}/templates/web")
|
225
226
|
else
|
226
227
|
clean_path_to(file)
|
@@ -349,10 +349,21 @@ module Origen
|
|
349
349
|
|
350
350
|
unless options[:inhibit] || !Origen.tester.generate? || job.test?
|
351
351
|
stats.collect_for_pattern(job.output_pattern) do
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
352
|
+
# If the tester is going to deal with writing out the final pattern. The use case for this is when
|
353
|
+
# the pattern is comprised of multiple files instead of the more conventional case here which each
|
354
|
+
# pattern is one file.
|
355
|
+
if tester.respond_to?(:open_and_write_pattern)
|
356
|
+
tester.open_and_write_pattern(job.output_pattern) do
|
357
|
+
[:header, :body, :footer].each do |section|
|
358
|
+
Origen.tester.format(stage.bank(section), section)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
else
|
362
|
+
File.open(job.output_pattern, 'w') do |f|
|
363
|
+
[:header, :body, :footer].each do |section|
|
364
|
+
Origen.tester.format(stage.bank(section), section) do |line|
|
365
|
+
f.puts line
|
366
|
+
end
|
356
367
|
end
|
357
368
|
end
|
358
369
|
end
|
@@ -362,7 +373,7 @@ module Origen
|
|
362
373
|
log.info "Pattern vectors: #{stats.number_of_vectors_for(job.output_pattern).to_s.ljust(10)}"
|
363
374
|
log.info 'Execution time'.ljust(15) + ': %.6f' % stats.execution_time_for(job.output_pattern)
|
364
375
|
log.info '----------------------------------------------------------------------'
|
365
|
-
check_for_changes(job.output_pattern, job.reference_pattern)
|
376
|
+
check_for_changes(job.output_pattern, job.reference_pattern) unless tester.try(:disable_pattern_diffs)
|
366
377
|
stats.record_pattern_completion(job.output_pattern)
|
367
378
|
end
|
368
379
|
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Origen
|
2
|
+
module Limits
|
3
|
+
class Limit
|
4
|
+
attr_accessor :expr, :value, :owner, :type
|
5
|
+
|
6
|
+
def initialize(expr, type, owner, options = {})
|
7
|
+
@expr = expr
|
8
|
+
@owner = owner
|
9
|
+
@type = type
|
10
|
+
@value = evaluate_expr
|
11
|
+
end
|
12
|
+
|
13
|
+
# If the value is still a String then it could be
|
14
|
+
# due to referencing another LimitSet that is
|
15
|
+
# yet to be defined
|
16
|
+
def value
|
17
|
+
if @value.is_a?(String)
|
18
|
+
evaluate_expr
|
19
|
+
else
|
20
|
+
@value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Backwards compatibility
|
25
|
+
def exp
|
26
|
+
@expr
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def fetch_reference_value(ref)
|
32
|
+
ref = ref.to_sym unless ref.is_a?(Symbol)
|
33
|
+
# Check if the reference is to another limit set
|
34
|
+
if owner.limits.include? ref
|
35
|
+
return owner.limits(ref).send(type).value
|
36
|
+
# Check if the reference is to a power domain
|
37
|
+
end
|
38
|
+
if Origen.top_level.respond_to? :power_domains
|
39
|
+
if Origen.top_level.power_domains.include? ref
|
40
|
+
# Need to check the limit type and retrieve the appropriate value
|
41
|
+
case @type.to_s
|
42
|
+
when /target|typ/
|
43
|
+
return Origen.top_level.power_domains(ref).nominal_voltage
|
44
|
+
else
|
45
|
+
return Origen.top_level.power_domains(ref).send(@type)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
# Check if the reference is to a clock
|
50
|
+
if Origen.top_level.respond_to? :clocks
|
51
|
+
if Origen.top_level.clocks.include? ref
|
52
|
+
# Need to check the limit type and retrieve the appropriate value
|
53
|
+
case @type.to_s
|
54
|
+
when /target|typ/
|
55
|
+
return Origen.top_level.clocks(ref).freq_target
|
56
|
+
else
|
57
|
+
return Origen.top_level.clocks(ref).send(@type)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def evaluate_expr
|
64
|
+
return @expr if @expr.is_a?(Numeric)
|
65
|
+
return nil if @expr.nil?
|
66
|
+
if @expr.is_a? Symbol
|
67
|
+
@expr = ':' + @expr.to_s
|
68
|
+
else
|
69
|
+
@expr.gsub!("\n", ' ')
|
70
|
+
@expr.scrub!
|
71
|
+
end
|
72
|
+
result = false
|
73
|
+
if @expr.match(/\:\S+/)
|
74
|
+
limit_items = @expr.split(/\:|\s+/).reject(&:empty?)
|
75
|
+
if limit_items.size == 1
|
76
|
+
return fetch_reference_value(limit_items.first)
|
77
|
+
else
|
78
|
+
references = @expr.split(/\:|\s+/).select { |var| var.match(/^[a-zA-Z]\S+$/) }
|
79
|
+
new_limit_items = [].tap do |limit_ary|
|
80
|
+
limit_items.each do |item|
|
81
|
+
if references.include? item
|
82
|
+
limit_ary << fetch_reference_value(item)
|
83
|
+
next
|
84
|
+
else
|
85
|
+
limit_ary << item
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
new_limit = new_limit_items.join(' ')
|
90
|
+
new_limit_references = new_limit.split(/\:|\s+/).select { |var| var.match(/^[a-zA-Z]\S+$/) }
|
91
|
+
if new_limit_references.empty?
|
92
|
+
result = eval(new_limit).round(4)
|
93
|
+
else
|
94
|
+
return @expr
|
95
|
+
end
|
96
|
+
end
|
97
|
+
elsif !!(@expr.match(/^\d+\.\d+$/)) || !!(@expr.match(/^-\d+\.\d+$/))
|
98
|
+
result = Float(@expr).round(4) rescue false # rubocop:disable Style/RescueModifier
|
99
|
+
elsif !!(@expr.match(/\d+\.\d+\s+\d+\.\d+/))
|
100
|
+
Origen.log.debug "Found two numbers without an operator in the @expr string '#{@expr}', choosing the first..."
|
101
|
+
first_number = @expr.match(/(\d+\.\d+)\s+\d+\.\d+/).captures.first
|
102
|
+
result = Float(first_number).round(4) rescue false # rubocop:disable Style/RescueModifier
|
103
|
+
else
|
104
|
+
result = Integer(@expr) rescue false # rubocop:disable Style/RescueModifier
|
105
|
+
end
|
106
|
+
if result == false
|
107
|
+
# Attempt to eval the @expr because users could write a @expr like "3.3 + 50.mV"
|
108
|
+
# which would not work with the code above but should eval to a number 3.35
|
109
|
+
begin
|
110
|
+
result = eval(@expr)
|
111
|
+
return result.round(4) if result.is_a? Numeric
|
112
|
+
rescue ::SyntaxError, ::NameError, ::TypeError
|
113
|
+
Origen.log.debug "Limit '#{@expr}' had to be rescued, storing it as a #{@expr.class}"
|
114
|
+
if @expr.is_a? Symbol
|
115
|
+
return @expr
|
116
|
+
else
|
117
|
+
return "#{@expr}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
return result
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative './limit'
|
2
|
+
module Origen
|
3
|
+
module Limits
|
4
|
+
class LimitSet
|
5
|
+
attr_accessor :id, :min, :typ, :max, :target, :description, :static, :owner, :type
|
6
|
+
|
7
|
+
def initialize(id, owner, options)
|
8
|
+
@id = id
|
9
|
+
@description = options[:description]
|
10
|
+
@owner = owner
|
11
|
+
@min = Limit.new(options[:min], :min, @owner) unless options[:min].nil?
|
12
|
+
@typ = Limit.new(options[:typ], :typ, @owner) unless options[:typ].nil?
|
13
|
+
@max = Limit.new(options[:max], :max, @owner) unless options[:max].nil?
|
14
|
+
@target = Limit.new(options[:target], :target, @owner) unless options[:target].nil?
|
15
|
+
unless options[:static].nil?
|
16
|
+
unless [true, false].include? options[:static]
|
17
|
+
Origen.log.error("Static option must be set to 'true' or 'false'!")
|
18
|
+
fail
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@static = options[:static].nil? ? false : options[:static]
|
22
|
+
fail unless limits_ok?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Common alias
|
26
|
+
def name
|
27
|
+
@id
|
28
|
+
end
|
29
|
+
|
30
|
+
def frozen?
|
31
|
+
@static
|
32
|
+
end
|
33
|
+
|
34
|
+
def min=(val)
|
35
|
+
if frozen?
|
36
|
+
Origen.log.warn('Cannot change a frozen limit set!')
|
37
|
+
else
|
38
|
+
@min = Limit.new(val, :min, @owner)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def max=(val)
|
43
|
+
if frozen?
|
44
|
+
Origen.log.warn('Cannot change a frozen limit set!')
|
45
|
+
else
|
46
|
+
@max = Limit.new(val, :max, @owner)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def typ=(val)
|
51
|
+
if frozen?
|
52
|
+
Origen.log.warn('Cannot change a frozen limit set!')
|
53
|
+
else
|
54
|
+
@typ = Limit.new(val, :typ, @owner)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def target=(val)
|
59
|
+
if frozen?
|
60
|
+
Origen.log.warn('Cannot change a frozen limit set!')
|
61
|
+
else
|
62
|
+
@target = Limit.new(val, :target, @owner)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Check that min, max are not mixed with typ. If a user wants
|
69
|
+
# a baseline value for a spec use target as it will not be
|
70
|
+
# checked against pass/fail
|
71
|
+
def limits_ok?
|
72
|
+
status = true
|
73
|
+
# Must have at least one of the limit types defined
|
74
|
+
if @min.nil? && @max.nil? && @typ.nil? && @target.nil?
|
75
|
+
Origen.log.error("Limit set #{@id} does not have any limits defined!")
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
if @min.nil? ^ @max.nil?
|
79
|
+
@type = :single_sided
|
80
|
+
unless @typ.nil?
|
81
|
+
status = false
|
82
|
+
Origen.log.error "Limit set #{@id} has a typical limit defined with either min or max. They are mutually exclusive, use 'target' when using min or max"
|
83
|
+
end
|
84
|
+
# Check if the target is OK
|
85
|
+
unless @target.nil?
|
86
|
+
if @min.nil?
|
87
|
+
unless @target < @max
|
88
|
+
status = false
|
89
|
+
Origen.log.error("Limit set #{@id} has the target value #{@target} set greater than the max value #{@max}!")
|
90
|
+
end
|
91
|
+
else
|
92
|
+
unless @target > @min
|
93
|
+
status = false
|
94
|
+
Origen.log.error("Limit set #{@id} has the target value #{@target} set less than the min value #{@min}!")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
elsif @min.expr && @max.expr
|
99
|
+
@type = :double_sided
|
100
|
+
# Both min and max must be numerical to compare them
|
101
|
+
if @min.value.is_a?(Numeric) && @max.value.is_a?(Numeric)
|
102
|
+
# Check that min and max make sense
|
103
|
+
if @max.value <= @min.value || @min.value >= @max.value
|
104
|
+
status = false
|
105
|
+
Origen.log.error "Limit set #{@id} has min (#{@min.value}) and max (#{@max.value}) reversed"
|
106
|
+
end
|
107
|
+
# Check that target is OK
|
108
|
+
unless @target.nil?
|
109
|
+
if @target.value <= @min.value || @target.value >= @max.value
|
110
|
+
status = false
|
111
|
+
Origen.log.error "Limit set #{@id} has a target (#{@target.value}) that is not within the min (#{@min.value}) and max #{@max.value}) values"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
status
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative './limits/limit'
|
2
|
+
require_relative './limits/limit_set'
|
3
|
+
module Origen
|
4
|
+
module Limits
|
5
|
+
TYPES = [:min, :typ, :max, :target]
|
6
|
+
|
7
|
+
def add_limits(set, options)
|
8
|
+
@_limits ||= {}
|
9
|
+
options.ids.each do |limit_type|
|
10
|
+
unless TYPES.include? limit_type
|
11
|
+
Origen.log.error("Limit type '#{limit_type}' not supported, choose from #{TYPES}!")
|
12
|
+
fail
|
13
|
+
end
|
14
|
+
end
|
15
|
+
if @_limits.include? set
|
16
|
+
# Limit set already exists, modify it unless it is frozen
|
17
|
+
unless @_limits[set].frozen?
|
18
|
+
options.each do |limit_type, limit_expr|
|
19
|
+
@_limits[set].send("#{limit_type}=", limit_expr)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
else
|
23
|
+
# Create a default limit set
|
24
|
+
@_limits[set] = LimitSet.new(set, self, options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def limits(set = nil)
|
29
|
+
@_limits ||= {}
|
30
|
+
if set.nil?
|
31
|
+
@_limits
|
32
|
+
else
|
33
|
+
@_limits[set]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -11,16 +11,13 @@ module Origen
|
|
11
11
|
}.merge(options)
|
12
12
|
# file_path is for internal use, don't pass it from the application, use the :dir option if you
|
13
13
|
# want to change where the exported files are
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
FileUtils.rm_rf(file.to_s) if File.exist?(file.to_s)
|
22
|
-
FileUtils.mkdir_p(file.dirname)
|
23
|
-
File.open(file, 'w') do |f|
|
14
|
+
file = options[:file_path] || export_path(name, options)
|
15
|
+
dir = options[:dir_path] || export_dir(options)
|
16
|
+
path_to_file = Pathname.new(File.join(dir, file))
|
17
|
+
FileUtils.rm_rf(path_to_file.sub_ext('').to_s) if File.exist?(path_to_file.sub_ext('').to_s)
|
18
|
+
FileUtils.rm_rf(path_to_file.to_s) if File.exist?(path_to_file.to_s)
|
19
|
+
FileUtils.mkdir_p(path_to_file.dirname)
|
20
|
+
File.open(path_to_file, 'w') do |f|
|
24
21
|
export_wrap_with_namespaces(f, options) do |indent|
|
25
22
|
f.puts((' ' * indent) + 'def self.extended(model)')
|
26
23
|
indent += 2
|
@@ -51,12 +48,15 @@ module Origen
|
|
51
48
|
ground_pin_groups.each do |id, pins|
|
52
49
|
f.puts export_pin_group(id, pins, indent: indent, method: :add_ground_pin_group)
|
53
50
|
end
|
51
|
+
virtual_pins.each do |id, pin|
|
52
|
+
f.puts export_pin(id, pin, indent: indent, method: :add_virtual_pin)
|
53
|
+
end
|
54
54
|
f.puts
|
55
55
|
end
|
56
56
|
end
|
57
57
|
if options[:include_sub_blocks]
|
58
58
|
sub_blocks.each do |name, block|
|
59
|
-
f.puts export_sub_block(name, block, options.merge(indent: indent, file_path: file))
|
59
|
+
f.puts export_sub_block(name, block, options.merge(indent: indent, file_path: file, dir_path: dir))
|
60
60
|
end
|
61
61
|
f.puts unless sub_blocks.empty?
|
62
62
|
end
|
@@ -74,10 +74,18 @@ module Origen
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def import(name, options = {})
|
77
|
-
path = export_path(name, options)
|
77
|
+
path = File.join(export_dir(options), export_path(name, options))
|
78
78
|
if File.exist?(path)
|
79
79
|
require path
|
80
|
-
|
80
|
+
if options.key?(:namespace) && !options[:namespace]
|
81
|
+
extend name.to_s.gsub('.', '_').camelcase.constantize
|
82
|
+
else
|
83
|
+
if options[:namespace]
|
84
|
+
extend "#{options[:namespace].to_s.gsub('.', '_').camelcase}::#{name.to_s.gsub('.', '_').camelcase}".constantize
|
85
|
+
else
|
86
|
+
extend "#{Origen.app.namespace}::#{name.to_s.gsub('.', '_').camelcase}".constantize
|
87
|
+
end
|
88
|
+
end
|
81
89
|
true
|
82
90
|
else
|
83
91
|
if options[:allow_missing]
|
@@ -143,16 +151,16 @@ module Origen
|
|
143
151
|
if n == ''
|
144
152
|
nil
|
145
153
|
else
|
146
|
-
n.camelcase
|
154
|
+
n.to_s.gsub('.', '_').camelcase
|
147
155
|
end
|
148
156
|
end.compact
|
149
157
|
end
|
150
158
|
|
151
159
|
def export_path(name, options = {})
|
152
160
|
if options.key?(:namespace) && !options[:namespace]
|
153
|
-
|
161
|
+
"#{name.to_s.underscore}.rb"
|
154
162
|
else
|
155
|
-
File.join(
|
163
|
+
File.join((options[:namespace] || Origen.app.namespace).to_s.underscore, "#{name.to_s.underscore}.rb")
|
156
164
|
end
|
157
165
|
end
|
158
166
|
|
@@ -173,8 +181,11 @@ module Origen
|
|
173
181
|
line << ", #{pkg_meta}" unless pkg_meta == ''
|
174
182
|
Array(options[:attributes]).each do |attr|
|
175
183
|
unless (v = pin.send(attr)).nil?
|
176
|
-
|
184
|
+
case v
|
185
|
+
when Numeric, Array, Hash
|
177
186
|
line << ", #{attr}: #{v}"
|
187
|
+
when Symbol
|
188
|
+
line << ", #{attr}: :#{v}"
|
178
189
|
else
|
179
190
|
line << ", #{attr}: '#{v}'"
|
180
191
|
end
|
@@ -183,8 +194,11 @@ module Origen
|
|
183
194
|
unless pin.meta.empty?
|
184
195
|
line << ', meta: { '
|
185
196
|
line << pin.meta.map do |k, v|
|
186
|
-
|
197
|
+
case v
|
198
|
+
when Numeric, Array, Hash
|
187
199
|
"#{k}: #{v}"
|
200
|
+
when Symbol
|
201
|
+
"#{k}: :#{v}"
|
188
202
|
else
|
189
203
|
"#{k}: '#{v}'"
|
190
204
|
end
|
@@ -208,9 +222,9 @@ module Origen
|
|
208
222
|
|
209
223
|
def export_sub_block(id, block, options = {})
|
210
224
|
indent = ' ' * (options[:indent] || 0)
|
211
|
-
|
212
|
-
|
213
|
-
line = indent + "model.sub_block :#{id}, file: '#{
|
225
|
+
file_path = File.join(Pathname.new(options[:file_path]).sub_ext(''), "#{id}.rb")
|
226
|
+
dir_path = options[:dir_path]
|
227
|
+
line = indent + "model.sub_block :#{id}, file: '#{file_path}', dir: '#{dir_path}', lazy: true"
|
214
228
|
unless block.base_address == 0
|
215
229
|
line << ", base_address: #{block.base_address.to_hex}"
|
216
230
|
end
|
@@ -223,7 +237,7 @@ module Origen
|
|
223
237
|
line << ", #{key}: #{value}"
|
224
238
|
end
|
225
239
|
end
|
226
|
-
block.export(id, options.merge(file_path:
|
240
|
+
block.export(id, options.merge(file_path: file_path, dir_path: dir_path))
|
227
241
|
line
|
228
242
|
end
|
229
243
|
|
data/lib/origen/model.rb
CHANGED
@@ -34,6 +34,7 @@ module Origen
|
|
34
34
|
include Origen::Clocks
|
35
35
|
include Origen::Model::Exporter
|
36
36
|
include Origen::Component
|
37
|
+
include Origen::Limits
|
37
38
|
end
|
38
39
|
|
39
40
|
module ClassMethods
|
@@ -205,6 +206,7 @@ module Origen
|
|
205
206
|
unless top_level?
|
206
207
|
# Need to do this in case a class besides SubBlock includes Origen::Model
|
207
208
|
obj_above_self = parent.nil? ? Origen.top_level : parent
|
209
|
+
return nil if obj_above_self.nil?
|
208
210
|
if obj_above_self.current_mode
|
209
211
|
_modes[obj_above_self.current_mode.id] if _modes.include? obj_above_self.current_mode.id
|
210
212
|
end
|
@@ -216,6 +218,10 @@ module Origen
|
|
216
218
|
# Set the current mode configuration of the current model
|
217
219
|
def current_mode=(id)
|
218
220
|
@current_mode = id.is_a?(ChipMode) ? id.id : id
|
221
|
+
Origen.app.listeners_for(:on_mode_changed).each do |listener|
|
222
|
+
listener.on_mode_changed(mode: @current_mode)
|
223
|
+
end
|
224
|
+
@current_mode
|
219
225
|
end
|
220
226
|
alias_method :mode=, :current_mode=
|
221
227
|
|
data/lib/origen/parameters.rb
CHANGED
@@ -69,6 +69,18 @@ module Origen
|
|
69
69
|
_parameter_sets.empty? ? false : true
|
70
70
|
end
|
71
71
|
|
72
|
+
# Return value of param if it exists, nil otherwise.
|
73
|
+
def param?(name)
|
74
|
+
_param = name.to_s =~ /^params./ ? name.to_s : 'params.' + name.to_s
|
75
|
+
begin
|
76
|
+
val = eval("self.#{_param}")
|
77
|
+
rescue
|
78
|
+
nil
|
79
|
+
else
|
80
|
+
val
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
72
84
|
# @api private
|
73
85
|
def _parameter_current
|
74
86
|
if path = self.class.parameters_context
|
@@ -109,9 +109,22 @@ module Origen
|
|
109
109
|
v = tester.capture do
|
110
110
|
store!(sync: true)
|
111
111
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
if v.first
|
113
|
+
# Serial shift
|
114
|
+
if v.size == 1
|
115
|
+
reverse_shift_out_with_index do |bit, i|
|
116
|
+
bit.instance_variable_set('@updated_post_reset', true)
|
117
|
+
bit.instance_variable_set('@data', v.first[i])
|
118
|
+
end
|
119
|
+
# Parallel shift
|
120
|
+
else
|
121
|
+
reverse_shift_out_with_index do |bit, i|
|
122
|
+
bit.instance_variable_set('@updated_post_reset', true)
|
123
|
+
bit.instance_variable_set('@data', v[i].to_i)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
else
|
127
|
+
Origen.log.warning "No data was captured when attempting to sync register #{owner.name}, this is probably because the current read_register driver method does not implement store requests"
|
115
128
|
end
|
116
129
|
end
|
117
130
|
if size
|
@@ -119,8 +119,47 @@ module Origen
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
+
# Fetches any defined remotes, regardless of whether they are dirty or not
|
123
|
+
def resolve_remotes!
|
124
|
+
resolve_remotes
|
125
|
+
process_remotes
|
126
|
+
end
|
127
|
+
|
122
128
|
private
|
123
129
|
|
130
|
+
# Process each remote
|
131
|
+
def process_remotes
|
132
|
+
remotes.each do |_name, remote|
|
133
|
+
dir = workspace_of(remote)
|
134
|
+
rc_url = remote[:rc_url] || remote[:vault]
|
135
|
+
tag = remote[:tag].nil? ? Origen::VersionString.new(remote[:version]) : Origen::VersionString.new(remote[:tag])
|
136
|
+
version_file = dir.to_s + '/.current_version'
|
137
|
+
begin
|
138
|
+
if File.exist?("#{dir}/.initial_populate_successful")
|
139
|
+
FileUtils.rm_f(version_file) if File.exist?(version_file)
|
140
|
+
rc = RevisionControl.new remote: rc_url, local: dir
|
141
|
+
rc.send rc.remotes_method, version: prefix_tag(tag), force: true
|
142
|
+
File.open(version_file, 'w') do |f|
|
143
|
+
f.write tag
|
144
|
+
end
|
145
|
+
else
|
146
|
+
rc = RevisionControl.new remote: rc_url, local: dir
|
147
|
+
rc.send rc.remotes_method, version: prefix_tag(tag), force: true
|
148
|
+
FileUtils.touch "#{dir}/.initial_populate_successful"
|
149
|
+
File.open(version_file, 'w') do |f|
|
150
|
+
f.write tag
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue Origen::GitError, Origen::DesignSyncError, Origen::PerforceError => e
|
154
|
+
# If Git failed in the remote, its usually easy to see what the problem is, but now *where* it is.
|
155
|
+
# This will prepend the failing remote along with the error from the revision control system,
|
156
|
+
# then rethrow the error
|
157
|
+
e.message.prepend "When updating remotes for #{remote[:importer].name}: "
|
158
|
+
raise e
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
124
163
|
# Returns the name of the given import (a lower cased symbol)
|
125
164
|
def name_of(remote)
|
126
165
|
dir_defined?(remote)
|
@@ -243,6 +282,11 @@ module Origen
|
|
243
282
|
# * If multiple versions of the same remote are found the most
|
244
283
|
# recent one wins.
|
245
284
|
def add_remote(new)
|
285
|
+
# Cannot have both a tag and a version defined for a remote
|
286
|
+
if ([:tag, :version] - new.keys).empty?
|
287
|
+
Origen.log.error('Cannot define both a tag and a version for a remote!')
|
288
|
+
fail
|
289
|
+
end
|
246
290
|
name = name_of(new)
|
247
291
|
# If the current remote has been imported by one of it's dev dependencies
|
248
292
|
# then always use the local workspace
|
@@ -289,28 +333,27 @@ module Origen
|
|
289
333
|
end
|
290
334
|
if remote[:path]
|
291
335
|
create_symlink(remote[:path], dir)
|
292
|
-
|
293
336
|
else
|
294
337
|
rc_url = remote[:rc_url] || remote[:vault]
|
295
|
-
tag = Origen::VersionString.new(remote[:version])
|
338
|
+
tag = remote[:tag].nil? ? Origen::VersionString.new(remote[:version]) : Origen::VersionString.new(remote[:tag])
|
296
339
|
version_file = dir.to_s + '/.current_version'
|
297
340
|
begin
|
298
341
|
if File.exist?("#{dir}/.initial_populate_successful")
|
299
342
|
FileUtils.rm_f(version_file) if File.exist?(version_file)
|
300
343
|
rc = RevisionControl.new remote: rc_url, local: dir
|
301
|
-
rc.
|
344
|
+
rc.send rc.remotes_method, version: prefix_tag(tag), force: true
|
302
345
|
File.open(version_file, 'w') do |f|
|
303
346
|
f.write tag
|
304
347
|
end
|
305
348
|
else
|
306
349
|
rc = RevisionControl.new remote: rc_url, local: dir
|
307
|
-
rc.
|
350
|
+
rc.send rc.remotes_method, version: prefix_tag(tag), force: true
|
308
351
|
FileUtils.touch "#{dir}/.initial_populate_successful"
|
309
352
|
File.open(version_file, 'w') do |f|
|
310
353
|
f.write tag
|
311
354
|
end
|
312
355
|
end
|
313
|
-
rescue Origen::GitError, Origen::DesignSyncError => e
|
356
|
+
rescue Origen::GitError, Origen::DesignSyncError, Origen::PerforceError => e
|
314
357
|
# If Git failed in the remote, its usually easy to see what the problem is, but now *where* it is.
|
315
358
|
# This will prepend the failing remote along with the error from the revision control system,
|
316
359
|
# then rethrow the error
|
@@ -16,6 +16,8 @@ module Origen
|
|
16
16
|
attr_reader :remote
|
17
17
|
# Returns a pointer to the local location (a Pathname object)
|
18
18
|
attr_reader :local
|
19
|
+
# Method to use by Origen::RemoteManager to handle fetching a remote file
|
20
|
+
attr_reader :remotes_method
|
19
21
|
|
20
22
|
# rubocop:disable Lint/UnusedMethodArgument
|
21
23
|
|
@@ -27,6 +29,7 @@ module Origen
|
|
27
29
|
end
|
28
30
|
@remote = Pathname.new(options[:remote])
|
29
31
|
@local = Pathname.new(options[:local]).expand_path
|
32
|
+
@remotes_method = :checkout
|
30
33
|
initialize_local_dir(options)
|
31
34
|
end
|
32
35
|
|
@@ -192,6 +195,12 @@ module Origen
|
|
192
195
|
is_a?(Git) # :-)
|
193
196
|
end
|
194
197
|
|
198
|
+
# Returns true if the revision controller object uses Perforce
|
199
|
+
def p4?
|
200
|
+
is_a?(Perforce)
|
201
|
+
end
|
202
|
+
alias_method :perforce?, :p4?
|
203
|
+
|
195
204
|
# Returns true if the revision controller object uses Subversion
|
196
205
|
def svn?
|
197
206
|
is_a?(Subversion) # :-)
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'P4'
|
2
|
+
module Origen
|
3
|
+
module RevisionControl
|
4
|
+
class Perforce < Base
|
5
|
+
# P4 session
|
6
|
+
attr_reader :p4
|
7
|
+
|
8
|
+
# e.g. myfile.txt
|
9
|
+
attr_accessor :remote_file
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
super
|
13
|
+
@remotes_method = :print
|
14
|
+
@p4 = P4.new
|
15
|
+
@p4.maxresults = 1
|
16
|
+
parse_remote
|
17
|
+
@p4.connect
|
18
|
+
unless @p4.connected?
|
19
|
+
Origen.log.error("Could not connect to port #{@p4.port} on client #{@p4.client}!")
|
20
|
+
fail
|
21
|
+
end
|
22
|
+
@p4.run_login
|
23
|
+
end
|
24
|
+
|
25
|
+
# Downloads a file to a local directory, no workspace/client is created. Perfect
|
26
|
+
# for read-only access like an application remote
|
27
|
+
def print(options = {})
|
28
|
+
options = {
|
29
|
+
verbose: true,
|
30
|
+
version: 'Latest'
|
31
|
+
}.merge(options)
|
32
|
+
cmd = [__method__.to_s, '-o', "#{@local}/#{@remote_file.to_s.split('/')[-1]}", @remote_file.to_s]
|
33
|
+
run cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
def checkout(path = nil, options = {})
|
37
|
+
not_yet_supported(__method__)
|
38
|
+
end
|
39
|
+
|
40
|
+
def root
|
41
|
+
not_yet_supported(__method__)
|
42
|
+
end
|
43
|
+
|
44
|
+
def current_branch
|
45
|
+
not_yet_supported(__method__)
|
46
|
+
end
|
47
|
+
|
48
|
+
def diff_cmd
|
49
|
+
not_yet_supported(__method__)
|
50
|
+
end
|
51
|
+
|
52
|
+
def unmanaged
|
53
|
+
not_yet_supported(__method__)
|
54
|
+
end
|
55
|
+
|
56
|
+
def local_modifications
|
57
|
+
not_yet_supported(__method__)
|
58
|
+
end
|
59
|
+
|
60
|
+
def changes
|
61
|
+
not_yet_supported(__method__)
|
62
|
+
end
|
63
|
+
|
64
|
+
def checkin
|
65
|
+
not_yet_supported(__method__)
|
66
|
+
end
|
67
|
+
|
68
|
+
def build
|
69
|
+
not_yet_supported(__method__)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
# Needs to be in the form of an Array with command, as a Sting, as the first argument
|
75
|
+
# e.g. ["print", "-o", "pins/myfile.txt", "//depot/myprod/main/doc/pinout/myfile.txt"]
|
76
|
+
def run(cmd)
|
77
|
+
p4.run cmd
|
78
|
+
end
|
79
|
+
|
80
|
+
def not_yet_supported(m)
|
81
|
+
Origen.log.warn("The method #{m} is not currently supported by the Perforce API")
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_remote
|
86
|
+
(@p4.port, @remote_file) = @remote.to_s.match(/^p4\:\/\/(\S+\:\d+)(.*)/).captures unless @remote.nil?
|
87
|
+
end
|
88
|
+
|
89
|
+
def configure_client(options)
|
90
|
+
unless options.include? :local
|
91
|
+
Origen.log.error('Need options[:local] to know how to configure the Perforce client!')
|
92
|
+
fail
|
93
|
+
end
|
94
|
+
client_name = "#{Origen.app.name}_#{User.current.id}_#{Time.now.to_i}"
|
95
|
+
begin
|
96
|
+
client_spec = @p4.fetch_client
|
97
|
+
client_spec['Root'] = options[:local].to_s
|
98
|
+
client_spec['Client'] = client_name
|
99
|
+
client_spec['View'] = ["#{@remote_file} //#{client_name}/#{@remote_file.split('/')[-1]}"]
|
100
|
+
client_spec['Host'] = nil
|
101
|
+
@p4.save_client(client_spec)
|
102
|
+
@p4.client = client_name
|
103
|
+
rescue P4Exception
|
104
|
+
@p4.errors.each { |e| Origen.log.error e }
|
105
|
+
raise
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -4,6 +4,7 @@ module Origen
|
|
4
4
|
autoload :DesignSync, 'origen/revision_control/design_sync'
|
5
5
|
autoload :Git, 'origen/revision_control/git'
|
6
6
|
autoload :Subversion, 'origen/revision_control/subversion'
|
7
|
+
autoload :Perforce, 'origen/revision_control/perforce'
|
7
8
|
|
8
9
|
IGNORE_DIRS = %w(
|
9
10
|
.ws .lsf log output web coverage .ref .yardoc .collection .bin
|
@@ -36,6 +37,8 @@ module Origen
|
|
36
37
|
DesignSync.new(options)
|
37
38
|
when options[:remote] =~ /git/
|
38
39
|
Git.new(options)
|
40
|
+
when options[:remote] =~ /^p4/
|
41
|
+
Perforce.new(options)
|
39
42
|
else
|
40
43
|
fail "Could not work out the revision control system for: #{options[:remote]}"
|
41
44
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module Origen
|
2
2
|
module Specs
|
3
3
|
module Checkers
|
4
|
-
require 'nokogiri'
|
5
|
-
|
6
4
|
# rubocop:disable Style/RescueModifier:
|
7
5
|
def name_audit(name)
|
8
6
|
return name if name.nil?
|
@@ -74,7 +72,6 @@ module Origen
|
|
74
72
|
def evaluate_limit(limit)
|
75
73
|
return limit if limit.is_a?(Numeric)
|
76
74
|
return nil if limit.nil?
|
77
|
-
limit = limit.to_s if [Nokogiri::XML::NodeSet, Nokogiri::XML::Text, Nokogiri::XML::Element].include? limit.class
|
78
75
|
if limit.is_a? Symbol
|
79
76
|
limit = ':' + limit.to_s
|
80
77
|
else
|
data/lib/origen/sub_blocks.rb
CHANGED
@@ -364,11 +364,13 @@ module Origen
|
|
364
364
|
|
365
365
|
def materialize
|
366
366
|
file = attributes.delete(:file)
|
367
|
+
dir = attributes.delete(:dir) || owner.send(:export_dir)
|
367
368
|
block = owner.send(:instantiate_sub_block, name, klass, attributes)
|
368
369
|
if file
|
369
|
-
require File.join(
|
370
|
+
require File.join(dir, file)
|
370
371
|
block.extend owner.send(:export_module_names_from_path, file).join('::').constantize
|
371
372
|
end
|
373
|
+
block.owner = owner
|
372
374
|
block
|
373
375
|
end
|
374
376
|
|
data/lib/origen/tests/test.rb
CHANGED
data/lib/origen.rb
CHANGED
@@ -68,6 +68,7 @@ unless defined? RGen::ORIGENTRANSITION
|
|
68
68
|
autoload :Clocks, 'origen/clocks'
|
69
69
|
autoload :Value, 'origen/value'
|
70
70
|
autoload :OrgFile, 'origen/org_file'
|
71
|
+
autoload :Limits, 'origen/limits'
|
71
72
|
|
72
73
|
attr_reader :switch_user
|
73
74
|
|
@@ -79,6 +80,7 @@ unless defined? RGen::ORIGENTRANSITION
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
83
|
+
class PerforceError < OrigenError; status_code(11); end
|
82
84
|
class GitError < OrigenError; status_code(11); end
|
83
85
|
class DesignSyncError < OrigenError; status_code(12); end
|
84
86
|
class RevisionControlUninitializedError < OrigenError; status_code(13); end
|
data/templates/git/gitignore.erb
CHANGED
@@ -4,7 +4,7 @@ module Origen
|
|
4
4
|
module Export1
|
5
5
|
module Block1
|
6
6
|
def self.extended(model)
|
7
|
-
model.sub_block :x, file: 'origen/export1/block1/x.rb', lazy: true, base_address: 0x40000000
|
7
|
+
model.sub_block :x, file: 'origen/export1/block1/x.rb', dir: '/home/stephen/Code/github/origen/vendor/lib/models', lazy: true, base_address: 0x40000000
|
8
8
|
|
9
9
|
end
|
10
10
|
end
|
@@ -66,8 +66,10 @@ module Origen
|
|
66
66
|
model.add_ground_pin :gnd2
|
67
67
|
model.add_ground_pin :gnd3
|
68
68
|
model.add_ground_pin_group :gnd, :gnd1, :gnd2, :gnd3
|
69
|
+
model.add_virtual_pin :relay1
|
70
|
+
model.add_virtual_pin :relay2, packages: { bga: {} }
|
69
71
|
|
70
|
-
model.sub_block :block1, file: 'origen/export1/block1.rb', lazy: true
|
72
|
+
model.sub_block :block1, file: 'origen/export1/block1.rb', dir: '/home/stephen/Code/github/origen/vendor/lib/models', lazy: true
|
71
73
|
|
72
74
|
end
|
73
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: origen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.32.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen McGinty
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.7'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: nokogiri
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - '='
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 1.7.2
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - '='
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 1.7.2
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: rspec
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -366,6 +352,26 @@ dependencies:
|
|
366
352
|
- - "~>"
|
367
353
|
- !ruby/object:Gem::Version
|
368
354
|
version: 0.8.1
|
355
|
+
- !ruby/object:Gem::Dependency
|
356
|
+
name: p4ruby
|
357
|
+
requirement: !ruby/object:Gem::Requirement
|
358
|
+
requirements:
|
359
|
+
- - "~>"
|
360
|
+
- !ruby/object:Gem::Version
|
361
|
+
version: '2015.2'
|
362
|
+
- - ">="
|
363
|
+
- !ruby/object:Gem::Version
|
364
|
+
version: 2015.2.1313860
|
365
|
+
type: :runtime
|
366
|
+
prerelease: false
|
367
|
+
version_requirements: !ruby/object:Gem::Requirement
|
368
|
+
requirements:
|
369
|
+
- - "~>"
|
370
|
+
- !ruby/object:Gem::Version
|
371
|
+
version: '2015.2'
|
372
|
+
- - ">="
|
373
|
+
- !ruby/object:Gem::Version
|
374
|
+
version: 2015.2.1313860
|
369
375
|
description:
|
370
376
|
email:
|
371
377
|
- stephen.f.mcginty@gmail.com
|
@@ -494,6 +500,9 @@ files:
|
|
494
500
|
- lib/origen/generator/stage.rb
|
495
501
|
- lib/origen/global_app.rb
|
496
502
|
- lib/origen/global_methods.rb
|
503
|
+
- lib/origen/limits.rb
|
504
|
+
- lib/origen/limits/limit.rb
|
505
|
+
- lib/origen/limits/limit_set.rb
|
497
506
|
- lib/origen/location.rb
|
498
507
|
- lib/origen/location/base.rb
|
499
508
|
- lib/origen/location/map.rb
|
@@ -553,6 +562,7 @@ files:
|
|
553
562
|
- lib/origen/revision_control/base.rb
|
554
563
|
- lib/origen/revision_control/design_sync.rb
|
555
564
|
- lib/origen/revision_control/git.rb
|
565
|
+
- lib/origen/revision_control/perforce.rb
|
556
566
|
- lib/origen/revision_control/subversion.rb
|
557
567
|
- lib/origen/ruby_version_check.rb
|
558
568
|
- lib/origen/site_config.rb
|
@@ -640,7 +650,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
640
650
|
version: 1.8.11
|
641
651
|
requirements: []
|
642
652
|
rubyforge_project:
|
643
|
-
rubygems_version: 2.6.
|
653
|
+
rubygems_version: 2.6.8
|
644
654
|
signing_key:
|
645
655
|
specification_version: 4
|
646
656
|
summary: The Semiconductor Developer's Kit
|