class Object

Constants

Ms

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

NNs

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

Ns

The various combinations of bit strings to test.

S
STRs

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

Xs

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

Zs

Public Class Methods

booting?() click to toggle source

Tells HDLRuby has finised booting.

# File lib/HDLRuby/hruby_high.rb, line 4800
def self.booting?
    false
end
configure_high() click to toggle source

Enters in HDLRuby::High mode.

# File lib/HDLRuby/hruby_high.rb, line 4762
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
method_missing(m, *args, &ruby_block) click to toggle source

For main, missing methods are looked for in the namespaces.

# File lib/HDLRuby/hruby_high.rb, line 4772
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

Public Instance Methods

after(number, clk = $clk, rst = $rst, &code) click to toggle source
# 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
common() click to toggle source
# File lib/HDLRuby/hdr_samples/calculator.rb, line 15
def common
    s   <= tmp[7..0]
    zf  <= (s == 0)
    sf  <= tmp[7]
    cf  <= tmp[8]
    vf  <= tmp[8] ^ tmp[7]
    goto(:choice)
end
connect8(i0,i1,i2,i3,i4,i5,i6,i7, o0,o1,o2,o3,o4,o5,o6,o7) click to toggle source
# 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
eName2Exp(name) click to toggle source

Generate an expression from a signal or constant name

# 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
forward() click to toggle source

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

# 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_sub() click to toggle source

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.

# 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)]]
hello(name) click to toggle source
# File lib/HDLRuby/test_hruby_high.rb, line 536
def hello(name)
    $hello = "Hello #{name}."
end
hello_in() click to toggle source
# File lib/HDLRuby/high_samples/functions.rb, line 31
def hello_in
    puts "hello_in"
    a <= x + y
end
hello_mix(u,v,w) click to toggle source
# 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_out() click to toggle source
# File lib/HDLRuby/high_samples/functions.rb, line 6
def hello_out
    puts "hello_out"
end
make_reg(name,&blk) click to toggle source

Function generating a register declaration.

# 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) click to toggle source

Function generating the body of a register description.

# 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
rand_array(geometry,width) click to toggle source

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

# 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) click to toggle source

Generate a width bit (signed) random value.

# 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
sigmoid(a_width, a_point, d_width, d_point, addr) click to toggle source
# 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) click to toggle source

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

# 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) click to toggle source

Locate an executable from cmd.

# 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) click to toggle source

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.

# 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
xcd_generator(top, path) click to toggle source

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

# 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