origen_testers 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2bb719c179345dee09336e7c9ef743de9383d0bc32602c58226a682607c93016
4
- data.tar.gz: 7f98c2c6a7d9639bf70c42d4264ba3294b72b814b3c455e9983d4342c3ade773
3
+ metadata.gz: fe9e0d79136d4c5a7a16b3e73e098ac9069c0aa0d4efb70e4e9c93bb1b1d01d7
4
+ data.tar.gz: 115289be29ed7e600ee5e331a61649e05f649131956214bebd81a6afb963a0d7
5
5
  SHA512:
6
- metadata.gz: 5530008ddd55eb90eb4d6502dc8a61633eb28a88d1eed1baa8e9b51ed52bbd3b274c8fb7bd680318716b6c70d910a40c27c2515134b1ce067e69d6e2fde2fce6
7
- data.tar.gz: d599275895db3b446e5f8c3ebe9da2101aa759e8ba622ca5c9a94c14fb12159409f35a1b423df2f6383c70c19136a638c2383a3ce6ac62a2ddb2f48c4f37ca7f
6
+ metadata.gz: 13b81ab2f3f0c642ba283399fbc39df7f1fcf7f982995f53ae75ef4acef6b060ca196bec8ea9571b65a548831a712eba6653b6eadcd52b5672fd84cad91ff051
7
+ data.tar.gz: 1ee85240a3d5c559dff37c61f12110f02a1a8228fc36f828911fe7d13c79cfc12fff72d49ead48f7b0ca33ee24fc3263f2f4f357abfd014aad3bb418bb12b0be
@@ -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
- # Setting this to the spec area for testing of compiler
88
- config.pattern_output_directory do
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
@@ -0,0 +1,12 @@
1
+ case @command
2
+
3
+ when "convert"
4
+ require "#{Origen.root!}/lib/commands/convert"
5
+ exit 0
6
+
7
+ else
8
+ @global_commands << <<-EOT
9
+ convert Convert a tester pattern from one format to another
10
+ EOT
11
+
12
+ end
@@ -1,6 +1,6 @@
1
1
  module OrigenTesters
2
2
  MAJOR = 0
3
- MINOR = 20
3
+ MINOR = 21
4
4
  BUGFIX = 0
5
5
  DEV = nil
6
6
 
@@ -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
@@ -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'
@@ -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 str.sub(/#{step_comment_prefix}{#{timestamp.length - 1}}$/, timestamp)
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 any_clocks_running?
227
- update_running_clocks
228
- if options[:repeat]
229
- slice_repeats(options).each do |slice|
230
- options[:repeat] = slice[0]
231
- delay(options.delete(:repeat), options) do |options|
232
- push_vector(options)
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
- slice[1].each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
235
- options[:pin_vals] = current_pin_vals
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
- push_vector(options)
240
- pins_need_toggling.each { |clock_pin_name| clocks_running[clock_pin_name].toggle_clock }
241
- end
242
- else
243
- if options[:repeat]
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
@@ -6,6 +6,7 @@ module OrigenTesters
6
6
  attr_accessor :default_source_wave_name, :default_capture_wave_name
7
7
 
8
8
  def initialize
9
+ @name = 'pxie'
9
10
  @pat_extension = 'digipatsrc'
10
11
  @capture_history = {}
11
12
  @source_history = {}
@@ -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
@@ -0,0 +1,8 @@
1
+ module OrigenTesters
2
+ module StilBasedTester
3
+ class STIL < Base
4
+ end
5
+ end
6
+ # Support OrigenTesters::STIL.new
7
+ STIL = StilBasedTester::STIL
8
+ end
@@ -58,6 +58,8 @@ module OrigenTesters
58
58
  @digcap_settings = { digcap_format: :twos_complement }
59
59
  end
60
60
  @blocks = [Block.new(0, self), Block.new(1, self), Block.new(2, self)]
61
+
62
+ add_timeset 'tp0'
61
63
  end
62
64
 
63
65
  def on_create
@@ -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,
@@ -1,5 +1,5 @@
1
1
  # Pattern to exercise the Freq Counter feature
2
- unless $tester.v93k? || $tester.pxie6570?
2
+ unless $tester.v93k? || $tester.pxie6570? || $tester.stil?
3
3
  Pattern.create do
4
4
  $dut.freq_count
5
5
  end
@@ -1,4 +1,4 @@
1
- unless $tester.v93k? || $tester.pxie6570?
1
+ unless $tester.v93k? || $tester.pxie6570? || $tester.stil?
2
2
  # Pattern to exercise the memory test feature of tester
3
3
  Pattern.create(:memory_test => true) do
4
4
 
@@ -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
@@ -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
- self.resources_filename = 'prb1'
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
 
@@ -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
- self.resources_filename = 'prb2'
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
- <%= render "partials/placeholder.md" %>
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.20.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-02-06 00:00:00.000000000 Z
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.26.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.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