module BOAST::Intrinsics

@private

Constants

CONVERSIONS
INTRINSICS

Public Class Methods

check_coverage() click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 43
def check_coverage
  instrs = [X86, ARM].collect { |ar|
    ins = []
    INTRINSICS[ar].each { |i,v|
      if i == :CVT then
        v.each { |type1, h|
          h.each { |type2, instr|
            ins.push instr.to_s
          }
        }
      else
        v.each { |type, instr|
          ins.push instr.to_s
        }
      end
    }
    ins - INSTRUCTIONS[ar].keys
  }
  return instrs
end
generate_conversions() click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 451
def generate_conversions
  [X86, ARM].each { |arch|
    cvt_dgraph = RGL::DirectedAdjacencyGraph::new
    INTRINSICS[arch][:CVT].each { |dest, origs|
      origs.each { |orig, intrinsic|
        supported = false
        if MODELS[get_model.to_s] then
          INSTRUCTIONS[arch][intrinsic.to_s].each { |cpuid|
            if cpuid.kind_of?( Array ) then
              supported = true if (cpuid - MODELS[get_model.to_s]).empty?
            else
              supported = true if MODELS[get_model.to_s].include?( cpuid )
            end
          }
        end
        cvt_dgraph.add_edge(orig, dest) if supported
      }
    }
    cvt_dgraph.vertices.each { |source|
      hash = {}
      cvt_dgraph.edges.each { |e| hash[e.to_a] = 1 }
      paths = cvt_dgraph.dijkstra_shortest_paths( hash, source )
      paths.each { |dest, path|
        CONVERSIONS[arch][dest][source] = path if path
      }
    }
    types = []
    INTRINSICS[arch].each { |intrinsic, instructions|
      types += instructions.keys
    }
    types.uniq
    types.each { |type|
      CONVERSIONS[arch][type][type] = [type]
    }
  }
