Module: HDLRuby::High::Std

Defined in:
lib/HDLRuby/std/clocks.rb,
lib/HDLRuby/std/linear.rb,
lib/HDLRuby/std/reconf.rb,
lib/HDLRuby/std/channel.rb,
lib/HDLRuby/std/decoder.rb,
lib/HDLRuby/std/counters.rb,
lib/HDLRuby/std/fixpoint.rb,
lib/HDLRuby/std/pipeline.rb,
lib/HDLRuby/std/connector.rb,
lib/HDLRuby/std/function_generator.rb,
lib/HDLRuby/std/task.rb,
lib/HDLRuby/std/fsm.rb

Defined Under Namespace

Modules: HchannelI Classes: ChannelB, ChannelI, ChannelPort, ChannelPortA, ChannelPortB, ChannelPortObject, ChannelPortR, ChannelPortW, ChannelT, DecoderT, FsmT, PipelineT, ReconfI, ReconfT, TaskI, TaskPortA, TaskPortS, TaskPortSA, TaskT

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._included_fixpointObject



10
# File 'lib/HDLRuby/std/fixpoint.rb', line 10

alias_method :_included_fixpoint, :included

.channel(name, &ruby_block) ⇒ Object

Creates a new channel type named +name+ whose instances are creating executing +ruby_block+.



62
63
64
# File 'lib/HDLRuby/std/channel.rb', line 62

def self.channel(name,&ruby_block)
    return ChannelT.new(name,&ruby_block)
end

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

Creates directly an instance of channel named +name+ using +ruby_block+ built with +args+.



74
75
76
77
# File 'lib/HDLRuby/std/channel.rb', line 74

def self.channel_instance(name,*args,&ruby_block)
    # return ChannelT.new(:"",&ruby_block).instantiate(name,*args)
    return self.channel(:"",&ruby_block).instantiate(name,*args)
end

.channel_port(obj) ⇒ Object

Wrap object +obj+ to act like a channel port.



1412
1413
1414
1415
# File 'lib/HDLRuby/std/channel.rb', line 1412

def self.channel_port(obj)
    return obj if obj.is_a?(ChannelPort) # No need to wrap.
    return ChannelPortObject.new(obj)
end

.included(base) ⇒ Object

Redefines the include to add fixed point generation through the Type class.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
# File 'lib/HDLRuby/std/fixpoint.rb', line 15

def self.included(base)
    # Performs the previous included
    res = self.send(:_included_fixpoint,base)
    # Now modify the Type class if not already modified.
    unless ::HDLRuby::High::Type.instance_methods.include?(:"_[]_fixpoint") then
        ::HDLRuby::High::Type.class_eval do
            # Saves the former type generation method.
            alias_method :"_[]_fixpoint", :[]

            # Redefine the type generation method for supporting fixed point
            # type generation.
            def [](*args)
                if args.size == 1 then
                    return self.send(:"_[]_fixpoint",*args)
                else
                    # Handle the arguments and compute the fix point sizes.
                    arg0,arg1 = *args
                    if arg0.respond_to?(:to_i) then
                        isize = arg0
                    else
                        isize = (arg0.first-arg0.last).abs+1
                    end
                    if arg1.respond_to?(:to_i) then
                        fsize = arg1
                    else
                        fsize = (arg1.first-arg1.last).abs+1
                    end
                    # Build the type.
                    case(self.name)
                    when :bit
                        typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
                    when :unsigned
                        typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
                    when :signed
                        typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
                    else
                        raise "Invalid type for generating a fixed point type: #{self.name}"
                    end
                    # Redefine the multiplication and division for fixed point.
                    typ.define_operator(:*) do |left,right|
                        if (typ.signed?) then
                            (left.as(signed[isize+fsize*2])*right) >> fsize
                        else
                            (left.as([isize+fsize*2])*right) >> fsize
                        end
                    end
                    typ.define_operator(:/) do |left,right|
                        if (typ.signed?) then
                            (left.as(signed[isize+fsize*2]) << fsize) / right
                        else
                            (left.as([isize+fsize*2]) << fsize) / right
                        end
                    end
                    # Define the removal of the point.
                    typ.define_singleton_method(:no_point) do
                        if (typ.signed?) then
                            signed[typ.width]
                        else
                            bit[typ.width]
                        end
                    end
                    # Return the resulting typ.
                    typ
                end
            end
            return res
        end
    end
