Top Level Namespace

Defined Under Namespace

Modules: HDLRuby Classes: Array, CPU, CPUSimu, FalseClass, Float, Handshaker, Hash, Integer, MEI8, Numeric, Range, String, Symbol, TemplateExpander, TrueClass

Constant Summary collapse

Ns =

The various combinations of bit strings to test.

[ $n0,  $n1,  $n2,  $n3,  $n4,  $n5 ]
NNs =

NLs = [ $n0l, $n1l, $n2l, $n3l, $n4l, $n5l ]

[ $n0n, $n1n, $n2n, $n3n, $n4n, $n5n ]
Zs =
[ $z0,  $z1,  $z2,  $z3,  $z4,  $z5,  $z6 ]
Xs =

ZLs = [ $z0l, $z1l, $z2l, $z3l, $z4l, $z5l, $z6l ]

[ $x0,  $x1,  $x2,  $x3,  $x4,  $x5,  $x6 ]
Ms =

XLs = [ $x0l, $x1l, $x2l, $x3l, $x4l, $x5l, $x6l ]

[ $m0,  $m1,  $m2,  $m3,  $m4,  $m5,  $m6,  $m7 ]
STRs =

MLs = [ $m0l, $m1l, $m2l, $m3l, $m4l, $m5l, $m6l, $m7l ]

Ns + Zs + Xs + Ms

Constants included from HDLRuby::Low

HDLRuby::Low::Base, HDLRuby::Low::Bignum, HDLRuby::Low::FmI, HDLRuby::Low::Integer, HDLRuby::Low::Natural, HDLRuby::Low::Real, HDLRuby::Low::TruncersI, HDLRuby::Low::VERILOG_BASE_TYPES, HDLRuby::Low::VERILOG_REGS

Constants included from HDLRuby

HDLRuby::FIELDS_OF_REF, HDLRuby::FIELDS_TO_EXCLUDE, HDLRuby::FROM_BASICS_REFS, HDLRuby::Infinity, HDLRuby::REF_ARG_NAMES, HDLRuby::TO_BASICS, HDLRuby::TO_BASICS_TYPES, HDLRuby::TO_BASIC_NAMES, HDLRuby::VERSION

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HDLRuby::High::Std

_included_fixpoint, #before, channel, #channel, channel_instance, #channel_instance, channel_port, #channel_port, #configure_clocks, #decoder, #fsm, included, #initialize_lut, #make_2edge_clock, #make_clock, #pipeline, #reconf, #req_ack, #rst_req_ack, task, #task, task_instance, #task_instance, #with_counter

Methods included from HDLRuby::Low

v_string

Methods included from HDLRuby::Verilog

#name_to_verilog

Methods included from HDLRuby

basic_to_value, const_reduce, #error_manager, from_yaml, is_basic_HDLRuby?, #make_bit, show, show!, show?, uniq_name, value_to_basic, verbosity=

Class Method Details

.booting?Boolean

Tells HDLRuby has finised booting.

Returns:

  • (Boolean)


4832
4833
4834
# File 'lib/HDLRuby/hruby_high.rb', line 4832

def self.booting?
    false
end

.configure_highObject

Enters in HDLRuby::High mode.



4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
# File 'lib/HDLRuby/hruby_high.rb', line 4794

def self.configure_high
    if $HDLRuby_configure then
        # Already configured.
        return
    end
    # Now HDLRuby will be configured.
    $HDLRuby_configure = true
    include HDLRuby::High
    class << self
        # For main, missing methods are looked for in the namespaces.
        def method_missing(m, *args, &ruby_block)
            # print "method_missing in class=#{self.class} with m=#{m}\n"
            # Is the missing method an immediate value?
            value = m.to_value
            return value if value and args.empty?
            # puts "Universe methods: #{Universe.namespace.methods}"
            # Not a value, but maybe it is in the namespaces
            if Namespaces[-1].respond_to?(m) then
                # Yes use it.
                Namespaces[-1].send(m,*args,&ruby_block)
            else
                # puts "here: #{m}"
                # No, true error
                raise NotDefinedError, "undefined HDLRuby construct, local variable or method `#{m}'."
            end
        end
    end

    # Initialize the this.
    set_this

    # Generate the standard signals
    $clk = Universe.scope.inner :__universe__clk__
    $rst = Universe.scope.inner :__universe__rst__



    # Tells HDLRuby has finised booting.
    def self.booting?
        false
    end
