Class: HDLRuby::High::Std::SequencerFunctionT

Inherits:
Object
  • Object
show all
Defined in:
lib/HDLRuby/std/sequencer_func.rb

Overview

Describes a sequencer function definition.

NOTE: like with ruby, functions does not have types for their arguments, their are set when the function is called. This is handle by the eigen functions (see SequencerFunctionE).

Constant Summary collapse

ZERO =
:_b0.to_value
ONE =
:_sb01.to_value

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, depth = nil, overflow = nil, &ruby_block) ⇒ SequencerFunctionT

Creates a new sequencer function named +name+, with stack size +depth+ executing code given by +ruby_block+. Additionaly a HDLRuby block +overflow+ can be added to be executed when a stack overflow occured.

NOTE: if +depth+ is nil it will be automatically computed at call time.



39
40
41
42
43
44
# File 'lib/HDLRuby/std/sequencer_func.rb', line 39

def initialize(name, depth = nil, overflow = nil, &ruby_block)
    @name = name.to_sym
    @body = ruby_block
    @depth = depth ? depth.to_i : nil
    @overflow = overflow ? overflow.to_proc : nil
end

Instance Attribute Details

#bodyObject (readonly)

The body of the function.



29
30
31
# File 'lib/HDLRuby/std/sequencer_func.rb', line 29

def body
  @body
end

#nameObject (readonly)

The name of the function.



26
27
28
# File 'lib/HDLRuby/std/sequencer_func.rb', line 26

def name
  @name
end

#overflowObject (readonly)

The stack overflow code of the function if any.



32
33
34
# File 'lib/HDLRuby/std/sequencer_func.rb', line 32

def overflow
  @overflow
end

Instance Method Details

#call(*args) ⇒ Object

Call the function with arguments +args+.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/HDLRuby/std/sequencer_func.rb', line 47

def call(*args)
    # Check if there are extra arguments, they are used for configuring
    # the stack.
    if args.size > @body.arity then
        # The first extra argument is the depth of the stack for this
        # specific call.
        @depth = args.delete_at(@body.arity)
    end

    # Specialize the function with the types of the arguments.
    # (the result is the eigen function of funcI).
    funcE = SequencerFunctionE.new(self, args.map {|arg| arg.type })
    # Check if it is a recursion.
    funcI = SequencerFunctionI.recursion(funcE)
    if funcI then
        # puts "Recursive call"
        # Recursion, set the size of the stack.
        funcI.make_depth(@depth)
        # Call the function.
        st_call = funcI.recurse_call(*args)
        # adds the return address.
        depth = funcI.depth
        stack_ptr = funcI.stack_ptr
        # st_call.gotos << proc do
        old_code = st_call.code
        st_call.code = proc do
            old_code.call
            HDLRuby::High.top_user.instance_exec do
                # hprint("returning with stack_ptr=",stack_ptr,"\n")
                hif(stack_ptr <= depth) do
                    # hprint("poking recursive return value at idx=",funcI.returnIdx," with value=",st_call.value+1,"\n")
                    funcI.poke(funcI.returnIdx,st_call.value + ONE)
                end
            end
        end
    else
        # puts "First call"
        # No recursion, create an instance of the function
        funcI = SequencerFunctionI.new(funcE)
        # Call the function.
        st_call = funcI.first_call(*args)
        # Build the function... Indeed after the call, that
        # allows to avoid one state.
        st_func = funcI.build
        # adds the return value.
        # st_call.gotos << proc do
        old_code = st_call.code
        st_call.code = proc do
            old_code.call
            HDLRuby::High.top_user.instance_exec do
                # hprint("poking return value at idx=",funcI.returnIdx," with value=",st_func.value+1,"\n")
                funcI.poke(funcI.returnIdx,st_func.value + ONE)
            end
        end
    end
    # Return the created funcI return value.
    return funcI.return_value
end