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.



3747
3748
3749
# File 'lib/HDLRuby/hruby_high.rb', line 3747

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.



3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
# File 'lib/HDLRuby/hruby_high.rb', line 3775

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.



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

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.



3733
3734
3735
3736
3737
3738
3739
3740
3741
# File 'lib/HDLRuby/hruby_high.rb', line 3733

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



1519
1520
1521
1522
1523
1524
# File 'lib/HDLRuby/hruby_high.rb', line 1519

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.



3708
3709
3710
3711
3712
3713
3714
3715
# File 'lib/HDLRuby/hruby_high.rb', line 3708

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)


3752
3753
3754
# File 'lib/HDLRuby/hruby_high.rb', line 3752

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

.in_system?Boolean

Tells if within a system type.

Returns:

  • (Boolean)


3728
3729
3730
# File 'lib/HDLRuby/hruby_high.rb', line 3728

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.



3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
# File 'lib/HDLRuby/hruby_high.rb', line 3524

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.



3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
# File 'lib/HDLRuby/hruby_high.rb', line 3547

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.



4323
4324
4325
# File 'lib/HDLRuby/hruby_high.rb', line 4323

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.



4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
# File 'lib/HDLRuby/hruby_high.rb', line 4336

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)


4328
4329
4330
4331
4332
# File 'lib/HDLRuby/hruby_high.rb', line 4328

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

.names_popObject

Pops from the name stack.



4318
4319
4320
# File 'lib/HDLRuby/hruby_high.rb', line 4318

def self.names_pop
    NameStack.pop
end

.names_pushObject

Pushes on the name stack.



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

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:



3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
# File 'lib/HDLRuby/hruby_high.rb', line 3808

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.



3720
3721
3722
3723
3724
3725
# File 'lib/HDLRuby/hruby_high.rb', line 3720

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)


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

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

.space_index(namespace) ⇒ Object

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



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

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

.space_insert(index, namespace) ⇒ Object

Inserts +namespace+ at +index+.



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

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

.space_popObject

Pops a namespace.



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

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



3657
3658
3659
3660
3661
3662
# File 'lib/HDLRuby/hruby_high.rb', line 3657

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.



3801
3802
3803
3804
# File 'lib/HDLRuby/hruby_high.rb', line 3801

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.



3688
3689
3690
# File 'lib/HDLRuby/hruby_high.rb', line 3688

def self.space_top
    Namespaces[-1]
end

.space_top=(top) ⇒ Object

sets the top namespace.



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

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.



3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
# File 'lib/HDLRuby/hruby_high.rb', line 3787

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.



3702
3703
3704
# File 'lib/HDLRuby/hruby_high.rb', line 3702

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.



1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
# File 'lib/HDLRuby/hruby_high.rb', line 1859

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



1847
1848
1849
1850
1851
1852
# File 'lib/HDLRuby/hruby_high.rb', line 1847

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



1793
1794
1795
# File 'lib/HDLRuby/hruby_high.rb', line 1793

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.



1836
1837
1838
1839
1840
# File 'lib/HDLRuby/hruby_high.rb', line 1836

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.



2929
2930
2931
# File 'lib/HDLRuby/hruby_high.rb', line 2929

def this
    RefThis.new
end

#typedef(name, &ruby_block) ⇒ Object

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



1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
# File 'lib/HDLRuby/hruby_high.rb', line 1801

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