Class: Origen::Specs::Spec
Defined Under Namespace
Classes: Limit, SpecAttribute
Constant Summary collapse
- TYPES =
Origen::Specs::SPEC_TYPES
- ATTRS =
{ ip_name: SpecAttribute.new(:ip_name, Symbol, true, :design, 'The parent IP object of the specification'), name: SpecAttribute.new(:name, Symbol, true, :design, 'Specification Name'), type: SpecAttribute.new(:type, Symbol, true, :design, "Specification Type, acceptable values: #{TYPES}"), sub_type: SpecAttribute.new(:sub_type, Symbol, true, :design, 'Specification sub-type (e.g. :max_operating_condition)'), mode: SpecAttribute.new(:mode, Symbol, true, :design, 'Specification mode, inherited from the owning parent object'), symbol: SpecAttribute.new(:symbol, String, false, :design, 'Specification symbol, can contain HTML'), description: SpecAttribute.new(:description, String, false, :design, 'Specification description'), audience: SpecAttribute.new(:audience, Symbol, false, :design, 'Specification audience, acceptable values are :internal and :external'), min: SpecAttribute.new(:min, Limit, false, :design, 'Specification minimum limit. The limit expression is displayed, not a resolved value'), min_ovr: SpecAttribute.new(:min_ovr, Limit, false, :design, 'Specification minimum limit at SoC level. The limit expression is displaye,d not a resolved value'), max: SpecAttribute.new(:max, Limit, false, :design, 'Specification maximum limit. The limit expression is displayed, not a resolved value'), max_ovr: SpecAttribute.new(:max_ovr, Limit, false, :design, 'Specification maximum limit at SoC level. The limit expression is displaye,d not a resolved value'), typ: SpecAttribute.new(:typ, Limit, false, :design, 'Specification typical limit. The limit expression is displayed, not a resolved value'), typ_ovr: SpecAttribute.new(:typ_ovr, Limit, false, :design, 'Specification typical limit at SoC level. The limit expression is displaye,d not a resolved value'), unit: SpecAttribute.new(:unit, String, false, :design, 'Specification unit of measure'), constraints: SpecAttribute.new(:constraints, String, false, :design, "Single logical expression or a CSV list of logical expressions required for the spec to be valid (e.g. 'GVDD == 1.2V'"), limit_type: SpecAttribute.new(:limit_type, Symbol, false, :design, 'Auto-generated attribute based on analysis of the spec limits. Acceptable values are :single_sided and :double_sided'), notes: SpecAttribute.new(:notes, Hash, false, :design, 'Specification notes'), disposition_required: SpecAttribute.new(:disposition_required, TrueClass, false, :pde, 'Boolean representation of whether a specification needs a disposition based on silicon results or customer input'), priority: SpecAttribute.new(:priority, TrueClass, false, :pde, 'Integer value (1-4) to indicate which priority the cz for this spec will be: 1. Highest priority, for critical or historically risky specs 2. Medium priority, relatively low risk. Not required until all priority 1 specs have been handled 3. Lowest priority, very low risk, low performance specs 4. No plans to characterize'), target: SpecAttribute.new(:target, String, false, :pde, 'Specification target limit. Not used for pass/fail results but for data analysis'), guardband: SpecAttribute.new(:guardband, Limit, false, :pde, 'Specification guardband limit'), testable: SpecAttribute.new(:testable, TrueClass, false, :pde, 'Boolean representation of whether a specification is testable'), tested_at_probe: SpecAttribute.new(:tested_at_probe, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at probe'), tested_at_ft_hot: SpecAttribute.new(:tested_at_ft_hot, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at final test hot temperature'), tested_at_ft_ext_hot: SpecAttribute.new(:tested_at_ft_ext_hot, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at final test extended hot temperature'), tested_at_ft_cold: SpecAttribute.new(:tested_at_ft_cold, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at final test cold temperature'), tested_at_ft_ext_cold: SpecAttribute.new(:tested_at_ft_ext_cold, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at final test extended cold temperature'), tested_at_ft_room: SpecAttribute.new(:tested_at_ft_room, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested at final test room temperature'), guaranteed_by_prod_test: SpecAttribute.new(:guaranteed_by_prod_test, TrueClass, false, :pde, 'Boolean representation of whether a specification is guaranteed by production test'), guaranteed_by_proxy_test: SpecAttribute.new(:guaranteed_by_proxy_test, TrueClass, false, :pde, 'Boolean representation of whether a specification is guaranteed by production test via a proxy test such as BIST'), guaranteed_by_construction: SpecAttribute.new(:guaranteed_by_construction, TrueClass, false, :pde, 'Boolean representation of whether a specification is guaranteed by physical construction, design documentation required'), guaranteed_by_simulation: SpecAttribute.new(:guaranteed_by_simulation, TrueClass, false, :pde, 'Boolean representation of whether a specification is tested guaranteed by simulation, design documentation required'), cz_on_ate: SpecAttribute.new(:cz_on_ate, TrueClass, false, :pde, 'Boolean representation of whether a specification is characterized on ATE'), cz_ate_sample_size: SpecAttribute.new(:cz_ate_sample_size, Integer, false, :pde, 'Integer number representing the sample size of the split used for customer Cpk calculation as tested on ATE'), cz_ate_cpk: SpecAttribute.new(:cz_ate_cpk, Float, false, :pde, 'Float number representing the customer or representative Cpk of the specification as tested on ATE'), cz_on_bench: SpecAttribute.new(:cz_on_bench, TrueClass, false, :pde, 'Boolean representation of whether a specification is characterized on a bench setup'), cz_bench_sample_size: SpecAttribute.new(:cz_bench_sample_size, Integer, false, :pde, 'Integer number representing the sample size of the split used for customer Cpk calculation on a bench setup'), cz_bench_cpk: SpecAttribute.new(:cz_bench_cpk, Float, false, :pde, 'Float number representing the customer or representative Cpk of the specification as tested on a bench setup'), cz_on_system: SpecAttribute.new(:cz_on_system, TrueClass, false, :pde, 'Boolean representation of whether a specification is characterized in a system setup'), cz_system_sample_size: SpecAttribute.new(:cz_system_sample_size, Integer, false, :pde, 'Integer number representing the sample size of the split used for customer Cpk calculation in a system'), cz_system_cpk: SpecAttribute.new(:cz_system_cpk, Float, false, :pde, 'Float number representing the customer or representative Cpk of the specification as tested in a system') }
Instance Method Summary collapse
-
#add_note(id, options = {}) ⇒ Object
Add a specification note.
-
#diff(compare_spec) ⇒ Object
Do a ‘diff’ from the current spec (self) and the compare spec Returns a hash with attribute as key and an array of the attribute values that differed.
-
#include?(s) ⇒ Boolean
Monkey patch of hash/array include? method needed because Origen::Specs#specs can return a single Spec instance or an Array of Specs.
-
#initialize(name, type, mode, owner_name, &block) ⇒ Spec
constructor
There are at least three attributes needed to define a unique spec.
- #method_missing(method, *args, &block) ⇒ Object
-
#note_count ⇒ Object
Returns the number of notes as an Integer.
-
#notes(id = nil) ⇒ Object
Returns a Note object from the notes hash.
Constructor Details
#initialize(name, type, mode, owner_name, &block) ⇒ Spec
There are at least three attributes needed to define a unique spec.
1) name (e.g. :vdd)
2) type (e.g. :dc) Possible values are [:dc, :ac, :temperature]
3) mode (e.g. :global). mode defaults to the current mode found for the parent object
A mode is defined as a device state that requires some sequence of actions to be enabled. A type is a classification moniker that exists without any stimulus required. Some specs require a fourth attribute sub_type to be uniquely defined. For example, a global device level VDD specification would require four attributes to be unique. Here is an example of two spec definitions for a VDD power supply
name = :vdd, type: :dc, mode: :global, sub_type: , typ = "1.0V +/- 30mV"
name = :vdd, type: :dc, mode: :global, sub_type: , min = -0.3V, max = 1.8V
Whereas a typical DDR timing specification might only need three attributes to be unique
name: :tddkhas, type: :ac, mode: ddr4dr2400, sub_type: nil
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/origen/specs/spec.rb', line 81 def initialize(name, type, mode, owner_name, &block) @name = name_audit(name) fail 'Specification names must be of types Symbol or String and cannot start with a number' if @name.nil? @type = type @sub_type = nil # not necessary to be able to find a unique spec, but required for some specs @mode = mode @ip_name = owner_name @symbol = nil # Meant to be populated with HTML representing the way the spec name should look in a document @description = nil @min, @typ, @max, @target = nil, nil, nil, nil @min_ovr, @typ_ovr, @typ_ovr = nil, nil, nil @audience = nil @notes = {} @exhibits = {} @testable = nil @guardband = nil (block.arity < 1 ? (instance_eval(&block)) : block.call(self)) if block_given? fail "Spec type must be one of #{TYPES.join(', ')}" unless TYPES.include? type @min = Limit.new(@min) @max = Limit.new(@max) @typ = Limit.new(@typ) @min_ovr = Limit.new(@min_ovr) @max_ovr = Limit.new(@max_ovr) @typ_ovr = Limit.new(@typ_ovr) @guardband = Limit.new(@guardband) fail "Spec #{name} failed the limits audit!" unless limits_ok? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/origen/specs/spec.rb', line 109 def method_missing(method, *args, &block) ivar = "@#{method.to_s.gsub('=', '')}" ivar_sym = ":#{ivar}" if method.to_s =~ /=$/ define_singleton_method(method) do |val| instance_variable_set(ivar, val) end elsif instance_variables.include? ivar_sym instance_variable_get(ivar) else define_singleton_method(method) do instance_variable_get(ivar) end end send(method, *args, &block) end |
Instance Method Details
#add_note(id, options = {}) ⇒ Object
Add a specification note
181 182 183 184 185 186 187 |
# File 'lib/origen/specs/spec.rb', line 181 def add_note(id, = {}) = { type: :spec }.update() # Create the Note instance and add to the notes attribute @notes[id] = Origen::Specs::Note.new(id, [:type], ) end |
#diff(compare_spec) ⇒ Object
Do a ‘diff’ from the current spec (self) and the compare spec Returns a hash with attribute as key and an array of the attribute values that differed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/origen/specs/spec.rb', line 129 def diff(compare_spec) diff_results = Hash.new do |h, k| h[k] = [] end # Loop through self's isntance variables first instance_variables.each do |ivar| ivar_sym = ivar.to_s.gsub('@', '').to_sym next if ivar_sym == :notes # temporarily disable until notes diff method written ivar_str = ivar.to_s.gsub('@', '') if compare_spec.respond_to? ivar_sym # Check if the instance variable is a Limit and if so then find # all instance_variables and diff them as well if instance_variable_get(ivar).class == Origen::Specs::Spec::Limit limit_diff_results = diff_limits(instance_variable_get(ivar), compare_spec.instance_variable_get(ivar)) # Extract the limit diff pairs and merge with updated keys with the diff_results hash limit_diff_results.each do |k, v| limit_diff_key = "#{ivar_str}_#{k}".to_sym diff_results[limit_diff_key] = v end else unless instance_variable_get(ivar) == compare_spec.instance_variable_get(ivar) diff_results[ivar_sym] = [instance_variable_get(ivar), compare_spec.instance_variable_get(ivar)] Origen.log.debug "Found spec difference for instance variable #{ivar} for #{self} and #{compare_spec}" end end else # The compare spec doesn't have the current instance variable # so log a difference if instance_variable_get(ivar).class == Origen::Specs::Spec::Limit limit_diff_results = diff_limits(instance_variable_get(ivar), compare_spec.instance_variable_get(ivar)) # Extract the limit diff pairs and merge with updated keys with the diff_results hash limit_diff_results.each do |k, v| limit_diff_key = "#{ivar_str}_#{k}".to_sym diff_results[limit_diff_key] = v end else Origen.log.debug "Instance variable #{ivar} exists for #{self} and does not for #{compare_spec}" diff_results[ivar_sym] = [instance_variable_get(ivar), ''] end end end # Loop through unique instance variables for compare_spec diff_results end |
#include?(s) ⇒ Boolean
Monkey patch of hash/array include? method needed because Origen::Specs#specs can return a single Spec instance or an Array of Specs
176 177 178 |
# File 'lib/origen/specs/spec.rb', line 176 def include?(s) s == @name ? true : false end |
#note_count ⇒ Object
Returns the number of notes as an Integer
196 197 198 |
# File 'lib/origen/specs/spec.rb', line 196 def note_count @notes.size end |
#notes(id = nil) ⇒ Object
Returns a Note object from the notes hash
190 191 192 193 |
# File 'lib/origen/specs/spec.rb', line 190 def notes(id = nil) return nil if @notes.nil? @notes.filter(id) end |