class BOAST::Variable

@!parse module Functors; functorize Variable; end

Constants

ANNOTATIONS

Attributes

alignment[W]
allocate[R]
constant[RW]
deferred_shape[R]
dimension[R]
direction[RW]
force_replace_constant[RW]
local[R]
name[R]
optional[R]
reference[RW]
replace_constant[RW]
restrict[R]
sampler[R]
texture[R]
type[R]

Public Class Methods

from_type(name, type, properties={}) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 313
def self.from_type(name, type, properties={})
  hash = type.to_hash
  properties.each { |k,v|
    hash[k] = v
  }
  hash[:direction] = nil
  hash[:dir] = nil
  return Variable::new(name, type.class, hash)
end
new(name, type, properties={}) click to toggle source

Creates a new {Variable} @param [#to_s] name @param [DataType] type @param [Hash] properties a set of named properties. Properties are also propagated to the {DataType}. @option properties [Symbol] :direction (or :dir) can be one of :in, :out or :inout. Specify the intent of the variable. @option properties [Array<Dimension>] :dimension (or :dim) variable is an array rather than a scalar. Dimensions are given in Fortran order (contiguous first). @option properties [Object] :constant (or :const) states that the variable is a constant and give its value. For Variable with the :dimension property set must be a {ConstArray} @option properties [Boolean] :restrict specifies that the compiler can assume no aliasing to this array. @option properties [Boolean] :reference specifies that this variable is passed by reference. @option properties [Symbol] :allocate specify that the variable is to be allocated and where. Can only be :heap or :stack for now. @option properties [Boolean] :local indicates that the variable is to be allocated on the __local space of OpenCL devices or __shared__ space of CUDA devices. In C or FORTRAN this has the same effect as :allocate => :stack. @option properties [Boolean] :texture for OpenCL and CUDA. In OpenCL also specifies that a sampler has to be generated to access the array variable. @option properties [Integer] :align specifies the alignment the variable will be declared/allocated with if allocated or is supposed to have if it is coming from another context (in bytes). @option properties [Boolean] :replace_constant specifies that for scalar constants this variable should be replaced by its constant value. For constant arrays, the value of the array will be replaced if the index can be determined at evaluation. @option properties [Boolean] :deferred_shape for Fortran interface generation mainly see Fortran documentation @option properties [Boolean] :optional for Fortran interface generation mainly see Fortran documentation

# File lib/BOAST/Language/Variable.rb, line 265
def initialize(name, type, properties={})
  @name = name.to_s
  @direction = properties[:direction] or @direction = properties[:dir]
  @constant = properties[:constant] or @constant = properties[:const]
  @dimension = properties[:dimension] or @dimension = properties[:dim]
  @local = properties[:local] or @local = properties[:shared]

  @texture = properties[:texture]
  @allocate = properties[:allocate]
  @restrict = properties[:restrict]
  @alignment = properties[:align]
  @deferred_shape = properties[:deferred_shape]
  @optional = properties[:optional]
  @reference = properties[:reference]
  @force_replace_constant = false
  @replace_constant = properties[:replace_constant]

  if @texture and lang == CL then
    @sampler = Variable::new("sampler_#{name}", CustomType,:type_name => "sampler_t" ,:replace_constant => false, :constant => "CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST")
  else
    @sampler = nil
  end

  @scalar_output = false
  if @dimension then
    @dimension = [@dimension].flatten
  else
    @scalar_output = true if @direction == :out or @direction == :inout
  end

  @type = type::new(properties)
  @properties = properties
end

Public Instance Methods

[](*args) click to toggle source

Indexes a {Variable} with the :dimension (or :dim) property set @param [Array{#to_s, Range, [first, last, step], :all, nil}] args one entry for each {Dimension} of the {Variable}.

* Range: if an index is a Range, the result will be a {Slice}. The Range can be exclusive. The first and last item of the Range will be considered first and last index in the corresponding {Dimension}.
* [first, last, step]: if an index is an Array, the result will be a {Slice}. The first and last item of the array will be considered first and last index in the corresponding {Dimension}. If a step is given the range will be iterated by step.
* :all, nil: The whole dimension will be used for the slice. But indexing will start at #get_array_start instead of the original index.
* #to_s: If an index is none of the above it will be considered a scalar index. If all indexes are scalar an {Index} will be returned.

@return [Slice, Index]

# File lib/BOAST/Language/Variable.rb, line 363
def [](*args)
  slice = false
  args.each { |a|
    slice = true if a.kind_of?(Range) or a.kind_of?(Array) or a.kind_of?(Symbol) or a.nil?
  }
  if slice then
    return Slice::new(self, *args)
  else
    return Index::new(self, *args)
  end
end
align() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 407
def align
  if dimension? then
    if align? or default_align > 1 then
      a = ( align? ? alignment : 1 )
      a = ( a >= default_align ? a : default_align )
      return align_c(a) if lang == C
      return align_fortran(a) if lang == FORTRAN
    end
  elsif vector? then
    return align_fortran(alignment) if lang == FORTRAN
  end
  return nil
end
align?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 233
def align?
  alignment
end
alignment() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 188
def alignment
  return @type.total_size if __vector? and lang == FORTRAN and not @alignment
  return @alignment
end
alloc( dims = nil, align = get_address_size ) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 421
def alloc( dims = nil, align = get_address_size )
  @dimension = [dims].flatten if dims
  dims = @dimension
  raise "Cannot allocate array with unknown dimension!" unless dims
  return alloc_fortran(dims) if lang == FORTRAN
  return alloc_c(dims, align) if lang == C
end
allocate?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 197
def allocate?
  @allocate
end
boast_header(lang=C) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 375
def boast_header(lang=C)
  return decl_texture_s if texture?
  s = ""
  s << "const " if constant? or @direction == :in
  s << @type.decl
  if dimension? then
    s << " *" unless (use_vla? and lang != FORTRAN)
  end
  if not dimension? and ( lang == FORTRAN or @direction == :out or @direction == :inout or @reference ) then
    s << " *"
  end
  s << " #{@name}"
  if dimension? and use_vla? and lang != FORTRAN  then
    s << "["
    s << @dimension.reverse.collect(&:to_s).join("][")
    s << "]"
  end
  return s
end
constant?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 193
def constant?
  @constant
end
copy(name=nil,properties={}) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 299
def copy(name=nil,properties={})
  name = @name unless name
  h = @properties.clone
  properties.each { |k,v|
    h[k] = v
  }
  return Variable::new(name, @type.class, h)
end
dealloc() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 429
def dealloc
  return dealloc_fortran if lang == FORTRAN
  return dealloc_c if lang == C
end
decl() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 402
def decl
  return decl_fortran if lang == FORTRAN
  return decl_c if [C, CL, CUDA].include?( lang )
end
decl_ffi(alloc, lang) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 395
def decl_ffi(alloc, lang)
  return :pointer if lang == FORTRAN and not alloc
  return :pointer if dimension?
  return :pointer if @direction == :out or @direction == :inout or @reference and not alloc
  return @type.decl_ffi
end
deferred_shape?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 237
def deferred_shape?
  @deferred_shape
end
dereference() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 342
def dereference
  return copy("*(#{name})", :dimension => nil, :dim => nil, :direction => nil, :dir => nil) if [C, CL, CUDA].include?( lang )
  return Index::new(self, *(@dimension.collect { |d| d.start } ) ) if lang == FORTRAN
end
dimension?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 221
def dimension?
  @dimension
end
force_replace_constant?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 217
def force_replace_constant?
  @force_replace_constant
end
inc() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 352
def inc
  return Expression::new("++",self,nil)
end
local?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 205
def local?
  @local
end
method_missing(m, *a, &b) click to toggle source
Calls superclass method
# File lib/BOAST/Language/Variable.rb, line 152
def method_missing(m, *a, &b)
  if @type.kind_of?(CStruct) and @type.members[m.to_s] then
    return struct_reference(type.members[m.to_s])
  elsif __vector? and m.to_s[0] == 's' and lang != CUDA then
    required_set = m.to_s[1..-1].chars.to_a
    existing_set = [*('0'..'9'),*('a'..'z')].first(@type.vector_length)
    if required_set.length == required_set.uniq.length and (required_set - existing_set).empty? then
      return copy(name+"."+m.to_s, :vector_length => m.to_s[1..-1].length) if lang == CL
      return copy("#{name}(#{existing_set.index(required_set[0])+1})", :vector_length => 1) if lang == FORTRAN
      return copy("#{name}[#{existing_set.index(required_set[0])}]", :vector_length => 1) if lang == C
      return super
    else
      return super
    end
  else
    return super
  end
end
optional?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 229
def optional?
  @optional
end
reference?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 241
def reference?
  @reference
end
replace_constant?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 213
def replace_constant?
  @replace_constant
end
restrict?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 209
def restrict?
  @restrict
end
scalar_output?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 225
def scalar_output?
  @scalar_output
end
set(x) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 338
def set(x)
  return self === Set(x,self)
end
set_align(align) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 308
def set_align(align)
  @alignment = align
  return self
end
slice(*slices) click to toggle source
# File lib/BOAST/Language/Slice.rb, line 222
def slice(*slices)
  Slice::new(self, *slices)
end
struct_reference(x) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 347
def struct_reference(x)
  return x.copy(name+"."+x.name) if [C, CL, CUDA].include?( lang )
  return x.copy(name+"%"+x.name) if lang == FORTRAN
end
texture?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 201
def texture?
  @texture
end
to_s() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 323
def to_s
  if force_replace_constant? or ( ( replace_constant? or replace_constants? ) and constant? and not dimension? ) then
    s = @constant.to_s + @type.suffix
    return s
  end
  if @scalar_output or @reference and [C, CL, CUDA].include?( lang ) and not decl_module? then
    return "(*#{name})"
  end
  return @name
end
to_var() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 334
def to_var
  return self
end
vector?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 245
def vector?
  __vector?
end

Private Instance Methods

__align?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 472
def __align?
  return ( dimension? and (align? or default_align > 1) and (constant? or (allocate? and @allocate != :heap ) ) )
end
__attr_align?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 480
def __attr_align?
  return ( __align? or ( vector? and not @direction ) )
end
__const?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 436
def __const?
  return ( constant? or @direction == :in )
end
__dimension?(device = false) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 468
def __dimension?(device = false)
  return ( dimension? and ((local? and not device) or ( ( allocate? and @allocate != :heap ) and not constant?)) )
end
__global?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 440
def __global?
  return ( lang == CL and @direction and dimension? and not (@properties[:register] or @properties[:private] or local?) )
end
__local?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 444
def __local?
  return ( lang == CL and local? )
end
__pointer?(device = false) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 460
def __pointer?(device = false)
  return ( ( not dimension? and ( @direction == :out or @direction == :inout or @reference ) ) or __pointer_array?(device) )
end
__pointer_array?(device = false) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 456
def __pointer_array?(device = false)
  return ( dimension? and not constant? and not ( allocate? and @allocate != :heap ) and (not local? or (local? and device)) )
end
__restrict?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 464
def __restrict?
  return ( restrict? and not decl_module? )
end
__shared?(device = false) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 448
def __shared?(device = false)
  return ( lang == CUDA and local? and not device )
end
__vector?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 476
def __vector?
  return ( @type.vector? and @type.vector_length > 1 )
end
__vla_array?() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 452
def __vla_array?
  return ( use_vla? and dimension? and not decl_module? )
end
align_c(a) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 557
def align_c(a)
  return FuncCall::new("__assume_aligned", @name, a)
end
align_fortran(a) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 561
def align_fortran(a)
  return Pragma::new("DIR", "ASSUME_ALIGNED", "#{@name}: #{a}")
end
alloc_c( dims, align = get_address_size) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 570
def alloc_c( dims, align = get_address_size)
  ds = dims.collect(&:to_s).reverse.join(")*(")
  if align > (OS.bits/8) then
    # check alignment is a power of 2
    raise "Invalid alignment #{align}!" if align & (align - 1) != 0
    return FuncCall::new(:posix_memalign, address, align, FuncCall::new(:sizeof, @type.decl) * ds)
  else
    return self === FuncCall::new(:malloc, FuncCall::new(:sizeof, @type.decl) * ds).cast(self)
  end
end
alloc_fortran( dims ) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 565
def alloc_fortran( dims )
  dims.unshift( @type.vector_length ) if __vector?
  return FuncCall::new(:allocate, FuncCall(name, * dims ) )
end
dealloc_c() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 585
def dealloc_c
  return FuncCall::new(:free, self)
end
dealloc_fortran() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 581
def dealloc_fortran
  return FuncCall::new(:deallocate, self)
end
decl_c() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 548
def decl_c
  s = ""
  s << indent
  s << decl_c_s
  s << finalize
  output.print s
  return self
end
decl_c_s(device = false) click to toggle source
# File lib/BOAST/Language/Variable.rb, line 484
def decl_c_s(device = false)
  return decl_texture_s if texture?
  s = ""
  s << "const " if __const?
  s << "__global " if __global?
  s << "__local " if __local?
  s << "__shared__ " if __shared?(device)
  s << @type.decl
  if __vla_array? then
    s << " #{@name}["
    s << "__restrict__ " if __restrict?
    s << @dimension.reverse.collect(&:to_s).join("][")
    s << "]"
  else
    s << " *" if __pointer?(device)
    if __pointer_array?(device) and __restrict? then
      if lang == CL
        s << " restrict"
      else
        s << " __restrict__" unless use_vla?
      end
    end
    s << " #{@name}"
    if dimension? and constant? then
      s << "[]"
    end
    if __dimension?(device) then
      s << "[("
      s << @dimension.collect(&:to_s).reverse.join(")*(")
      s << ")]"
    end
  end
  if __align? and lang != CUDA then
    a = ( align? ? alignment : 1 )
    a = ( a >= default_align ? a : default_align )
    s << " __attribute((aligned(#{a})))"
  end
  s << " = #{@constant}" if constant?
  return s
end
decl_fortran() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 589
def decl_fortran
  s = ""
  s << indent
  s << @type.decl
  s << ", intent(#{@direction})" if @direction
  s << ", optional" if optional?
  s << ", allocatable" if allocate? and @allocate == :heap
  s << ", parameter" if constant?
  if dimension? or __vector? then
    s << ", dimension("
    if __vector? then
      s << "#{@type.vector_length}"
      s << ", " if dimension?
    end
    s << @dimension.collect { |d|
      if deferred_shape? or ( allocate? and @allocate == :heap )
        ":"
      else
        d.to_s
      end
    }.join(", ") if dimension?
    s << ")"
  end
  s << " :: #{@name}"
  if constant? then
    @constant.shape = self if dimension? and @constant.kind_of?(ConstArray)
    s << " = #{@constant}"
    s << @type.suffix if not dimension? and @type
  end
  s << finalize
  output.print s
  if ( dimension? and (align? or default_align > 1) and (constant? or ( allocate? and @allocate != :heap ) ) ) or ( vector? and not @direction ) then
    a = ( align? ? alignment : 1 )
    a = ( a >= default_align ? a : default_align )
    s = ""
    s << indent
    s << "!DIR$ ATTRIBUTES ALIGN: #{a}:: #{name}"
    s << finalize
    output.print s
  end
  return self
end
decl_texture_s() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 525
def decl_texture_s
  raise LanguageError, "Unsupported language #{lang} for texture!" unless [CL, CUDA].include?( lang )
  raise "Write is unsupported for textures!" unless (constant? or @direction == :in)
  dim_number = 1
  if dimension? then
    dim_number == @dimension.size
  end
  raise "Unsupported number of dimension: #{dim_number}!" if dim_number > 3
  s = ""
  if lang == CL then
    s << "__read_only "
    if dim_number < 3 then
      s << "image2d_t " #from OCL 1.2+ image1d_t is defined
    else
      s << "image3d_t "
    end
  else
    s << "texture<#{@type.decl}, cudaTextureType#{dim_number}D, cudaReadModeElementType> "
  end
  s << @name
  return s
end
finalize() click to toggle source
# File lib/BOAST/Language/Variable.rb, line 632
def finalize
   s = ""
   s << ";" if [C, CL, CUDA].include?( lang )
   s << "\n"
   return s
end