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.
- checksums.yaml +4 -4
- data/config/shared_commands.rb +11 -19
- data/config/version.rb +1 -1
- data/lib/origen_testers.rb +2 -0
- data/lib/origen_testers/callback_handlers.rb +7 -25
- data/lib/origen_testers/origen_ext/generator.rb +1 -1
- data/lib/origen_testers/pattern_compilers.rb +120 -66
- data/lib/origen_testers/pattern_compilers/assembler.rb +7 -3
- data/lib/origen_testers/pattern_compilers/base.rb +266 -0
- data/lib/origen_testers/pattern_compilers/igxl_based.rb +348 -0
- data/lib/origen_testers/pattern_compilers/j750.rb +80 -0
- data/lib/origen_testers/pattern_compilers/job.rb +49 -9
- data/lib/origen_testers/pattern_compilers/runner.rb +40 -0
- data/lib/origen_testers/pattern_compilers/templates/template.aiv.erb +31 -0
- data/lib/origen_testers/pattern_compilers/ultraflex.rb +92 -0
- data/lib/origen_testers/pattern_compilers/v93k.rb +455 -0
- data/lib/origen_testers/pattern_compilers/v93k/digcap.rb +107 -0
- data/lib/origen_testers/pattern_compilers/v93k/multiport.rb +80 -0
- metadata +14 -6
- data/lib/origen_testers/pattern_compilers/ultraflex_pattern_compiler.rb +0 -599
@@ -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
|