Top Level Namespace

Defined Under Namespace

Modules: HDLRuby, RCSimCinterface Classes: Array, CPU, CPUSimu, FalseClass, Float, Handshaker, Hash, Integer, MEI8, Numeric, RCSimPointer, 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, #delay, #delayp, #fsm, #hs_client, #hs_pipe, #hs_server, 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?, show, show!, show?, uniq_name, value_to_basic, verbosity=

Class Method Details

.booting?Boolean

Tells HDLRuby has finised booting.

Returns:

  • (Boolean)


5226
5227
5228
# File 'lib/HDLRuby/hruby_high.rb', line 5226

def self.booting?
    false
end

.configure_highObject

Enters in HDLRuby::High mode.



5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
# File 'lib/HDLRuby/hruby_high.rb', line 5188

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

#hdr_codeObject



349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/HDLRuby/hdrlib.rb', line 349

def hdr_code
    # Gather the non-HDLRuby code.
    $top_system.each_systemT_deep do |systemT|
        systemT.scope.each_scope_deep do |scope|
            scope.each_code do |code|
                non_hdlruby << code
            end
        end
    end
    # Generates its code.
    $non_hdlruby.each {|code| code.to_file($output) }
end

#hdr_hdrObject



367
368
369
# File 'lib/HDLRuby/hdrlib.rb', line 367

def hdr_hdr
    puts $top_system.to_hdr
end

#hdr_load(input) ⇒ Object

Read some files.



324
325
326
327
328
329
330
331
332
333
# File 'lib/HDLRuby/hdrlib.rb', line 324

def hdr_load(input)
    # loader = HDRLoad.new($top,input,"./",*params)
    # loader.read_all
    # loader.check_all
    # # Not debug mode, use the error management.
    # error_manager(loader.requires + [input]) { top_instance = loader.parse }
    # $top_system = top_instance.to_low.systemT
    # $top_intance = nil # Free as much memory as possible.
    load(input)
end

#hdr_make(sys, params = []) ⇒ Object

Process a system for generation.



337
338
339
340
341
342
343
344
345
# File 'lib/HDLRuby/hdrlib.rb', line 337

def hdr_make(sys,params = [])
    if sys.is_a?(SystemI) then
        $top_system = sys.to_low.systemT
    elsif params.empty? then
        $top_system = sys.(HDLRuby.uniq_name).to_low.systemT
    else
        $top_system = sys.(*params).(HDLRuby.uniq_name).to_low.systemT
    end
end

#hdr_output(output = $output) ⇒ Object



314
315
316
317
318
319
# File 'lib/HDLRuby/hdrlib.rb', line 314

def hdr_output(output = $output)
    # Create a directory if necessary.
    unless File.directory?($output)
        FileUtils.mkdir_p($output)
    end
end

#hdr_simObject



371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
# File 'lib/HDLRuby/hdrlib.rb', line 371

