Module: HDLRuby::High

Defined in:
lib/HDLRuby/hruby_high.rb,
lib/HDLRuby/hruby_error.rb

Overview

High-level libraries for describing digital hardware.

Defined Under Namespace

Modules: HArrow, HBlock, HExpression, HRef, HScope_missing, HStatement, HbasicType, Hinner, Hmissing, Hmux, Htype, HvectorType, SingletonExtend, Std Classes: AnyError, Behavior, Binary, Block, Case, Cast, Chunk, Code, Concat, Connection, Delay, Event, If, Namespace, NotDefinedError, RefConcat, RefIndex, RefName, RefObject, RefRange, RefThis, Scope, Select, SignalC, SignalI, SystemI, SystemT, TimeBehavior, TimeBlock, TimeRepeat, TimeWait, Transmit, Type, TypeDef, TypeFloat, TypeGen, TypeSigned, TypeStruct, TypeTuple, TypeUnsigned, TypeVector, Unary, Value, When

Constant Summary collapse

Low =

Base = HDLRuby::Base

HDLRuby::Low
Void =

The void type

define_type(:void)
Bit =

The bit type.

define_type(:bit)
Signed =

The signed bit type.

define_type(:signed)
Unsigned =

The unsigned bit type.

define_type(:unsigned)
Float =

The float bit type

define_type(:float)
Universe =

The universe, i.e., the top system type.

SystemT.new(:"") {}
NameStack =

The stack of names for creating new names without conflicts.

[ Set.new ]
Integer =

Standard vector types.

TypeSigned.new(:integer)
Char =
TypeSigned.new(:char,7..0)
Natural =
TypeUnsigned.new(:natural)
Bignum =
TypeSigned.new(:bignum,HDLRuby::Infinity..0)
Real =
TypeFloat.new(:float)
@@cur_behavior =

The current behavior: by default none.

nil

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.booting?Boolean

Tells HDLRuby is currently booting.

Returns:

  • (Boolean)


17
18
19
# File 'lib/HDLRuby/hruby_high.rb', line 17

def self.booting?
    true
end

.cur_behaviorObject

Gets the enclosing behavior if any.



3709
3710
3711
# File 'lib/HDLRuby/hruby_high.rb', line 3709

def self.cur_behavior
    return @@cur_behavior
end

.cur_block(level = 0) ⇒ Object

Gets the enclosing block if any.

NOTE: +level+ allows to get an upper block of the currently enclosing block.



3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
# File 'lib/HDLRuby/hruby_high.rb', line 3737

def self.cur_block(level = 0)
    if Namespaces[-1-level].user.is_a?(Scope) then
        raise AnyError, 
              "Not within a block: #{Namespaces[-1-level].user.class}"
    elsif Namespaces[-1-level].user.is_a?(Block) then
        return Namespaces[-1-level].user
    else
        return cur_block(level+1)
    end
end

.cur_scope(level = 0) ⇒ Object

Gets the enclosing scope if any.

NOTE: +level+ allows to get an upper scope of the currently enclosing scope.



3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
# File 'lib/HDLRuby/hruby_high.rb', line 3722

def self.cur_scope(level = 0)
    if level < 0 then
        raise AnyError, "Not within a scope: #{Namespaces[-1].user.class}"
    end
    if Namespaces[-1-level].user.is_a?(Scope) then
        return Namespaces[-1-level].user
    else
        return cur_scope(level+1)
    end
end

.cur_systemObject

Gets the enclosing system type if any.



3695
3696
3697
3698
3699
3700
3701
3702
3703
# File 'lib/HDLRuby/hruby_high.rb', line 3695

def self.cur_system
    if Namespaces.size <= 1 then
        raise AnyError, "Not within a system type."
    else
        return Namespaces.reverse_each.find do |space|
            space.user.is_a?(Scope) and space.user.parent.is_a?(SystemT)
        end.user.parent
    end
end

.define_type(name) ⇒ Object

Defines a basic type +name+.



