origen_testers 0.45.4 → 0.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,120 @@
1
+ module OrigenTesters
2
+ module Charz
3
+ # A Charz Profile
4
+ # Used to store characterization routines as well as flow control, conditional execution, and test placement meta data
5
+ class Profile
6
+ # @!attribute id
7
+ # @return [Symbol] the id of the current profile, used as a key in OrigenTesters::Charz#charz_profiles hash
8
+ # @!attribute name
9
+ # @return [Symbol] the value used (if the user decides) to generate the name of the created charz test. defaults to the value of @id
10
+ # @!attribute placement
11
+ # @return [Symbol] placement of the to be created charz tests, defaults to inline, accepts :eof as well. Other placements can be used as well if @valid_placements is altered
12
+ # @!attribute on_result
13
+ # @return [Symbol] indicates if the resulting charz tests are depending on the point tests result, valid values include :on_fail, and :on_pass
14
+ # @!attribute enables
15
+ # @return [Symbol, String, Array, Hash] enable gates to be wrapped around the resulting charz tests
16
+ # @!attribute flags
17
+ # @return [Symbol, String, Array, Hash] flag gates to be wrapped around the resulting charz tests
18
+ # @!attribute routines
19
+ # @return [Array] list of charz routines to be called under this profile
20
+ # @!attribute charz_only
21
+ # @return [Boolean] indicates if the point tests should or shouldn't be added to the flow
22
+ attr_accessor :id, :name, :placement, :on_result, :enables, :flags, :routines, :charz_only
23
+
24
+ def initialize(id, options, &block)
25
+ @id = id
26
+ @id = @id.symbolize unless id.is_a? Symbol
27
+ options.each { |k, v| instance_variable_set("@#{k}", v) }
28
+ (block.arity < 1 ? (instance_eval(&block)) : block.call(self)) if block_given?
29
+ @name ||= id
30
+ @placement ||= :inline
31
+ @defined_routines = options.delete(:defined_routines)
32
+ attrs_ok?
33
+ end
34
+
35
+ def attrs_ok?
36
+ return if @quality_check == false
37
+
38
+ unknown_routines = @routines - @defined_routines
39
+ unless unknown_routines.empty?
40
+ Origen.log.error "Profile #{id}: unknown routines: #{unknown_routines}"
41
+ fail
42
+ end
43
+
44
+ @valid_placements ||= [:inline, :eof]
45
+ unless @valid_placements.include? @placement
46
+ Origen.log.error "Profile #{id}: invalid placement value, must be one of: #{@valid_placements}"
47
+ fail
48
+ end
49
+
50
+ if @on_result
51
+ @valid_on_results ||= [:on_fail, :fail, :failed, :on_pass, :pass, :passed]
52
+ unless @valid_on_results.include?(@on_result)
53
+ Origen.log.error "Profile #{id}: invalid on_result value, must be one of: #{@valid_on_results}"
54
+ fail
55
+ end
56
+ end
57
+
58
+ if @charz_only && @on_result
59
+ Origen.log.error "Profile #{id}: @charz_only is set, but @on_result (#{@on_result}) requires the parent test to exist in the flow"
60
+ fail
61
+ end
62
+
63
+ unless @gate_checks == false
64
+ gate_check(@enables, :enables) if @enables
65
+ gate_check(@flags, :flags) if @flags
66
+ end
67
+ end
68
+
69
+ def gate_check(gates, gate_type)
70
+ case gates
71
+ when Symbol, String
72
+ return
73
+ when Array
74
+ unknown_gates = gates.reject { |gate| [String, Symbol].include? gate.class }
75
+ if unknown_gates.empty?
76
+ return
77
+ else
78
+ Origen.log.error "Profile #{id}: Unknown #{gate_type} type(s) in #{gate_type} array."
79
+ Origen.log.error "Arrays must contain Strings and/or Symbols, but #{unknown_gates.map(&:class).uniq } were found in #{gates}"
80
+ fail
81
+ end
82
+ when Hash
83
+ gates.each do |gate, gated_routines|
84
+ if gate.is_a? Hash
85
+ Origen.log.error "Profile #{id}: #{gate_type} Hash keys cannot be of type Hash, but only Symbol, String, or Array"
86
+ fail
87
+ end
88
+ gate_check(gate, gate_type)
89
+ gated_routines = [gated_routines] unless gated_routines.is_a? Array
90
+ unknown_routines = gated_routines - @defined_routines
91
+ unless unknown_routines.empty?
92
+ Origen.log.error "Profile #{id}: unknown routines found in @#{gate_type}[#{gate.is_a?(Symbol) ? ':' : ''}#{gate}]: #{unknown_routines}"
93
+ fail
94
+ end
95
+ end
96
+ else
97
+ Origen.log.error "Profile #{id}: Unknown #{gate_type} type: #{gates.class}. #{gate_type} must be of type Symbol, String, Array, or Hash"
98
+ fail
99
+ end
100
+ end
101
+
102
+ def method_missing(m, *args, &block)
103
+ ivar = "@#{m.to_s.gsub('=', '')}"
104
+ ivar_sym = ":#{ivar}"
105
+ if m.to_s =~ /=$/
106
+ define_singleton_method(m) do |val|
107
+ instance_variable_set(ivar, val)
108
+ end
109
+ elsif instance_variables.include? ivar_sym
110
+ instance_variable_get(ivar)
111
+ else
112
+ define_singleton_method(m) do
113
+ instance_variable_get(ivar)
114
+ end
115
+ end
116
+ send(m, *args, &block)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,38 @@
1
+ module OrigenTesters
2
+ module Charz
3
+ # A Generic charz routine
4
+ # Used to store characterization test specific meta data, values of which are used by the user to determine test parameter values
5
+ class Routine
6
+ # @!attribute id
7
+ # @return [Symbol] charz routine symbol, used as a key in OrigenTesters::Charz#charz_routines
8
+ # @!attribute name
9
+ # @return [Symbol] the value used (if the user decides) to generate the name of the created charz test. defaults to the value of @id
10
+ attr_accessor :id, :name
11
+
12
+ def initialize(id, options = {}, &block)
13
+ @id = id
14
+ @id = @id.symbolize unless id.is_a? Symbol
15
+ options.each { |k, v| instance_variable_set("@#{k}", v) }
16
+ (block.arity < 1 ? (instance_eval(&block)) : block.call(self)) if block_given?
17
+ @name ||= @id
18
+ end
19
+
20
+ def method_missing(m, *args, &block)
21
+ ivar = "@#{m.to_s.gsub('=', '')}"
22
+ ivar_sym = ":#{ivar}"
23
+ if m.to_s =~ /=$/
24
+ define_singleton_method(m) do |val|
25
+ instance_variable_set(ivar, val)
26
+ end
27
+ elsif instance_variables.include? ivar_sym
28
+ instance_variable_get(ivar)
29
+ else
30
+ define_singleton_method(m) do
31
+ instance_variable_get(ivar)
32
+ end
33
+ end
34
+ send(m, *args, &block)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,42 @@
1
+ module OrigenTesters
2
+ module Charz
3
+ # a 1D search routine
4
+ class SearchRoutine < Routine
5
+ # @!attribute start
6
+ # @return [Numeric] search start value
7
+ # @!attribute stop
8
+ # @return [Numeric] search stop value
9
+ # @!attribute res
10
+ # @return [Numeric] search resolution
11
+ # @!attribute spec
12
+ # @return [Numeric] spec parameter to be searched
13
+ attr_accessor :start, :stop, :res, :spec
14
+
15
+ # Runs the same initialization as Routine
16
+ # performs some rudimentary quality checks, which can be disabled by setting @quality_check = false
17
+ def initialize(id, options = {}, &block)
18
+ super
19
+ attrs_ok?
20
+ end
21
+
22
+ def attrs_ok?
23
+ return if @quality_check == false
24
+
25
+ @required_attrs ||= [:start, :stop, :res, :spec]
26
+ attrs = @required_attrs.map { |attr| instance_variable_get("@#{attr}") }
27
+ if attrs.compact.size != @required_attrs.size
28
+ Origen.log.error "SearchRoutine #{@id}: unspecified attributes, each of #{@required_attrs} must have a value"
29
+ fail
30
+ end
31
+
32
+ return if @attr_value_check == false
33
+ if [@start, @stop, @res].all? { |attr| attr.is_a? Numeric }
34
+ unless @res <= (@start - @stop).abs
35
+ Origen.log.error "SearchRoutine #{@id}: Search resolution (#{@res}) is larger than the search range: #{(@start - @stop).abs}"
36
+ fail
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ module OrigenTesters
2
+ module Charz
3
+ # A 2D search or "Shmoo" routine
4
+ class ShmooRoutine < Routine
5
+ # @!attribute x_start
6
+ # @return [Numeric] the starting search value for the x dimension's spec search
7
+ # @!attribute x_stop
8
+ # @return [Numeric] the stopping search value for the x dimension's spec search
9
+ # @!attribute x_res
10
+ # @return the search resolution value for the x dimension's spec search
11
+ # @!attribute x_spec
12
+ # @return [Symbol, String] the spec parameter of interest for the x dimension
13
+ attr_accessor :x_start, :x_stop, :x_res, :x_spec
14
+ # @!attribute y_start
15
+ # @return [Numeric] the starting search value for the x dimension's spec search
16
+ # @!attribute y_stop
17
+ # @return [Numeric] the stopping search value for the x dimension's spec search
18
+ # @!attribute y_res
19
+ # @return the search resolution value for the x dimension's spec search
20
+ # @!attribute y_spec
21
+ # @return [Symbol, String] the spec parameter of interest for the x dimension
22
+ attr_accessor :y_start, :y_stop, :y_res, :y_spec
23
+
24
+ def initialize(id, options = {}, &block)
25
+ super
26
+ attrs_ok?
27
+ end
28
+
29
+ def attrs_ok?
30
+ return if @quality_check == false
31
+
32
+ @required_attrs ||= [:x_start, :x_stop, :x_res, :x_spec, :y_start, :y_stop, :y_res, :y_spec]
33
+ attrs = @required_attrs.map { |attr| instance_variable_get("@#{attr}") }
34
+ if attrs.compact.size != @required_attrs.size
35
+ Origen.log.error "ShmooRoutine #{@id}: unspecified attributes, each of #{@required_attrs} must have a value"
36
+ fail
37
+ end
38
+
39
+ return if @attr_value_check == false
40
+
41
+ # not sure if I want this check, if so need to scope out if step count is common
42
+
43
+ # if [@x_start, @x_stop, @x_res].all? { |attr| attr.is_a? Numeric }
44
+ # unless @x_res <= (@x_start - @x_stop).abs
45
+ # Origen.log.error "ShmooRoutine #{@id}: Search x_resolution (#{@x_res} is larger than the search x_range (#{@x_start - @x_stop).abs})"
46
+ # fail
47
+ # end
48
+ # end
49
+ # if [@y_start, @y_stop, @y_res].all? { |attr| attr.is_a? Numeric }
50
+ # unless @y_res <= (@y_start - @y_stop).abs
51
+ # Origen.log.error "ShmooRoutine #{@id}: Search y_resolution (#{@y_res} is larger than the search y_range (#{@y_start - @y_stop).abs})"
52
+ # fail
53
+ # end
54
+ # end
55
+ unless @x_spec != @y_spec
56
+ Origen.log.error "ShmooRoutine #{@id}: Search x_spec is identical to y_spec"
57
+ fail
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,100 @@
1
+ module OrigenTesters
2
+ module Charz
3
+ # A charz session
4
+ # contains the final combination of charz object (routines/profiles) and user options to determine how and what charz tests should be created
5
+ # the session should be checked in your interface to determine the current status and can be queried to make charz generation decisions
6
+ class Session < Profile
7
+ # @!attribute defaults
8
+ # @return [Hash] list of values to instantiate the inherited attributes from Profile with if not altered by the session update
9
+ attr_accessor :defaults
10
+
11
+ def initialize(options = {})
12
+ @id = :current_charz_session
13
+ @active = false
14
+ @valid = false
15
+ if options[:defaults]
16
+ @defaults = options[:defaults]
17
+ else
18
+ @defaults = {
19
+ placement: :inline,
20
+ on_result: nil,
21
+ enables: nil,
22
+ flags: nil,
23
+ name: 'charz',
24
+ charz_only: false
25
+ }
26
+ end
27
+ end
28
+
29
+ # Pauses the current session's activity while maintaining everthing else about the sessions state
30
+ def pause
31
+ @active = false
32
+ end
33
+
34
+ # Resume activity, if the session is valid
35
+ def resume
36
+ if @valid
37
+ @active = true
38
+ end
39
+ end
40
+
41
+ # Takes a Routine or Profile, and queries it to setup the session's attributes
42
+ # the attributes values can be set from 3 different sources, in order of priority (first is most important):
43
+ # - options
44
+ # - charz object
45
+ # - defaults
46
+ #
47
+ # If the resulting session is invalid, @valid will turn false. Otherwise, the session becomes active
48
+ def update(charz_obj, options)
49
+ @valid = false
50
+ if charz_obj.nil?
51
+ @active = false
52
+ @valid = false
53
+ return @valid
54
+ end
55
+ @defined_routines = options.delete(:defined_routines)
56
+ assign_by_priority(:placement, charz_obj, options)
57
+ assign_by_priority(:on_result, charz_obj, options)
58
+ assign_by_priority(:enables, charz_obj, options)
59
+ assign_by_priority(:flags, charz_obj, options)
60
+ assign_by_priority(:routines, charz_obj, options)
61
+ assign_by_priority(:name, charz_obj, options)
62
+ assign_by_priority(:charz_only, charz_obj, options)
63
+ attrs_ok?
64
+ massage_gates
65
+ @active = true
66
+ @valid = true
67
+ end
68
+
69
+ private
70
+
71
+ # convert hash gates to set convert their routines to type array if not already
72
+ def massage_gates
73
+ if @enables.is_a?(Hash)
74
+ @enables = {}.tap do |new_h|
75
+ @enables.each { |gates, routines| new_h[gates] = [routines].flatten }
76
+ end
77
+ end
78
+ if @flags.is_a?(Hash)
79
+ @flags = {}.tap do |new_h|
80
+ @flags.each { |gates, routines| new_h[gates] = [routines].flatten }
81
+ end
82
+ end
83
+ end
84
+
85
+ # see initialize
86
+ def assign_by_priority(ivar, charz_obj, options)
87
+ if options.keys.include?(ivar)
88
+ instance_variable_set("@#{ivar}", options[ivar])
89
+ elsif charz_obj.send(ivar)
90
+ instance_variable_set("@#{ivar}", charz_obj.send(ivar))
91
+ elsif @defaults.keys.include?(ivar)
92
+ instance_variable_set("@#{ivar}", @defaults[ivar])
93
+ else
94
+ Origen.log.error "Charz Session: No value could be determined for #{ivar}"
95
+ fail
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -138,6 +138,7 @@ module Origen
138
138
  end
