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.



3730
3731
3732
# File 'lib/HDLRuby/hruby_high.rb', line 3730

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.



3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
# File 'lib/HDLRuby/hruby_high.rb', line 3758

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.



3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
# File 'lib/HDLRuby/hruby_high.rb', line 3743

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.



3716
3717
3718
3719
3720
3721
3722
3723
3724
# File 'lib/HDLRuby/hruby_high.rb', line 3716

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+.



1512
1513
1514
1515
1516
1517
# File 'lib/HDLRuby/hruby_high.rb', line 1512

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.



3691
3692
3693
3694
3695
3696
3697
3698
# File 'lib/HDLRuby/hruby_high.rb', line 3691

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)


3735
3736
3737
# File 'lib/HDLRuby/hruby_high.rb', line 3735

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

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


3711
3712
3713
# File 'lib/HDLRuby/hruby_high.rb', line 3711

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.



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

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.



3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
# File 'lib/HDLRuby/hruby_high.rb', line 3530

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.



4306
4307
4308
# File 'lib/HDLRuby/hruby_high.rb', line 4306

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.



4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
# File 'lib/HDLRuby/hruby_high.rb', line 4319

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)


4311
4312
4313
4314
4315
# File 'lib/HDLRuby/hruby_high.rb', line 4311

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

.names_popObject

Pops from the name stack.



4301
4302
4303
# File 'lib/HDLRuby/hruby_high.rb', line 4301

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



4296
4297
4298
# File 'lib/HDLRuby/hruby_high.rb', line 4296

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:



3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
# File 'lib/HDLRuby/hruby_high.rb', line 3791

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.



3703
3704
3705
3706
3707
3708
# File 'lib/HDLRuby/hruby_high.rb', line 3703

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)


3661
3662
3663
# File 'lib/HDLRuby/hruby_high.rb', line 3661

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

.space_index(namespace) ⇒ Object

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



3666
3667
3668
# File 'lib/HDLRuby/hruby_high.rb', line 3666

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

.space_insert(index, namespace) ⇒ Object

Inserts +namespace+ at +index+.



3648
3649
3650
# File 'lib/HDLRuby/hruby_high.rb', line 3648

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

.space_popObject

Pops a namespace.



3653
3654
3655
3656
3657
3658
# File 'lib/HDLRuby/hruby_high.rb', line 3653

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+.



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

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.



3784
3785
3786
3787
# File 'lib/HDLRuby/hruby_high.rb', line 3784

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.



3671
3672
3673
# File 'lib/HDLRuby/hruby_high.rb', line 3671

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



3676
3677
3678
3679
3680
3681
# File 'lib/HDLRuby/hruby_high.rb', line 3676

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.



3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
# File 'lib/HDLRuby/hruby_high.rb', line 3770

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.



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

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.



1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
# File 'lib/HDLRuby/hruby_high.rb', line 1852

def function(name, &ruby_block)
    if HDLRuby::High.in_system? then
        define_singleton_method(name.to_sym) do |*args,&other_block|
            sub do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &ruby_block)
                # ruby_block.call(*args)
            end
        end
    else
        define_method(name.to_sym) do |*args,&other_block|
            sub do
                HDLRuby::High.top_user.instance_exec(*args,*other_block,
                                                     &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.



1840
1841
1842
1843
1844
1845
# File 'lib/HDLRuby/hruby_high.rb', line 1840

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+.



1786
1787
1788
# File 'lib/HDLRuby/hruby_high.rb', line 1786

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.



1829
1830
1831
1832
1833
# File 'lib/HDLRuby/hruby_high.rb', line 1829

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.



2912
2913
2914
# File 'lib/HDLRuby/hruby_high.rb', line 2912

def this
    RefThis.new
end

#typedef(name, &ruby_block) ⇒ Object

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



1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
# File 'lib/HDLRuby/hruby_high.rb', line 1794

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