end

Instance Method Details

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



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/HDLRuby/high_samples/paper_after.rb', line 5

def after(number, clk = $clk, rst = $rst, &code)
    if in_behavior? and cur_behavior.on_edge? then
        counter = HDLRuby.uniq_name
        counter = [Math::log2(number).to_i+1].inner counter
        hif(rst) { counter <= 0 }
        helsif(counter < number) do
            counter <= counter + 1
        end
        # hif(counter >= number) { code.call }
        hif(counter >= number) { instance_eval(&code) }
    else
        counter = HDLRuby.uniq_name
        cur_system.open do
            counter = [Math::log2(number).to_i+1].inner counter
            par(clk.posedge,rst.posedge) do
                hif(rst) { counter <= 0 }
                helse { counter <= counter + 1 }
            end
        end
        # hif(counter >= number) { code.call }
        hif(counter >= number) { instance_eval(&code) }
    end
end

#bwObject

Module generating a neuron bias or weight. Params:

  • +typ+: the data type of the neural signals.
  • +init_bw+: initial value of the bias/weight.


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/HDLRuby/hdr_samples/neural/bw.rb', line 6

system :bw do |typ,init_bw|
    # The control signals.
    input :clk, :reset    # Clock and reset
    input :select_initial # Initialization of the bias/weight
    input :select_update  # Update of the bias/weight

    # Update of the bias/weight
    typ.input :dbw
    # Output of the bias/weight
    typ.output :bwo

    # Behavior controlling the bias/weight
    par(clk.posedge) do
        hif(reset == 1) { bwo <= 0 }
        helsif(select_initial == 1) { bwo <= init_bw }
        helsif(select_update == 1)  { bwo <= bwo+dbw }
    end
end

#connect8(i0, i1, i2, i3, i4, i5, i6, i7, o0, o1, o2, o3, o4, o5, o6, o7) ⇒ Object



2
3
4
5
6
7
8
9
10
11
12
# File 'lib/HDLRuby/hdr_samples/with_to_array.rb', line 2

def connect8(i0,i1,i2,i3,i4,i5,i6,i7,
             o0,o1,o2,o3,o4,o5,o6,o7)
    o0 <= i0
    o1 <= i1
    o2 <= i2
    o3 <= i3
    o4 <= i4
    o5 <= i5
    o6 <= i6
    o7 <= i7
end

#counterObject

Module generating the sample counter. Params:

  • +num+: the number of samples.


5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/HDLRuby/hdr_samples/neural/counter.rb', line 5

system :counter do |typ,num|
    # The input control signals.
    input :clk, :reset
    # The output counter.
    typ.output :out

    par(clk.posedge) do
        hif(reset == 1) { out <= 0 }
        helsif(out == num-1) { out <= 0 }
        helse { out <= out+1 }
    end
end

#eName2Exp(name) ⇒ Object

Generate an expression from a signal or constant name



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/HDLRuby/test_hruby_low.rb', line 258

def eName2Exp(name)
    # puts "eName2Exp with name=#{name}"
    ref = $refs.find do |ref|
        if ref.ref.respond_to?(:name) then
            ref.ref.name == name.to_sym
        else
            ref.name == name.to_sym
        end
    end
    # puts "ref=#{ref}"
    unless ref
        return Value.new($bit8,name.to_i)
    end
    return ref
end

#forwardObject

Module Generating a foward propagation structure of a NN. Params:

  • +typ+: the data type for standard computations.
  • +arch+: the architecture of the NN as a array of columns sizes
  • +samps+: the NN input and expected outputs samples as a 3D array
  • +b_init+:the bias initial values as a 2D array
  • +w_init+:the weights initial values as a 3D array
  • +actP+: the activation proc, default: ReLU
  • +sopP+: the sum of production function, default: basic operators


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
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/HDLRuby/hdr_samples/neural/forward.rb', line 19

