Module: HDLRuby::High::HExpression

Included in:
Binary, Cast, Concat, Select, Std::PipelineT::PipeSignal, StringE, Unary, Value
Defined in:
lib/HDLRuby/hruby_high.rb,
lib/HDLRuby/std/sequencer.rb,
lib/HDLRuby/std/sequencer.rb,
lib/HDLRuby/std/hruby_enum.rb,
lib/HDLRuby/std/hruby_enum.rb

Overview

module HDLRuby::High::HRef

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#systemTObject (readonly)

The system type the expression has been resolved in, if any.



3063
3064
3065
# File 'lib/HDLRuby/hruby_high.rb', line 3063

def systemT
  @systemT
end

#typeObject

The type of the expression if any.



3065
3066
3067
# File 'lib/HDLRuby/hruby_high.rb', line 3065

def type
  @type
end

Class Method Details

.orig_operator(op) ⇒ Object

Gets the origin method for operation +op+.



3245
3246
3247
# File 'lib/HDLRuby/hruby_high.rb', line 3245

def self.orig_operator(op)
    return (op.to_s + "_orig").to_sym
end

Instance Method Details

#<=>(expr) ⇒ Object

The <=> operator is also supported by is transformed into a sub with a signed result.



3321
3322
3323
# File 'lib/HDLRuby/hruby_high.rb', line 3321

def <=>(expr)
    return (self.as(self.type.base[self.type.width+1])-expr).to_signed
end

#[](typ, rng = nil) ⇒ Object

Creates an access to elements of range +rng+ of the signal, and set the type of elements as +typ+ if given.

NOTE: +rng+ can be a single expression in which case it is an index.



3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
# File 'lib/HDLRuby/hruby_high.rb', line 3330

def [](typ,rng=nil)
    # Treat the number of arguments
    rng, typ = typ, nil unless rng
    # Process the range.
    if rng.is_a?(::Range) then
        first = rng.first
        if (first.is_a?(::Integer)) then
            first = self.type.size+first if first < 0
        end
        last = rng.last
        if (last.is_a?(::Integer)) then
            last = self.type.size+last if last < 0
        end
        rng = first..last
    end
    if rng.is_a?(::Integer) && rng < 0 then
        rng = self.type.size+rng
    end
    if rng.respond_to?(:to_expr) then
        # Number range: convert it to an expression.
        rng = rng.to_expr
    end 
    if rng.is_a?(HDLRuby::Low::Expression) then
        # Index case
        if typ then
           return RefIndex.new(typ,self.to_expr,rng)
        else
           return RefIndex.new(self.type.base,self.to_expr,rng)
        end
    else
        # Range case, ensure it is made among expression.
        first = rng.first.to_expr
        last = rng.last.to_expr
        # And create the reference.
        if typ then
           return RefRange.new(typ,
                               self.to_expr,first..last)
        else
           return RefRange.new(self.type.slice(first..last),
                               self.to_expr,first..last)
        end
    end
end

#as(type) ⇒ Object

Casts as +type+.



3163
3164
3165
3166
3167
3168
3169
# File 'lib/HDLRuby/hruby_high.rb', line 3163

def as(type)
    if (self.parent)
        return Cast.new(type.to_type,self.to_expr)
    else
        return Cast.new(type.to_type,self)
    end
end

#coerce(obj) ⇒ Object

Coerce by forcing convertion of obj to expression.



3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
# File 'lib/HDLRuby/hruby_high.rb', line 3288

def coerce(obj)
    if obj.is_a?(HDLRuby::Low::Expression) then
        # Already an expression, nothing to do.
        return [obj,self]
    elsif obj.respond_to?(:to_expr) then
        # Can be converted to an expression, do it.
        return [obj.to_expr, self]
    else
        return [obj,self]
    end
end

#constant?Boolean

Tell if the expression is constant.

Returns:

  • (Boolean)


3141
3142
3143
3144
3145
3146
3147
# File 'lib/HDLRuby/hruby_high.rb', line 3141

def constant?
    # By default not constant.
    return false unless self.each_node.any?
    # If any sub node, check if all of them are constants.
    self.each_node { |node| return false unless node.constant? }
    return true
end

#heach(&ruby_block) ⇒ Object

Iterate over the elements.

Returns an enumerator if no ruby block is given.



997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
# File 'lib/HDLRuby/std/hruby_enum.rb', line 997

def heach(&ruby_block)
  # No ruby block? Return an enumerator.
  # return self unless ruby_block
  if !ruby_block then
    return HEnumeratorWrapper.new(self)
  end
  # A block? Apply it on each element.
  # Create a namespace.
  base_block = ruby_block
  caught = false
  ruby_block = proc do |*args|
    HDLRuby::High.top_user.sub do
      caught = true
      catch(:HDLRubyThrow) do
        base_block.call(*args)
        caught = false
      end
    end
    throw(:HDLRubyThrow) if caught
  end
  # Iterate.
  self.type.range.heach do |i|
    # yield(self[i])
    ruby_block.call(self[i])
  end
