class HDLRuby::Low::Behavior
Describes a behavior.
Describes a behavior.
Extends the Behavior
class with generation of C text.
Extends the Behavior
class with generation of hdr text.
Add the conversion to high.
Extends the Behavior
class with functionality for converting par block to seq.
Extends the Behavior
class with conversion to symbol.
Extends the Behavior
class with generation of HDLRuby::High
text.
Extends the Behavior
class with fixing of types and constants.
Describes a behavior.
Extends the Behaviour class for converting types of comparison and operations on it to boolean type.
Extends the Behavior
class with separation between signals and variables.
Extends the Behavior
class with functionality for moving the declarations to the upper namespace.
Attributes
The block executed by the behavior.
Public Class Methods
Creates a new behavior executing block
.
# File lib/HDLRuby/hruby_low.rb, line 2107 def initialize(block) # Initialize the sensitivity list. @events = [] # Check and set the block. return unless block # No block case # There is a block self.block = block # unless block.is_a?(Block) # raise AnyError, "Invalid class for a block: #{block.class}." # end # # Time blocks are only supported in Time Behaviors. # if block.is_a?(TimeBlock) # raise AnyError, "Timed blocks are not supported in common behaviors." # end # # Set the block's parent. # block.parent = self # # And set the block # @block = block end
Public Instance Methods
Adds an event
to the sensitivity list.
# File lib/HDLRuby/hruby_low.rb, line 2168 def add_event(event) unless event.is_a?(Event) raise AnyError, "Invalid class for a event: #{event.class}" end # Set the event's parent. event.parent = self # And add the event. @events << event event end
Converts the par sub blocks to seq.
# File lib/HDLRuby/hruby_low2seq.rb, line 62 def blocks2seq! # Converts the block to seq. self.block.to_seq! return self end
Deletes a event.
# File lib/HDLRuby/hruby_low_mutable.rb, line 388 def delete_event!(event) if @events.include?(event) then # The event is present, delete it. @events.delete(event) # And remove its parent. event.parent = nil end event end
Iterates over the blocks.
# File lib/HDLRuby/hruby_low.rb, line 2208 def each_block(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block) unless ruby_block # A ruby block? # Apply on it. ruby_block.call(@block) end
Iterates over all the blocks of the system type and its system instances.
# File lib/HDLRuby/hruby_low.rb, line 2218 def each_block_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block_deep) unless ruby_block # A ruby block? # Recurse. @block.each_block_deep(&ruby_block) end
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 2255 def each_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_deep) unless ruby_block # A ruby block? First apply it to current. ruby_block.call(self) # Then apply on each event. self.each_event do |event| event.each_deep(&ruby_block) end # Then apply on the block. self.block.each_deep(&ruby_block) end
Iterates over the events of the sensitivity list.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 2182 def each_event(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_event) unless ruby_block # A ruby block? Apply it on each event. @events.each(&ruby_block) end
Iterates over all the nodes of the system type and its system instances.
# File lib/HDLRuby/hruby_low.rb, line 2228 def each_node_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node_deep) unless ruby_block # A ruby block? # Recurse on the block. @block.each_node_deep(&ruby_block) end
Iterates over the statements.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 2241 def each_statement(&ruby_block) @block.each_statement(&ruby_block) end
Comparison for hash: structural comparison.
# File lib/HDLRuby/hruby_low.rb, line 2148 def eql?(obj) return false unless obj.is_a?(Behavior) idx = 0 obj.each_event do |event| return false unless @events[idx].eql?(event) idx += 1 end return false unless idx == @events.size return false unless @block.eql?(obj.block) return true end
Explicit the types conversions in the scope.
# File lib/HDLRuby/hruby_low_fix_types.rb, line 46 def explicit_types! # Fix the types of the block. self.block.explicit_types! return self end
Extract the declares from the scope and returns them into an array.
NOTE: do not recurse into the sub scopes or behaviors!
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 438 def extract_declares! # Recurse on the block. return self.block.extract_declares! end
Tells if there is any event.
# File lib/HDLRuby/hruby_low.rb, line 2190 def has_event? return !@events.empty? end
Hash
function.
# File lib/HDLRuby/hruby_low.rb, line 2161 def hash return [@events,@block].hash end
Returns the last statement.
# File lib/HDLRuby/hruby_low.rb, line 2269 def last_statement @block.last_statement end
Maps on the events.
# File lib/HDLRuby/hruby_low_mutable.rb, line 379 def map_events!(&ruby_block) @events.map! do |event| event = ruby_block.call(event) event.parent = self unless event.parent event end end
Converts the par sub blocks to seq if they are not full par.
# File lib/HDLRuby/hruby_low2seq.rb, line 69 def mixblocks2seq! # Is the block mix? return unless block.mix? # Mixed, do convert. # Converts the block to seq. self.block.to_seq! end
Tells if there is a positive or negative edge event.
# File lib/HDLRuby/hruby_low.rb, line 2200 def on_edge? @events.each do |event| return true if event.on_edge? end return false end
Tells if it is activated on one of events
.
# File lib/HDLRuby/hruby_low.rb, line 2195 def on_event?(*events) @events.any? { |ev0| events.any? { |ev1| ev0.eql?(ev1) } } end
Gets the parent system, i.e., the parent of the top scope.
# File lib/HDLRuby/hruby_low.rb, line 2279 def parent_system return self.top_scope.parent end
Replaces recursively former
name by nname
until it is redeclared.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 444 def replace_names!(former,nname) # Recurse on the block. self.block.replace_names!(former,nname) end
Reverse iterates over the statements.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 2248 def reverse_each_statement(&ruby_block) @block.reverse_each_statement(&ruby_block) end
Sets the block.
# File lib/HDLRuby/hruby_low_mutable.rb, line 374 def set_block!(block) self.block = block end
Generates the text of the equivalent HDLRuby
code. level
is the hierachical level of the object and time
is a flag telling if the behavior is timed or not.
# File lib/HDLRuby/hruby_low2c.rb, line 586 def to_c(level = 0, time = false) # puts "For behavior: #{self}" # The resulting string. res = "" # Declare the global variable holding the behavior. res << "Behavior #{Low2C.obj_name(self)};\n\n" # Generate the code of the behavior. # The header of the behavior. res << " " * level*3 res << "Behavior #{Low2C.make_name(self)}() {\n" res << " " * (level+1)*3 # Allocate the behavior. res << "Behavior behavior = malloc(sizeof(BehaviorS));\n" res << " " * (level+1)*3 res << "behavior->kind = BEHAVIOR;\n"; # Sets the global variable of the behavior. res << "\n" res << " " * (level+1)*3 res << "#{Low2C.obj_name(self)} = behavior;\n" # Register it as a time behavior if it is one of them. */ if time then res << " " * (level+1)*3 res << "register_timed_behavior(behavior);\n" end # Set the owner if any. if self.parent then res << " " * (level+1)*3 res << "behavior->owner = (Object)" + "#{Low2C.obj_name(self.parent)};\n" else res << "behavior->owner = NULL;\n" end # Set the behavior as inactive. */ res << " " * (level+1)*3 res << "behavior->activated = 0;\n" # Tells if the behavior is timed or not. res << " " * (level+1)*3 res << "behavior->timed = #{time ? 1 : 0};\n" # Is it a clocked behavior? events = self.each_event.to_a if events.empty? && !self.is_a?(TimeBehavior) then # No events, this is not a clock behavior. # And it is not a time behavior neigther. # Generate the events list from the right values. # First get the references. refs = self.block.each_node_deep.select do |node| node.is_a?(RefName) && !node.leftvalue? && !node.parent.is_a?(RefName) end.to_a # Keep only one ref per signal. refs.uniq! { |node| node.full_name } # Generate the event. events = refs.map {|ref| Event.new(:anyedge,ref.clone) } # Add them to the behavior for further processing. events.each {|event| self.add_event(event) } end # Add the events and register the behavior as activable # on them. # First allocates the array containing the events. res << " " * (level+1)*3 res << "behavior->num_events = #{events.size};\n" res << " " * (level+1)*3 res << "behavior->events = calloc(sizeof(Event)," + "behavior->num_events);\n" # Then, create and add them. events.each_with_index do |event,i| # puts "for event=#{event}" # Add the event. res << " " * (level+1)*3 res << "behavior->events[#{i}] = #{event.to_c};\n" # Register the behavior as activable on this event. # Select the active field. field = "any" field = "pos" if event.type == :posedge field = "neg" if event.type == :negedge # puts "Adding #{field} event: #{event}\n" # Get the target signal access sigad = event.ref.resolve.to_c_signal # Add the behavior to the relevant field. res << " " * (level+1)*3 res << "#{sigad}->num_#{field} += 1;\n" res << " " * (level+1)*3 res << "#{sigad}->#{field} = realloc(#{sigad}->#{field}," + "#{sigad}->num_#{field}*sizeof(Object));\n" res << "#{sigad}->#{field}[#{sigad}->num_#{field}-1] = " + "(Object)behavior;\n" end # Adds the block. res << " " * (level+1)*3 res << "behavior->block = #{Low2C.make_name(self.block)}();\n" # Generate the Returns of the result. res << "\n" res << " " * (level+1)*3 res << "return behavior;\n" # Close the behavior makeing. res << " " * level*3 res << "}\n\n" return res end
Generates the content of the h file.
# File lib/HDLRuby/hruby_low2c.rb, line 701 def to_ch res = "" # Declare the global variable holding the signal. res << "extern Behavior #{Low2C.obj_name(self)};\n\n" # Generate the access to the function making the behavior. res << "extern Behavior #{Low2C.make_name(self)}();\n\n" # Generate the accesses to the block of the behavior. res << self.block.to_ch return res; end
Generates the text of the equivalent hdr text. level
is the hierachical level of the object and timed
tells if the behavior is a time behavior or not.
# File lib/HDLRuby/hruby_low2hdr.rb, line 251 def to_hdr(level = 0,timed = false) # The resulting string. res = " " * (level*3) # Generate the header. if timed then res << "timed" else res << self.block.mode.to_s end if self.each_event.any? then res << "( " res << self.each_event.map do |event| event.to_hdr(level) end.join(", ") res << " )" end res << " do\n" # Generate the content. res << self.block.to_hdr(level+1,false) # Close the behavior. res << " " * (level*3) << "end\n" # Return the result. return res end
Creates a new high behavior.
# File lib/HDLRuby/hruby_low2high.rb, line 130 def to_high # Create the resulting behavior. res = HDLRuby::High::Behavior.new(self.block.to_high) # Adds the events. self.each_event { |ev| res.add_event(ev.to_high) } return res end
Moves the declarations to the upper namespace.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 430 def to_upper_space! # Recurse on the block. self.block.to_upper_space! end
Generates the text of the equivalent HDLRuby::High
code. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2vhd.rb, line 748 def to_vhdl(level = 0) # Gather the variables. # It is assumed that the inners are all in declared in the # direct sub block and that they represent variables, i.e., # Low::to_upper_space! and Low::with_var! has been called. vars = self.block.each_inner.to_a # The resulting string. res = "" # Generate the TimeRepeat as different processes if any. self.block.each_statement_deep do |stmnt| if stmnt.is_a?(TimeRepeat) then res << stmnt.process_to_vhdl(vars,level) end end # Generate the header. res << " " * (level*3) unless self.block.name.empty? then res << Low2VHDL.vhdl_name(self.block.name) << ": " end res << "process " # Generate the senitivity list if not a timed block. unless self.block.is_a?(TimeBlock) then if self.each_event.any? then # If there is a clock. res << "(" res << self.each_event.map do |event| event.ref.to_vhdl(level) end.join(", ") res << ")" else # If no clock, generate the sensitivity list from the right # values. list = self.block.each_node_deep.select do |node| node.is_a?(RefName) && !node.leftvalue? && !node.parent.is_a?(RefName) && # Also skip the variables !vars.find {|var| var.name == node.name } end.to_a # Keep only one ref per signal. list.uniq! { |node| node.name } # Generate the sensitivity list from it. res << "(" res << list.map {|node| node.to_vhdl(level) }.join(", ") res << ")" end end res << "\n" # Generate the variables. vars.each do |var| res << " " * ((level+1)*3) res << "variable " res << Low2VHDL.vhdl_name(var.name) << ": " res << var.type.to_vhdl << ";\n" end # Generate the content. res << " " * (level*3) res << "begin\n" # Generate the edges if any. if self.each_event.find {|event| event.type != :change} then # Generate the edge test. level = level + 1 res << " " * (level*3) res << "if (" res << self.each_event.map do |event| if event.type == :posedge then "rising_edge(" << event.ref.to_vhdl(level) << ")" else "falling_edge(" << event.ref.to_vhdl(level)<< ")" end # The change mode is not an edge! end.join(" and ") res << ") then\n" # Generate the body. res << self.block.to_vhdl(vars,level+2) # Close the edge test. res << " " * (level*3) res << "end if;\n" level = level - 1 else # Generate the body directly. res << self.block.to_vhdl(vars,level+1) end # Insert an infinite wait is the top block is a timed block. if self.block.is_a?(TimeBlock) then res << " " * ((level+1)*3) res << "wait;\n" end # Close the process. res << " " * (level*3) res << "end process;\n\n" # Return the result. return res end
Gets the top scope, i.e. the first scope of the current system.
# File lib/HDLRuby/hruby_low.rb, line 2274 def top_scope return parent.top_scope end
Converts to a variable-compatible system.
NOTE: the result is the same Behaviour.
# File lib/HDLRuby/hruby_low_with_bool.rb, line 74 def with_boolean! self.each_statement { |statement| statement.with_boolean! } end
Converts to a variable-compatible behavior.
NOTE: the result is the same systemT.
# File lib/HDLRuby/hruby_low_with_var.rb, line 45 def with_var!(upper = nil) @block = @block.with_var @block.parent = self return self end
Private Instance Methods
Sets the block if not already set.
# File lib/HDLRuby/hruby_low.rb, line 2131 def block=(block) # Check the block. unless block.is_a?(Block) raise AnyError, "Invalid class for a block: #{block.class}." end # Time blocks are only supported in Time Behaviors. if block.is_a?(TimeBlock) raise AnyError, "Timed blocks are not supported in common behaviors." end # Set the block's parent. block.parent = self # And set the block @block = block end