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

#systemT ⇒ Object (readonly)

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



3194
3195
3196
# File 'lib/HDLRuby/hruby_high.rb', line 3194

def systemT
  @systemT
end

#type ⇒ Object

The type of the expression if any.



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

def type
  @type
end

Class Method Details

.orig_operator(op) ⇒ Object

Gets the origin method for operation op.



3377
3378
3379
# File 'lib/HDLRuby/hruby_high.rb', line 3377

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.



3453
3454
3455
# File 'lib/HDLRuby/hruby_high.rb', line 3453

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.



3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
# File 'lib/HDLRuby/hruby_high.rb', line 3462

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.



3294
3295
3296
3297
3298
3299
3300
# File 'lib/HDLRuby/hruby_high.rb', line 3294

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.



3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
# File 'lib/HDLRuby/hruby_high.rb', line 3420

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)


3272
3273
3274
3275
3276
3277
3278
# File 'lib/HDLRuby/hruby_high.rb', line 3272

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

#hsize ⇒ Object

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.



3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
# File 'lib/HDLRuby/hruby_high.rb', line 3239

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.



3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
# File 'lib/HDLRuby/hruby_high.rb', line 3199

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.



3318
3319
3320
# File 'lib/HDLRuby/hruby_high.rb', line 3318

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

#lr(n) ⇒ Object

Left rotate of n bits.



3408
3409
3410
3411
# File 'lib/HDLRuby/hruby_high.rb', line 3408

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.



3398
3399
3400
# File 'lib/HDLRuby/hruby_high.rb', line 3398

def ls(n)
    return self << n
end

#match_type(typ) ⇒ Object

Match the type with typ: cast if different type.



3368
3369
3370
3371
3372
3373
3374
# File 'lib/HDLRuby/hruby_high.rb', line 3368

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.



3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
# File 'lib/HDLRuby/hruby_high.rb', line 3515

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



3380
3381
3382
# File 'lib/HDLRuby/hruby_high.rb', line 3380

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

#output(name) ⇒ Object

Creates output port name and connect it to the expression.



3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
# File 'lib/HDLRuby/hruby_high.rb', line 3219

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.



3323
3324
3325
# File 'lib/HDLRuby/hruby_high.rb', line 3323

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

#rr(n) ⇒ Object

Right rotate of n bits.



3414
3415
3416
3417
# File 'lib/HDLRuby/hruby_high.rb', line 3414

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.



3403
3404
3405
# File 'lib/HDLRuby/hruby_high.rb', line 3403

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.



3333
3334
3335
3336
# File 'lib/HDLRuby/hruby_high.rb', line 3333

def sext(n)
    # return self.ljust(n,self[-1])
  return self.as(HDLRuby::High.top_user.signed[self.type.width]).as(HDLRuby::High.top_user.signed[n])
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_bit ⇒ Object

Casts to a bit vector type.



3303
3304
3305
# File 'lib/HDLRuby/hruby_high.rb', line 3303

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

#to_expr ⇒ Object

Converts to a new expression.

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

Raises:



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

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

#to_signed ⇒ Object

Casts to a signed bit vector type.



3313
3314
3315
# File 'lib/HDLRuby/hruby_high.rb', line 3313

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

#to_unsigned ⇒ Object

Casts to an unsigned bit vector type.



3308
3309
3310
# File 'lib/HDLRuby/hruby_high.rb', line 3308

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

#to_value ⇒ Object

Converts to a new value.

NOTE: to be redefined.

Raises:



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

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)


3259
3260
3261
# File 'lib/HDLRuby/hruby_high.rb', line 3259

def to_value?
    return false
end

#zext(n) ⇒ Object

Extends on the left to n bits filling with 0.



3328
3329
3330
# File 'lib/HDLRuby/hruby_high.rb', line 3328

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