module HDLRuby::High::Std
Standard HDLRuby::High
library: universal generic function generator based on the work of Ryota Sakai from NN4H
Public Class Methods
Creates a new channel type named name
whose instances are creating executing ruby_block
.
# File lib/HDLRuby/std/channel.rb, line 62 def self.channel(name,&ruby_block) return ChannelT.new(name,&ruby_block) end
Creates directly an instance of channel named name
using ruby_block
built with args
.
# 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
Wrap object obj
to act like a channel port.
# 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
Redefines the include to add fixed point generation through the Type
class.
# 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
Creates a new task type named name
whose instances are creating executing ruby_block
.
# File lib/HDLRuby/std/task.rb, line 60 def self.task(name,&ruby_block) return TaskT.new(name,&ruby_block) end
Creates directly an instance of task named name
using ruby_block
built with args
.
# 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
Public Instance Methods
Redefine the type generation method for supporting fixed point type generation.
# File lib/HDLRuby/std/fixpoint.rb, line 26 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
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
.
# 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
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
.
# 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
Creates a new channel type named name
whose instances are creating executing ruby_block
.
# File lib/HDLRuby/std/channel.rb, line 68 def channel(name,&ruby_block) HDLRuby::High::Std.channel(name,&ruby_block) end
Creates directly an instance of channel named name
using ruby_block
built with args
.
# 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
# File lib/HDLRuby/std/channel.rb, line 1416 def channel_port(obj) return HDLRuby::High::Std.channel_port(obj) end
Initialize the clock generator with rst
as reset signal.
# File lib/HDLRuby/std/clocks.rb, line 10 def configure_clocks(rst = $rst) @@__clocks_rst = rst end
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.
# 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
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.
# 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
Make an array consists of a point of any activation function. @param [Integer] lut_size the lut_size of LUT @return [Array] table an array consists of a point of tanh
# File lib/HDLRuby/std/function_generator.rb, line 123 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
Creates a clock inverted every times
occurence of an event
and its everted.
# 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
Create a clock inverted every times
occurence of an event
.
# 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
Declare a new pipeline with name
.
# File lib/HDLRuby/std/pipeline.rb, line 216 def pipeline(name) return PipelineT.new(name) end
Creates a new reconfigurable component type named name
whose instances are creating executing ruby_block
.
# 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
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.
# 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
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.
# 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
Creates a new task type named name
whose instances are creating executing ruby_block
.
# File lib/HDLRuby/std/task.rb, line 66 def task(name,&ruby_block) HDLRuby::High::Std.task(name,&ruby_block) end
Creates directly an instance of task named name
using ruby_block
built with args
.
# 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
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
.
# 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