origen_testers 0.45.4 → 0.48.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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