end

.task(name, &ruby_block) ⇒ Object

Creates a new task type named +name+ whose instances are creating executing +ruby_block+.



60
61
62
# File 'lib/HDLRuby/std/task.rb', line 60

def self.task(name,&ruby_block)
    return TaskT.new(name,&ruby_block)
end

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

Creates directly an instance of task named +name+ using +ruby_block+ built with +args+.



72
73
74
75
# File 'lib/HDLRuby/std/task.rb', line 72

def self.task_instance(name,*args,&ruby_block)
    # return TaskT.new(:"",&ruby_block).instantiate(name,*args)
    return self.task(:"",&ruby_block).instantiate(name,*args)
end

Instance Method Details

#after(init, rst = $rst, clk = $clk, &code) ⇒ Object

Sets a counter to +init+ when +rst+ is 1 that is decreased according to +clk+. When this counter reaches 0, +code+ is executed. When not within a block, a behavior will be created which is activated on the rising edge of +clk+.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/HDLRuby/std/counters.rb', line 65

def after(init, rst = $rst, clk = $clk, &code)
    with_counter(init,rst,clk) do |counter|
        seq do
            hif(rst.to_expr == 1) do
                counter.to_ref <= init.to_expr
            end
            helsif(counter.to_expr == 0) do
                # code.call
                instance_eval(&code)
            end
            helse do
                counter.to_ref <= counter.to_expr - 1
            end
        end
    end
end

#before(init, rst = $rst, clk = $clk, &code) ⇒ Object

Sets a counter to +init+ when +rst+ is 1 that is decreased according to +clk+. As long as this counter does not reach 0, +code+ is executed. When not within a block, a behavior will be created which is activated on the rising edge of +clk+.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/HDLRuby/std/counters.rb', line 45

def before(init, rst = $rst, clk = $clk, &code)
    with_counter(init,rst,clk) do |counter|
        seq do
            hif(rst.to_expr == 1) do
                counter.to_ref <= init.to_expr
            end
            helsif(counter.to_expr != 0) do
                counter.to_ref <= counter.to_expr - 1
                # code.call
                instance_eval(&code)
            end
        end
    end
end

#channel(name, &ruby_block) ⇒ Object

Creates a new channel type named +name+ whose instances are creating executing +ruby_block+.



68
69
70
# File 'lib/HDLRuby/std/channel.rb', line 68

def channel(name,&ruby_block)
    HDLRuby::High::Std.channel(name,&ruby_block)
end

#channel_instance(name, *args, &ruby_block) ⇒ Object

Creates directly an instance of channel named +name+ using +ruby_block+ built with +args+.



81
82
83
# File 'lib/HDLRuby/std/channel.rb', line 81

def channel_instance(name,*args,&ruby_block)
    HDLRuby::High::Std.channel_instance(name,*args,&ruby_block)
end

#channel_port(obj) ⇒ Object



1416
1417
1418
# File 'lib/HDLRuby/std/channel.rb', line 1416

def channel_port(obj)
    return HDLRuby::High::Std.channel_port(obj)
end

#configure_clocks(rst = $rst) ⇒ Object

Initialize the clock generator with +rst+ as reset signal.



10
11
12
# File 'lib/HDLRuby/std/clocks.rb', line 10

def configure_clocks(rst = $rst)
    @@__clocks_rst = rst
end

#decoder(*args, &ruby_block) ⇒ Object

Declare a new decoder. The arguments can be any of (but in this order):

  • +name+:: name.
  • +expr+:: the expression to decode.

If provided, +ruby_block+ the fsm is directly instantiated with it.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/HDLRuby/std/decoder.rb', line 194

def decoder(*args, &ruby_block)
    # Sets the name if any
    unless args[0].respond_to?(:to_expr) then
        name = args.shift.to_sym
    else
        name = :""
    end
    # Create the decoder.
    decoderI = DecoderT.new(name)

    # Is there a ruby block?
    if ruby_block then
        # Yes, generate the decoder.
        decoderI.build(*args,&ruby_block)
    else
        # No return the decoder structure for later generation.
        return decoderI
    end
end

#fsm(*args, &ruby_block) ⇒ Object

Declare a new fsm. The arguments can be any of (but in this order):

  • +name+:: name.
  • +clk+:: clock.
  • +event+:: clock event.
  • +rst+:: reset. (must be declared AFTER clock or clock event).

