module OrigenTesters module IGXLBasedTester class Base class FlowLine attr_accessor :type, :id, :cz_setup # cz_setup is a virtual attrib since it is not part of the regular flow line # cz_setup combine with instance name when characterize opcode is used # Map any aliases to the official names here, multiple aliases for a given attribute # are allowed ALIASES = { bin: :bin_fail, softbin: :sort_fail, soft_bin: :sort_fail, sbin: :sort_fail, name: :tname, number: :tnum, if_enable: :enable, if_enabled: :enable, enabled: :enable, hi_limit: :hilim, hi: :hilim, lo_limit: :lolim, lo: :lolim, # Aliases can also be used to set defaults on multiple attributes like this, # use :value to refer to the value passed in to the given alias flag_false: { device_condition: 'flag-false', device_name: :value }, flag_true: { device_condition: 'flag-true', device_name: :value }, flag_false_any: { group_specifier: 'any-active', group_condition: 'flag-false', group_name: :value }, flag_false_all: { group_specifier: 'all-active', group_condition: 'flag-false', group_name: :value }, flag_true_any: { group_specifier: 'any-active', group_condition: 'flag-true', group_name: :value }, flag_true_all: { group_specifier: 'all-active', group_condition: 'flag-true', group_name: :value }, flag_clear: { device_condition: 'flag-clear', device_name: :value } } # Assign attribute defaults here, generally this should match whatever defaults # Teradyne has set whenever you create a new test instance, etc. DEFAULTS = { test: { opcode: 'Test', result: 'Fail' }, cz: { opcode: 'characterize', result: 'None' }, goto: { opcode: 'goto' }, nop: { opcode: 'nop' }, set_device: { opcode: 'set-device' }, set_error_bin: { opcode: 'set-error-bin' }, enable_flow_word: { opcode: 'enable-flow-word' }, disable_flow_word: { opcode: 'disable-flow-word' }, logprint: { opcode: 'logprint' }, use_limit: { opcode: 'Use-Limit', result: 'Fail' }, flag_false: { opcode: 'flag-false' }, flag_false_all: { opcode: 'flag-false-all' }, flag_true: { opcode: 'flag-true' }, flag_true_all: { opcode: 'flag-true-all' } } def self.define # Generate accessors for all attributes and their aliases self::TESTER_FLOWLINE_ATTRS.each do |attr| writer = "#{attr}=".to_sym reader = attr.to_sym attr_reader attr.to_sym unless method_defined? reader attr_writer attr.to_sym unless method_defined? writer end ALIASES.each do |_alias, val| if val.is_a? Hash if ((self::TESTER_FLOWLINE_ATTRS.map(&:to_sym)) & val.keys) == val.keys writer = "#{_alias}=".to_sym unless method_defined? writer define_method("#{_alias}=") do |v| val.each do |k, _v| myval = _v == :value ? v : _v send("#{k}=", myval) end end end end else if self::TESTER_FLOWLINE_ATTRS.include? "#{val}" writer = "#{_alias}=".to_sym reader = _alias.to_sym unless method_defined? writer define_method("#{_alias}=") do |v| send("#{val}=", v) end end unless method_defined? reader define_method("#{_alias}") do send(val) end end end end end end def initialize(type, attrs = {}) @ignore_missing_instance = attrs.delete(:instance_not_available) self.cz_setup = attrs.delete(:cz_setup) @type = type # Set the defaults DEFAULTS[@type.to_sym].each do |k, v| send("#{k}=", v) if self.respond_to?("#{k}=") end # Then the values that have been supplied attrs.each do |k, v| send("#{k}=", v) if self.respond_to?("#{k}=") end end def parameter=(value) if (@type == :test || @test == :cz) && !@ignore_missing_instance if value.is_a?(String) || value.is_a?(Symbol) fail "You must supply the actual test instance object for #{value} when adding it to the flow" end end @parameter = value end def parameter # When referring to the test instance take the opportunity to refresh the current # version of the test instance @parameter = Origen.interface.identity_map.current_version_of(@parameter) end # Returns the fully formatted flow line for insertion into a flow sheet def to_s l = "\t" self.class::TESTER_FLOWLINE_ATTRS.each do |attr| if attr == 'parameter' ins = parameter if ins.respond_to?(:name) l += "#{ins.name}" else l += "#{ins}" end if type == :cz && cz_setup l += " #{cz_setup}\t" else l += "\t" end else l += "#{send(attr)}\t" end end "#{l}" end def job if !if_jobs.empty? && !unless_jobs.empty? fail "Both if and unless jobs have been defined for test: #{parameter}" elsif !if_jobs.empty? if_jobs.join(',') elsif !unless_jobs.empty? unless_jobs.map { |j| "!#{j}" }.join(',') else '' end end alias_method :jobs, :job def unless_enable=(*args) end alias_method :unless_enabled=, :unless_enable= def if_jobs @if_jobs ||= [] end def unless_jobs @unless_jobs ||= [] end def if_job=(jobs) [jobs].flatten.compact.each do |job| job = job.to_s.upcase if job =~ /!/ self.unless_job = job else if_jobs << job unless if_jobs.include?(job) end end end alias_method :if_jobs=, :if_job= alias_method :add_if_jobs, :if_job= alias_method :add_if_job, :if_job= def unless_job=(jobs) [jobs].flatten.compact.each do |job| job = job.to_s.upcase job.gsub!('!', '') unless_jobs << job unless unless_jobs.include?(job) end end alias_method :unless_jobs=, :unless_job= alias_method :add_unless_jobs, :unless_job= alias_method :add_unless_job, :unless_job= def continue_on_fail self.result = 'None' end def continue_pass self.result = 'Pass' end def debug_assume_pass self.debug_assume = 'Pass' end def debug_assume_fail self.debug_assume = 'Fail' end # def debug_sites # self.debug_sites = "All" # end def set_flag_on_fail self.flag_fail = "#{id}_FAILED" end def set_flag_on_pass self.flag_pass = "#{id}_PASSED" end def set_flag_on_ran self.flag_pass = "#{id}_RAN" end def run_if_any_passed(parent) parent.continue_on_fail self.flag_true_any = parent.set_flag_on_pass end def run_if_all_passed(parent) parent.continue_on_fail self.flag_true_all = parent.set_flag_on_pass end def run_if_any_failed(parent) parent.continue_on_fail self.flag_true_any = parent.set_flag_on_fail end def run_if_all_failed(parent) parent.continue_on_fail self.flag_true_all = parent.set_flag_on_fail end def run_if_all_(args) # code end def id @id || "#{parameter}_#{unique_counter}" end def unique_counter @unique_counter ||= self.class.unique_counter end def self.unique_counter @ix ||= -1 @ix += 1 end def test? @type == :test end end end end end