def hdr_sim
    $top_system.each_systemT_deep do |systemT|
        HDLRuby.show "seq2seq step..."
        # Coverts the par blocks in seq blocks to seq blocks to match
        # the simulation engine.
        systemT.par_in_seq2seq!
        HDLRuby.show Time.now
        HDLRuby.show "connections_to_behaviors step..."
        # Converts the connections to behaviors.
        systemT.connections_to_behaviors!
        HDLRuby.show Time.now
        # Break the RefConcat.
        HDLRuby.show "concat_assigns step..."
        systemT.break_concat_assigns! 
        HDLRuby.show Time.now
        # Explicits the types.
        HDLRuby.show "explicit_types step..."
        systemT.explicit_types!
        HDLRuby.show Time.now
    end
    # Generate the C.
    # Get the base name of the input file, it will be used for
    # generating the main name of the multiple result files.
    $basename = File.basename($input,File.extname($input))
    $basename = $output + "/" + $basename
    # Multiple files generation mode.
    # Generate the h file.
    $hname = $output + "/hruby_sim_gen.h"
    $hnames = [ File.basename($hname) ]
    $outfile = File.open($hname,"w")
    # Adds the generated globals
    $top_system.each_systemT_deep do |systemT|
        systemT.to_ch($outfile)
        # # # Close the file.
        # # output.close
        # # # Clears the name.
        # # hname = nil
    end
    # Adds the globals from the non-HDLRuby code
    $non_hdlruby.each do |code|
        code.each_chunk do |chunk|
            if chunk.name == :sim then
                $outfile << "extern "
                $outfile << HDLRuby::Low::Low2C.prototype(chunk.to_c(""))
            end
        end
    end
    $outfile.close

    # Prepare the initial name for the main file.
    $name = $basename + ".c"
    # Generate the code for it.
    $main = File.open($name,"w")

    # Select the vizualizer depending on the options.
    init_visualizer = $options[:vcd] ? "init_vcd_visualizer" :
        "init_default_visualizer"

    # Gather the system to generate and sort them in the right order
    # to ensure references are generated before being used.
    # Base: reverse order of the tree.
    # Then, multiple configuration of a system instance must be
    # reverversed so that the base configuration is generated first.
    c_systems = $top_system.each_systemT_deep_ref
    # Generate the code of the main function.
    # HDLRuby start code
    $main << HDLRuby::Low::Low2C.main("hruby_simulator",
                                      init_visualizer,
                                      $top_system,
                                      c_systems,
                                      $hnames)
    $main.close

    $top_system.each_systemT_deep do |systemT|
        # For the c file.
        name = $output + "/" +
            HDLRuby::Low::Low2C.c_name(systemT.name) +
            ".c"
        # show? "for systemT=#{systemT.name} generating: #{name}"
        # Open the file for current systemT
        outfile = File.open(name,"w")
        # Generate the C code in to.
        # outfile << systemT.to_c(0,*$hnames)
        systemT.to_c(outfile,0,*$hnames)
        # Close the file.
        outfile.close
        # Clears the name.
        name = nil
    end

    # Simulation mode, compile and exectute.
    # Path of the simulator core files.
    $simdir = $hdr_dir + "/sim/"
    # Generate and execute the simulation commands.
    # Kernel.system("cp -n #{simdir}* #{$output}/; cd #{$output}/ ; make -s ; ./hruby_simulator")
    Dir.entries($simdir).each do |filename| 
        if !File.directory?(filename) && /\.[ch]$/ === filename then
            FileUtils.cp($simdir + "/" + filename,$output)
        end
    end
    Dir.chdir($output)
    # Find the compiler.
    cc_cmd = which('cc')
    unless cc_cmd then
        cc_cmd = which('gcc')
    end
    unless cc_cmd then
        raise "Could not find any compiler, please compile by hand as follows:\n" +
            "   In folder #{$output} execute:\n" +
            "     <my compiler> -o hruby_simulator *.c -lpthread\n" +
            "   Then execute:\n   hruby_simulator"
    end
    # Use it.
    Kernel.system("#{cc_cmd} -o3 -o hruby_simulator *.c -lpthread")
    Kernel.system("./hruby_simulator")
    Dir.chdir("..")
end

#hdr_testObject



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/HDLRuby/hdrlib.rb', line 283

def hdr_test
    $top = "__test__"
    tests = $options[:test]
    if tests then
        tests = tests.to_s.split(",")
        tests.map! {|test| ":\"#{test}\"" }
        tests = ", #{tests.join(",")}"
    else
        tests = ""
    end
    # Generate the unit test file.
    $test_file = Tempfile.new('tester.rb',Dir.getwd)
    $test_file.write("require 'std/hruby_unit.rb'\nrequire_relative '#{$input}'\n\n" +
                     "HDLRuby::Unit.test(:\"#{$top}\"#{tests})\n")
    # $test_file.rewind
    # show? $test_file.read
    # exit
    $test_file.rewind
    # It is the new input file.
    $input = $test_file
end

#hdr_verilogObject



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
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/HDLRuby/hdrlib.rb', line 489