system :forward do |typ,arch,samps,b_init,w_init,
                    actP = proc { |z| mux(z < 0, 0, z) },
                    sopP = proc do |xs,ws| 
                        xs.zip(ws).map{ |x,w| x*w }.reduce(:+)
                    end |
    ###
    # The interface signals

    # The control signals
    input :clk, :reset
    input :din, :select_initial
    # The input signals for updating of the weights and biases,
    # and the output signals giving the corresponding current values.
    cap_bs = []
    bs = []
    cap_ws = []
    ws = []
    arch[1..-1].each.with_index do |col,i|
        cap_bs << []
        bs << []
        # The biase update inputs and value outputs
        col.times do |j| 
            cap_bs[-1] << ( typ.input  :"cap_b#{i+1}_#{j+1}" )
            bs[-1] <<     ( typ.output :"b#{i+1}_#{j+1}"     )
        end
        # The weigh update inputs and value outputs
        cap_ws << []
        ws << []
        col.times do |j0|
            cap_ws[-1] << []
            ws[-1] << []
            arch[i].times do |j1|
                cap_ws[-1][-1] << ( typ.input  :"cap_w#{i+1}_#{j0+1}#{j1+1}" )
                ws[-1][-1] <<     ( typ.output :"w#{i+1}_#{j0+1}#{j1+1}"     )
            end
        end
    end
    # The output signals giving each neuron output.
    as = []
    arch[1..-1].each.with_index do |col,i|
        as << []
        col.times do |j|
            as[-1] << ( typ.output :"a#{i+1}_#{j+1}" )
        end
    end
    # The output signals indicating the current NN input and expected
    # answer (they are provided by an inner memory).
    ks = []
    arch[0].times do |i|
        # NN input
        ks << ( typ.output :"k#{i+1}" )
    end
    ts = []
    arch[-1].times do |i|
        # NN expected answer
        ts << ( typ.output :"t#{i+1}" )
    end

    ###
    # The inner signals

    # The control signals
    inner :select_update
    typedef(:outT) { [Math::log2(samps[0][0].size).ceil] } # Sample counter type
    outT.inner :out

    # The neurons sum results.
    zs = []
    arch[1..-1].each.with_index do |col,i|
        zs << []
        col.times do |j|
            zs[-1] << ( typ.inner :"z#{i+1}_#{j+1}" )
        end
    end

    ###
    # The structural description (instantiation of thre neuron computation
    # systems)

    # Sample counter
    counter(outT,samps[0][0].size).(:counterI).(clk, reset, out)

    # Neuron update selector, the skip size is (NN depth)*4+1
    # (4-cycle neurons and one addition sync cycle).
    selector(arch.size*4+1).(:selectorI).(clk, reset, select_update)

    # Input and expected output memories
    arch[0].times do |i|
        # Samples for input i
        mem(typ,outT,samps[0][i]).(:"k#{i+1}I").(clk, din, out, ks[i])
    end
    arch[-1].times do |i|
        # Expected values for output i
        mem(typ,outT,samps[1][i]).(:"t#{i+1}I").(clk, din, out, ts[i])
    end

    # Biases and weights
    arch[1..-1].each.with_index do |col,i|
        # Biases
        col.times do |j|
            bw(typ,b_init[i][j]).
                (:"b#{i+1}_#{j+1}I").(clk, reset, cap_bs[i][j],
                    select_initial, select_update, bs[i][j])
        end
        # Weights
        col.times do |j0|
            arch[i].times do |j1|
                bw(typ,w_init[i][j0][j1]).
                    (:"w#{i+1}_#{j0+1}#{j1+1}I").(clk,reset,cap_ws[i][j0][j1],
                    select_initial, select_update, ws[i][j0][j1])
            end
        end
    end

    # Weighted Sums
    # First column
    arch[1].times do |j|
        z(typ,ks.size,sopP).(:"z2_#{j+1}I").
            (clk, reset, *ks, *ws[0][j], bs[0][j], zs[0][j])
    end
    # Other columns
    arch[2..-1].each.with_index do |col,i|
        col.times do |j|
            z(typ,as[i].size,sopP).(:"z#{i+3}_#{j+1}I").
                (clk, reset, *as[i], *ws[i+1][j], bs[i+1][j], zs[i+1][j])
        end
    end

    # Activations
    arch[1..-1].each.with_index do |col,i|
        col.times do |j|
            a(typ,actP).(:"a#{i+1}_#{j+1}I").(clk, reset, zs[i][j], as[i][j])
        end
    end
end

#forward_subObject

A fully specified forward module with 8.24-bit fixed point computation and 4.4bit table-based sigmoid activation function. Structure: 2 inputs, one 3-column hidden layer and 2 outputs.



9
10
11
12
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/HDLRuby/hdr_samples/neural/forward_sub.rb', line 9