If provided, +ruby_block+ the fsm is directly instantiated with it.



486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/HDLRuby/std/fsm.rb', line 486

def fsm(*args, &ruby_block)
    # Sets the name if any
    unless args[0].respond_to?(:to_event) then
        name = args.shift.to_sym
    else
        name = :""
    end
    # Get the options from the arguments.
    options, args = args.partition {|arg| arg.is_a?(Symbol) }
    # Create the fsm.
    fsmI = FsmT.new(name,*options)
    
    # Process the clock event if any.
    unless args.empty? then
        fsmI.for_event(args.shift)
    end
    # Process the reset if any.
    unless args.empty? then
        fsmI.for_reset(args.shift)
    end
    # Is there a ruby block?
    if ruby_block then
        # Yes, generate the fsm.
        fsmI.build(&ruby_block)
    else
        # No return the fsm structure for later generation.
        return fsmI
    end
end

#initialize_lut(func, otyp, awidth, xrange, yrange) ⇒ Array

Make an array consists of a point of any activation function.

Parameters:

  • lut_size (Integer)

    the lut_size of LUT

Returns:

  • (Array)

    table an array consists of a point of tanh



125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/HDLRuby/std/function_generator.rb', line 125

def initialize_lut(func, otyp, awidth, xrange, yrange)
    # Compute the x step between discret values.
    xstep = (xrange.last-xrange.first)/(2 ** awidth)

    # Generate the discrete set of x values.
    x_values = xrange.step(xstep)
    # Generate the table.
    table = x_values.map do |x_value|
        ((func.call(x_value)-yrange.first)/(yrange.last-yrange.first)*
         2**otyp.width).to_i.to_expr.as(otyp)
    end

    return table
end

#make_2edge_clock(event, times) ⇒ Object

Creates a clock inverted every +times+ occurence of an +event+ and its everted.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/HDLRuby/std/clocks.rb', line 84

def make_2edge_clock(event,times)
    clock = nil # The resulting clock

    # Enters the current system
    HDLRuby::High.cur_system.open do
        # Ensure times is a value.
        times = times.to_value

        # Create the event counter.
        # Create the name of the counter.
        name = HDLRuby.uniq_name
        # Declare the counter.
        [times.width].inner(name)
        # Get the signal of the counter.
        counter = get_inner(name)

        # Create the inverted event counter.
        # Create the name of the counter.
        name = HDLRuby.uniq_name
        # Declare the counter.
        [times.width].inner(name)
        # Get the signal of the counter.
        counter_inv = get_inner(name)

        # Create the clock.
        # Create the name of the clock.
        name = HDLRuby.uniq_name
        # Declare the clock.
        bit.inner(name)
        # Get the signal of the clock.
        clock = get_inner(name)

        # Control the event counter
        par(event) do
            hif(@@__clocks_rst | counter.to_expr == 0) do
                counter.to_ref <= times.to_expr/2 + 1
            end
        end
        # Control the inverteed event counter
        par(event.invert) do
            hif(@@__clocks_rst | counter_inv.to_expr == 0) do
                counter_inv.to_ref <= times.to_expr/2 + 1
            end
        end
        # Compute the clock.
        clock.to_ref <= (counter.to_expr == times.to_expr/2 + 1) |
            (counter_inv.to_expr == times.to_expr/2 + 1)
    end
    # Return it.
    return clock
end

#make_clock(event, times) ⇒ Object

Create a clock inverted every +times+ occurence of an +event+.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/HDLRuby/std/clocks.rb', line 15

def make_clock(event, times)
    clock = nil # The resulting clock

    # Enters the current system
    HDLRuby::High.cur_system.open do

        # Ensures times is a value.
        times = times.to_value

        # Create the counter.
        # Create the name of the counter.
        name = HDLRuby.uniq_name
        # Declare the counter.
        [times.width].inner(name)
        # Get the signal of the counter.
        counter = get_inner(name)

        # Create the clock.
        # Create the name of the clock.
        name = HDLRuby.uniq_name
        # Declares the clock.
        bit.inner(name)
        # Get the signal of the clock.
        clock = get_inner(name)
        
        # Control it.
        par(event) do
            hif(@@__clocks_rst) do
                counter.to_ref <= times.to_expr
                clock.to_ref <= 0
            end
            helsif(counter.to_expr == 0) do
                counter.to_ref <= times.to_expr 
                clock.to_ref <= ~ clock.to_expr
            end
            helse do
                counter.to_ref <= counter.to_expr + 1
            end
        end
    end
    return clock