end

#hsizeObject

Size.



1025
1026
1027
# File 'lib/HDLRuby/std/hruby_enum.rb', line 1025

def hsize
  self.type.size
end

#htimes(&ruby_block) ⇒ Object

HW times iteration.



1042
1043
1044
1045
1046
1047
# File 'lib/HDLRuby/std/hruby_enum.rb', line 1042

def htimes(&ruby_block)
  unless self.respond_to?(:to_i) then
    raise "htimes unsupported for such an expression: #{self}."
  end
  return self.to_i.htimes(&ruby_block)
end

#hupto(val, &ruby_block) ⇒ Object

HW upto iteration.



1050
1051
1052
1053
1054
1055
# File 'lib/HDLRuby/std/hruby_enum.rb', line 1050

def hupto(val,&ruby_block)
  unless self.respond_to?(:to_i) then
    raise "hupto unsupported for such an expression: #{self}."
  end
  return self.to_i.hupto(val,&ruby_block)
end

#inout(name) ⇒ Object

Creates inout port +name+ and connect it to the expression.



3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
# File 'lib/HDLRuby/hruby_high.rb', line 3108

def inout(name)
    # Ensures the name is a symbol.
    name = name.to_sym
    # Get access to the current expression
    obj = self
    # Create the inout.
    port = nil
    HDLRuby::High.cur_system.open do
        port = obj.type.inout(name)
    end
    # Make the connection when the instance is ready.
    HDLRuby::High.cur_system.on_instance do |inst|
        obj.scope.open do
            RefObject.new(inst,port.to_ref) <= obj
        end
    end
    return port
end

#input(name) ⇒ Object

Creates input port +name+ and connect it to the expression.



3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
# File 'lib/HDLRuby/hruby_high.rb', line 3068

def input(name)
    # Ensures the name is a symbol.
    name = name.to_sym
    # Get access to the current expression
    obj = self
    # Create the input.
    port = nil
    HDLRuby::High.cur_system.open do
        port = obj.type.input(name)
    end
    # Make the connection when the instance is ready.
    HDLRuby::High.cur_system.on_instance do |inst|
        obj.scope.open do
            RefObject.new(inst,port.to_ref) <= obj
        end
    end
    return port
end

#ljust(n, v) ⇒ Object

Extends on the left to +n+ bits filling with +v+ bit values.



3187
3188
3189
# File 'lib/HDLRuby/hruby_high.rb', line 3187

def ljust(n,v)
    return [(v.to_s * (n-self.width)).to_expr, self]
end

#lr(n) ⇒ Object

Left rotate of +n+ bits.



3276
3277
3278
3279
# File 'lib/HDLRuby/hruby_high.rb', line 3276

def lr(n)
    w = self.type.width
    return [self[w-(n+1)..0], self[w-1..w-(n)]]
end

#ls(n) ⇒ Object

Left shift of +n+ bits.



3266
3267
3268
# File 'lib/HDLRuby/hruby_high.rb', line 3266

def ls(n)
    return self << n
end

#match_type(typ) ⇒ Object

Match the type with +typ+: cast if different type.



3236
3237
3238
3239
3240
3241
3242
# File 'lib/HDLRuby/hruby_high.rb', line 3236

def match_type(typ)
    if self.type.eql?(typ) then
        return self
    else
        return self.as(typ)
    end
end

#mux(*choices) ⇒ Object

Converts to a select operator using current expression as condition for one of the +choices+.

NOTE: +choices+ can either be a list of arguments or an array. If +choices+ has only two entries (and it is not a hash), +value+ will be converted to a boolean.



3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
# File 'lib/HDLRuby/hruby_high.rb', line 3383

def mux(*choices)
    select = self
    select = select ? 1 : 0 if [true,false,nil].include?(select)
    if select.respond_to?(:to_i) then
      # The mux can be evaluate straight away. 
      # Do metaprograming.
      return choices[select.to_i]
    end
    # Process the choices.
    choices = choices.flatten(1) if choices.size == 1
    choices.map! { |choice| choice.to_expr }
    # Generate the select expression.
    return Select.new(choices[0].type,"?",select.to_expr,*choices)
end

#orig_operator(op) ⇒ Object



3248
3249
3250
# File 'lib/HDLRuby/hruby_high.rb', line 3248

def orig_operator(op)
    HExpression.orig_operator(op)
end

#output(name) ⇒ Object

Creates output port +name+ and connect it to the expression.



3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
# File 'lib/HDLRuby/hruby_high.rb', line 3088

def output(name)
    # Ensures the name is a symbol.
    name = name.to_sym
    # Get access to the current expression
    obj = self
    # Create the output.
    port = nil
    HDLRuby::High.cur_system.open do
        port = obj.type.output(name)
    end
    # Make the connection when the instance is ready.
    HDLRuby::High.cur_system.on_instance do |inst|
        obj.scope.open do
            obj <= RefObject.new(inst,port.to_ref)
        end
    end
    return port