system :forward_sub, forward(
    signed[31..0],   # Data type
    [2,3,2], # NN structure
    [
        # Input samples.
          # First input.
        [[_sh08000000, _sh08000000, _sh05000000, _sh05000000, 
          *([_sh00000000]*28)],
          # Second input.
         [_sh08000000, _sh05000000, _sh08000000, _sh05000000,
          *([_sh00000000]*28)]],
        # Expected outputs
          # First output
        [[_sh01000000, _sh00000000, _sh00000000, _sh00000000, 
          *([_sh00000000]*28)],
          # Second output
         [_sh00000000, _sh01000000, _sh01000000, _sh01000000,
          *([_sh00000000]*28)]]
    ],
    # Biases initial values
    [
        # Second column
        [_shFF000000, _shFF000000, _shFF000000],
        # Third column
        [_shFF000000, _shFF000000]
    ],
    # Weights initial values
    [
        # Second column
        [
            # First neuron
            [ _sh00199999, _sh00666666 ],
            # Second neuron
            [ _sh004CCCCC, _sh00800000 ],
            # Third neuron
            [ _sh00999999, _sh00199999 ]
        ],
        # Third column
        [
            # First neuron
            [ _sh00B33333, _sh00333333, _sh0014CCCC ],
            # Second neuron
            [ _sh00333333, _sh00800000, _sh01199999 ]
        ]
    ],
    # The activation function.
    proc{|addr| sigmoid(8,4,32,24,addr)},
    # The sum of production function.
    proc do |xs,ws|
        (xs.zip(ws).map { |x,w| x*w }.reduce(:+))[27..20]
    end
) do
end

#hello_mix(u, v, w) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/HDLRuby/high_samples/functions.rb', line 10

def hello_mix(u,v,w)
    puts "hello_mix"
    par do
        inner :something
        w <= u - v
    end
end

#hello_outObject



6
7
8
# File 'lib/HDLRuby/high_samples/functions.rb', line 6

def hello_out
    puts "hello_out"
end

#make_reg(name, &blk) ⇒ Object

Function generating a register declaration.



123
124
125
126
127
128
129
130
131
132
# File 'lib/HDLRuby/high_samples/registers.rb', line 123

def make_reg(name,&blk)
    system name do |*arg|
        input :clk, :rst
        blk.(*arg).input :d
        blk.(*arg).output :q,:qb

        qb <= ~q
        (q <= d & [~rst]*blk.(*arg).width).at(clk.posedge)
    end
end

#make_reg_body(typ) ⇒ Object

Function generating the body of a register description.



87
88
89
90
91
92
93
94
# File 'lib/HDLRuby/high_samples/registers.rb', line 87

def make_reg_body(typ)
    input :clk, :rst
    typ.input :d
    typ.output :q,:qb

    qb <= ~q
    (q <= d & [~rst]*typ.width).at(clk.posedge)
end

#memObject

Module generating a lookup table memory. Params:

  • +inT+: the data type of the input (address).
  • +outT+: the data type of the output (data).
  • +ar+: the contents of the memory as an array.


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/HDLRuby/hdr_samples/neural/mem.rb', line 7

system :mem do |inT,outT,ar|
    # The control signals.
    input :clk # Clock
    input :din # Read enable

    # The interface signals.
    inT.input   :addr  # Address
    outT.output :data  # Data

    # The memory.
    outT[ar.size].inner :contents

    # Fills the memory (static)
    # ar.each.with_index do |val,i|
    #     contents[i] <= val
    # end
    contents <= ar

    # Handle the access to the memory.
    par(clk.posedge) do
        hif(din == 1) { data <= contents[addr] }
        helse         { data <= :"_#{"z"*outT.width}" }
    end
end

#rand_array(geometry, width) ⇒ Object

Generates a N-dimension array described by +geometry+ filled with +width+ bit values.



8
9
10
11
12
13
14
15
16
# File 'lib/HDLRuby/hdr_samples/neural/random.rb', line 8

def rand_array(geometry,width)
    if geometry.is_a?(Array) then
        # Geometry is hierarchical, recurse on it.
        return geometry.map {|elem| rand_array(elem,width) }
    else
        # Geometry is a size of a 1-D array, generate it.
        return geometry.times.map { |i| rand_signed(width) }
    end
end

#rand_signed(width) ⇒ Object

