origen_testers 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ module OrigenTesters
2
+ module PatternCompilers
3
+ module Runner
4
+ # Run the pattern (or list) through the (specified) compiler
5
+ def self.run_compiler(pattern, options = {})
6
+ compiler = nil
7
+ if options[:compiler_instance]
8
+ compiler = options[:compiler_instance]
9
+ unless dut.pattern_compilers.include? compiler
10
+ fail_msg = "Pattern Compiler instance '#{compiler}' does not exist for this tester, "
11
+ fail_msg += "choose from \(#{dut.pattern_compilers.keys.join(', ')}\) or change tester target."
12
+ fail fail_msg
13
+ end
14
+ else
15
+ if dut.pattern_compilers.count == 1
16
+ # Only one compiler defined (for current platform), use that one
17
+ compiler = dut.pattern_compilers.keys[0]
18
+ else
19
+ # Multiple compilers defined, used one assigned to default or named :default, otherwise fail
20
+ if dut.default_pattern_compiler
21
+ compiler = dut.default_pattern_compiler
22
+ elsif dut.pattern_compilers.keys.include? :default
23
+ compiler = :default
24
+ else
25
+ fail_msg = "No 'default' Pattern Compiler defined, choose from "
26
+ fail_msg += "\(#{dut.pattern_compilers.keys.join(', ')}\) or set one to be the default."
27
+ fail fail_msg
28
+ end
29
+ end
30
+ end
31
+
32
+ Origen.log.info "Compiling... #{pattern}"
33
+
34
+ # Everything is verified and ready, last thing to do is COMPILE
35
+ dut.pattern_compilers[compiler].find_jobs(pattern)
36
+ dut.pattern_compilers[compiler].run
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ AI_DIR_FILE
2
+ tmp_dir <%= tmp_dir %>
3
+ tmf_dir ./
4
+ vbc_dir ./
5
+ avc_dir <%= avc_dir %>
6
+ pinconfig_file <%= pinconfig_file.to_s %>
7
+ single_binary_pattern_dir <%= binl_dir %>
8
+
9
+ <%= render_aiv2b_options_line %>
10
+
11
+ <%= render_aiv_patterns_header %>
12
+ % @avc_files.each do |f|
13
+ <%= render_aiv_patterns_entry(f) %>
14
+ % end
15
+ %
16
+ % # MULTIPORT ENTRIES (if necessary)
17
+ % if multiport?
18
+ % @avc_files.each do |f|
19
+ % multiport.render_aiv_lines(f).each do |line|
20
+ <%= line %>
21
+ % end
22
+ % end
23
+ % end
24
+ %
25
+ % # DIGCAP SETTINGS (if necessary)
26
+ % if digcap? && !digcap.empty?
27
+ % digcap.render_aiv_lines.each do |line|
28
+ <%= line %>
29
+ % end
30
+ % end
31
+
@@ -0,0 +1,92 @@
1
+ module OrigenTesters
2
+ module PatternCompilers
3
+ class UltraFLEXPatternCompiler < IGXLBasedPatternCompiler
4
+ # Linux compiler executable path
5
+ def self.linux_compiler
6
+ Origen.site_config.origen_testers[:uflex_linux_pattern_compiler]
7
+ end
8
+
9
+ # Windows compiler executable path
10
+ def self.windows_compiler
11
+ Origen.site_config.origen_testers[:uflex_windows_pattern_compiler]
12
+ end
13
+
14
+ # Pre-compile environment setup if necessary
15
+ def self.atpc_setup
16
+ Origen.site_config.origen_testers[:uflex_atpc_setup]
17
+ end
18
+
19
+ # Resolves to correct compiler based on operating system
20
+ def self.compiler
21
+ Origen.running_on_windows? ? windows_compiler : linux_compiler
22
+ end
23
+
24
+ def self.compiler_cmd
25
+ Pathname.new(compiler).absolute? ? compiler : eval('"' + compiler + '"')
26
+ end
27
+
28
+ def self.compiler_options
29
+ "#{compiler_cmd} -help"
30
+ end
31
+
32
+ def self.compiler_version
33
+ "#{compiler_cmd} -version"
34
+ end
35
+
36
+ def initialize(id, options = {})
37
+ super
38
+
39
+ @user_options = {}.merge(@user_options)
40
+
41
+ @job_options = {
42
+ tester: :ultraflex,
43
+ compiler: self.class.compiler, # required
44
+ }.merge(@job_options)
45
+
46
+ # These are compiler options that are specific to UltraFLEX (builds on options from IGXL-Based)
47
+ # Set all of these compiler options that don't have args to true/flase. if true then send compiler '-opt'
48
+ @compiler_options = {
49
+ lock: false, # prevents pattern from being reverse compiled or opened in PatternTool
50
+ multiinst: false, # indicates more than one instrument is connected to a single pin
51
+ nocompress: false, # do not compress pattern data blocks
52
+ stdin: false, # Compile data from standard input. Do not use -cpp or specify any pattern file(s) when using this option.
53
+ }.merge(@compiler_options)
54
+
55
+ # These are compiler options that are specific to UltraFLEX (builds on options from IGXL-Based)
56
+ @compiler_options_with_args = {
57
+ pat_version: nil, # version of pattern file to compile
58
+ scan_type: nil, # type of scan data
59
+ includes: nil, # include paths to be passed to C- preprocessor.
60
+ post_processor: nil, # <pathname> customer's post-process executable.
61
+ post_processor_args: nil, # <args> customer's post-process executable arguments
62
+ cdl_cache: nil, # 'yes' | 'no', turns on/off CDL caching, default on compiler side is 'yes'
63
+ init_pattern: nil, # <pattern>, uses the specified pattern module/file/set as an init patterns
64
+ check_set_msb: nil, # 'yes' | 'no', turns on/off check the 'set' or 'set_infinite' opcode
65
+ time_domain: nil, # <time domain>, specifies time domain for pins in patterns
66
+ allow_mto_dash: nil, # Turn on/off support for channel data runtime repeat,i.e. vector dash in MTO patterns. Default value is "no".
67
+ check_vm_min_size: nil, # Turns on/off the check on minimum size of a VM pattern. Default value is "yes".
68
+ check_vm_mod_size: nil, # Turns on/off the check on a VM pattern module size. Default value is "yes".
69
+ check_oob_size: nil, # Turns on/off the check on size of OOB regions. Yes means size must be modulo 10. Default value is "no".
70
+ allow_mixed_1x2x: nil, # Turns on/off the support of mixed 1x/2x pin groups. Default value is "no".
71
+ allow_differential: nil, # Turns on/off support for differential pins. Default value is "yes".
72
+ allow_scan_in_srm: nil, # Allow/disallow scan vectors in SRM pattern modules. Default value is "no".
73
+ vm_block_size: nil, # Specifies uncompressed size in bytes of a pattern data block
74
+ }.merge(@compiler_options_with_args)
75
+
76
+ update_common_options(options) # Update common options with default (see BasePatternCompiler)
77
+ verify_pinmap_is_specified # verify pinmap specified correctly - IGXL specific
78
+ clean_and_verify_options # Standard cleaning and verifying (see BasePatternCompiler)
79
+ end
80
+
81
+ # Executes the compiler for each job in the queue
82
+ def run(list = nil, options = {})
83
+ fail "Error: the tester #{Origen.tester} is not an Ultrflex tester,exiting..." unless is_ultraflex?
84
+ msg = "Error: application #{Origen.app.name} is running on Windows, "
85
+ msg += 'to run the pattern compiler you must be on a Linux machine'
86
+ fail msg if Origen.running_on_windows?
87
+
88
+ super
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,455 @@
1
+ module OrigenTesters
2
+ module PatternCompilers
3
+ class V93KPatternCompiler < BasePatternCompiler
4
+ require_relative 'v93k/multiport'
5
+ include MultiportAPI
6
+ require_relative 'v93k/digcap'
7
+ include DigCapAPI
8
+
9
+ attr_reader :avc_files, :max_avcfilename_size, :vec_per_frame
10
+
11
+ TEMPLATE = "#{Origen.root!}/lib/origen_testers/pattern_compilers/templates/template.aiv.erb"
12
+
13
+ # Linux compiler executable path
14
+ def self.linux_compiler
15
+ Origen.site_config.origen_testers[:v93k_linux_pattern_compiler]
16
+ end
17
+
18
+ # Windows compiler executable path - not available for V93K
19
+ def self.windows_compiler
20
+ nil
21
+ end
22
+
23
+ # Resolves to correct compiler (linux is only available)
24
+ def self.compiler
25
+ linux_compiler
26
+ end
27
+
28
+ def self.compiler_cmd
29
+ Pathname.new(compiler).absolute? ? compiler : eval('"' + compiler + '"')
30
+ end
31
+
32
+ def self.compiler_options
33
+ "#{compiler_cmd} -h"
34
+ end
35
+
36
+ def self.compiler_version
37
+ "#{compiler_cmd} -V"
38
+ end
39
+
40
+ def initialize(id, options = {})
41
+ super
42
+
43
+ @user_options = {
44
+ config_dir: nil, # Common directory where all configs can be stored
45
+ pinconfig_dir: nil, # Can override common config_dir if pinconfig stored elsewhere
46
+ pinconfig: nil, # Can specify just file name (to use config_dir/pinconfig_dir), or give full path
47
+ tmf_dir: nil, # Can override common config_dir if tmf stored elsewhere
48
+ tmf: nil, # Can specify just file name (to use config_dir/tmf_dir), or give full path
49
+ vbc_dir: nil, # Can override common config_dir if vbc stored elsewhere
50
+ vbc: nil, # Can specify just file name (to use config_dir/vbc_dir), or give full path
51
+ incl_dir: nil,
52
+ includes: [], # Array of files that will be copied into tmp job workspace before compilation
53
+ tmp_dir: nil,
54
+ avc_dir: nil,
55
+ binl_dir: nil,
56
+ multiport: nil, # Optional hash for multiport settings: port_bursts, port_in_focus, prefix, postfix
57
+ digcap: nil, # Optional hash for digcap settings: pins, vps, nrf, char
58
+ }.merge(@user_options)
59
+
60
+ @job_options = {
61
+ tester: :v93k,
62
+ compiler: self.class.compiler, # required
63
+ }.merge(@job_options)
64
+
65
+ @compiler_options = {
66
+
67
+ }.merge(@compiler_options)
68
+
69
+ @compiler_options_with_args = {
70
+ aiv2b_opts: nil
71
+ }.merge(@compiler_options_with_args)
72
+
73
+ @avc_files = []
74
+ @vec_per_frame = {}
75
+
76
+ update_common_options(options) # Update common options with default (see BasePatternCompiler)
77
+ verify_pinconfig_is_specified # Verify pinconfig specified correctly - Smartest specific
78
+ verify_tmf_is_specified # Verify tmf specified correctly - Smartest specific
79
+ clean_and_verify_options # Standard cleaning and verifying (see BasePatternCompiler)
80
+ end
81
+
82
+ def pinconfig_file
83
+ @pinconfig_file ||= build_file(:pinconfig)
84
+ end
85
+
86
+ def tmf_file
87
+ @tmf_file ||= build_file(:tmf)
88
+ end
89
+
90
+ def vbc_file
91
+ @vbc_file ||= build_file(:vbc)
92
+ end
93
+
94
+ def verify_pinconfig_is_specified
95
+ fail 'Pinconfig file is not defined! Pass as an option.' if pinconfig_file.nil?
96
+ fail 'Pinconfig is not a file!' unless pinconfig_file.file?
97
+ end
98
+
99
+ def verify_tmf_is_specified
100
+ fail 'Timing Map File (tmf) is not defined! Pass as an option.' if tmf_file.nil?
101
+ fail 'Timing Map File (tmf) is not a file!' unless tmf_file.file?
102
+ end
103
+
104
+ # Executes the compiler for each job in the queue
105
+ def run(aiv = nil, options = {})
106
+ aiv, options = nil, aiv if aiv.is_a? Hash
107
+
108
+ fail "Error: the tester #{Origen.tester} is not an V93K tester, exiting..." unless is_v93k?
109
+
110
+ msg = "Error: application #{Origen.app.name} is running on Windows, "
111
+ msg += 'to run the pattern compiler you must be on a Linux machine'
112
+ fail msg if Origen.running_on_windows?
113
+
114
+ # Check if there was a pattern list passed as an argument
115
+ # If so, then compile the patterns inside it.
116
+ # Otherwise compile the jobs in the queue
117
+ if aiv.nil?
118
+ if empty?
119
+ empty_msg
120
+ return
121
+ end
122
+ @jobs.each do |job|
123
+ unless options[:ignore_ready]
124
+ fail "Error: compiler #{job.id} not ready for pattern #{job.name}" unless job.ready?
125
+ end
126
+ if job.location == :lsf
127
+ # puts "#{self.class.aiv_setup} ; #{job.cmd}"
128
+ # Origen.app.lsf.submit(self.class.aiv_setup + '; ' + job.cmd)
129
+ Origen.app.lsf.submit(job.cmd)
130
+ else
131
+ Origen.profile "Linux pattern compiler compiles pattern #{job.pattern}" do
132
+ Dir.chdir(job.output_directory) do
133
+ # puts "#{job.cmd}"
134
+ system job.cmd
135
+ end
136
+ end
137
+ end
138
+ end
139
+ if @job_options[:location] == :local
140
+ if @job_options[:clean] == true
141
+ puts 'Log file :clean option set to true, deleting log files'
142
+ clean_output
143
+ end
144
+ end
145
+ # Clear @jobs
146
+ clear
147
+
148
+ else
149
+ # Assumes .aiv file and all workspace collateral has been built up
150
+ aiv = convert_to_pathname(aiv)
151
+ fail 'File does not exist! Please specify existing aiv file.' unless aiv.file?
152
+ current_job_options = @job_options.merge(@compiler_options_with_args)
153
+ current_job_options = current_job_options.merge(extract_job_options_from_aiv(aiv))
154
+ current_job_options = current_job_options.merge(options)
155
+ current_job_options[:output_directory] = aiv.dirname
156
+
157
+ @jobs << Job.new(Pathname.new(aiv), current_job_options, @compiler_options)
158
+ inspect_jobs
159
+ run(options)
160
+ end
161
+ end
162
+
163
+ # Output the compiler jobs in the queue to the console
164
+ def inspect_jobs(index = nil)
165
+ return empty_msg if empty?
166
+ desc = []
167
+ puts "\n"
168
+ @jobs.each_with_index do |j, i|
169
+ unless index.nil?
170
+ next unless i == index
171
+ end
172
+ desc << '| Job: ' + " #{i + 1} ".rjust(8) + '|' + 'Pattern/AIV:'.rjust(18) + " #{j.pattern.basename}".ljust(125) + '|'
173
+ desc << '| |' + 'Compiler ID:'.rjust(18) + " #{j.id} ".ljust(125) + '|'
174
+ desc << '| |' + 'AVC Files:'.rjust(18) + " #{j.count} ".ljust(125) + '|'
175
+ desc << '| |' + 'Output Directory:'.rjust(18) + " #{j.output_directory} ".ljust(125) + '|'
176
+ desc << '| |' + '.avc directory:'.rjust(18) + " #{j.avc_dir} ".ljust(125) + '|'
177
+ desc << '| |' + '.binl directory:'.rjust(18) + " #{j.binl_dir} ".ljust(125) + '|'
178
+ desc << '| |' + 'LSF:'.rjust(18) + " #{j.location == :lsf ? true : false} ".ljust(125) + '|'
179
+ desc << '| |' + 'Delete log files:'.rjust(18) + " #{j.clean} ".ljust(125) + '|'
180
+ desc << '| |' + 'Verbose:'.rjust(18) + " #{j.verbose} ".ljust(125) + '|'
181
+ if j.aiv2b_opts && j.aiv2b_opts.is_a?(String)
182
+ aiv2b_opts = j.aiv2b_opts.gsub('AI_V2B_OPTIONS ', '')
183
+ else
184
+ aiv2b_opts = render_aiv2b_options_line.gsub('AI_V2B_OPTIONS', '')
185
+ end
186
+ desc << '| |' + 'AI_V2B Options:'.rjust(18) + " #{aiv2b_opts} ".ljust(125) + '|'
187
+ desc << '-' * desc.first.size
188
+ end
189
+ puts desc.flatten.join("\n")
190
+ end
191
+
192
+ # Finds the patterns and creates a compiler job for each one found.
193
+ # Handles singles files (.atp, .atp.gz, or .list) and directories (recursively or flat)
194
+ def find_jobs(p = @path)
195
+ # First-level verification: file/directory was given and exists
196
+ msg = 'Pass in a valid file (.avc, .avc.gz, .list) or a valid directory'
197
+ fail "Pattern path is set to nil! #{msg}" if p.nil?
198
+ path = Pathname.new(p)
199
+ fail "Pattern path does not exist! #{msg}" unless path.exist?
200
+ path = path.expand_path
201
+
202
+ # Set the reference directory for pattern sub-dir mirroring
203
+ set_reference_directory
204
+
205
+ # Collect file, list, or directory (recursively)
206
+ Origen.profile 'Linux pattern compiler finds patterns' do
207
+ if path.directory?
208
+ # Get all of the patterns inside this dir or inside this directory recursively
209
+ process_directory(path, @files, @user_options[:recursive])
210
+ else
211
+ # Found a file so no searching is necessary, process as single pattern or list
212
+ process_file(path, @files)
213
+ end
214
+ end
215
+
216
+ fail "Did not fild a valid file to compile! #{msg}" if @files.empty?
217
+
218
+ Origen.profile 'Linux pattern compiler creates job' do
219
+ # For V93K, only single AIV file is really sent to the compiler, but need list of all
220
+ # avc files that will be compiled using that aiv file, so keep a separate array.
221
+ @max_avcfilename_size = 0
222
+ @files.each do |f|
223
+ @avc_files << Pathname.new(f).basename.sub_ext('').to_s
224
+ @max_avcfilename_size = @avc_files[-1].size > @max_avcfilename_size ? @avc_files[-1].size : @max_avcfilename_size
225
+ end
226
+
227
+ rel_dir = Pathname.new("#{path.dirname.to_s[@user_options[:reference_directory].to_s.size..-1]}")
228
+
229
+ # Resolve output directory
230
+ if @job_options[:output_directory].nil?
231
+ # job output dir not specified, create a unique (hash) based on path/compiler_name
232
+ s = Digest::MD5.new
233
+ s << @user_options[:reference_directory].to_s
234
+ s << @id.to_s
235
+ out = "#{@user_options[:reference_directory]}/job_#{@id}_#{s.to_s[0..6].upcase}#{rel_dir}"
236
+ job_output_dir = Pathname.new(out)
237
+ else
238
+ job_output_dir = Pathname.new("#{@job_options[:output_directory]}#{rel_dir}")
239
+ end
240
+
241
+ # Create any necessary output directories before trying to compile
242
+ unless job_output_dir.directory?
243
+ puts "Output directory #{job_output_dir} does not exist, creating it..."
244
+ FileUtils.mkdir_p(job_output_dir)
245
+ end
246
+
247
+ job_avc_dir = avc_dir.absolute? ? avc_dir : Pathname.new("#{job_output_dir}/#{avc_dir}").cleanpath
248
+ unless job_avc_dir.directory?
249
+ puts "AVC Output directory #{job_avc_dir} does not exist, creating it..."
250
+ FileUtils.mkdir_p(job_avc_dir)
251
+ end
252
+ job_binl_dir = binl_dir.absolute? ? binl_dir : Pathname.new("#{job_output_dir}/#{binl_dir}").cleanpath
253
+ unless job_binl_dir.directory?
254
+ puts "BINL Output directory #{job_binl_dir} does not exist, creating it..."
255
+ FileUtils.mkdir_p(job_binl_dir)
256
+ end
257
+
258
+ # Move AVC files into job space (through pre-processor)
259
+ @files.each do |file|
260
+ contents = File.open(file, 'rb') { |f| f.read }
261
+ new_contents = preprocess_avc(contents)
262
+ new_avc_file = Pathname.new("#{job_avc_dir}/#{Pathname.new(file).basename}").cleanpath
263
+ File.open(new_avc_file, 'w') { |f| f.write(new_contents) }
264
+ avc_key = Pathname.new(file).basename.sub_ext('').to_s.to_sym
265
+ @vec_per_frame[avc_key] = digcap? ? avc_digcap_vpf(new_contents) : 0
266
+ end
267
+
268
+ # Generate the AIV file using the template with all the pattern compiler parameters
269
+ aiv_file = "#{job_output_dir}/#{path.basename.to_s.split('.')[0]}.aiv"
270
+ Origen.log.info "Creating... #{aiv_file}"
271
+ contents = Origen.compile(self.class::TEMPLATE, scope: self, preserve_target: true)
272
+ File.open(aiv_file, 'w') { |f| f.write(contents) }
273
+
274
+ # Copy Timing Map File to local AIV workspace
275
+ dest = Pathname.new("#{job_output_dir}/#{tmf_file.basename}").cleanpath
276
+ FileUtils.cp tmf_file, dest
277
+
278
+ # Copy VBC file to local AIV workspace (if specified)
279
+ if vbc_file
280
+ dest = Pathname.new("#{job_output_dir}/#{vbc_file.basename}").cleanpath
281
+ FileUtils.cp vbc_file, dest
282
+ end
283
+
284
+ # Copy any extra files needed (includes)
285
+ @user_options[:includes].each do |incl|
286
+ src = build_file(:incl, incl)
287
+ dest = Pathname.new("#{job_output_dir}/#{src.basename}").cleanpath
288
+ FileUtils.cp src, dest
289
+ end
290
+
291
+ # Gather up job options
292
+ current_job_options = @job_options.merge(@compiler_options_with_args)
293
+ current_job_options[:output_directory] = job_output_dir
294
+ current_job_options[:pinconfig] = pinconfig_file
295
+ current_job_options[:tmf] = tmf_file
296
+ current_job_options[:count] = @avc_files.count
297
+ current_job_options[:avc_dir] = avc_dir
298
+ current_job_options[:binl_dir] = binl_dir
299
+
300
+ # Create new job
301
+ @jobs << Job.new(Pathname.new(aiv_file), current_job_options, @compiler_options)
302
+ current_job_options = {}
303
+ end
304
+
305
+ # Clear files and avc_files now that job has successfully been queued
306
+ @files = []
307
+ @avc_files = []
308
+ @vec_per_frame = {}
309
+ inspect_jobs
310
+ end
311
+
312
+ # Given the file contents, parse and calculate number of capture vectors
313
+ def avc_digcap_vpf(contents)
314
+ capture_vectors = 0
315
+ contents.each_line do |line|
316
+ capture_vectors += 1 if /#{digcap.capture_string}/.match(line)
317
+ end
318
+ capture_vectors
319
+ end
320
+
321
+ def avc_dir
322
+ @avc_dir ||= begin
323
+ if @user_options[:avc_dir]
324
+ clean_path(@user_options[:avc_dir].to_s)
325
+ else
326
+ Pathname.new('./AVC') # default value
327
+ end
328
+ end
329
+ end
330
+
331
+ def binl_dir
332
+ @binl_dir ||= begin
333
+ if @user_options[:binl_dir]
334
+ clean_path(@user_options[:binl_dir].to_s)
335
+ else
336
+ Pathname.new('./BINL') # default value
337
+ end
338
+ end
339
+ end
340
+
341
+ def tmp_dir
342
+ @tmp_dir ||= begin
343
+ if @user_options[:tmp_dir]
344
+ clean_path(@user_options[:tmp_dir].to_s)
345
+ else
346
+ Pathname.new('./tmp') # default value
347
+ end
348
+ end
349
+ end
350
+
351
+ # Given path string, return Pathname object with cleaned up path
352
+ def clean_path(path_str)
353
+ path = Pathname.new(path_str).cleanpath
354
+ if path.absolute?
355
+ return path
356
+ else
357
+ return Pathname.new("./#{path}")
358
+ end
359
+ end
360
+
361
+ # Placeholder - TopLevel can monkey patch this method to do more
362
+ # sophisticated AVC modification prior to compilation
363
+ def preprocess_avc(contents)
364
+ new_contents = contents # no manipulation done here
365
+ new_contents
366
+ end
367
+
368
+ def render_aiv2b_options_line
369
+ line = 'AI_V2B_OPTIONS'
370
+ if @compiler_options_with_args[:aiv2b_opts]
371
+ if @compiler_options_with_args[:aiv2b_opts].is_a? Array
372
+ @compiler_options_with_args[:aiv2b_opts].each do |opt|
373
+ line += " #{opt}"
374
+ end
375
+ elsif @compiler_options_with_args[:aiv2b_opts].is_a? String
376
+ line += " #{@compiler_options[:aiv2b]}"
377
+ else
378
+ fail 'aiv2b options must be an array or string'
379
+ end
380
+ end
381
+ line += " -c #{vbc_file.basename}" if vbc_file
382
+ line
383
+ end
384
+
385
+ def render_aiv_patterns_header
386
+ line = 'PATTERNS '
387
+ line += 'name'.ljust(max_avcfilename_size + 2)
388
+ line += 'port'.ljust(multiport.port_in_focus.size + 2) if multiport?
389
+ line += 'tmf_file'
390
+ line
391
+ end
392
+
393
+ def render_aiv_patterns_entry(pattern)
394
+ line = ' '
395
+ line += "#{pattern}".ljust(max_avcfilename_size + 2)
396
+ line += "#{multiport.port_in_focus}".ljust(multiport.port_in_focus.size + 2) if multiport?
397
+ line += "#{tmf_file.basename}"
398
+ line
399
+ end
400
+
401
+ private
402
+
403
+ def extract_job_options_from_aiv(file)
404
+ options = {}
405
+ contents = File.open(file, 'rb') { |f| f.read }
406
+ count = 0
407
+ counting = false
408
+ contents.each_line do |line|
409
+ if match = line.match(/^avc_dir\s*(\S*)/)
410
+ options[:avc_dir] = match.captures[0]
411
+ end
412
+ if match = line.match(/^pinconfig_file\s*(\S*)/)
413
+ options[:pinconfig] = Pathname.new(match.captures[0])
414
+ end
415
+ if match = line.match(/^single_binary_pattern_dir\s*(\S*)/)
416
+ options[:binl_dir] = match.captures[0]
417
+ end
418
+ if match = line.match(/^AI_V2B_OPTIONS/)
419
+ options[:aiv2b_opts] = match.captures[0]
420
+ end
421
+ if counting
422
+ if line.match(/\w+/)
423
+ count += 1
424
+ else
425
+ counting = false
426
+ end
427
+ end
428
+ if match = line.match(/^PATTERNS/)
429
+ counting = true
430
+ end
431
+ end
432
+ options[:count] = count
433
+ options
434
+ end
435
+
436
+ def build_file(type, fstr = nil)
437
+ type_dir = "#{type}_dir".to_sym
438
+ fstr ||= @user_options[type]
439
+ if fstr.nil?
440
+ nil
441
+ else
442
+ if Pathname.new(fstr).absolute?
443
+ Pathname.new(fstr)
444
+ elsif @user_options[type_dir]
445
+ Pathname.new("#{@user_options[type_dir]}/#{fstr}").cleanpath
446
+ elsif @user_options[:config_dir]
447
+ Pathname.new("#{@user_options[:config_dir]}/#{fstr}").cleanpath
448
+ else
449
+ Pathname.new("#{Origen.root!}/#{fstr}").cleanpath
450
+ end
451
+ end
452
+ end
453
+ end
454
+ end
455
+ end