139
139
  Origen.interface.startup(options) if Origen.interface.respond_to?(:startup)
140
140
  interface.instance_eval(&block)
141
+ Origen.interface.generate_eof_charz_tests if Origen.interface.respond_to?(:generate_eof_charz_tests)
141
142
  Origen.interface.shutdown(options) if Origen.interface.respond_to?(:shutdown)
142
143
  interface.at_flow_end if interface.respond_to?(:at_flow_end)
143
144
  Origen.app.listeners_for(:on_flow_end).each do |listener|
@@ -18,7 +18,7 @@ module OrigenTesters
18
18
  # Returns an array containing all runtime variables which get set by the flow
19
19
  attr_reader :set_runtime_variables
20
20
 
21
- attr_accessor :add_flow_enable, :flow_name, :flow_bypass, :flow_description
21
+ attr_accessor :add_flow_enable, :flow_name, :flow_bypass, :flow_description, :subdirectory
22
22
 
23
23
  def self.generate_flag_name(flag)
24
24
  case flag[0]
@@ -119,6 +119,7 @@ module OrigenTesters
119
119
  o[:test_name] = extract_test_name(node, o)
120
120
  o[:test_number] = extract_test_number(node, o)
121
121
  o[:limits] = extract_limits(node, o)
122
+ o[:test_text] = node.find(:test_text).try(:value)
122
123
  if on_fail = node.find(:on_fail)