Generate a +width+ bit (signed) random value.



2
3
4
# File 'lib/HDLRuby/hdr_samples/neural/random.rb', line 2

def rand_signed(width)
    :"_s#{width.times.map { Random.rand(0..1).to_s }.join }".to_expr
end

#selectorObject

Module generating the selector that decides if a neuron is to update or not. Params:

  • +skip+: the number of clocks to skip.


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/HDLRuby/hdr_samples/neural/selector.rb', line 5

system :selector do |skip|
    input :clk, :reset
    output :enable_update

    # The clock counter.
    [Math::log2(skip).ceil].inner :counter

    # The behavior handling the skip counter
    par(clk.posedge) do
        hif(reset == 1) { counter <= 0 }
        helse do
            hif(counter == skip-1) { counter <=0 }
            helse        {counter <= counter + 1 }
        end
    end

    # The behavior handling the update signal
    par(clk.posedge) do
        hif(reset == 1) { enable_update <= 0 }
        helse do
            hif(counter == skip-1) { enable_update <= 1 }
            helse                  { enable_update <= 0 }
        end
    end
end

#sigmoid(a_width, a_point, d_width, d_point, addr) ⇒ Object



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/HDLRuby/hdr_samples/neural/sigmoid.rb', line 1

def sigmoid(a_width, a_point, d_width, d_point, addr)
   # Initialize the result to force it as a ruby variable.
    High.cur_system.open do
      sub do
         # Generates the rom
         [d_width][2**a_width].inner :contents
         contents <= (2**a_width).times.map do |i|
            # Converts i to a float
            i = i.to_f * 2**(-a_point)
            # Compute the sigmoid
            sigm = (1.0 / (1+Math.exp(i)))
            # Convert it to fixed point
            (sigm * 2**d_point).to_i
         end

         # Use it for the access
         contents[addr[(a_point+d_width-1-d_point)..a_point-d_point]]
      end
   end
end

#times_loop(clk_e, num, &ruby_block) ⇒ Object

Loop +num+ times executing +ruby_block+. The loop is synchronized on +clk_e+.



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/HDLRuby/std/loop.rb', line 91

def times_loop(clk_e, num, &ruby_block)
    # Compute the width of the counter.
    width = num.respond_to?(:width) ? num.width : num.type.width
    # Declares the counter.
    cnt = [width].inner(HDLRuby.uniq_name)
    # Create the loop.
    return while_loop(clk_e, proc{cnt<=0}, cnt<num) do
        cnt <= cnt + 1
        ruby_block.call
    end
end

#which(cmd) ⇒ Object

Locate an executable from cmd.



256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/HDLRuby/hdrcc.rb', line 256

def which(cmd)
    # Get the possible exetensions (for windows case).
    exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
    # Look for the command within the executable paths.
    ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
        exts.each do |ext|
            exe = File.join(path, "#{cmd}#{ext}")
            return exe if File.executable?(exe) && !File.directory?(exe)
        end
    end
    nil
end

#while_loop(clk_e, init, condition = nil, &ruby_block) ⇒ Object

A simplified loop: loops until +condition+ is met execution +ruby_block+. The loop is synchronized on +clk_e+ and initialized by +init+. If +condition+ is nil, then +init+ is used as +condition+.



80
81
82
83
84
85
86
87
# File 'lib/HDLRuby/std/loop.rb', line 80

def while_loop(clk_e, init, condition = nil, &ruby_block)
    # Create the loop task.
    tsk = while_task(clk_e,init,condition,ruby_block).(HDLRuby.uniq_name)
    # Create the inner access port.
    prt = tsk.inner HDLRuby.uniq_name
    # Return the access port.
    return prt
end

#while_taskObject

While loop: loops until +condition+ is met execution +ruby_block+. The loop is synchronized on +clk_e+ and initialized by +init+. If +condition+ is nil, then +init+ is used as +condition+.



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
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
# File 'lib/HDLRuby/std/loop.rb', line 13

