origen_testers 0.14.0 → 0.15.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.
@@ -0,0 +1,107 @@
1
+ module OrigenTesters
2
+ module PatternCompilers
3
+ class V93KPatternCompiler
4
+ module DigCapAPI
5
+ class DigCap
6
+ attr_accessor :owner, :pins, :vps, :nrf, :char
7
+
8
+ def initialize(owner, options)
9
+ @owner = owner
10
+ @pins = nil
11
+
12
+ if options && options[:pins] && options[:vps]
13
+ @pins = options[:pins] # required: pins to be captured
14
+ @vps = options[:vps] # required: vecotrs per sample
15
+ @nrf = options[:nrf] || 1 # optional: nr_frames (defaults to 1)
16
+ @char = options[:char] || 'C' # optional: vector character representing capture
17
+ elsif options
18
+ fail 'Must specifiy pins and vps for digcap setup!'
19
+ end
20
+ end
21
+
22
+ def render_aiv_lines
23
+ lines = []
24
+ lines << ''
25
+ lines << 'AI_DIGCAP_SETTINGS {'
26
+ lines << render_digcap_header
27
+ avc_files.each do |f|
28
+ if vec_per_frame[f.to_sym] > 0
29
+ lines << render_digcap_entry(f)
30
+ end
31
+ end
32
+ lines << '};'
33
+ lines
34
+ end
35
+
36
+ def capture_string
37
+ " #{char * num_pins} "
38
+ end
39
+
40
+ def num_pins
41
+ if pins.is_a? String
42
+ pins.split(' ').size
43
+ elsif pins.is_a? Symbol
44
+ dut.pins(pins).size
45
+ elsif pins.is_a? Array
46
+ fail 'Digcap Pins does not support array yet'
47
+ end
48
+ end
49
+
50
+ def enabled?
51
+ pins.nil? ? false : true
52
+ end
53
+
54
+ def empty?
55
+ vec_per_frame.each do |k, v|
56
+ return false if v > 0
57
+ end
58
+ true # digcap setup but no avc contain capture vectors
59
+ end
60
+
61
+ private
62
+
63
+ def render_digcap_header
64
+ line = 'variable'.ljust(max_filename_size + 4)
65
+ line += ' '
66
+ line += 'label'.ljust(max_filename_size)
67
+ line += ' '
68
+ line += 'vec_per_frame vec_per_sample nr_frames {pins};'
69
+ line
70
+ end
71
+
72
+ def render_digcap_entry(pattern)
73
+ line = "#{pattern}_var".ljust(max_filename_size + 4)
74
+ line += ' '
75
+ line += "#{pattern}".ljust(max_filename_size)
76
+ line += ' '
77
+ line += "#{vec_per_frame[pattern.to_sym]}".ljust(15)
78
+ line += "#{vps}".ljust(16)
79
+ line += "#{nrf}".ljust(11)
80
+ line += "{#{pins}};"
81
+ line
82
+ end
83
+
84
+ def avc_files
85
+ owner.avc_files
86
+ end
87
+
88
+ def max_filename_size
89
+ owner.max_avcfilename_size
90
+ end
91
+
92
+ def vec_per_frame
93
+ owner.vec_per_frame
94
+ end
95
+ end
96
+
97
+ def digcap
98
+ @digcap ||= DigCap.new(self, @user_options[:digcap])
99
+ end
100
+
101
+ def digcap?
102
+ digcap.enabled?
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,80 @@
1
+ module OrigenTesters
2
+ module PatternCompilers
3
+ class V93KPatternCompiler
4
+ module MultiportAPI
5
+ class Multiport
6
+ attr_accessor :port_in_focus, :port_bursts, :prefix, :postfix
7
+
8
+ def initialize(options)
9
+ @port_in_focus = nil
10
+
11
+ if options && options[:port_in_focus]
12
+ @port_in_focus = options[:port_in_focus]
13
+ @port_bursts = options[:port_bursts]
14
+ @prefix = options[:prefix].nil? ? '' : "#{options[:prefix]}_"
15
+ @postfix = options[:postfix].nil? ? '' : "_#{options[:postfix]}"
16
+ end
17
+ end
18
+
19
+ def render_aiv_lines(pattern)
20
+ mpb_entry = []
21
+ mpb_entry << ''
22
+ mpb_entry << render_mpb_header(pattern)
23
+ mpb_entry << render_mpb_port_line(pattern)
24
+ mpb_entry << render_mpb_burst_line(pattern)
25
+ mpb_entry
26
+ end
27
+
28
+ def enabled?
29
+ port_in_focus.nil? ? false : true
30
+ end
31
+
32
+ private
33
+
34
+ def render_mpb_header(pattern)
35
+ "MULTI_PORT_BURST #{prefix}#{pattern}#{postfix}"
36
+ end
37
+
38
+ def render_mpb_port_line(pattern)
39
+ line = 'PORTS '
40
+ line += port_in_focus.to_s
41
+ line += mpb_padding(port_in_focus.to_s, pattern, 0)
42
+ if port_bursts
43
+ port_bursts.each do |k, v|
44
+ line += k.to_s
45
+ line += mpb_padding(k.to_s, v.to_s, 0)
46
+ end
47
+ end
48
+ line
49
+ end
50
+
51
+ def render_mpb_burst_line(pattern)
52
+ line = ' '
53
+ line += pattern.to_s
54
+ line += mpb_padding(port_in_focus.to_s, pattern, 1)
55
+ if port_bursts
56
+ port_bursts.each do |k, v|
57
+ line += v.to_s
58
+ line += mpb_padding(k.to_s, v.to_s, 1)
59
+ end
60
+ end
61
+ line
62
+ end
63
+
64
+ def mpb_padding(str0, str1, index = 0)
65
+ width = str0.size > str1.size ? str0.size : str1.size
66
+ index == 0 ? ' ' * (width + 2 - str0.size) : ' ' * (width + 2 - str1.size)
67
+ end
68
+ end
69
+
70
+ def multiport
71
+ @multiport ||= Multiport.new(@user_options[:multiport])
72
+ end
73
+
74
+ def multiport?
75
+ multiport.enabled?
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: origen_testers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.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: 2017-11-20 00:00:00.000000000 Z
11
+ date: 2017-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: origen
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.40
19
+ version: 0.26.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.40
26
+ version: 0.26.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: require_all
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -233,8 +233,16 @@ files:
233
233
  - lib/origen_testers/parser/searchable_hash.rb