1496
1497
1498
1499
1500
1501
# File 'lib/HDLRuby/hruby_high.rb', line 1496

def self.define_type(name)
    name = name.to_sym
    type = Type.new(name)
    self.send(:define_method,name) { type }
    return type
end

.from_users(method) ⇒ Object

Gather the result of the execution of +method+ from all the users of the namespaces.



3670
3671
3672
3673
3674
3675
3676
3677
# File 'lib/HDLRuby/hruby_high.rb', line 3670

def self.from_users(method)
    Namespaces.reverse_each.reduce([]) do |res,space|
        user = space.user
        if user.respond_to?(method) then
            res += [*user.send(method)]
        end
    end
end

.in_behavior?Boolean

Tell if we are in a behavior.

Returns:

  • (Boolean)


3714
3715
3716
# File 'lib/HDLRuby/hruby_high.rb', line 3714

def self.in_behavior?
    top_user.is_a?(Block)
end

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


3690
3691
3692
# File 'lib/HDLRuby/hruby_high.rb', line 3690

def self.in_system?
    return Namespaces.size > 1
end

.make_block(mode = nil, name = :"", &ruby_block) ⇒ Object

Creates a block executed in +mode+, with possible +name+, that can be timed or not depending on the enclosing object and build it by executing the enclosing +ruby_block+.

NOTE: not a method to include since it can only be used with a behavior or a block. Hence set as module method.



3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
# File 'lib/HDLRuby/hruby_high.rb', line 3486

def self.make_block(mode = nil, name = :"", &ruby_block)
    unless mode then
        # No type of block given, get a default one.
        if top_user.is_a?(Block) then
            # There is an upper block, use its mode.
            mode = top_user.mode
        else
            # There is no upper block, use :par as default.
            mode = :par
        end
    end
    if top_user.is_a?(TimeBlock) then
        return TimeBlock.new(mode,name,&ruby_block)
    else
        return Block.new(mode,name,&ruby_block)
    end
end

.make_time_block(mode = nil, name = :"", &ruby_block) ⇒ Object

Creates a specifically timed block in +mode+, with possible +name+ and build it by executing the enclosing +ruby_block+.

NOTE: not a method to include since it can only be used with a behavior or a block. Hence set as module method.



3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
# File 'lib/HDLRuby/hruby_high.rb', line 3509

def self.make_time_block(mode = nil, name = :"", &ruby_block)
    unless mode then
        # No type of block given, get a default one.
        if top_user.is_a?(Block) then
            # There is an upper block, use its mode.
            mode = block.mode
        else
            # There is no upper block, use :par as default.
            mode = :par
        end
    end
    return TimeBlock.new(mode,name,&ruby_block)
end

.names_add(name) ⇒ Object

Adds a +name+ to the top of the stack.



4285
4286
4287
# File 'lib/HDLRuby/hruby_high.rb', line 4285

def self.names_add(name)
    NameStack[-1].add(name.to_s)
end

.names_create(base) ⇒ Object

Creates and adds the new name from +base+ that do not collides with the exisiting names.



4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
# File 'lib/HDLRuby/hruby_high.rb', line 4298

def self.names_create(base)
    base = base.to_s.clone
    # Create a non-conflicting name
    if self.names_has?(base) then
        count = 0
        while (self.names_has?(base + count.to_s)) do
            count += 1
        end
        base << count.to_s
    end
    # Add and return it
    self.names_add(base)
    # puts "created name: #{base}"
    return base.to_sym
end

.names_has?(name) ⇒ Boolean

Checks if a +name+ is present in the stack.

Returns:

  • (Boolean)


4290
4291
4292
4293
4294
# File 'lib/HDLRuby/hruby_high.rb', line 4290

def self.names_has?(name)
    NameStack.find do |names|
        names.include?(name)
    end 
end

.names_popObject

Pops from the name stack.



4280
4281
4282
# File 'lib/HDLRuby/hruby_high.rb', line 4280

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



4275
4276
4277
# File 'lib/HDLRuby/hruby_high.rb', line 4275

def self.names_push
    NameStack.push(Set.new)