HDLRuby::High::Std.task(:while_task) do |clk_e, init, condition, ruby_block|
    # Ensure clk_e is an event, if not set it to a positive edge.
    clk_e = clk_e.posedge unless clk_e.is_a?(Event)

    # Ensures there is a condition.
    unless condition then
        condition = init
        init = nil
    end

    # Transform condition into a proc if it is not the case.
    unless condition.is_a?(Proc) then
        condition_expr = condition
        condition = proc { condition_expr }
    end

    # Ensures init to be a proc if not nil
    init = init.to_proc unless init == nil

    # Declares the signals for controlling the loop.
    inner :req  # Signal to set to 1 for running the loop.

    # Declares the runner signals.
    runner_output :req

    par(clk_e) do
        # Performs the loop.
        hif(req) do
            # By default the loop is not finished.
            # If the condition is still met go on looping.
            hif(condition.call,&ruby_block)
        end
        # # if (init) then
        # #     # There is an initialization, do it when there is no req.
        # #     helse do
        # #         init.call
        # #     end
        # # end
    end

    # The code for reseting the task.
    if (init) then
        # reseter(&init)
        reseter do
            req <= 0
            init.call
        end
    end

    # The code for running the task.
    runner do
        # top_block.unshift { req <= 0 }
        req <= 1
    end

    # The code for checking the end of execution.
    finisher do |blk|
        hif(~condition.call,&blk)
    end

end

#xcd_generator(top, path) ⇒ Object

Generates a xcd file from the HDLRuby objects from +top+ using their 'xcd' properties. The file is saved in +path+ directory.



11
12
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
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
# File 'lib/HDLRuby/drivers/xcd.rb', line 11

def xcd_generator(top, path)
    # Ensure top is a system.
    if top.is_a?(HDLRuby::Low::SystemI) then
        top = top.systemT
    elsif !top.is_a?(HDLRuby::Low::SystemT) then
        raise "The 'xcd_generator' driver can only be applied on SystemT objects."
    end

    # Get the name of the resulting file if any.
    if (top.properties.key?(:xcd_file)) then
        xcd_file = top.properties[:xcd_file].join
    else
        # Default file name.
        xcd_file = "default.xcd"
    end

    # Get the target template.
    xcd_target       = top.properties[:xcd_target].join
    xcd_target_name  = xcd_target
    xcd_target_name += ".xcd" unless xcd_target_name.end_with?(".xcd")
    xcd_target_tries = [ xcd_target_name,
                         File.join(path,xcd_target_name),
                         File.join(File.dirname(__FILE__),"xcd",xcd_target_name) ]
    xcd_target_file = xcd_target_tries.find { |fname| File.exist?(fname) }
    unless xcd_target_file then
        raise "XCD target template not found for #{xcd_target}."
    end
    # Load the template.
    template = File.read(xcd_target_file)

    # Gather the signals by xcd key.
    xcd2sig = top.each_signal.reduce([]) do |ar,sig|
        ar += sig.properties.each_with_key(:xcd).map do |val|
            [val,sig.name.to_s]
        end
    end

    # Create the template expander that will generate the xcd file.
    expander = TemplateExpander.new([
        [ /^\?.*(\n|\z)/, proc do |str| # Signal link to port
            if xcd2sig.any? do |match,rep|
                if str.include?(match) then
                    str = str.gsub("<>",rep)[1..-1]
                else
                    false
                end
            end then
            str
            else
                ""
            end
        end ]
    ])

    # # Generate the xcd file.
    # File.open(File.join(path,xcd_file),"w") do |file|
    #     # Generate the signals mapping.
    #     top.each_signal do |signal|
    #         signal.properties.each_with_key(:xcd) do |value|
    #             file << "#{value}\n"
    #         end
    #     end
    # end
    
    # Generate the xcd file.
    File.open(File.join(path,xcd_file),"w") do |file|
        expander.expand(template,file)
    end
end

#zObject

Module generating a neuron sum. Params:

  • +typ+: the data type of the neural signals.
  • +ary+: the arity of the neuron.
  • +sopP+: the sum of product function.


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/HDLRuby/hdr_samples/neural/z.rb', line 7

system :z do |typ,ary,sopP|
    # The control signals.
    input :clk, :reset    # Clock and reset

    # The inputs of the neuron.
    ins = []
    wgs = []
    ary.times do |i|
        # The input values
        ins << typ.input(:"x#{i}")
    end
    ary.times do |i|
        # The weights
        wgs << typ.input(:"w#{i}")
    end
    # The bias
    typ.input :bias

    # The sum output
    typ.output :z

    # Behavior controlling the bias/weight
    par(clk.posedge) do
        hif(reset == 1) { z <= 0 }
        helse           { z <= sopP.(ins + [1],wgs + [bias]) }
    end
end