Module: RubyHDL::High

Defined in:
lib/HDLRuby/std/sequencer_sw.rb

Defined Under Namespace

Modules: HEnumerable, SEnumerable Classes: Binary, Expression, Hif, Print, Ref, RefIndex, RefName, RefRange, Ruby, Sblock, SblockTop, Sbreak, Scall, Scontinue, Select, SequencerT, SfunctionT, Sif, SignalI, Siter, Sloop, Sreturn, Statement, Step, Sterminate, Swhile, Sync, Transmit, Type, TypeDef, TypeFloat, TypeGen, TypeSigned, TypeStruct, TypeTuple, TypeUnsigned, TypeVector, Unary, Value, VerbatimExpression, VerbatimStatement

Constant Summary collapse

SBLOCK_STACK =

The stack of SW blocks.

[ SblockTop.new ]
RUBY_OPERATOR =

The translation of operators into Ruby code.

{
  # Unary operators.
  :"-@" => "-(%{l})", :"+@" => "+(%{l})", :"~" => "~(%{l})",
  :abs => "(%{l}).abs",
  :boolean => "%{l}", :bit => "%{l}", 
  :signed => "%{l}", :unsigned => "(%{l}) & 0xFFFFFFFFFFFFFFFF",

  # Binary operators.
  :"+" => "(%{l})+(%{r})", :"-" => "(%{l})-(%{r})", 
  :"*" => "(%{l})*(%{r})", :"/" => "(%{l})/(%{r})", 
  :"%" => "(%{l})%%(%{r})", :"**" => "(%{l})**(%{r})",
  :"&" => "(%{l})&(%{r})", :"|" => "(%{l})|(%{r})", 
  :"^" => "(%{l})^(%{r})",
  :"<<" => "(%{l})<<(%{r})", :">>" => "(%{l})>>(%{r})",
  :"==" => "((%{l}) & %{m}==(%{r}) & %{m}) ? 1:0", 
  :"!=" => "((%{l}) & %{m}!=(%{r}) & %{m}) ? 1:0",
  :"<" => "((%{l}) & %{m}%{s} < (%{r}) & %{m}%{s}) ? 1:0", 
  :">" => "((%{l}) & %{m}%{s} > (%{r}) & %{m}%{s}) ? 1:0", 
  :"<=" => "((%{l}) & %{m}%{s} <=(%{r}) & %{m}%{s}) ? 1:0",
  :">=" => "((%{l}) & %{m}%{s} >=(%{r}) & %{m}%{s}) ? 1:0"
}
C_OPERATOR =

The translation of operators into C code.

{
  # Unary operators.
  :"-@" => "-(%s)", :"+@" => "+(%s)", :"~" => "~(%s)",
  :abs => "(%s).abs",
  :boolean => "%s", :bit => "%s", 
  :signed => "%s", :unsigned => "(%s) & 0xFFFFFFFFFFFFFFFF",

  # Binary operators.
  :"+" => "(%s)+(%s)", :"-" => "(%s)-(%s)",  :"*" => "(%s)*(%s)",
  :"/" => "(%s)/(%s)", :"%" => "(%s)%%(%s)", :"**" => "pow((%s),(%s))",
  :"&" => "(%s)&(%s)", :"|" => "(%s)|(%s)",  :"^" => "(%s)^(%s)",
  :"<<" => "(%s)<<(%s)", :">>" => "(%s)>>(%s)",
  :"==" => "(%s)==(%s)", :"!=" => "(%s)!=(%s)",
  :"<" => "(%s)<(%s)", :">" => "(%s)>(%s)", 
  :"<=" => "(%s)<=(%s)",:">=" => "(%s)>=(%s)"
}
PYTHON_OPERATOR =

The translation of operators into Python code.