end

.space_call(name, *args, &ruby_block) ⇒ Object

Looks up and calls method +name+ from the namespace stack with arguments +args+ and block +ruby_block+.

Raises:



3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
# File 'lib/HDLRuby/hruby_high.rb', line 3770

def self.space_call(name,*args,&ruby_block)
    # print "space_call with name=#{name}\n"
    # Ensures name is a symbol.
    name = name.to_sym
    # Look from the top of the namespace stack.
    Namespaces.reverse_each do |space|
        # puts "space=#{space.singleton_methods}"
        if space.respond_to?(name) then
            # print "Found is space user with class=#{space.user.class}\n"
            # The method is found, call it.
            return space.send(name,*args,&ruby_block)
        elsif space.user.respond_to?(name) then
            # The method is found in the user, call it.
            return space.user.send(name,*args,&ruby_block)
        end
    end
    # Look in the global methods.
    if HDLRuby::High.respond_to?(name) then
        # Found.
        return HDLRuby::High.send(name,*args,&ruby_block)
    end
    # Not found.
    raise NotDefinedError,
          "undefined HDLRuby construct, local variable or method `#{name}'."
end

.space_each(&ruby_block) ⇒ Object

Iterates over each namespace.

Returns an enumerator if no ruby block is given.



3682
3683
3684
3685
3686
3687
# File 'lib/HDLRuby/hruby_high.rb', line 3682

def self.space_each(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:space_each) unless ruby_block
    # A block? Apply it on each system instance.
    Namespaces.each(&ruby_block)
end

.space_include?(namespace) ⇒ Boolean

Tells if +namespace+ in included within the stack.

Returns:

  • (Boolean)


3640
3641
3642
# File 'lib/HDLRuby/hruby_high.rb', line 3640

def self.space_include?(namespace)
    return Namespaces.include?(namespace)
end

.space_index(namespace) ⇒ Object

Gets the index of a +namespace+ within the stack.



3645
3646
3647
# File 'lib/HDLRuby/hruby_high.rb', line 3645

def self.space_index(namespace)
    return Namespaces.index(namespace)
end

.space_insert(index, namespace) ⇒ Object

Inserts +namespace+ at +index+.



3627
3628
3629
# File 'lib/HDLRuby/hruby_high.rb', line 3627

def self.space_insert(index,namespace)
    Namespaces.insert(index.to_i,namespace.to_namespace)
end

.space_popObject

Pops a namespace.



3632
3633
3634
3635
3636
3637
# File 'lib/HDLRuby/hruby_high.rb', line 3632

def self.space_pop
    if Namespaces.size <= 1 then
        raise AnyError, "Internal error: cannot pop further namespaces."
    end
    Namespaces.pop
end

.space_push(namespace) ⇒ Object

Pushes +namespace+.



3619
3620
3621
3622
3623
3624
# File 'lib/HDLRuby/hruby_high.rb', line 3619

def self.space_push(namespace)
    # Emsure namespace is really a namespace.
    namespace = namespace.to_namespace
    # Adds the namespace to the top.
    Namespaces.push(namespace)
end

.space_reg(name, &ruby_block) ⇒ Object

Registers hardware referencing method +name+ to the current namespace.



3763
3764
3765
3766
# File 'lib/HDLRuby/hruby_high.rb', line 3763

def self.space_reg(name,&ruby_block)
    # print "registering #{name} in #{Namespaces[-1]}\n"
    Namespaces[-1].add_method(name,&ruby_block)
end

.space_topObject

Gets the top of the namespaces stack.



3650
3651
3652
# File 'lib/HDLRuby/hruby_high.rb', line 3650

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



3655
3656
3657
3658
3659
3660
# File 'lib/HDLRuby/hruby_high.rb', line 3655

def self.space_top=(top)
    unless top.is_a?(Namespace) then
        raise "Invalid class for a Namspace: #{top.class}"
    end
    Namespaces[-1] = top
end

.top_block(level = 0) ⇒ Object

Gets the top enclosing block if any.