end

#pipeline(name) ⇒ Object

Declare a new pipeline with +name+.



216
217
218
# File 'lib/HDLRuby/std/pipeline.rb', line 216

def pipeline(name)
    return PipelineT.new(name)
end

#reconf(name, &ruby_block) ⇒ Object

Creates a new reconfigurable component type named +name+ whose instances are creating executing +ruby_block+.



59
60
61
62
# File 'lib/HDLRuby/std/reconf.rb', line 59

def reconf(name,&ruby_block)
    # puts "reconf with ruby_block=#{ruby_block}"
    return ReconfT.new(name,&ruby_block)
end

#req_ack(clk_e, req, ack, port) ⇒ Object

Encapsulate a task for integrating a control with simple request and acknowledge (+ack+) signals, synchronised on +clk_e+. +port+ is assumed to return a TaskPortSA. If +clk_e+ is nil, work in asynchronous mode.



846
847
848
# File 'lib/HDLRuby/std/task.rb', line 846

def req_ack(clk_e,req,ack,port)
    rst_req_ack(clk_e,nil,req,ack,port)
end

#rst_req_ack(clk_e, rst, req, ack, port) ⇒ Object

Encapsulate a task for integrating a control with simple reset (+rst+), request and acknowledge (+ack+) signals, synchronised on +clk_e+. +port+ is assumed to return a TaskPortSA. If +clk_e+ is nil, work in asynchronous mode. If +rst+ is nil, no reset is handled.



814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
# File 'lib/HDLRuby/std/task.rb', line 814

def rst_req_ack(clk_e,rst,req,ack,port)
    if clk_e then
        # Ensures clk_e is an event.
        clk_e = clk_e.posedge unless clk_e.is_a?(Event)
        par(clk_e) do
            # Handle the reset.
            hif(rst) { port.reset } if rst
            ack <= 0
            # Control the start of the task.
            hif(req) { port.run }
            # Control the end of the task: set ack to 1.
            port.finish { ack <= 1 }
        end
    else
        par do
            # Handle the reset
            hif(rst) { port.reset } if rst
            # Control the start of the task.
            hif(req) { port.run }
            ack <= 0
            # Control the end of the task: set ack to 1.
            port.finish { ack <= 1 }
        end
    end
end

#task(name, &ruby_block) ⇒ Object

Creates a new task type named +name+ whose instances are creating executing +ruby_block+.



66
67
68
# File 'lib/HDLRuby/std/task.rb', line 66

def task(name,&ruby_block)
    HDLRuby::High::Std.task(name,&ruby_block)
end

#task_instance(name, *args, &ruby_block) ⇒ Object

Creates directly an instance of task named +name+ using +ruby_block+ built with +args+.



79
80
81
# File 'lib/HDLRuby/std/task.rb', line 79

def task_instance(name,*args,&ruby_block)
    HDLRuby::High::Std.task_instance(name,*args,&ruby_block)
end

#with_counter(init, rst = $rst, clk = $clk, &code) ⇒ Object

Sets a counter to +init+ when +rst+ is 1 that is decreased according to +clk+. +code+ will be applied on this counter. When not within a block, a behavior will be created which is activated on the rising edge of +clk+.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/HDLRuby/std/counters.rb', line 13

def with_counter(init, rst = $rst, clk = $clk, &code)
    # Are we in a block?
    if HDLRuby::High.top_user.is_a?(HDLRuby::High::SystemT) then
        # No, create a behavior.
        behavior(clk.posedge) do
            with_counter(init,rst,clk,&code)
        end
    else
        # Ensure init is a value.
        init = init.to_value
        # Creates the counter
        # counter = HDLRuby::High::SignalI.new(HDLRuby.uniq_name,
        #                           TypeVector.new(:"",bit,init.width),
        #                           :inner)
        # Create the name of the counter.
        name = HDLRuby.uniq_name
        # Declare the counter.
        [init.width].inner(name)
        # Get the signal of the counter.
        counter = HDLRuby::High.cur_block.get_inner(name)
        # Apply the code on the counter.
        # code.call(counter)
        instance_exec(counter,&code)
    end
end