234
234
  - lib/origen_testers/pattern_compilers.rb
235
235
  - lib/origen_testers/pattern_compilers/assembler.rb
236
+ - lib/origen_testers/pattern_compilers/base.rb
237
+ - lib/origen_testers/pattern_compilers/igxl_based.rb
238
+ - lib/origen_testers/pattern_compilers/j750.rb
236
239
  - lib/origen_testers/pattern_compilers/job.rb
237
- - lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb
240
+ - lib/origen_testers/pattern_compilers/runner.rb
241
+ - lib/origen_testers/pattern_compilers/templates/template.aiv.erb
242
+ - lib/origen_testers/pattern_compilers/ultraflex.rb
243
+ - lib/origen_testers/pattern_compilers/v93k.rb
244
+ - lib/origen_testers/pattern_compilers/v93k/digcap.rb
245
+ - lib/origen_testers/pattern_compilers/v93k/multiport.rb
238
246
  - lib/origen_testers/program_generators.rb
239
247
  - lib/origen_testers/smartest_based_tester.rb
240
248
  - lib/origen_testers/smartest_based_tester/base.rb
@@ -348,7 +356,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
348
356
  version: 1.8.11
349
357
  requirements: []
350
358
  rubyforge_project:
351
- rubygems_version: 2.5.2
359
+ rubygems_version: 2.6.7
352
360
  signing_key:
353
361
  specification_version: 4
354
362
  summary: This plugin provides Origen tester models to drive ATE type testers like