def hdr_verilog
    # Make description compatible with verilog generation.
    $top_system.each_systemT_deep do |systemT|
        # HDLRuby.show "casts_without_expression! step..."
        # systemT.casts_without_expression!
        # HDLRuby.show Time.now
        HDLRuby.show "to_upper_space! step..."
        systemT.to_upper_space!
        HDLRuby.show Time.now
    end
    HDLRuby.show "to_global_space! step (global)..."
    $top_system.to_global_systemTs!
    HDLRuby.show Time.now
    $top_system.each_systemT_deep do |systemT|
        ## systemT.break_types!
        ## systemT.expand_types!
        HDLRuby.show "par_in_seq2seq! step..."
        systemT.par_in_seq2seq!
        HDLRuby.show Time.now
        HDLRuby.show "initial_concat_to_timed! step..."
        systemT.initial_concat_to_timed!
        HDLRuby.show Time.now
        HDLRuby.show "with_port! step..."
        systemT.with_port!
        HDLRuby.show Time.now
    end
    # # Verilog generation
    # $output << top_system.to_verilog
    # Generate the Verilog.
    # Get the base name of the input file, it will be used for
    # generating the main name of the multiple result files.
    $basename = File.basename($input,File.extname($input))
    $basename = $output + "/" + $basename
    # # File name counter.
    # $namecount = 0
    # Prepare the initial name for the main file.
    $name = $basename + ".v"
    # Multiple files generation mode.
    $top_system.each_systemT_deep do |systemT|
        # Generate the name if necessary.
        unless $name
            $name = $output + "/" +
                HDLRuby::Verilog.name_to_verilog(systemT.name) +
                ".v"
        end
        # Open the file for current systemT
        outfile = File.open($name,"w")
        # Generate the Verilog code in to.
        outfile << systemT.to_verilog
        # Close the file.
        outfile.close
        # Clears the name.
        $name = nil
    end
end

#hdr_vhdlObject



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/HDLRuby/hdrlib.rb', line 545

def hdr_vhdl
    # top_system = $top_instance.to_low.systemT
    # top_system = $top_system
    # Make description compatible with vhdl generation.
    $top_system.each_systemT_deep do |systemT|
        systemT.outread2inner!            unless $options[:vhdl08] || $options[:alliance]
        systemT.with_boolean!
        systemT.boolean_in_assign2select! unless $options[:alliance]
        systemT.bit2vector2inner!         unless $options[:vhdl08] || $options[:alliance]
        systemT.select2case!              # if     $options[:alliance]
        systemT.break_concat_assigns!     # if     $options[:alliance]
        systemT.to_upper_space!
        systemT.to_global_systemTs!
        systemT.break_types!
        systemT.with_port!
        systemT.with_var!
        systemT.cleanup!
    end
    # Generate the vhdl.
    # Get the base name of the input file, it will be used for
    # generating the main name of the multiple result files.
    $basename = File.basename($input,File.extname($input))
    $basename = $output + "/" + $basename
    # # File name counter.
    # $namecount = 0
    # Prepare the initial name for the main file.
    $name = $basename + ".vhd"
    # Multiple files generation mode.
    $top_system.each_systemT_deep do |systemT|
        # Generate the name if necessary.
        unless $name
            $name = $output + "/" +
                HDLRuby::Low::Low2VHDL.entity_name(systemT.name) +
                ".vhd"
        end
        # Open the file for current systemT
        outfile = File.open($name,"w")
        # Generate the VHDL code in to.
        outfile << systemT.to_vhdl
        # Close the file.
        outfile.close
        # Clears the name.
        $name = nil
    end
end

#hdr_yamlObject



363
364
365
# File 'lib/HDLRuby/hdrlib.rb', line 363

def hdr_yaml
    puts $top_system.to_yaml
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

#lut84(content, addr) ⇒ Object

A test of def.



2
3
4
5
# File 'lib/HDLRuby/hdr_samples/with_def.rb', line 2

def lut84(content,addr)
   bit[8][-4].inner tbl? => content.to_a
   tbl![addr]
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

#rom_gen(addr, &func) ⇒ Object

Rom access generator, def case.



2
3
4
5
# File 'lib/HDLRuby/hdr_samples/rom_nest.rb', line 2

def rom_gen(addr,&func)
    bit[8][-8].constant tbl? => 8.times.map {|i| func.(i).to_i }
    tbl![addr]
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/hdrlib.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

#with_printObject

A simple system for testing hw print and strings.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/HDLRuby/hdr_samples/print_bench.rb', line 5

system :with_print do
    input  :clk, :rst
    [4].output :counter

    seq(clk.posedge) do
        hif(rst) do
            counter <= 0
        end
        helse do
            counter <= counter + 1
            hprint("In '#{__FILE__}' line #{__LINE__}: ")
            hprint("Counter=", counter, "\n")
        end
    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