{
  # Unary operators.
  :"-@" => "-(%{l})", :"+@" => "+(%{l})", :"~" => "~(%{l})",
  :abs => "abs(%{l})",
  :boolean => "%{l}", :bit => "%{l}", 
  :signed => "%{l}", :unsigned => "(%{l}) & 0xFFFFFFFFFFFFFFFF",

  # Binary operators.
  :"+" => "(%{l})+(%{r})", :"-" => "(%{l})-(%{r})", 
  :"*" => "(%{l})*(%{r})", :"/" => "(%{l})/(%{r})", 
  :"%" => "(%{l})%%(%{r})", :"**" => "(%{l})**(%{r})",
  :"&" => "(%{l})&(%{r})", :"|" => "(%{l})|(%{r})", 
  :"^" => "(%{l})^(%{r})",
  :"<<" => "(%{l})<<(%{r})", :">>" => "(%{l})>>(%{r})",
  :"==" => "1 if ((%{l}) & %{m}==(%{r}) & %{m}) else 0", 
  :"!=" => "1 if ((%{l}) & %{m}!=(%{r}) & %{m}) else 0",
  :"<" => "1 if ((%{l}) & %{m}%{s} < (%{r}) & %{m}%{s}) else 0", 
  :">" => "1 if ((%{l}) & %{m}%{s} > (%{r}) & %{m}%{s}) else 0", 
  :"<=" => "1 if ((%{l}) & %{m}%{s} <=(%{r}) & %{m}%{s}) else 0",
  :">=" => "1 if ((%{l}) & %{m}%{s} >=(%{r}) & %{m}%{s}) else 0"
}
TF_OPERATOR =

The translation of operators into TensorFlow code.

{
  # Unary operators.
  :"-@" => "-(%{l})", :"+@" => "+(%{l})", 
  :"~" => "tf.bitwise.bitwise_not(%{l})",
  :abs => "tf.abs(%{l})",
  :boolean => "%{l}", :bit => "%{l}", 
  :signed => "%{l}", 
  :unsigned => "tf.bitwise.bitwise_and(%{l}),0xFFFFFFFFFFFFFFFF",

  # Binary operators.
  :"+" => "(%{l})+(%{r})", :"-" => "(%{l})-(%{r})", 
  :"*" => "(%{l})*(%{r})", :"/" => "(%{l})/(%{r})", 
  :"%" => "(%{l})%%(%{r})", :"**" => "(%{l})**(%{r})",
  :"&" => "tf.bitwise.bitwise_and((%{l}),(%{r}))", 
  :"|" => "tf.bitwise.bitwise_or((%{l}),(%{r}))", 
  :"^" => "tf.bitwise.bitwise_xor((%{l}),(%{r}))",
  :"<<" => "tf.bitwise.bitwise_left_shift((%{l}),(%{r}))", 
  :">>" => "tf.bitwise.bitwise_right_shift((%{l}),(%{r}))",
  :"==" => "tf.equal(%{l},%{r})", 
  :"!=" => "tf.not_equal(%{l},%{r})",
  :"<" =>  "tf.less(%{l},%{r})", 
  :">" =>  "tf.greater(%{l},%{r})", 
  :"<=" => "tf.less_equal(%{l},%{r})",
  :">=" => "tf.greater_equal(%{l},%{r})"
}
Void =

The void type

define_type(:void)
Bit =

The bit type.

define_type(:bit)
Signed =

The signed bit type.

define_type(:signed)
Unsigned =

The unsigned bit type.

define_type(:unsigned)
Float =

The float bit type

define_type(:float)
StringT =

The string type

define_type(:string)
@@absoluteCounter =

The absolute name counter.

-1 # The absolute name counter.
@@uniq_names =
Set.new(Symbol.all_symbols.map {|sym| sym.to_s})

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call_sblock(m, *args, &ruby_block) ⇒ Object

Calling a method from the stack.



170
171
172
173
174
175
176
177
178
179
180
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 170

def self.call_sblock(m,*args,&ruby_block)
    SBLOCK_STACK.reverse_each do |sblock|
      if sblock.callable?(m) then
        # return sblock.callable(m,*args,&ruby_block)
        res = sblock.callable(m,*args,&ruby_block)
        return res
      end
    end
    # Method not found.
    method_missing(m,*args,&ruby_block)
end

.define_type(name) ⇒ Object

Defines a basic type +name+.



1494
1495
1496
1497
1498
1499
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 1494