end
get_conversion_path(type_dest, type_orig) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 105
def get_conversion_path(type_dest, type_orig)
  conversion_path = CONVERSIONS[get_architecture][get_vector_name(type_dest)][get_vector_name(type_orig)]
  raise IntrinsicsError, "Unavailable conversion from #{get_vector_name(type_orig)} to #{get_vector_name(type_dest)} on #{get_architecture_name}#{get_architecture==X86 ? "(#{get_model})" : "" }!" unless conversion_path
  return conversion_path
end
get_vector_decl( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 147
def get_vector_decl( data_type )
  case get_architecture
  when X86
    get_vector_decl_X86( data_type )
  when ARM
    get_vector_decl_ARM( data_type )
  else
    return get_vector_name( data_type )
  end
end
get_vector_decl_ARM( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 131
def get_vector_decl_ARM( data_type )
  raise IntrinsicsError, "Unsupported vector size on ARM: #{data_type.total_size*8}!" unless [64,128].include?( data_type.total_size*8 )
  case data_type
  when Int
    raise IntrinsicsError, "Unsupported data size for int vector on ARM: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
    return get_vector_name( data_type ).to_s
  when Real
    raise IntrinsicsError, "Unsupported data size for real vector on ARM: #{data_type.size*8}!" unless [4,8].include?( data_type.size )
    return get_vector_name( data_type ).to_s
  else
    raise IntrinsicsError, "Unsupported data type #{data_type} for vector on ARM!"
  end
end
get_vector_decl_X86( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 113
def get_vector_decl_X86( data_type )
  raise IntrinsicsError, "Unsupported vector size on X86: #{data_type.total_size*8}!" unless [64,128,256,512].include?( data_type.total_size*8 )
  s = "__m#{data_type.total_size*8}"
  case data_type
  when Int
    raise IntrinsicsError, "Unsupported data size for int vector on X86: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
    return s << "#{data_type.total_size*8>64 ? "i" : ""}"
  when Real
    return s if data_type.size == 4
    return s << "d" if data_type.size == 8
    raise IntrinsicsError, "Unsupported data size for real vector on X86: #{data_type.size*8}!"
  else
    raise IntrinsicsError, "Unsupported data type #{data_type} for vector on X86!"
  end
end
get_vector_name( type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 160
def get_vector_name( type )
  s = ""
  case type
  when Int
    s << "u" unless type.signed?
    s << "int"
  when Real
    s << "float"
  else
    raise InternalIntrinsicsError, "Undefined vector type!"
  end
  s << "#{type.size*8}"
  s << "x#{type.vector_length}_t"
  return s.to_sym
end
intrinsics(intr_symbol, type, type2=nil) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 99
def intrinsics(intr_symbol, type, type2=nil)
  return intrinsics_by_vector_name(intr_symbol, get_vector_name(type), type2 ? get_vector_name(type2) : nil)
end
intrinsics_by_vector_name(intr_symbol, type, type2=nil) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 66
    def intrinsics_by_vector_name(intr_symbol, type, type2=nil)
      if type2 then
        instruction = INTRINSICS[get_architecture][intr_symbol][type][type2]
      else
        instruction = INTRINSICS[get_architecture][intr_symbol][type]
      end
      raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? " and #{type2}" : ""} on #{get_architecture_name}!" unless instruction
      supported = false
      INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
        if cpuid.kind_of?( Array ) then
          supported = true if (cpuid - MODELS[get_model.to_s]).empty?
        else
          supported = true if MODELS[get_model.to_s].include?( cpuid )
        end
      }
#      supported = (INSTRUCTIONS[instruction.to_s] & MODELS[get_model.to_s]).size > 0
      unless supported then
        required = ""
        INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
          required << " or " if required != ""
          if cpuid.kind_of?( Array ) then
            required << "( #{cpuid.join(" and ")} )"
          else
            required << "#{cpuid}"
          end
        }
        raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? " and #{type2}" : ""} on #{get_model}! (requires #{required})"
      end
      return instruction
    end
type_name_ARM( type, size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 202
def type_name_ARM( type, size, sign = :signed )
  s = ""
  case type
  when :int
    case sign
    when :signed
      s << "s"
    when :unsigned
      s << "u"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
  when :float
    s << "f"
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  s << "#{size}"
  return s
end
type_name_X86( type, size, vector_size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 225
def type_name_X86( type, size, vector_size, sign = :signed )
  s = ""
  case type
  when :int
    e = ( vector_size > 64 ? "e" : "" )
    s << "#{e}p"
    case sign
    when :signed
      s << "i"
    when :unsigned
      s << "u"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
    s << "#{size}"
  when :float
    s << "p"
    case size
    when 32
      s << "s"
    when 64
      s << "d"
    else
      raise InternalIntrinsicsError, "Invalid size!"
    end
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  return s
end
vector_type_name( type, size, vector_size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 178
def vector_type_name( type, size, vector_size, sign = :signed )
  s = ""
  case type
  when :int
    case sign
    when :signed
      s << "int"
    when :unsigned
      s << "uint"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
  when :float
    s << "float"
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  s << "#{size}"
  s << "x#{vector_size/size}_t"
  return s.to_sym
end

Private Instance Methods

check_coverage() click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 43
def check_coverage
  instrs = [X86, ARM].collect { |ar|
    ins = []
    INTRINSICS[ar].each { |i,v|
      if i == :CVT then
        v.each { |type1, h|
          h.each { |type2, instr|
            ins.push instr.to_s
          }
        }
      else
        v.each { |type, instr|
          ins.push instr.to_s
        }
      end
    }
    ins - INSTRUCTIONS[ar].keys
  }
  return instrs
end
generate_conversions() click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 451
def generate_conversions
  [X86, ARM].each { |arch|
    cvt_dgraph = RGL::DirectedAdjacencyGraph::new
    INTRINSICS[arch][:CVT].each { |dest, origs|
      origs.each { |orig, intrinsic|
        supported = false
        if MODELS[get_model.to_s] then
          INSTRUCTIONS[arch][intrinsic.to_s].each { |cpuid|
            if cpuid.kind_of?( Array ) then
              supported = true if (cpuid - MODELS[get_model.to_s]).empty?
            else
              supported = true if MODELS[get_model.to_s].include?( cpuid )
            end
          }
        end
        cvt_dgraph.add_edge(orig, dest) if supported
      }
    }
    cvt_dgraph.vertices.each { |source|
      hash = {}
      cvt_dgraph.edges.each { |e| hash[e.to_a] = 1 }
      paths = cvt_dgraph.dijkstra_shortest_paths( hash, source )
      paths.each { |dest, path|
        CONVERSIONS[arch][dest][source] = path if path
      }
    }
    types = []
    INTRINSICS[arch].each { |intrinsic, instructions|
      types += instructions.keys
    }
    types.uniq
    types.each { |type|
      CONVERSIONS[arch][type][type] = [type]
    }
  }
end
get_conversion_path(type_dest, type_orig) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 105
def get_conversion_path(type_dest, type_orig)
  conversion_path = CONVERSIONS[get_architecture][get_vector_name(type_dest)][get_vector_name(type_orig)]
  raise IntrinsicsError, "Unavailable conversion from #{get_vector_name(type_orig)} to #{get_vector_name(type_dest)} on #{get_architecture_name}#{get_architecture==X86 ? "(#{get_model})" : "" }!" unless conversion_path
  return conversion_path
end
get_vector_decl( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 147
def get_vector_decl( data_type )
  case get_architecture
  when X86
    get_vector_decl_X86( data_type )
  when ARM
    get_vector_decl_ARM( data_type )
  else
    return get_vector_name( data_type )
  end
end
get_vector_decl_ARM( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 131
def get_vector_decl_ARM( data_type )
  raise IntrinsicsError, "Unsupported vector size on ARM: #{data_type.total_size*8}!" unless [64,128].include?( data_type.total_size*8 )
  case data_type
  when Int
    raise IntrinsicsError, "Unsupported data size for int vector on ARM: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
    return get_vector_name( data_type ).to_s
  when Real
    raise IntrinsicsError, "Unsupported data size for real vector on ARM: #{data_type.size*8}!" unless [4,8].include?( data_type.size )
    return get_vector_name( data_type ).to_s
  else
    raise IntrinsicsError, "Unsupported data type #{data_type} for vector on ARM!"
  end
end
get_vector_decl_X86( data_type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 113
def get_vector_decl_X86( data_type )
  raise IntrinsicsError, "Unsupported vector size on X86: #{data_type.total_size*8}!" unless [64,128,256,512].include?( data_type.total_size*8 )
  s = "__m#{data_type.total_size*8}"
  case data_type
  when Int
    raise IntrinsicsError, "Unsupported data size for int vector on X86: #{data_type.size*8}!" unless [1,2,4,8].include?( data_type.size )
    return s << "#{data_type.total_size*8>64 ? "i" : ""}"
  when Real
    return s if data_type.size == 4
    return s << "d" if data_type.size == 8
    raise IntrinsicsError, "Unsupported data size for real vector on X86: #{data_type.size*8}!"
  else
    raise IntrinsicsError, "Unsupported data type #{data_type} for vector on X86!"
  end
end
get_vector_name( type ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 160
def get_vector_name( type )
  s = ""
  case type
  when Int
    s << "u" unless type.signed?
    s << "int"
  when Real
    s << "float"
  else
    raise InternalIntrinsicsError, "Undefined vector type!"
  end
  s << "#{type.size*8}"
  s << "x#{type.vector_length}_t"
  return s.to_sym
end
intrinsics(intr_symbol, type, type2=nil) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 99
def intrinsics(intr_symbol, type, type2=nil)
  return intrinsics_by_vector_name(intr_symbol, get_vector_name(type), type2 ? get_vector_name(type2) : nil)
end
intrinsics_by_vector_name(intr_symbol, type, type2=nil) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 66
    def intrinsics_by_vector_name(intr_symbol, type, type2=nil)
      if type2 then
        instruction = INTRINSICS[get_architecture][intr_symbol][type][type2]
      else
        instruction = INTRINSICS[get_architecture][intr_symbol][type]
      end
      raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? " and #{type2}" : ""} on #{get_architecture_name}!" unless instruction
      supported = false
      INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
        if cpuid.kind_of?( Array ) then
          supported = true if (cpuid - MODELS[get_model.to_s]).empty?
        else
          supported = true if MODELS[get_model.to_s].include?( cpuid )
        end
      }
#      supported = (INSTRUCTIONS[instruction.to_s] & MODELS[get_model.to_s]).size > 0
      unless supported then
        required = ""
        INSTRUCTIONS[get_architecture][instruction.to_s].each { |cpuid|
          required << " or " if required != ""
          if cpuid.kind_of?( Array ) then
            required << "( #{cpuid.join(" and ")} )"
          else
            required << "#{cpuid}"
          end
        }
        raise IntrinsicsError, "Unsupported operation #{intr_symbol} for #{type}#{type2 ? " and #{type2}" : ""} on #{get_model}! (requires #{required})"
      end
      return instruction
    end
type_name_ARM( type, size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 202
def type_name_ARM( type, size, sign = :signed )
  s = ""
  case type
  when :int
    case sign
    when :signed
      s << "s"
    when :unsigned
      s << "u"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
  when :float
    s << "f"
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  s << "#{size}"
  return s
end
type_name_X86( type, size, vector_size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 225
def type_name_X86( type, size, vector_size, sign = :signed )
  s = ""
  case type
  when :int
    e = ( vector_size > 64 ? "e" : "" )
    s << "#{e}p"
    case sign
    when :signed
      s << "i"
    when :unsigned
      s << "u"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
    s << "#{size}"
  when :float
    s << "p"
    case size
    when 32
      s << "s"
    when 64
      s << "d"
    else
      raise InternalIntrinsicsError, "Invalid size!"
    end
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  return s
end
vector_type_name( type, size, vector_size, sign = :signed ) click to toggle source
# File lib/BOAST/Language/Intrinsics.rb, line 178
def vector_type_name( type, size, vector_size, sign = :signed )
  s = ""
  case type
  when :int
    case sign
    when :signed
      s << "int"
    when :unsigned
      s << "uint"
    else
      raise InternalIntrinsicsError, "Invalid sign!"
    end
  when :float
    s << "float"
  else
    raise InternalIntrinsicsError, "Invalid type!"
  end
  s << "#{size}"
  s << "x#{vector_size/size}_t"
  return s.to_sym
end