origen_testers 0.20.0 → 0.21.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/application.rb +9 -7
- data/config/global_commands.rb +12 -0
- data/config/version.rb +1 -1
- data/lib/commands/convert.rb +105 -0
- data/lib/origen_testers.rb +2 -0
- data/lib/origen_testers/api.rb +34 -26
- data/lib/origen_testers/igxl_based_tester/ultraflex/flow.rb +39 -0
- data/lib/origen_testers/labview_based_tester/pxie6570.rb +1 -0
- data/lib/origen_testers/origen_ext/generator/pattern.rb +137 -0
- data/lib/origen_testers/stil_based_tester.rb +10 -0
- data/lib/origen_testers/stil_based_tester/base.rb +377 -0
- data/lib/origen_testers/stil_based_tester/d10.rb +18 -0
- data/lib/origen_testers/stil_based_tester/stil.rb +8 -0
- data/lib/origen_testers/test/dut.rb +2 -0
- data/lib/origen_testers/timing.rb +4 -0
- data/lib/origen_testers/vector_generator.rb +10 -0
- data/pattern/freq_counter.rb +1 -1
- data/pattern/mem_test.rb +1 -1
- data/program/basic_interface.rb +9 -0
- data/program/prb1.rb +3 -1
- data/program/prb2.rb +3 -1
- data/templates/origen_guides/pattern/stil.md.erb +35 -0
- data/templates/origen_guides/program/j750.md.erb +53 -0
- data/templates/origen_guides/program/ultraflex.md.erb +34 -1
- metadata +26 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe9e0d79136d4c5a7a16b3e73e098ac9069c0aa0d4efb70e4e9c93bb1b1d01d7
|
4
|
+
data.tar.gz: 115289be29ed7e600ee5e331a61649e05f649131956214bebd81a6afb963a0d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13b81ab2f3f0c642ba283399fbc39df7f1fcf7f982995f53ae75ef4acef6b060ca196bec8ea9571b65a548831a712eba6653b6eadcd52b5672fd84cad91ff051
|
7
|
+
data.tar.gz: 1ee85240a3d5c559dff37c61f12110f02a1a8228fc36f828911fe7d13c79cfc12fff72d49ead48f7b0ca33ee24fc3263f2f4f357abfd014aad3bb418bb12b0be
|
data/config/application.rb
CHANGED
@@ -4,6 +4,7 @@ class OrigenTestersApplication < Origen::Application
|
|
4
4
|
|
5
5
|
config.shared = {
|
6
6
|
command_launcher: "config/shared_commands.rb",
|
7
|
+
global_launcher: "config/global_commands.rb",
|
7
8
|
origen_guides: "templates/origen_guides",
|
8
9
|
origen_guides_index: -> (index) do
|
9
10
|
index.section :pattern, heading: "Pattern Generator", after: :controllers do |section|
|
@@ -18,6 +19,7 @@ class OrigenTestersApplication < Origen::Application
|
|
18
19
|
section.page :j750, heading: "J750 API"
|
19
20
|
section.page :v93k, heading: "V93K API"
|
20
21
|
section.page :ultraflex, heading: "UltraFlex API"
|
22
|
+
section.page :stil, heading: "STIL & Other Formats"
|
21
23
|
section.page :custom, heading: "Custom Testers"
|
22
24
|
section.page :running, heading: "Running The PatGen"
|
23
25
|
end
|
@@ -84,13 +86,13 @@ class OrigenTestersApplication < Origen::Application
|
|
84
86
|
dir
|
85
87
|
end
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
dir = "#{Origen.root}/spec/patterns/atp"
|
90
|
-
# Check if running on windows, if so, substitute :: with _
|
91
|
-
dir.gsub!("::","_") if Origen.os.windows?
|
92
|
-
dir
|
93
|
-
end
|
89
|
+
# config.pattern_output_directory do
|
90
|
+
# # Setting this to the spec area for testing of compiler
|
91
|
+
# dir = "#{Origen.root}/spec/patterns/atp"
|
92
|
+
# # Check if running on windows, if so, substitute :: with _
|
93
|
+
# dir.gsub!("::","_") if Origen.os.windows?
|
94
|
+
# dir
|
95
|
+
# end
|
94
96
|
|
95
97
|
# Run the tests before deploying to generate test coverage numbers
|
96
98
|
def before_deploy_site
|
data/config/version.rb
CHANGED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'pathname'
|
3
|
+
require 'origen_testers'
|
4
|
+
require 'origen_stil'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
ENVIRONMENTS = {
|
9
|
+
j750: OrigenTesters::J750,
|
10
|
+
uflex: OrigenTesters::UltraFLEX,
|
11
|
+
v93k_smt7: OrigenTesters::V93K
|
12
|
+
}.with_indifferent_access
|
13
|
+
|
14
|
+
opt_parser = OptionParser.new do |opts|
|
15
|
+
if Origen.running_globally?
|
16
|
+
opts.banner = <<-EOT
|
17
|
+
Convert the given pattern file to another environment (tester) format.
|
18
|
+
|
19
|
+
Usage: origen convert FILE -e v93k_smt7 [options]
|
20
|
+
EOT
|
21
|
+
else
|
22
|
+
opts.banner = <<-EOT
|
23
|
+
Convert the given pattern file to another environment (tester) format.
|
24
|
+
|
25
|
+
Usage: origen convert FILE [options]
|
26
|
+
EOT
|
27
|
+
end
|
28
|
+
opts.on('-o', '--output DIR', String, 'Override the default output directory') { |t| options[:output] = t }
|
29
|
+
if Origen.running_globally?
|
30
|
+
opts.on('-e', '--environment NAME', ENVIRONMENTS, 'Specify the target environment:', ' ' + ENVIRONMENTS.keys.join(', ')) { |e| options[:environment] = e }
|
31
|
+
else
|
32
|
+
opts.on('-e', '--environment NAME', String, 'Override the default environment, NAME can be a full path or a fragment of an environment file name') { |e| options[:environment] = e }
|
33
|
+
opts.on('-t', '--target NAME', String, 'Override the default target, NAME can be a full path or a fragment of a target file name') { |t| options[:target] = t }
|
34
|
+
end
|
35
|
+
opts.on('-d', '--debugger', 'Enable the debugger') { options[:debugger] = true }
|
36
|
+
opts.on('-m', '--mode MODE', Origen::Mode::MODES, 'Force the Origen operating mode:', ' ' + Origen::Mode::MODES.join(', ')) { |_m| }
|
37
|
+
opts.separator ''
|
38
|
+
opts.on('-h', '--help', 'Show this message') { puts opts; exit 0 }
|
39
|
+
end
|
40
|
+
|
41
|
+
opt_parser.parse! ARGV
|
42
|
+
|
43
|
+
if Origen.running_globally?
|
44
|
+
|
45
|
+
module OrigenTesters
|
46
|
+
class AnonymousDUT
|
47
|
+
include Origen::TopLevel
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless options[:environment]
|
52
|
+
puts 'You must specify the target environment (tester) via the -e switch with one of the following values:'
|
53
|
+
puts ' ' + ENVIRONMENTS.keys.join(', ')
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
Origen.target.temporary = lambda do
|
58
|
+
OrigenTesters::AnonymousDUT.new
|
59
|
+
options[:environment].new
|
60
|
+
# Stops the generated pattern being compared to a reference
|
61
|
+
tester.define_singleton_method(:disable_pattern_diffs) { true }
|
62
|
+
end
|
63
|
+
else
|
64
|
+
|
65
|
+
Origen.environment.temporary = options[:environment] if options[:environment]
|
66
|
+
Origen.target.temporary = options[:target] if options[:target]
|
67
|
+
end
|
68
|
+
|
69
|
+
def converter(file, options = {})
|
70
|
+
snippet = IO.read(file, 2000) # Read first 2000 characters
|
71
|
+
case snippet
|
72
|
+
when /STIL \d+\.\d+/
|
73
|
+
lambda do
|
74
|
+
STIL.add_pins(file)
|
75
|
+
# Use raw pin names in the output pattern and not the ALL pin group or similar, maybe
|
76
|
+
# make this an option in future though
|
77
|
+
dut.pin_pattern_order(*dut.pins.map { |id, pin| id })
|
78
|
+
STIL.execute(file, set_timesets: true)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
Origen.log.error "Unknown input format for file: #{file}"
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
ARGV.each do |input|
|
87
|
+
if c = converter(input)
|
88
|
+
name = Pathname.new(input).basename('.*').to_s
|
89
|
+
|
90
|
+
job = Origen::Generator::Job.new('anonymous', {})
|
91
|
+
Origen.app.current_jobs << job
|
92
|
+
if options[:output]
|
93
|
+
FileUtils.mkdir_p(options[:output]) unless File.exist?(options[:output])
|
94
|
+
job.instance_variable_set(:@output_pattern_directory, options[:output])
|
95
|
+
end
|
96
|
+
|
97
|
+
Origen.load_target
|
98
|
+
|
99
|
+
Origen::Generator::Pattern.convert(input) do
|
100
|
+
Pattern.create name: name do
|
101
|
+
c.call
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/origen_testers.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support/concern'
|
|
5
5
|
require 'require_all'
|
6
6
|
require 'atp'
|
7
7
|
require 'pathname'
|
8
|
+
require 'origen_testers/origen_ext/generator/pattern'
|
8
9
|
require 'origen_testers/origen_ext/generator/flow'
|
9
10
|
require 'origen_testers/origen_ext/generator/resources'
|
10
11
|
require 'origen_testers/origen_ext/application/runner'
|
@@ -41,6 +42,7 @@ end
|
|
41
42
|
|
42
43
|
require 'origen_testers/igxl_based_tester'
|
43
44
|
require 'origen_testers/smartest_based_tester'
|
45
|
+
require 'origen_testers/stil_based_tester'
|
44
46
|
require 'origen_testers/labview_based_tester'
|
45
47
|
require 'origen_testers/pattern_compilers'
|
46
48
|
require 'origen_testers/pattern_compilers/runner'
|
data/lib/origen_testers/api.rb
CHANGED
@@ -76,11 +76,6 @@ module OrigenTesters
|
|
76
76
|
!is_vector_based?
|
77
77
|
end
|
78
78
|
|
79
|
-
def stil?
|
80
|
-
defined?(OrigenTesters::StilBasedTester::Base) &&
|
81
|
-
is_a?(OrigenTesters::StilBasedTester::Base)
|
82
|
-
end
|
83
|
-
|
84
79
|
def j750?
|
85
80
|
is_a?(OrigenTesters::IGXLBasedTester::J750)
|
86
81
|
end
|
@@ -98,6 +93,14 @@ module OrigenTesters
|
|
98
93
|
end
|
99
94
|
alias_method :uflex?, :ultraflex?
|
100
95
|
|
96
|
+
def stil?
|
97
|
+
is_a?(OrigenTesters::StilBasedTester::Base)
|
98
|
+
end
|
99
|
+
|
100
|
+
def d10?
|
101
|
+
is_a?(OrigenTesters::StilBasedTester::D10)
|
102
|
+
end
|
103
|
+
|
101
104
|
def link?
|
102
105
|
!!(self.class.to_s =~ /^OrigenLink::/)
|
103
106
|
end
|
@@ -140,6 +143,7 @@ module OrigenTesters
|
|
140
143
|
# cc "step comment"
|
141
144
|
# end
|
142
145
|
def c1(msg, options = {})
|
146
|
+
PatSeq.add_thread(msg) unless options[:no_thread_id]
|
143
147
|
prefix = comment_char + ' '
|
144
148
|
prefix += step_comment_prefix + ' ' if @step_comment_on
|
145
149
|
if Origen.tester.generating == :program
|
@@ -171,7 +175,7 @@ module OrigenTesters
|
|
171
175
|
def ss(msg = nil)
|
172
176
|
div = step_comment_prefix.length
|
173
177
|
div = 1 if div == 0
|
174
|
-
c1(step_comment_prefix * (70 / div))
|
178
|
+
c1(step_comment_prefix * (70 / div), no_thread_id: true)
|
175
179
|
@step_comment_on = true
|
176
180
|
if block_given?
|
177
181
|
yield
|
@@ -182,9 +186,9 @@ module OrigenTesters
|
|
182
186
|
if $_testers_enable_vector_comments
|
183
187
|
timestamp = " #{execution_time_in_ns}ns #{step_comment_prefix}"
|
184
188
|
str = step_comment_prefix * (70 / div)
|
185
|
-
c1
|
189
|
+
c1(str.sub(/#{step_comment_prefix}{#{timestamp.length - 1}}$/, timestamp), no_thread_id: true)
|
186
190
|
else
|
187
|
-
c1(step_comment_prefix * (70 / div))
|
191
|
+
c1(step_comment_prefix * (70 / div), no_thread_id: true)
|
188
192
|
end
|
189
193
|
end
|
190
194
|
|
@@ -223,29 +227,33 @@ module OrigenTesters
|
|
223
227
|
repeat: nil
|
224
228
|
}.merge(options)
|
225
229
|
|
226
|
-
if
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
230
|
+
if PatSeq.thread
|
231
|
+
PatSeq.thread.cycle(options)
|
232
|
+
else
|
233
|
+
if any_clocks_running?
|
234
|
+
update_running_clocks
|
235
|
+
if options[:repeat]
|
236
|
+
slice_repeats(options).each do |slice|
|
237
|
+
options[:repeat] = slice[0]
|
238
|
+
delay(options.delete(:repeat), options) do |options|
|
239
|
+
push_vector(options)
|
240
|
+
end
|
241
|
+
slice[1].each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
242
|
+
options[:pin_vals] = current_pin_vals
|
233
243
|
end
|
234
|
-
|
235
|
-
|
244
|
+
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
245
|
+
else
|
246
|
+
push_vector(options)
|
247
|
+
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
236
248
|
end
|
237
|
-
pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
|
238
249
|
else
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
delay(options.delete(:repeat), options) do |options|
|
250
|
+
if options[:repeat]
|
251
|
+
delay(options.delete(:repeat), options) do |options|
|
252
|
+
push_vector(options)
|
253
|
+
end
|
254
|
+
else
|
245
255
|
push_vector(options)
|
246
256
|
end
|
247
|
-
else
|
248
|
-
push_vector(options)
|
249
257
|
end
|
250
258
|
end
|
251
259
|
end
|
@@ -31,6 +31,7 @@ module OrigenTesters
|
|
31
31
|
lo = ins.lo
|
32
32
|
hi = ins.hi
|
33
33
|
end
|
34
|
+
|
34
35
|
size = 1
|
35
36
|
if lo.is_a?(Array)
|
36
37
|
size = lo.size if lo.size > size
|
@@ -80,6 +81,44 @@ module OrigenTesters
|
|
80
81
|
completed_lines << line
|
81
82
|
end
|
82
83
|
end
|
84
|
+
# finish off any limit lines from sub tests
|
85
|
+
unless @limit_lines.nil?
|
86
|
+
tl = completed_lines.last
|
87
|
+
tnum = tl.tnum
|
88
|
+
@limit_lines.each do |line|
|
89
|
+
line.parameter = tl.parameter
|
90
|
+
line.sbin = tl.sbin
|
91
|
+
line.bin = tl.bin
|
92
|
+
line.tnum = tnum += 1 if tnum.is_a?(Numeric) && !line.tnum
|
93
|
+
completed_lines << line
|
94
|
+
end
|
95
|
+
@limit_lines = nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def on_sub_test(node)
|
100
|
+
# for now assuming sub tests will be limits
|
101
|
+
tname = node.find(:object).value
|
102
|
+
# for some reason new_line :use_limit does not provide hbin, sbin etc accessors, duplicating behavior in on_test above
|
103
|
+
line = open_lines.last.dup
|
104
|
+
line.type = :use_limit
|
105
|
+
line.opcode = 'Use-Limit'
|
106
|
+
line.tname = tname
|
107
|
+
line.tnum = nil
|
108
|
+
open_lines << line
|
109
|
+
process_all(node.children)
|
110
|
+
@limit_lines = [] if @limit_lines.nil?
|
111
|
+
@limit_lines << open_lines.pop
|
112
|
+
end
|
113
|
+
|
114
|
+
def on_limit(node)
|
115
|
+
value, rule, unit, selector = *node
|
116
|
+
case rule
|
117
|
+
when 'gte'
|
118
|
+
current_line.lolim = value
|
119
|
+
when 'lte'
|
120
|
+
current_line.hilim = value
|
121
|
+
end
|
83
122
|
end
|
84
123
|
|
85
124
|
# Returns the scale that should be best used to represent the given number, returns
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# This responsibility should be with OrigenTesters, starting to override the methods here
|
2
|
+
# within OrigenTesters over time and it will be removed from Origen in future once fully
|
3
|
+
# transferred
|
4
|
+
require 'origen/generator/pattern'
|
5
|
+
module Origen
|
6
|
+
class Generator
|
7
|
+
class Pattern
|
8
|
+
# @api private
|
9
|
+
def self.convert(file)
|
10
|
+
@converting = file
|
11
|
+
yield
|
12
|
+
@converting = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
def self.converting
|
17
|
+
@converting
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def converting
|
23
|
+
self.class.converting
|
24
|
+
end
|
25
|
+
|
26
|
+
def header
|
27
|
+
Origen.tester.pre_header if Origen.tester.doc?
|
28
|
+
inject_separator
|
29
|
+
if $desc
|
30
|
+
c2 'DESCRIPTION:'
|
31
|
+
$desc.split(/\n/).each { |line| cc line }
|
32
|
+
inject_separator
|
33
|
+
end
|
34
|
+
c2 'GENERATED:'
|
35
|
+
c2 " Time: #{Origen.launch_time}"
|
36
|
+
c2 " By: #{Origen.current_user.name}"
|
37
|
+
c2 " Mode: #{Origen.mode}"
|
38
|
+
if converting
|
39
|
+
c2 " Source: #{converting}"
|
40
|
+
|
41
|
+
else
|
42
|
+
l = " Command: origen g #{job.requested_pattern} -t #{Origen.target.file.basename}"
|
43
|
+
if Origen.environment && Origen.environment.file
|
44
|
+
l += " -e #{Origen.environment.file.basename}"
|
45
|
+
end
|
46
|
+
c2(l)
|
47
|
+
end
|
48
|
+
inject_separator
|
49
|
+
c2 'ENVIRONMENT:'
|
50
|
+
unless converting
|
51
|
+
c2 ' Application'
|
52
|
+
if Origen.app.rc
|
53
|
+
if Origen.app.rc.git?
|
54
|
+
c2 " Source: #{Origen.config.rc_url}"
|
55
|
+
else
|
56
|
+
c2 " Vault: #{Origen.config.vault}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
c2 " Version: #{Origen.app.version}"
|
60
|
+
unless Origen.app.config.release_externally
|
61
|
+
c2 " Workspace: #{Origen.root}"
|
62
|
+
end
|
63
|
+
if Origen.app.rc && Origen.app.rc.git?
|
64
|
+
begin
|
65
|
+
@branch ||= Origen.app.rc.current_branch
|
66
|
+
@commit ||= Origen.app.rc.current_commit
|
67
|
+
status = "#{@branch}(#{@commit})"
|
68
|
+
@pattern_local_mods = !Origen.app.rc.local_modifications.empty? unless @pattern_local_mods_fetched
|
69
|
+
@pattern_local_mods_fetched = true
|
70
|
+
status += ' (+local edits)' if @pattern_local_mods
|
71
|
+
c2 " Branch: #{status}"
|
72
|
+
rescue
|
73
|
+
# No problem, we did our best
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
c2 ' Origen'
|
78
|
+
c2 ' Source: https://github.com/Origen-SDK/origen'
|
79
|
+
c2 " Version: #{Origen.version}"
|
80
|
+
unless Origen.app.plugins.empty?
|
81
|
+
c2 ' Plugins'
|
82
|
+
Origen.app.plugins.sort_by { |p| p.name.to_s }.each do |plugin|
|
83
|
+
c2 " #{plugin.name}:".ljust(30) + plugin.version
|
84
|
+
end
|
85
|
+
end
|
86
|
+
inject_separator
|
87
|
+
|
88
|
+
unless Origen.app.plugins.empty?
|
89
|
+
# Plugins can use config.shared_pattern_header to inject plugin-specific comments into the patterns header
|
90
|
+
header_printed = false
|
91
|
+
Origen.app.plugins.sort_by { |p| p.name.to_s }.each do |plugin|
|
92
|
+
unless plugin.config.shared_pattern_header.nil?
|
93
|
+
unless header_printed
|
94
|
+
c2 'Header Comments From Shared Plugins:'
|
95
|
+
header_printed = true
|
96
|
+
end
|
97
|
+
inject_pattern_header(
|
98
|
+
config_loc: plugin,
|
99
|
+
scope: :shared_pattern_header,
|
100
|
+
message: "Header Comments From Shared Plugin: #{plugin.name}:",
|
101
|
+
message_spacing: 2,
|
102
|
+
line_spacing: 4,
|
103
|
+
no_separator: true
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
inject_separator if header_printed
|
108
|
+
end
|
109
|
+
|
110
|
+
if Origen.app.plugins.current && !Origen.app.plugins.current.config.send(:current_plugin_pattern_header).nil?
|
111
|
+
# The top level plugin (if one is set) can further inject plugin-specific comment into the header.
|
112
|
+
# These will only appear if the plugin is the top-level plugin though.
|
113
|
+
inject_pattern_header(
|
114
|
+
config_loc: Origen.app.plugins.current,
|
115
|
+
scope: :current_plugin_pattern_header,
|
116
|
+
message: "Header Comments From The Current Plugin: #{Origen.app.plugins.current.name}:"
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
unless Origen.app.config.send(:application_pattern_header).nil?
|
121
|
+
inject_pattern_header(
|
122
|
+
config_loc: Origen.app,
|
123
|
+
scope: :application_pattern_header,
|
124
|
+
message: "Header Comments From Application: #{Origen.app.name}:"
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
if Origen.config.pattern_header
|
129
|
+
Origen.log.deprecated 'Origen.config.pattern_header is deprecated.'
|
130
|
+
Origen.log.deprecated 'Please use config.shared_pattern_header, config.application_pattern_header, or config.current_plugin_pattern_header instead.'
|
131
|
+
inject_separator
|
132
|
+
end
|
133
|
+
Origen.tester.close_text_block if Origen.tester.doc?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
autoload :Base, 'origen_testers/stil_based_tester/base.rb'
|
4
|
+
autoload :D10, 'origen_testers/stil_based_tester/d10.rb'
|
5
|
+
autoload :STIL, 'origen_testers/stil_based_tester/stil.rb'
|
6
|
+
end
|
7
|
+
# Convenience/Legacy names without the IGXLBasedTester namespace
|
8
|
+
autoload :D10, 'origen_testers/stil_based_tester/d10.rb'
|
9
|
+
autoload :STIL, 'origen_testers/stil_based_tester/stil.rb'
|
10
|
+
end
|
@@ -0,0 +1,377 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
class Base
|
4
|
+
include VectorBasedTester
|
5
|
+
|
6
|
+
# When set to true generated patterns will only contain Pattern blocks, i.e. only vectors
|
7
|
+
attr_accessor :pattern_only
|
8
|
+
|
9
|
+
# Returns a new J750 instance, normally there would only ever be one of these
|
10
|
+
# assigned to the global variable such as $tester by your target:
|
11
|
+
# $tester = J750.new
|
12
|
+
def initialize(options = {})
|
13
|
+
self.pattern_only = options.delete(:pattern_only)
|
14
|
+
@max_repeat_loop = 65_535
|
15
|
+
@min_repeat_loop = 2
|
16
|
+
@pat_extension = 'stil'
|
17
|
+
@compress = true
|
18
|
+
|
19
|
+
# @support_repeat_previous = true
|
20
|
+
@match_entries = 10
|
21
|
+
@name = 'stil'
|
22
|
+
@comment_char = '//'
|
23
|
+
@level_period = true
|
24
|
+
@inline_comments = true
|
25
|
+
@header_done = false
|
26
|
+
@footer_done = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def stil_based?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# An internal method called by Origen to create the pattern header
|
34
|
+
def pattern_header(options = {})
|
35
|
+
options = {
|
36
|
+
}.merge(options)
|
37
|
+
|
38
|
+
@pattern_name = options[:pattern]
|
39
|
+
|
40
|
+
unless pattern_only
|
41
|
+
microcode 'STIL 1.0;'
|
42
|
+
|
43
|
+
microcode ''
|
44
|
+
microcode 'Signals {'
|
45
|
+
ordered_pins.each do |pin|
|
46
|
+
line = ''
|
47
|
+
line << "#{pin.name} "
|
48
|
+
if pin.direction == :input
|
49
|
+
line << 'In;'
|
50
|
+
elsif pin.direction == :output
|
51
|
+
line << 'Out;'
|
52
|
+
else
|
53
|
+
line << 'InOut;'
|
54
|
+
end
|
55
|
+
microcode " #{line}"
|
56
|
+
end
|
57
|
+
microcode '}'
|
58
|
+
|
59
|
+
microcode ''
|
60
|
+
microcode 'SignalGroups {'
|
61
|
+
line = "\"#{ordered_pins_name || 'ALL'}\" = '"
|
62
|
+
ordered_pins.each_with_index do |pin, i|
|
63
|
+
unless i == 0
|
64
|
+
line << '+'
|
65
|
+
end
|
66
|
+
line << pin.name.to_s
|
67
|
+
end
|
68
|
+
microcode " #{line}';"
|
69
|
+
microcode '}'
|
70
|
+
|
71
|
+
microcode ''
|
72
|
+
microcode "Timing t_#{@pattern_name} {"
|
73
|
+
(@wavesets || []).each_with_index do |w, i|
|
74
|
+
microcode '' if i != 0
|
75
|
+
microcode " WaveformTable Waveset#{i + 1} {"
|
76
|
+
microcode " Period '#{w[:period]}ns';"
|
77
|
+
microcode ' Waveforms {'
|
78
|
+
w[:lines].each do |line|
|
79
|
+
microcode " #{line}"
|
80
|
+
end
|
81
|
+
microcode ' }'
|
82
|
+
microcode ' }'
|
83
|
+
end
|
84
|
+
microcode '}'
|
85
|
+
|
86
|
+
microcode ''
|
87
|
+
microcode "PatternBurst b_#{@pattern_name} {"
|
88
|
+
microcode " PatList { #{@pattern_name}; }"
|
89
|
+
microcode '}'
|
90
|
+
|
91
|
+
microcode ''
|
92
|
+
microcode "PatternExec e_#{@pattern_name} {"
|
93
|
+
microcode " Timing t_#{@pattern_name};"
|
94
|
+
microcode " PatternBurst b_#{@pattern_name};"
|
95
|
+
microcode '}'
|
96
|
+
microcode ''
|
97
|
+
end
|
98
|
+
|
99
|
+
microcode "Pattern \"#{@pattern_name}\" {"
|
100
|
+
microcode "#{@pattern_name}:"
|
101
|
+
@header_done = true
|
102
|
+
|
103
|
+
if tester.ordered_pins_name.nil? && pattern_only
|
104
|
+
Origen.log.warn "WARN: SigName must be defined for STIL format. Use pin_pattern_order(*pins, name: <sigName>). Defaulting to use 'ALL'"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_timeset(timeset, period_in_ns = nil)
|
109
|
+
super
|
110
|
+
if pattern_only
|
111
|
+
# Why does D10 not include this?
|
112
|
+
# microcode "W #{timeset};"
|
113
|
+
else
|
114
|
+
@wavesets ||= []
|
115
|
+
wave_number = nil
|
116
|
+
@wavesets.each_with_index do |w, i|
|
117
|
+
if w[:name] == @timeset.name && w[:period] = @timeset.period_in_ns
|
118
|
+
wave_number = i
|
119
|
+
end
|
120
|
+
end
|
121
|
+
unless wave_number
|
122
|
+
lines = []
|
123
|
+
ordered_pins.each do |pin|
|
124
|
+
if pin.direction == :input || pin.direction == :io
|
125
|
+
line = "#{pin.name} { 01 { "
|
126
|
+
wave = pin.drive_wave
|
127
|
+
(wave ? wave.evaluated_events : []).each do |t, v|
|
128
|
+
line << "'#{t}ns' "
|
129
|
+
if v == 0
|
130
|
+
line << 'D'
|
131
|
+
elsif v == 0
|
132
|
+
line << 'U'
|
133
|
+
else
|
134
|
+
line << 'D/U'
|
135
|
+
end
|
136
|
+
line << '; '
|
137
|
+
end
|
138
|
+
line << '}}'
|
139
|
+
lines << line
|
140
|
+
end
|
141
|
+
if pin.direction == :output || pin.direction == :io
|
142
|
+
line = "#{pin.name} { LHX { "
|
143
|
+
wave = pin.compare_wave
|
144
|
+
(wave ? wave.evaluated_events : []).each_with_index do |tv, i|
|
145
|
+
t, v = *tv
|
146
|
+
if i == 0 && t != 0
|
147
|
+
line << "'0ns' X; "
|
148
|
+
end
|
149
|
+
line << "'#{t}ns' "
|
150
|
+
if v == 0
|
151
|
+
line << 'L'
|
152
|
+
elsif v == 0
|
153
|
+
line << 'H'
|
154
|
+
else
|
155
|
+
line << 'L/H/X'
|
156
|
+
end
|
157
|
+
line << '; '
|
158
|
+
end
|
159
|
+
line << '}}'
|
160
|
+
lines << line
|
161
|
+
end
|
162
|
+
end
|
163
|
+
@wavesets << { name: @timeset.name, period: @timeset.period_in_ns, lines: lines }
|
164
|
+
wave_number = @wavesets.size
|
165
|
+
end
|
166
|
+
microcode "W Waveset#{wave_number};"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Capture the pin data from a vector to the tester.
|
171
|
+
#
|
172
|
+
# This method uses the Digital Capture feature (Selective mode) of the V93000 to capture
|
173
|
+
# the data from the given pins on the previous vector.
|
174
|
+
# Note that is does not actually generate a new vector.
|
175
|
+
#
|
176
|
+
# Note also that any drive cycles on the target pins can also be captured, to avoid this
|
177
|
+
# the wavetable should be set up like this to infer a 'D' (Don't Capture) on vectors where
|
178
|
+
# the target pin is being used to drive data:
|
179
|
+
#
|
180
|
+
# PINS nvm_fail
|
181
|
+
# 0 d1:0 r1:D 0
|
182
|
+
# 1 d1:1 r1:D 1
|
183
|
+
# 2 r1:C Capt
|
184
|
+
# 3 r1:D NoCapt
|
185
|
+
#
|
186
|
+
# Sometimes when generating vectors within a loop you may want to apply a capture
|
187
|
+
# retrospectively to a previous vector, passing in an offset option will allow you
|
188
|
+
# to do this.
|
189
|
+
#
|
190
|
+
# ==== Examples
|
191
|
+
# $tester.cycle # This is the vector you want to capture
|
192
|
+
# $tester.store :pin => pin(:fail) # This applys the required opcode to the given pins
|
193
|
+
#
|
194
|
+
# $tester.cycle # This one gets captured
|
195
|
+
# $tester.cycle
|
196
|
+
# $tester.cycle
|
197
|
+
# $tester.store(:pin => pin(:fail), :offset => -2) # Just realized I need to capture that earlier vector
|
198
|
+
#
|
199
|
+
# # Capturing multiple pins:
|
200
|
+
# $tester.cycle
|
201
|
+
# $tester.store :pins => [pin(:fail), pin(:done)]
|
202
|
+
#
|
203
|
+
# Since the STIL store operates on a pin level (rather than vector level as on the J750)
|
204
|
+
# equivalent functionality can also be achieved by setting the store attribute of the pin
|
205
|
+
# itself prior to calling $tester.cycle.
|
206
|
+
# However it is recommended to use the tester API to do the store if cross-compatibility with
|
207
|
+
# other platforms, such as the J750, is required.
|
208
|
+
def store(*pins)
|
209
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
210
|
+
options = { offset: 0
|
211
|
+
}.merge(options)
|
212
|
+
pins = pins.flatten.compact
|
213
|
+
if pins.empty?
|
214
|
+
fail 'For the STIL generation you must supply the pins to store/capture'
|
215
|
+
end
|
216
|
+
pins.each do |pin|
|
217
|
+
pin.restore_state do
|
218
|
+
pin.capture
|
219
|
+
update_vector_pin_val pin, offset: options[:offset]
|
220
|
+
last_vector(options[:offset]).dont_compress = true
|
221
|
+
last_vector(options[:offset]).contains_capture = true
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
alias_method :capture, :store
|
226
|
+
|
227
|
+
# Same as the store method, except that the capture will be applied to the next
|
228
|
+
# vector to be generated.
|
229
|
+
#
|
230
|
+
# @example
|
231
|
+
# $tester.store_next_cycle
|
232
|
+
# $tester.cycle # This is the vector that will be captured
|
233
|
+
def store_next_cycle(*pins)
|
234
|
+
options = pins.last.is_a?(Hash) ? pins.pop : {}
|
235
|
+
options = {
|
236
|
+
}.merge(options)
|
237
|
+
pins = pins.flatten.compact
|
238
|
+
if pins.empty?
|
239
|
+
fail 'For STIL generation you must supply the pins to store/capture'
|
240
|
+
end
|
241
|
+
pins.each { |pin| pin.save; pin.capture }
|
242
|
+
# Register this clean up function to be run after the next vector
|
243
|
+
# is generated, cool or what!
|
244
|
+
preset_next_vector do |vector|
|
245
|
+
vector.contains_capture = true
|
246
|
+
pins.each(&:restore)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
alias_method :store!, :store_next_cycle
|
250
|
+
|
251
|
+
def match(pin, state, timeout_in_cycles, options = {})
|
252
|
+
Origen.log.warning "Call to match loop on pin #{pin.id} is not supported by the STIL generator and has been ignored"
|
253
|
+
end
|
254
|
+
|
255
|
+
# Add a loop to the pattern.
|
256
|
+
#
|
257
|
+
# Pass in the number of times to execute it, all vectors
|
258
|
+
# generated by the given block will be captured in the loop.
|
259
|
+
#
|
260
|
+
# ==== Examples
|
261
|
+
# $tester.loop_vectors 3 do # Do this 3 times...
|
262
|
+
# $tester.cycle
|
263
|
+
# some_other_method_to_generate_vectors
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# For compatibility with the J750 you can supply a name as the first argument
|
267
|
+
# and that will simply be ignored when generated for the V93K tester...
|
268
|
+
#
|
269
|
+
# $tester.loop_vectors "my_loop", 3 do # Do this 3 times...
|
270
|
+
# $tester.cycle
|
271
|
+
# some_other_method_to_generate_vectors
|
272
|
+
# end
|
273
|
+
def loop_vectors(name = nil, number_of_loops = 1, _global = false)
|
274
|
+
# The name argument is present to maych J750 API, sort out the
|
275
|
+
unless name.is_a?(String) || name.is_a?(Symbol)
|
276
|
+
name, number_of_loops, global = 'loop', name, number_of_loops
|
277
|
+
end
|
278
|
+
if number_of_loops > 1
|
279
|
+
@loop_counters ||= {}
|
280
|
+
if @loop_counters[name]
|
281
|
+
@loop_counters[name] += 1
|
282
|
+
else
|
283
|
+
@loop_counters[name] = 0
|
284
|
+
end
|
285
|
+
loop_name = @loop_counters[name] == 0 ? name : "#{name}_#{@loop_counters[name]}"
|
286
|
+
loop_name = loop_name.symbolize
|
287
|
+
microcode "#{loop_name}: Loop #{number_of_loops} {"
|
288
|
+
yield
|
289
|
+
microcode '}'
|
290
|
+
else
|
291
|
+
yield
|
292
|
+
end
|
293
|
+
end
|
294
|
+
alias_method :loop_vector, :loop_vectors
|
295
|
+
|
296
|
+
# An internal method called by Origen to generate the pattern footer
|
297
|
+
def pattern_footer(options = {})
|
298
|
+
cycle dont_compress: true # one extra single vector before stop microcode
|
299
|
+
microcode 'Stop;' unless options[:subroutine]
|
300
|
+
microcode '}'
|
301
|
+
@footer_done = true
|
302
|
+
end
|
303
|
+
|
304
|
+
# Returns an array of subroutines called while generating the current pattern
|
305
|
+
def called_subroutines
|
306
|
+
@called_subroutines ||= []
|
307
|
+
end
|
308
|
+
|
309
|
+
# Call a subroutine.
|
310
|
+
#
|
311
|
+
# This calls a subroutine immediately following previous vector, it does not
|
312
|
+
# generate a new vector.
|
313
|
+
#
|
314
|
+
# Subroutines should always be called through this method as it ensures a running
|
315
|
+
# log of called subroutines is maintained and which then gets output in the pattern
|
316
|
+
# header to import the right dependencies.
|
317
|
+
#
|
318
|
+
# An offset option is available to make the call on earlier vectors.
|
319
|
+
#
|
320
|
+
# Repeated calls to the same subroutine will automatically be compressed unless
|
321
|
+
# option :suppress_repeated_calls is supplied and set to false. This means that for
|
322
|
+
# the common use case of calling a subroutine to implement an overlay the subroutine
|
323
|
+
# can be called for every bit that has the overlay and the pattern will automatically
|
324
|
+
# generate correctly.
|
325
|
+
#
|
326
|
+
# ==== Examples
|
327
|
+
# $tester.call_subroutine("mysub")
|
328
|
+
# $tester.call_subroutine("my_other_sub", :offset => -1)
|
329
|
+
def call_subroutine(name, options = {})
|
330
|
+
options = {
|
331
|
+
offset: 0,
|
332
|
+
suppress_repeated_calls: true
|
333
|
+
}.merge(options)
|
334
|
+
called_subroutines << name.to_s.chomp unless called_subroutines.include?(name.to_s.chomp) || @inhibit_vectors
|
335
|
+
|
336
|
+
code = "Call #{name};"
|
337
|
+
if !options[:suppress_repeated_calls] ||
|
338
|
+
last_object != code
|
339
|
+
microcode code, offset: (options[:offset] * -1)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def push_comment(msg)
|
344
|
+
if @footer_done
|
345
|
+
stage.store msg unless @inhibit_comments
|
346
|
+
else
|
347
|
+
stage.store "Ann {*#{msg}*}" unless @inhibit_comments
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
# This is an internal method use by Origen which returns a fully formatted vector
|
352
|
+
# You can override this if you wish to change the output formatting at vector level
|
353
|
+
def format_vector(vec)
|
354
|
+
timeset = vec.timeset ? "#{vec.timeset.name}" : ''
|
355
|
+
pin_vals = vec.pin_vals ? "#{vec.pin_vals};".gsub(' ', '') : ''
|
356
|
+
sig_name = tester.ordered_pins_name || 'ALL'
|
357
|
+
if sig_name.nil?
|
358
|
+
Origen.log.warn "WARN: SigName must be defined for STIL format. Use pin_pattern_order(*pins, name: <sigName>). Default to 'ALL'"
|
359
|
+
sig_name = 'ALL'
|
360
|
+
end
|
361
|
+
if vec.repeat > 1
|
362
|
+
microcode = "Loop #{vec.repeat} {\n"
|
363
|
+
else
|
364
|
+
microcode = vec.microcode ? vec.microcode : ''
|
365
|
+
end
|
366
|
+
if vec.pin_vals && ($_testers_enable_vector_comments || vector_comments)
|
367
|
+
comment = "// V:#{vec.number} C:#{vec.cycle} #{vec.inline_comment}"
|
368
|
+
else
|
369
|
+
comment = vec.inline_comment.empty? ? '' : "Ann {*// #{vec.inline_comment}*}"
|
370
|
+
end
|
371
|
+
|
372
|
+
microcode_post = vec.repeat > 1 ? "\n}" : ''
|
373
|
+
"#{microcode} V { \"#{sig_name}\" = #{pin_vals} }#{comment}#{microcode_post}"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module OrigenTesters
|
2
|
+
module StilBasedTester
|
3
|
+
class D10 < Base
|
4
|
+
def initialize(options = {})
|
5
|
+
options = {
|
6
|
+
pattern_only: true
|
7
|
+
}.merge(options)
|
8
|
+
super(options)
|
9
|
+
@name = 'd10'
|
10
|
+
end
|
11
|
+
|
12
|
+
def d10?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
D10 = StilBasedTester::D10
|
18
|
+
end
|
@@ -196,6 +196,10 @@ module OrigenTesters
|
|
196
196
|
end
|
197
197
|
@_last_timeset_change = change
|
198
198
|
end
|
199
|
+
if dut.timesets[timeset.name]
|
200
|
+
dut.timeset = timeset.name
|
201
|
+
dut.current_timeset_period = timeset.period_in_ns
|
202
|
+
end
|
199
203
|
end
|
200
204
|
|
201
205
|
def before_timeset_change(options = {})
|
@@ -389,6 +389,16 @@ module OrigenTesters
|
|
389
389
|
@ordered_pins_cache ||= ordered_pins(options)
|
390
390
|
end
|
391
391
|
|
392
|
+
# Retrieve optional 'name' meta passed in with the pin_pattern_order call
|
393
|
+
def ordered_pins_name
|
394
|
+
pinorder = Origen.app.pin_pattern_order.dup
|
395
|
+
if Origen.app.pin_pattern_order.last.is_a?(Hash)
|
396
|
+
options = pinorder.pop
|
397
|
+
name = options[:name]
|
398
|
+
end
|
399
|
+
name
|
400
|
+
end
|
401
|
+
|
392
402
|
def ordered_pins(options = {})
|
393
403
|
options = {
|
394
404
|
include_inhibited_pins: false,
|
data/pattern/freq_counter.rb
CHANGED
data/pattern/mem_test.rb
CHANGED
data/program/basic_interface.rb
CHANGED
@@ -2,4 +2,13 @@ Flow.create interface: 'OrigenTesters::Test::BasicInterface' do
|
|
2
2
|
|
3
3
|
functional :test1, sbin: 100, number: 20000
|
4
4
|
|
5
|
+
# test multi limit support if uflex, not sure what platforms support this or the syntax
|
6
|
+
if tester.uflex?
|
7
|
+
functional :test2, sbin: 101, number: 20020,
|
8
|
+
sub_tests: [
|
9
|
+
sub_test(:lim1, lo: -2, hi: 2),
|
10
|
+
sub_test(:lim2, lo: -1, hi: 1)
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
5
14
|
end
|
data/program/prb1.rb
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
# similar to Pattern.create.
|
5
5
|
Flow.create interface: 'OrigenTesters::Test::Interface', flow_description: 'Probe1 Main' do
|
6
6
|
|
7
|
-
|
7
|
+
unless Origen.app.environment.name == 'v93k_global'
|
8
|
+
self.resources_filename = 'prb1'
|
9
|
+
end
|
8
10
|
|
9
11
|
import 'components/prb1_main'
|
10
12
|
|
data/program/prb2.rb
CHANGED
@@ -5,7 +5,9 @@ Flow.create interface: 'OrigenTesters::Test::Interface' do
|
|
5
5
|
# Test that this can be overridden from the target at flow-level
|
6
6
|
self.add_flow_enable = :enabled
|
7
7
|
|
8
|
-
|
8
|
+
unless Origen.app.environment.name == 'v93k_global'
|
9
|
+
self.resources_filename = 'prb2'
|
10
|
+
end
|
9
11
|
|
10
12
|
func :erase_all, duration: :dynamic, number: 10000
|
11
13
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
% render "layouts/guides.html" do
|
2
|
+
|
3
|
+
#### STIL
|
4
|
+
|
5
|
+
Patterns can be generated into STIL cyclized vector format by creating an environment like this:
|
6
|
+
|
7
|
+
~~~ruby
|
8
|
+
# environment/stil.rb
|
9
|
+
OrigenTesters::STIL.new
|
10
|
+
~~~
|
11
|
+
|
12
|
+
All of the
|
13
|
+
[Common Pattern API](<%= path "guides/pattern/common" %>) should be supported in addition to
|
14
|
+
[custom waveform codes](<%= path "guides/pattern/v93k" %>) like the V93K.
|
15
|
+
|
16
|
+
If the timeset waveforms used by the pattern are
|
17
|
+
[fully defined within your Origen application](<%= path "guides/pattern/timing/#Defining_Timesets" %>)
|
18
|
+
then that information will also be represented within the generated STIL pattern.
|
19
|
+
|
20
|
+
A pattern containing a `Pattern { }` block only - i.e. only vectors and without the `Signals { }`,
|
21
|
+
`Timing { }` and other frontmatter blocks - can be generated by setting up your environment as follows:
|
22
|
+
|
23
|
+
~~~ruby
|
24
|
+
OrigenTesters::STIL.new pattern_only: true
|
25
|
+
~~~
|
26
|
+
|
27
|
+
An alias for this configuration is the `D10` tester environment setup:
|
28
|
+
|
29
|
+
~~~ruby
|
30
|
+
# environment/d10.rb
|
31
|
+
OrigenTesters::D10.new
|
32
|
+
~~~
|
33
|
+
|
34
|
+
|
35
|
+
% end
|
@@ -136,6 +136,59 @@ information):
|
|
136
136
|
* other
|
137
137
|
* empty
|
138
138
|
|
139
|
+
#### Custom Test Instance Types
|
140
|
+
|
141
|
+
The <code>add_til</code> method is available to describe a custom instance. An example is below.
|
142
|
+
|
143
|
+
~~~ruby
|
144
|
+
# app_interface
|
145
|
+
|
146
|
+
def initialize(options = {})
|
147
|
+
add_til :my_lib,
|
148
|
+
test_a: {
|
149
|
+
# Basic arg
|
150
|
+
input1: :arg0,
|
151
|
+
# Arg with default value
|
152
|
+
input2: [:arg1, 'default'],
|
153
|
+
# Arg with default and list of predefined allowed values
|
154
|
+
input3: [:arg2, 'volt', %w(volt curr)],
|
155
|
+
# Attribute aliases can be defined like this:
|
156
|
+
aliases: {
|
157
|
+
some_alias_name: :input1,
|
158
|
+
another_alias: :input2
|
159
|
+
},
|
160
|
+
# Define any methods you want for the instance like this
|
161
|
+
methods: {
|
162
|
+
# An optional finalize method can be supplied, this method will be called
|
163
|
+
# immediately before the test instance is rendered. The test object itself
|
164
|
+
# will be passed as an argument.
|
165
|
+
finalize: lambda do |ti|
|
166
|
+
ti.proc_name = 'blah_blah'
|
167
|
+
ti.proc_called_as = ''
|
168
|
+
end,
|
169
|
+
set_some_arg: lambda do |ti, val|
|
170
|
+
ti.input1 = val
|
171
|
+
end
|
172
|
+
}
|
173
|
+
},
|
174
|
+
|
175
|
+
test_b: {
|
176
|
+
# ...
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
# Here's how to use the custom library
|
181
|
+
def do_test_a(name, options = {})
|
182
|
+
ti = test_instances.my_lib.test_a name
|
183
|
+
ti.input1 = 50.0
|
184
|
+
ti.input3 = 'curr'
|
185
|
+
|
186
|
+
# ...
|
187
|
+
end
|
188
|
+
~~~
|
189
|
+
|
190
|
+
#### Legacy Custom Test Instance Types (prefered method is above)
|
191
|
+
|
139
192
|
If you need a different type you can still call the add method, the difference in the
|
140
193
|
returned instance for an unrecognized type is:
|
141
194
|
|
@@ -1,5 +1,38 @@
|
|
1
1
|
% render "layouts/guides.html" do
|
2
2
|
|
3
|
-
|
3
|
+
Be sure to read and understand the guide to
|
4
|
+
[Creating an Interface](<%= path "guides/program/interface" %>)
|
5
|
+
and
|
6
|
+
[J750 API](<%= path "guides/program/j750" %>)
|
7
|
+
before reading this section.
|
8
|
+
This guide will describe the API differences between UFlex/IG-XL and J750/IG-XL test program
|
9
|
+
generation.
|
10
|
+
|
11
|
+
### Creating a flow entry with multiple Use-Limit lines
|
12
|
+
|
13
|
+
~~~ruby
|
14
|
+
functional :test2, sbin: 101, number: 20020,
|
15
|
+
sub_tests: [
|
16
|
+
sub_test(:limit_name1, lo: -2, hi: 2),
|
17
|
+
sub_test(:limit_name2, lo: -1, hi: 1)
|
18
|
+
]
|
19
|
+
~~~
|
20
|
+
|
21
|
+
~~~ruby
|
22
|
+
# Another example using a custom instance
|
23
|
+
def sar_cal_test(name, options = {})
|
24
|
+
ti = test_instances.sar_tests.sar_cal name
|
25
|
+
# ...
|
26
|
+
|
27
|
+
# Assign fixed limits
|
28
|
+
options[:sub_tests] = [
|
29
|
+
sub_test(:source_gain, lo: 0.99, hi: 1.01),
|
30
|
+
sub_test(:source_offset, lo: -0.001, hi: 0.001)
|
31
|
+
]
|
32
|
+
|
33
|
+
# add the test to the flow
|
34
|
+
flow.test ti, options
|
35
|
+
end
|
36
|
+
~~~
|
4
37
|
|
5
38
|
% 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.
|
4
|
+
version: 0.21.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: 2019-
|
11
|
+
date: 2019-05-23 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.
|
19
|
+
version: 0.44.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.
|
26
|
+
version: 0.44.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: require_all
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +58,20 @@ dependencies:
|
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 1.1.3
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: origen_stil
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.2.1
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.2.1
|
61
75
|
description:
|
62
76
|
email:
|
63
77
|
- stephen.f.mcginty@gmail.com
|
@@ -68,10 +82,12 @@ files:
|
|
68
82
|
- config/application.rb
|
69
83
|
- config/boot.rb
|
70
84
|
- config/commands.rb
|
85
|
+
- config/global_commands.rb
|
71
86
|
- config/shared_commands.rb
|
72
87
|
- config/users.rb
|
73
88
|
- config/version.rb
|
74
89
|
- lib/commands/build.rb
|
90
|
+
- lib/commands/convert.rb
|
75
91
|
- lib/commands/run.rb
|
76
92
|
- lib/origen_testers.rb
|
77
93
|
- lib/origen_testers/api.rb
|
@@ -230,6 +246,7 @@ files:
|
|
230
246
|
- lib/origen_testers/origen_ext/application/runner.rb
|
231
247
|
- lib/origen_testers/origen_ext/generator.rb
|
232
248
|
- lib/origen_testers/origen_ext/generator/flow.rb
|
249
|
+
- lib/origen_testers/origen_ext/generator/pattern.rb
|
233
250
|
- lib/origen_testers/origen_ext/generator/resources.rb
|
234
251
|
- lib/origen_testers/origen_ext/pins/pin.rb
|
235
252
|
- lib/origen_testers/origen_ext/pins/pin_collection.rb
|
@@ -287,6 +304,10 @@ files:
|
|
287
304
|
- lib/origen_testers/smartest_based_tester/v93k/test_suite.rb
|
288
305
|
- lib/origen_testers/smartest_based_tester/v93k/test_suites.rb
|
289
306
|
- lib/origen_testers/smartest_based_tester/v93k/variables_file.rb
|
307
|
+
- lib/origen_testers/stil_based_tester.rb
|
308
|
+
- lib/origen_testers/stil_based_tester/base.rb
|
309
|
+
- lib/origen_testers/stil_based_tester/d10.rb
|
310
|
+
- lib/origen_testers/stil_based_tester/stil.rb
|
290
311
|
- lib/origen_testers/test/basic_interface.rb
|
291
312
|
- lib/origen_testers/test/block.rb
|
292
313
|
- lib/origen_testers/test/custom_test_interface.rb
|
@@ -351,6 +372,7 @@ files:
|
|
351
372
|
- templates/origen_guides/pattern/pins.md.erb
|
352
373
|
- templates/origen_guides/pattern/registers.md.erb
|
353
374
|
- templates/origen_guides/pattern/running.md.erb
|
375
|
+
- templates/origen_guides/pattern/stil.md.erb
|
354
376
|
- templates/origen_guides/pattern/timing.md.erb
|
355
377
|
- templates/origen_guides/pattern/ultraflex.md.erb
|
356
378
|
- templates/origen_guides/pattern/v93k.md.erb
|