def self.define_type(name)
  name = name.to_sym
  type = Type.new(name)
  self.send(:define_method,name) { type }
  return type
end

.global_sblockObject



153
154
155
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 153

def self.global_sblock
  SBLOCK_STACK[0]
end

.pop_sblockObject



165
166
167
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 165

def self.pop_sblock
  SBLOCK_STACK.pop
end

.push_sblock(sblock) ⇒ Object



161
162
163
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 161

def self.push_sblock(sblock)
  SBLOCK_STACK << sblock
end

.top_sblockObject



157
158
159
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 157

def self.top_sblock
  SBLOCK_STACK[-1]
end

.uniq_name(base = "") ⇒ Object

Generates an absolute uniq name.



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 25

def self.uniq_name(base = "")
  @@absoluteCounter += 1
  name = base.to_s + ":#{@@absoluteCounter}"
  if @@uniq_names.include?(name) then
    # The symbol exists, try again.
    return self.uniq_name
  else
    @@uniq_names.add(name)
    return name.to_sym
  end
end

Instance Method Details

#inner(*names) ⇒ Object

Create a 1-bit inner signal.



5041
5042
5043
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 5041

def inner(*names)
  return [1].inner(*names)
end

#input(*names) ⇒ Object

Create a 1-bit input signal.



5031
5032
5033
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 5031

def input(*names)
  return [1].input(*names)
end

#output(*names) ⇒ Object

Create a 1-bit output signal.



5036
5037
5038
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 5036

def output(*names)
  return [1].output(*names)
end

#sdef(name, &ruby_block) ⇒ Object

Create a new function named +name+, built using block +ruby_block+.



5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 5046

def sdef(name,&ruby_block)
  name = name.to_sym
  # Get the arguments of the ruby_block.
  block_args = ruby_block.parameters.map {|typ,name| name.to_s }
  # Create function.
  cur_sblock = RubyHDL::High.top_sblock
  # Register the call.
  cur_sblock.register(name.to_sym) do |*args|
    # Create the function.
    # Get the current sequencer.
    cur_seq = RubyHDL::High.top_sblock.sequencer
    # Get the function from the sequencer if any.
    function = cur_seq.sfunction(name)
    unless function then
      # There were no function for the sequencer, create it.
      # Execute the ruby block in a sequencer environment for building
      # the sblock.
      sblock = Sblock.new(cur_seq,&ruby_block)
      # Create the arguments.
      block_args.each_with_index do |block_arg,i|
        # puts "args[#{i}]=(#{args[i].name},#{args[i].type})"
        sblock.make_inners(args[i].type,block_arg.to_sym)
      end
      # Create the function.
      function = SfunctionT.new(name,sblock,*block_args)
      # Add it to the current sequencer.
      cur_seq.add_sfunction(name,function)
    end
    # And create the call
    Scall.new(function,cur_seq,*args)
  end
end

#sequencer(clk = nil, start = nil, &ruby_block) ⇒ Object

Create a new sequencer block, with clock counter +clk+ and run control +start+



5024
5025
5026
5027
5028
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 5024

def sequencer(clk = nil, start = nil, &ruby_block)
  # Ensure the clock is global.
  clk.global! if clk
  return SequencerT.new(clk,start,&ruby_block)
end

#struct(content) ⇒ Object

Creates an unnamed structure type from a +content+.



2162
2163
2164
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 2162

def struct(content)
  return TypeStruct.new(:"",:little,content)
end

#typedef(name, &ruby_block) ⇒ Object

Declares a high-level generic type named +name+, and using +ruby_block+ for construction.



2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
# File 'lib/HDLRuby/std/sequencer_sw.rb', line 2170

def typedef(name, &ruby_block)
  # Ensure there is a block.
  ruby_block = proc {} unless block_given?
  type = TypeGen.new(name,&ruby_block)
  define_singleton_method(name.to_sym) do |*args|
    if (args.size < ruby_block.arity) then
      # Not enough arguments get generic type as is.
      type
    else
      # There are arguments, specialize the type.
      gtype = type.generate(*args)
      # And add it as a local type of the system.
      RubyHDL::High.top_sblock.add_type(gtype)
      gtype
    end
  end
end