end

#rjust(n, v) ⇒ Object

Extends on the right to +n+ bits filling with +v+ bit values.



3192
3193
3194
# File 'lib/HDLRuby/hruby_high.rb', line 3192

def rjust(n,v)
    return [self, (v.to_s * (n-self.width)).to_expr]
end

#rr(n) ⇒ Object

Right rotate of +n+ bits.



3282
3283
3284
3285
# File 'lib/HDLRuby/hruby_high.rb', line 3282

def rr(n)
    w = self.type.width
    return [self[(n-1)..0], self[w-1..n]]
end

#rs(n) ⇒ Object

Right shift of +n+ bits.



3271
3272
3273
# File 'lib/HDLRuby/hruby_high.rb', line 3271

def rs(n)
    return self >> n
end

#sdownto(val, &ruby_block) ⇒ Object

HW downto iteration.



2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
# File 'lib/HDLRuby/std/sequencer.rb', line 2190

def sdownto(val,&ruby_block)
    # Create the hardware iterator.
    # range = val..(self.to_i)
    range = AnyRange.new(val,self)
    hw_enum = SEnumeratorBase.new(signed[32],range.size) do |idx|
        range.last - idx
    end
    # Is there a ruby block?
    if(ruby_block) then
        # Yes, apply it.
        return hw_enum.seach(&ruby_block)
    else
        # No, return the resulting enumerator.
        return hw_enum
    end
end

#seach(&ruby_block) ⇒ Object

HW iteration on each element.



2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
# File 'lib/HDLRuby/std/sequencer.rb', line 2141

def seach(&ruby_block)
    # Create the hardware iterator.
    this = self
    hw_enum = SEnumeratorBase.new(this.type.base,this.type.size) do |idx,val = nil|
        if val then
            # Write access
            this[idx] <= val
        else
            # Read access
            this[idx]
        end
    end
    # Is there a ruby block?
    if(ruby_block) then
        # Yes, apply it.
        return hw_enum.seach(&ruby_block)
    else
        # No, return the resulting enumerator.
        return hw_enum
    end
end

#sext(n) ⇒ Object

Extends on the left to +n+ bits preserving the signe.



3202
3203
3204
# File 'lib/HDLRuby/hruby_high.rb', line 3202

def sext(n)
    return self.ljust(self[-1])
end

#stimes(&ruby_block) ⇒ Object

HW times iteration.



2176
2177
2178
2179
2180
2181
# File 'lib/HDLRuby/std/sequencer.rb', line 2176

def stimes(&ruby_block)
    # Ensures there is a ruby block. This allows to use empty while
    # statement.
    ruby_block = proc { } unless ruby_block
    return AnyRange.new(0,self-1).seach(&ruby_block)
end

#supto(val, &ruby_block) ⇒ Object

HW upto iteration.



2184
2185
2186
2187
# File 'lib/HDLRuby/std/sequencer.rb', line 2184

def supto(val,&ruby_block)
    # return (self..val).seach(&ruby_block)
    return AnyRange.new(self,val).seach(&ruby_block)
end

#to_bitObject

Casts to a bit vector type.



3172
3173
3174
# File 'lib/HDLRuby/hruby_high.rb', line 3172

def to_bit
    return self.as(HDLRuby::High.top_user.bit[self.type.width])
end

#to_exprObject

Converts to a new expression.

NOTE: to be redefined in case of non-expression class.

Raises:



3153
3154
3155
# File 'lib/HDLRuby/hruby_high.rb', line 3153

def to_expr
    raise AnyError, "Internal error: to_expr not defined yet for class: #{self.class}"
end

#to_signedObject

Casts to a signed bit vector type.



3182
3183
3184
# File 'lib/HDLRuby/hruby_high.rb', line 3182

def to_signed
    return self.as(HDLRuby::High.top_user.signed[self.type.width])
end

#to_unsignedObject

Casts to an unsigned bit vector type.



3177
3178
3179
# File 'lib/HDLRuby/hruby_high.rb', line 3177

def to_unsigned
    return self.as(HDLRuby::High.top_user.unsigned[self.type.width])
end

#to_valueObject

Converts to a new value.

NOTE: to be redefined.

Raises:



3135
3136
3137
3138
# File 'lib/HDLRuby/hruby_high.rb', line 3135

def to_value
    raise AnyError,
          "Expression cannot be converted to a value: #{self.class}"
end

#to_value?Boolean

Tell if the expression can be converted to a value.

Returns:

  • (Boolean)


3128
3129
3130
# File 'lib/HDLRuby/hruby_high.rb', line 3128

def to_value?
    return false
end

#zext(n) ⇒ Object

Extends on the left to +n+ bits filling with 0.



3197
3198
3199
# File 'lib/HDLRuby/hruby_high.rb', line 3197

def zext(n)
    return self.ljust(n,0)
end