module Origen::Specs::Checkers

Public Instance Methods

evaluate_limit(limit) click to toggle source
# File lib/origen/specs/checkers.rb, line 74
def evaluate_limit(limit)
  return limit if limit.is_a?(Numeric)
  return nil if limit.nil?

  if limit.is_a? Symbol
    limit = ':' + limit.to_s
  else
    limit.gsub!("\n", ' ')
    limit.scrub!
  end
  result = false
  if limit.match(/\:\S+/)
    limit_items = limit.split(/\:|\s+/).reject(&:empty?)
    references = limit.split(/\:|\s+/).select { |var| var.match(/^[a-zA-Z]\S+$/) }
    new_limit_items = [].tap do |limit_ary|
      limit_items.each do |item|
        if references.include? item
          # See if the limit is referencing a power domain, this should be extended to clocks
          # TODO: Expand limit references to check Origen::Clocks
          if Origen.top_level.respond_to? :power_domains
            if Origen.top_level.power_domains.include? item.to_sym
              limit_ary << Origen.top_level.power_domains(item.to_sym).nominal_voltage
              next
            end
          end
          if Origen.top_level.respond_to? :clocks
            if Origen.top_level.clocks.include? item.to_sym
              limit_ary << Origen.top_level.clocks(item.to_sym).freq_target
              next
            end
          end
          limit_ary << item
        else
          limit_ary << item
        end
      end
    end
    new_limit = new_limit_items.join(' ')
    new_limit_references = new_limit.split(/\:|\s+/).select { |var| var.match(/^[a-zA-Z]\S+$/) }
    if new_limit_references.empty?
      result = eval(new_limit).round(4)
    else
      return limit
    end
  elsif !!(limit.match(/^\d+\.\d+$/)) || !!(limit.match(/^-\d+\.\d+$/))
    result = Float(limit).round(4) rescue false # Use the same four digits of accuracy as the Spec model
  elsif !!(limit.match(/\d+\.\d+\s+\d+\.\d+/)) # workaround for multiple specs authoring bug
    Origen.log.debug "Found two numbers without an operator in the limit string '#{limit}', choosing the first..."
    first_number = limit.match(/(\d+\.\d+)\s+\d+\.\d+/).captures.first
    result = Float(first_number).round(4) rescue false # Use the same four digits of accuracy as the Spec model
  # elsif !!(limit.match(/^tbd$/i)) # unique case of TBD or To Be Determined, will convert to symbol
  #  limit = limit.downcase.to_sym
  else
    result = Integer(limit) rescue false
  end
  if result == false
    # Attempt to eval the limit because users could write a limit like "3.3 + 50.mV"
    # which would not work with the code above but should eval to a number 3.35
    begin
      result = eval(limit)
      return result.round(4) if result.is_a? Numeric
    rescue ::SyntaxError, ::NameError, ::TypeError
      Origen.log.debug "Limit '#{limit}' had to be rescued, storing it as a #{limit.class}"
      if limit.is_a? Symbol
        limit
      else
        "#{limit}"
      end
    end
  else
    result
  end
end
get_mode() click to toggle source
# File lib/origen/specs/checkers.rb, line 60
def get_mode
  spec_mode = nil
  if current_mode.nil?
    if self == Origen.top_level
      spec_mode = :global
    else
      spec_mode = :local
    end
  else
    spec_mode = current_mode.name
  end
  spec_mode
end
limits_ok?() click to toggle source

Check that min, max are not mixed with typ. If a user wants a baseline value for a spec use target as it will not be checked against pass/fail

# File lib/origen/specs/checkers.rb, line 27
def limits_ok?
  status = true
  if (@min.exp.to_s.include? '/') || (@max.exp.to_s.include? '/')
    return status
  end

  if @min.exp.nil? ^ @max.exp.nil?
    @limit_type = :single_sided
    if @typ.exp
      # status = false
      Origen.log.debug "Spec #{@name} has a typical limit defined with either min or max.  They are mutually exclusive, use 'target' when using min or max"
    end
  elsif @min.exp && @max.exp
    @limit_type = :double_sided
    # Both min and max must be numerical to compare them
    if @min.value.is_a?(Numeric) && @max.value.is_a?(Numeric)
      # Check that min and max make sense
      if @max.value <= @min.value || @min.value >= @max.value
        status = false
        Origen.log.debug "Spec #{@name} has min (#{@min.value}) and max (#{@max.value}) reversed"
      end
      # Check that target is OK
      unless @target.nil?
        if @target.value <= @min.value || @target.value >= @max.value
          status = false
          Origen.log.debug "Spec #{@name} has a target (#{@target.value}) that is not within the min (#{@min.value}) and max #{@max.value}) values"
        end
      end
    end
  end
  status
end
name_audit(name) click to toggle source

rubocop:disable Style/RescueModifier:

# File lib/origen/specs/checkers.rb, line 5
def name_audit(name)
  return name if name.nil?
  return nil unless name.is_a?(Symbol) || name.is_a?(String)

  if name == :inspect
    Origen.log.debug ':inspect is a reserved spec name'
    return nil
  end
  if name.match(/^\d/)
    Origen.log.debug "Spec #{name} starts with a number"
    return nil
  end
  if name.match(/\s+/)
    Origen.log.debug "Spec #{name} contains white space, removing it"
    name.delete!(/\s+/)
  end
  name.is_a?(String) ? name.downcase.to_sym : name
end