@@ -1,599 +0,0 @@
1
- module OrigenTesters
2
- module PatternCompilers
3
- class UltraFlexPatternCompiler
4
- require 'pathname'
5
- require_relative 'assembler'
6
- require_relative 'job'
7
-
8
- # Linux compiler executable path
9
- LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
10
- # LINUX_PATTERN_COMPILER = "#{Origen.root!}/bin/latest/bin/atpcompiler"
11
-
12
- # Windows compiler executable path
13
- WINDOWS_PATTERN_COMPILER = "#{ENV['IGXLROOT']}/bin/apc.exe"
14
-
15
- # Linux compiler preamble
16
- ATPC_SETUP = "#{Origen.root!}/bin/latest/etc/atpcrc.csh"
17
-
18
- # ID will allow users to set default configurations for the compiler for unique pattern types
19
- attr_accessor :id
20
-
21
- # Compiler commands array
22
- attr_accessor :jobs
23
-
24
- def initialize(id, options = {})
25
- @id = id
26
- @id = @id.to_sym
27
-
28
- @user_options = {
29
- path: nil, # required: will be passed in or parsed from a .list file
30
- reference_directory: nil, # optional: will be set to @path or Origen.app.config.pattern_output_directory
31
- target: nil, # optional: allows user to temporarily set target and run compilation
32
- recursive: false # optional: controls whether to look for patterns in a directory recursively
33
- }
34
- @job_options = {
35
- compiler: running_on_windows? ? WINDOWS_PATTERN_COMPILER : LINUX_PATTERN_COMPILER, # required
36
- id: @id, # required
37
- pinmap_workbook: $dut.pinmap, # required: will default to $dut.pinmap
38
- location: :local, # optional: controls whether the commands go to the LSF or run locally
39
- clean: false, # optional: controls whether compiler log files are deleted after compilation
40
- output_directory: nil, # optional:
41
- verbose: false # optional: controls whether the compiler output gets put to STDOUT
42
- }
43
- @compiler_options = { # Set all of these compiler options that don't have args to true/flase. if true then send compiler '-opt'
44
- import_all_undefineds: false, # automatically import all undefined symbols. the key is mis-spelled but correct!
45
- cpp: false, # runs C++ preprocessor on pattern file
46
- comments: false, # saves comments in binary file for tools visibility. pass '-comments' if set to true
47
- # pass nothing if set to false
48
- nocompress: false, # do not compress pattern data blocks
49
- suppress_log: false, # disables output to main log file
50
- multiinst: false, # indicates more than one instrument is connected to a single pin
51
- lock: false, # prevents pattern from being reverse compiled or opened in PatternTool
52
- stdin: false, # Compile data from standard input. Do not use -cpp or specify any pattern file(s) when using this option.
53
- debug: false, # generate intermediate file(s) to simplify debug ( application dependent )
54
- template: false, # generate setup template
55
- timestamp: false, # enable log timestamp
56
- }
57
- @compiler_options_with_args = {
58
- output: nil, # Output filename, compiler defaults to <pattern name>.PAT
59
- pinmap_sheet: nil, # <sheetname>
60
- digital_inst: nil, # 'HSD4G', 'HSDM', or 'HSDMQ'
61
- opcode_mode: nil, # HSDM mode: 'single' | 'dual'. HSDMQ mode: 'single' | 'dual' | 'quad'
62
- pat_version: nil, # version of pattern file to compile
63
- scan_type: nil, # type of scan data
64
- max_errors: nil, # <n>, defaults to 200 on compiler side, valu eof 0 will never abort compilation
65
- logfile: nil, # <filename>, directs any compiler messages to <filename>. will default to output directory if nil
66
- define: nil, # defines values of macros passed to C++ preprocessor.
67
- # can only be defined once per pattern with space delimited list
68
- includes: nil, # include paths to be passed to C- preprocessor.
69
- post_processor: nil, # <pathname> customer's post-process executable.
70
- # need to pass 'post-processor' to compiler
71
- post_processor_args: nil, # <args> customer's post-process executable arguments
72
- # need to pass 'post-processor_args' to compiler
73
- cdl_cache: nil, # 'yes' | 'no', turns on/off CDL caching, default on compiler side is 'yes'
74
- init_pattern: nil, # <pattern>, uses the specified pattern module/file/set as an init patterns
75
- check_set_msb: nil, # 'yes' | 'no', turns on/off check the 'set' or 'set_infinite' opcode
76
- # is preceded by a 'set_msb' or 'set_msb_infinite' opcode. compiler default is 'yes'
77
- time_domain: nil, # <time domain>, specifies time domain for pins in patterns
78
- allow_mto_dash: nil, # Turn on/off support for channel data runtime repeat,i.e. vector dash in MTO patterns. Default value is "no".
79
- check_vm_min_size: nil, # Turns on/off the check on minimum size of a VM pattern. Default value is "yes".
80
- check_vm_mod_size: nil, # Turns on/off the check on a VM pattern module size. Default value is "yes".
81
- 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".
82
- allow_mixed_1x2x: nil, # Turns on/off the support of mixed 1x/2x pin groups. Default value is "no".
83
- allow_differential: nil, # Turns on/off support for differential pins. Default value is "yes".
84
- allow_scan_in_srm: nil, # Allow/disallow scan vectors in SRM pattern modules. Default value is "no".
85
- vm_block_size: nil, # Specifies uncompressed size in bytes of a pattern data block
86
- setup: nil, # path to setup file
87
- }
88
-
89
- @user_options.update_common(options)
90
- @job_options.update_common(options)
91
- @compiler_options.update_common(options)
92
- @compiler_options_with_args.update_common(options)
93
-
94
- # Check to make sure @compiler_options and @compiler_options_with_args do not have any keys in common
95
- fail "Error: @compiler_options and @compiler_options_with_args share keys #{@compiler_options.intersections(@compiler_options_with_args)}. They should be mutually exclusive, exiting..." if @compiler_options.intersect? @compiler_options_with_args
96
-
97
- # Convert any path related options to Pathname object and expand the path
98
- unless @user_options[:path].nil?
99
- if @user_options[:path].is_a? Pathname
100
- @path = @user_options[:path]
101
- else
102
- @path = Pathname.new(@user_options[:path])
103
- end
104
- @path = @path.expand_path
105
- # path is set but output_directory is not so set output_directory to path
106
- @job_options[:output_directory] = @path if @job_options[:output_directory].nil?
107
- end
108
-
109
- set_reference_directory
110
-
111
- if @job_options[:output_directory].nil?
112
- fail 'Output directory is not set!'
113
- else
114
- @job_options[:output_directory] = convert_to_pathname(@job_options[:output_directory])
115
- # output_directory can not exist, will create for user
116
- unless @job_options[:output_directory].directory?
117
- puts "Output directory #{@job_options[:output_directory]} does not exist, creating it..."
118
- FileUtils.mkdir_p(@job_options[:output_directory])
119
- end
120
- end
121
-
122
- # Pinmap is required
123
- if @job_options[:pinmap_workbook].nil?
124
- # Check if the app has $dut.pinmap defined
125
- if File.exist? $dut.pinmap
126
- @job_options[:pinmap_workbook] = $dut.pinmap
127
- else
128
- fail 'Pinmap is not defined! Pass as an option or set $dut.pinmap.'
129
- end
130
- end
131
- @job_options[:pinmap_workbook] = convert_to_pathname(@job_options[:pinmap_workbook])
132
- fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
133
-
134
- # Logfile is optional
135
- unless @compiler_options[:logfile].nil?
136
- @compiler_options[:logfile] = convert_to_pathname(@compiler_options[:logfile])
137
- fail 'Pinmap is not a file' unless @job_options[:pinmap_workbook].file?
138
- end
139
-
140
- # Check if the LSF is setup in the application
141
- if Origen.app.config.lsf.project.nil? || Origen.app.config.lsf.project.empty?
142
- puts 'LSF is not set at Origen.app.config.lsf.project, changing to local compilation'
143
- @job_options[:location] = :local
144
- end
145
-
146
- # Compiler jobs
147
- @jobs = []
148
-
149
- # .atp/.atp.gz files found
150
- @files = []
151
- end
152
-
153
- # Return the id/name of the compiler instance
154
- def name
155
- @id
156
- end
157
-
158
- # Return the compiler instance pinmap
159
- def pinmap
160
- @job_options[:pinmap_workbook]
161
- end
162
-
163
- # Allow users to search for a pattern in the job queue or default
164
- # to return all jobs
165
- def jobs(search = nil)
166
- found = false
167
- if search.nil?
168
- inspect_jobs
169
- found = true
170
- elsif search.is_a? String
171
- @jobs.each_with_index do |job, index|
172
- if job.pattern.to_s.match(search)
173
- inspect_jobs(index)
174
- found = true
175
- else
176
- puts "No match found for #{search}"
177
- end
178
- end
179
- elsif search.is_a? Regexp
180
- @jobs.each_with_index do |job, index|
181
- if search.match(job.pattern.to_s)
182
- inspect_jobs(index)
183
- found = true
184
- else
185
- puts "No match found for #{search}"
186
- end
187
- end
188
- elsif search.is_a? Integer
189
- if @jobs[search].nil?
190
- puts "The compiler queue does not contain a job at index #{search}"
191
- else
192
- inspect_jobs(search)
193
- found = true
194
- end
195
- else
196
- fail 'Search argument must be of type String, Regexp, or Integer'
197
- end
198
- found
199
- end
200
-
201
- # Finds the patterns and creates a compiler job for each one found.
202
- # Handles singles files (.atp, .atp.gz, or .list) and directories (recursively or flat)
203
- def find_jobs(path = @path)
204
- fail 'Pattern path is set to nil, pass in a valid file (.atp or .atp.gz) or a valid directory' if path.nil?
205
- @path = Pathname.new(path)
206
- fail 'Pattern path does not exist, pass in a valid file (.atp or .atp.gz) or a valid directory' unless @path.exist?
207
- @path = @path.expand_path
208
- # Set the reference directory for pattern sub-dir mirroring
209
- set_reference_directory
210
- Origen.profile 'Linux pattern compiler finds patterns' do
211
- # Check if the path is a file or a directory
212
- if @path.directory?
213
- # Get all of the patterns inside this dir or inside this directory recursively
214
- # Check if the recursive arg was passed
215
- if @user_options[:recursive] == true
216
- process_directory(@path, @files, true)
217
- else # Just grab the files found inside this directory
218
- process_directory(@path, @files, false)
219
- end
220
- elsif @path.file? # Found a file so no searching is necessary
221
- process_file(@path, @files)
222
- else # Didn't find a directory or a file so user must want a search for this arg string * NOT SUPPORTED YET
223
- fail 'Error: Did not find a file or directory to compile, exiting...'
224
- end
225
- end
226
-
227
- Origen.profile 'Linux pattern compiler creates jobs' do
228
- @files.each do |f|
229
- rel_dir = Pathname.new("#{f.dirname.to_s[@user_options[:reference_directory].to_s.size..-1]}")
230
- output_dir = Pathname.new("#{@job_options[:output_directory]}#{rel_dir}")
231
- unless output_dir.directory?
232
- puts "Output directory #{output_dir} for pattern #{f.basename} does not exist, creating it..."
233
- FileUtils.mkdir_p(output_dir)
234
- end
235
- current_job_options = @job_options.merge(@compiler_options_with_args)
236
- current_job_options[:output_directory] = output_dir
237
- @jobs << Job.new(f, current_job_options, @compiler_options)
238
- current_job_options = {}
239
- end
240
- end
241
- @files = []
242
- if empty?
243
- empty_msg
244
- else
245
- inspect_jobs
246
- end
247
- end
248
- alias_method :find, :find_jobs
249
-
250
- # Executes the compiler for each job in the queue
251
- def run(list = nil, options = {})
252
- fail "Error: the tester #{Origen.tester} is not an Ultrflex tester,exiting..." unless is_ultraflex?
253
- fail "Error: application #{Origen.app.name} is running on Windows, to run the pattern compiler you must be on a Linux machine" if running_on_windows?
254
-
255
- # Check if there was a pattern list passed as an argument
256
- # If so, then compile the patterns inside it.
257
- # Otherwise compile the jobs in the queue
258
- if list.nil?
259
- if empty?
260
- empty_msg
261
- return
262
- end
263
- @jobs.each do |job|
264
- fail "Error: compiler #{job.id} not ready for pattern #{job.name}" unless job.ready?
265
- if job.location == :lsf
266
- Origen.app.lsf.submit(ATPC_SETUP + '; ' + job.cmd)
267
- else
268
- Origen.profile "Linux pattern compiler compiles pattern #{job.pattern}" do
269
- system job.cmd
270
- end
271
- end
272
- end
273
- if @job_options[:location] == :local
274
- if @job_options[:clean] == true
275
- puts 'Log file :clean option set to true, deleting log files'
276
- clean_output
277
- end
278
- end
279
- # Clear @jobs
280
- clear
281
- else
282
- list = convert_to_pathname(list)
283
- fail "Error: pattern list #{list} does not exist, exiting..." unless list.file?
284
- File.open(list, 'r') do |file|
285
- while (line = file.gets)
286
- current_job_options = @job_options.merge(@compiler_options_with_args)
287
- current_job_options.update_common(options)
288
- # puts "current job options is #{current_job_options}"
289
- compiler_opts = {}
290
- line.strip!
291
- pattern = line.match(/^(\S+)\s+(.*)/).captures[0]
292
- unless File.file? pattern
293
- puts "Warning: Pattern #{pattern} does not exist, skipping..."
294
- next
295
- end
296
- pattern = convert_to_pathname(pattern)
297
- line.match(/^\S+\s+(.*)/).captures[0].split(/\s+/).each do |e|
298
- opt, arg = e.split(':')
299
- opt.gsub!('-', '')
300
- if arg.nil?
301
- compiler_opts[opt.to_sym] = true
302
- else
303
- # Check for some specific options
304
- case opt
305
- when 'pinmap_workbook'
306
- current_job_options[opt.to_sym] = Pathname.new(arg)
307
- when 'output'
308
- dot_pat = Pathname.new(arg)
309
- current_job_options[:output_directory] = dot_pat.dirname
310
- else
311
- current_job_options[opt.to_sym] = arg
312
- end
313
- end
314
- end
315
- @jobs << Job.new(pattern, current_job_options, compiler_opts)
316
- inspect_jobs
317
- end
318
- end
319
- run
320
- # Clear @jobs
321
- clear
322
- end
323
- end
324
-
325
- # Clear the job queue
326
- def clear
327
- @jobs = []
328
- @files = []
329
- end
330
-
331
- # Output all of the jobs into a pattern list so it can be compiled later
332
- # Must be executed after the 'find_jobs' method and before the 'run' method
333
- # or @jobs will be empty
334
- def to_list(options = {})
335
- options = {
336
- name: @id,
337
- output_directory: Dir.pwd,
338
- expand: true,
339
- force: false
340
- }.update_common(options)
341
- list = "#{options[:output_directory]}/#{options[:name]}.list"
342
- list = convert_to_pathname(list)
343
- if empty?
344
- empty_msg
345
- return
346
- end
347
- if list.file?
348
- if options[:force] == true
349
- puts "Pattern list file #{list} already exists, deleting it..."
350
- list.delete
351
- else
352
- fail "Pattern list file #{list} already exists, exiting..."
353
- end
354
- end
355
- File.open(list, 'w') do |patlist|
356
- @jobs.each do |job|
357
- if options[:expand] == true
358
- pinmap = job.pinmap_workbook
359
- dot_pat_name = "#{job.output_directory}/#{job.pattern.basename.to_s.split('.').first}.PAT"
360
- dot_atp_name = job.pattern
361
- else
362
- pinmap = job.pinmap_workbook.basename
363
- dot_pat_name = "#{job.pattern.basename.to_s.split('.').first}.PAT"
364
- dot_atp_name = job.pattern.basename
365
- end
366
- patlist.print("#{dot_atp_name} -pinmap_workbook:#{pinmap} -output:#{dot_pat_name}")
367
- job.compiler_options.each_key { |k| patlist.print(" -#{k}") }
368
- job.compiler_options_with_args.each_pair { |k, v| patlist.print(" -#{k}:#{v}") }
369
- patlist.puts('')
370
- end
371
- end
372
- end
373
-
374
- # For future checks on incorrect or incompatible arguments to compiler options
375
- def options_ok?
376
- end
377
-
378
- def ready?
379
- ready = true
380
- paths_contain_data = true
381
- # check for nil
382
- ready = paths_contain_data && !@job_options[:output_directory].nil? &&
383
- !@user_options[:reference_directory].nil? &&
384
- !@path.nil? &&
385
- !@job_options[:pinmap_workbook].nil?
386
- ready && @job_options[:output_directory].directory? &&
387
- @user_options[:reference_directory].directory? &&
388
- @path.exist? &&
389
- @job_options[:pinmap_workbook].file? &&
390
- [true, false].include?(@job_options[:clean]) &&
391
- [:local, :lsf].include?(@job_options[:location]) &&
392
- File.exist?(@job_options[:compiler])
393
- end
394
-
395
- def bad_options
396
- bad = []
397
- options = {
398
- output_directory: @job_options[:output_directory],
399
- reference_directory: @user_options[:reference_directory],
400
- path: @path,
401
- pinmap_workbook: @job_options[:pinmap_workbook],
402
- clean: @job_options[:clean],
403
- location: @job_options[:location],
404
- compiler: @job_options[:compiler]
405
- }
406
- options.each do |k, v|
407
- bad << k if v.nil?
408
- if v.is_a? String # compiler
409
- v = Pathname.new(v)
410
- bad << k unless v.file?
411
- elsif v.is_a? Symbol # clean
412
- bad << k unless [:local, :lsf].include? v
413
- elsif v.is_a? Pathname
414
- if k.match(/directory/)
415
- bad << k unless v.directory?
416
- elsif k == :path
417
- bad << k unless v.exist?
418
- else # pinmap
419
- bad << k unless v.file?
420
- end
421
- end
422
- end
423
- bad
424
- end
425
- alias_method :bad_opts, :bad_options
426
-
427
- # Output the compiler options to the console
428
- def inspect_options(verbose = nil)
429
- desc = []
430
- # Find the longest option argument string
431
- my_job_options = @job_options
432
- my_job_options.delete(:compiler)
433
- all_arguments = @user_options.values + my_job_options.values + @compiler_options.values + @compiler_options_with_args.values
434
- min_argument_padding = 'Argument'.length + 2
435
- argument_padding = all_arguments.max_by { |e| e.to_s.length }.to_s.length + 3
436
- argument_padding = min_argument_padding if argument_padding < min_argument_padding
437
- puts "\n"
438
- header = '| Option ' + '| Argument'.ljust(argument_padding) + '| Required |'
439
- desc << header
440
- desc << '-' * header.length
441
- [@user_options, my_job_options, @compiler_options, @compiler_options_with_args].each do |opt|
442
- opt.each_pair do |k, v|
443
- if k.match(/pinmap_workbook|path|id|directory|clean|location|recursive/i)
444
- req = 'true '
445
- else
446
- next if v.nil? || v == false
447
- req = 'false'
448
- end
449
- desc << "| #{k}".ljust(22) + "| #{v}".ljust(argument_padding) + "| #{req} |"
450
- end
451
- end
452
- puts desc
453
- end
454
-
455
- # Output the compiler jobs in the queue to the console
456
- def inspect_jobs(index = nil)
457
- return empty_msg if empty?
458
- desc = []
459
- puts "\n"
460
- @jobs.each_with_index do |j, i|
461
- unless index.nil?
462
- next unless i == index
463
- end
464
- desc << '| Job: ' + "#{i + 1} ".rjust(8) + '|' + 'Pattern:'.rjust(18) + " #{j.pattern.basename}".ljust(100) + '|'
465
- desc << '| |' + 'Compiler ID:'.rjust(18) + " #{j.id}".ljust(100) + '|'
466
- desc << '| |' + 'Pinmap:'.rjust(18) + " #{j.pinmap_workbook}".ljust(100) + '|'
467
- desc << '| |' + '.atp directory:'.rjust(18) + " #{j.pattern.dirname}".ljust(100) + '|'
468
- desc << '| |' + '.pat directory:'.rjust(18) + " #{j.output_directory}".ljust(100) + '|'
469
- desc << '| |' + 'LSF:'.rjust(18) + " #{j.location == :lsf ? true : false}".ljust(100) + '|'
470
- desc << '| |' + 'Delete log files:'.rjust(18) + " #{j.clean}".ljust(100) + '|'
471
- desc << '| |' + 'Verbose:'.rjust(18) + " #{j.verbose}".ljust(100) + '|'
472
- fragment = '| |' + 'Compiler args:'.rjust(18)
473
- overflow_fragment = '| |' + ' '.rjust(18)
474
- compiler_args = []
475
- compiler_fragment = ''
476
- j.compiler_options.each_key do |k|
477
- if compiler_fragment.size + " -#{k}".size >= 100
478
- compiler_args << compiler_fragment
479
- compiler_fragment = nil
480
- end
481
- compiler_fragment += " -#{k}"
482
- end
483
- compiler_args << compiler_fragment unless compiler_fragment.nil?
484
- compiler_fragment = ''
485
- j.compiler_options_with_args.each_pair do |k, v|
486
- if compiler_fragment.size + " -#{k}:#{v}".size >= 100
487
- compiler_args << compiler_fragment
488
- compiler_fragment = nil
489
- end
490
- compiler_fragment += " -#{k}:#{v}"
491
- end
492
- compiler_args << compiler_fragment unless compiler_fragment.nil?
493
- if compiler_args.join.length <= 100
494
- desc << fragment + "#{compiler_args.join}".ljust(100) + '|'
495
- else
496
- # Need to cycle through compiler args and build a fragment <= 100 characters
497
- # and print it. Keep going until the remaining args is <= 100 and print again
498
- char_cnt = 0
499
- line_cnt = 0
500
- args = []
501
- compiler_args = compiler_args.join.strip.split(/\s+/)
502
- until compiler_args.empty?
503
- args = compiler_args.select { |e| (char_cnt += e.length + 1) < 100 }
504
- # remove the args that fit on the first line
505
- compiler_args -= args
506
- if line_cnt == 0
507
- desc << fragment + " #{args.join(' ')}".ljust(100) + '|'
508
- else
509
- desc << overflow_fragment + " #{args.join(' ')}".ljust(100) + '|'
510
- end
511
- args = []
512
- line_cnt += 1
513
- char_cnt = 0
514
- end
515
- end
516
- desc << '-' * desc.first.size
517
- end
518
- puts desc.flatten.join("\n")
519
- end
520
-
521
- # Returns the number of jobs in the compiler
522
- def count
523
- @jobs.size
524
- end
525
-
526
- # Checks if the compiler queue is empty
527
- def empty?
528
- @jobs.empty?
529
- end
530
-
531
- private
532
-
533
- def running_on_windows?
534
- RUBY_PLATFORM == 'i386-mingw32'
535
- end
536
-
537
- def empty_msg
538
- puts "No compiler jobs created, check the compiler options\n" if self.empty?
539
- end
540
-
541
- def convert_to_pathname(opt)
542
- if opt.is_a? String
543
- opt = Pathname.new(opt)
544
- opt = opt.expand_path
545
- elsif opt.is_a? Pathname
546
- opt = opt.expand_path
547
- else
548
- fail "Option #{opt} is not a String, cannot convert to Pathname"
549
- end
550
- opt
551
- end
552
-
553
- def set_reference_directory
554
- if @user_options[:reference_directory].nil?
555
- # Nothing passed for reference directory so set it to Origen.app.config.pattern_output_directory if valid
556
- if File.directory? Origen.app.config.pattern_output_directory
557
- @user_options[:reference_directory] = Pathname.new(Origen.app.config.pattern_output_directory)
558
- elsif @path
559
- if @path.directory?
560
- @user_options[:reference_directory] = @path
561
- else
562
- @user_options[:reference_directory] = @path.dirname
563
- end
564
- end
565
- elsif File.directory?(@user_options[:reference_directory])
566
- @user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
567
- else
568
- debug 'Reference directory not set, creating it...'
569
- @user_options[:reference_directory] = Pathname.new(@user_options[:reference_directory])
570
- FileUtils.mkdir_p(@user_options[:reference_directory])
571
- end
572
- @user_options[:reference_directory] = @user_options[:reference_directory].expand_path
573
- # reference_directory must be a subset of @path. if it is not then set to @path if @path exists
574
- unless @path.nil?
575
- if @path.directory?
576
- @user_options[:reference_directory] = @path unless @path.to_s.include? @user_options[:reference_directory].to_s
577
- elsif @path.file?
578
- @user_options[:reference_directory] = @path.dirname
579
- else
580
- debug "Path is set to #{@path} which is not a valid directory or file!"
581
- end
582
- end
583
- end
584
-
585
- # Check if the current tester is an Ultraflex
586
- def is_ultraflex?
587
- platform == :ultraflex ? true : false
588
- end
589
-
590
- def platform
591
- if $tester.nil?
592
- fail 'No tester instantiated, $tester is set to nil'
593
- else
594
- $tester.class.to_s.downcase.split('::').last.to_sym
595
- end
596
- end
597
- end
598
- end
599
- end