123
124
  if set_result = on_fail.find(:set_result)
124
125
  if bin = set_result.find(:bin)
@@ -252,9 +253,12 @@ module OrigenTesters
252
253
  # "Test Number"
253
254
  l << f(options[:test_number])
254
255
  # "Test Text"
255
- # l << f(options[:bin_s_name] || options[:bin_h_name])
256
- names = ["#{options[:suite_name]}", "#{options[:test_name]}"]
257
- l << f(names.uniq.join('.'))
256
+ if options[:test_text]
257
+ l << f(options[:test_text])
258
+ else
259
+ names = ["#{options[:suite_name]}", "#{options[:test_name]}"]
260
+ l << f(names.uniq.join('.'))
261
+ end
258
262
  if test_modes.empty?
259
263
  # "Low Limit"
260
264
  l << f((options[:limits][nil] || {})[:lsl])
@@ -6,7 +6,7 @@ module OrigenTesters
6
6
  include OrigenTesters::Generator
7
7
 
8
8
  attr_reader :flow, :paths
9
- attr_accessor :filename, :id
9
+ attr_accessor :filename, :id, :subdirectory
10
10
 
11
11
  def initialize(flow = nil)
12
12
  @flow = flow
@@ -18,7 +18,7 @@ module OrigenTesters
18
18
  end