3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
# File 'lib/HDLRuby/hruby_high.rb', line 3749

def self.top_block(level = 0)
    blk = cur_block(level)
    unless blk.is_a?(Block)
        raise AnyError,
            "Not within a block: #{blk.user.class}"
    end
    if Namespaces[-1-level-1].user.is_a?(Scope) then
        return blk
    else
        return top_block(level+1)
    end
end

.top_userObject

Gets construct whose namespace is the top of the namespaces stack.



3664
3665
3666
# File 'lib/HDLRuby/hruby_high.rb', line 3664

def self.top_user
    self.space_top.user
end

Instance Method Details

#function(name, &ruby_block) ⇒ Object

Declares a function named +name+ using +ruby_block+ as body.

NOTE: a function is a short-cut for a method that creates a scope.



1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
# File 'lib/HDLRuby/hruby_high.rb', line 1836

def function(name, &ruby_block)
    if HDLRuby::High.in_system? then
        define_singleton_method(name.to_sym) do |*args|
            sub do
                HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
                # ruby_block.call(*args)
            end
        end
    else
        define_method(name.to_sym) do |*args|
            sub do
                HDLRuby::High.top_user.instance_exec(*args,&ruby_block)
            end
        end
    end
end

#infinityObject

Gets the infinity.



25
26
27
# File 'lib/HDLRuby/hruby_high.rb', line 25

def infinity
    return HDLRuby::Infinity
end

#instance(name, *includes, &ruby_block) ⇒ Object

Declares a high-level system instance named +name+, with +includes+ mixins system types and using +ruby_block+ for instantiating.

NOTE: this is for generating directly an instance without declaring it system type.



1824
1825
1826
1827
1828
1829
# File 'lib/HDLRuby/hruby_high.rb', line 1824

def instance(name, *includes, &ruby_block)
    # Creates the system type.
    systemT = system(:"",*includes,&ruby_block)
    # Instantiate it with +name+.
    return systemT.instantiate(name) 
end

#struct(content) ⇒ Object

Creates an unnamed structure type from a +content+.



1770
1771
1772
# File 'lib/HDLRuby/hruby_high.rb', line 1770

def struct(content)
    return TypeStruct.new(:"",:little,content)
end

#system(name = :"", *includes, &ruby_block) ⇒ Object

Declares a high-level system type named +name+, with +includes+ mixins system types and using +ruby_block+ for instantiating.



1813
1814
1815
1816
1817
# File 'lib/HDLRuby/hruby_high.rb', line 1813

def system(name = :"", *includes, &ruby_block)
    # print "system ruby_block=#{ruby_block}\n"
    # Creates the resulting system.
    return SystemT.new(name,*includes,&ruby_block)
end

#thisObject

Gives access to the this reference.



2891
2892
2893
# File 'lib/HDLRuby/hruby_high.rb', line 2891

def this
    RefThis.new
end

#typedef(name, &ruby_block) ⇒ Object

Declares a high-level generic type named +name+, and using +ruby_block+ for construction.



1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
# File 'lib/HDLRuby/hruby_high.rb', line 1778

def typedef(name, &ruby_block)
    type = TypeGen.new(name,&ruby_block)
    if HDLRuby::High.in_system? then
        # Must be inside a scope.
        unless HDLRuby::High.top_user.is_a?(Scope) then
            raise AnyError, "A local type cannot be declared within a #{HDLRuby::High.top_user.class}."
        end
        define_singleton_method(name.to_sym) do |*args|
            if (args.size < ruby_block.arity) then
                # Not enough arguments get generic type as is.
                type
            else
                # There are arguments, specialize the type.
                gtype = type.generate(*args)
                # And add it as a local type of the system.
                HDLRuby::High.top_user.add_type(gtype)
            end
        end
    else
        define_method(name.to_sym) do |*args|
            if (args.size < ruby_block.arity) then
                # Not enough arguments, get generic type as is.
                type
            else
                # There are arguments, specialize the type.
                type.generate(*args)
            end
        end
    end
end