19
19
 
20
20
  def subdirectory
21
- 'vectors'
21
+ @subdirectory ||= 'vectors'
22
22
  end
23
23
 
24
24
  def paths
@@ -85,7 +85,13 @@ module OrigenTesters
85
85
  end
86
86
  # Finally set any initial values that have been supplied
87
87
  options[:attrs].each do |k, v|
88
- send("#{k}=", v) if respond_to?("#{k}=")
88
+ accessor = "#{k}="
89
+ if respond_to?(accessor)
90
+ send(accessor, v)
91
+ else
92
+ accessor = "#{k.to_s.underscore}="
93
+ send(accessor, v) if respond_to?(accessor)
94
+ end
89
95
  end
90
96
  end
91
97
 
@@ -13,14 +13,14 @@ module OrigenTesters
13
13
 
14
14
  def method_missing(method, *args, &block)
15
15
  if definitions[method]
16
- m = platform::TestMethod.new methods: definitions[method].dup,
17
- attrs: (args.first || {}),
18
- type: method,
19
- library: self
20
- test_methods.add(m)
21
- m
16
+ instantiate_test_method(method, args)
22
17
  else
23
- super
18
+ method = method.to_s.underscore.to_sym
19
+ if definitions[method]
20
+ instantiate_test_method(method, args)
21
+ else
22
+ super
23
+ end
24
24
  end
25
25
  end
26
26
 
@@ -31,6 +31,17 @@ module OrigenTesters
31
31
  def definitions
32
32
  @definitions || self.class::TEST_METHODS
33
33
  end
34
+
35
+ private
36
+
37
+ def instantiate_test_method(method, args)
38
+ m = platform::TestMethod.new methods: definitions[method].dup,
39
+ attrs: (args.first || {}),
40
+ type: method,
41
+ library: self
42
+ test_methods.add(m)
43
+ m
44
+ end
34
45
  end
35
46
  end
36
47
  end