Class: HDLRuby::Low::Behavior
- Inherits:
-
Base::Behavior
- Object
- Base::Behavior
- HDLRuby::Low::Behavior
- Includes:
- Hparent, Low2Symbol
- Defined in:
- lib/HDLRuby/hruby_db.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2hdr.rb,
lib/HDLRuby/hruby_low2seq.rb,
lib/HDLRuby/hruby_low2sym.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_resolve.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_with_var.rb,
lib/HDLRuby/hruby_low_fix_types.rb,
lib/HDLRuby/hruby_low_with_bool.rb,
lib/HDLRuby/hruby_low_without_namespace.rb
Overview
Extends the Behavior class with functionality for moving the declarations to the upper namespace.
Direct Known Subclasses
Constant Summary
Constants included from Low2Symbol
Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable
Instance Attribute Summary collapse
-
#block ⇒ Object
readonly
The block executed by the behavior.
Attributes included from Hparent
Instance Method Summary collapse
-
#add_event(event) ⇒ Object
Adds an +event+ to the sensitivity list.
-
#blocks2seq! ⇒ Object
Converts the par sub blocks to seq.
-
#delete_event!(event) ⇒ Object
Deletes a event.
-
#each_block(&ruby_block) ⇒ Object
Iterates over the blocks.
-
#each_block_deep(&ruby_block) ⇒ Object
Iterates over all the blocks of the system type and its system instances.
-
#each_deep(&ruby_block) ⇒ Object
Iterates over each object deeply.
-
#each_event(&ruby_block) ⇒ Object
Iterates over the events of the sensitivity list.
-
#each_node_deep(&ruby_block) ⇒ Object
Iterates over all the nodes of the system type and its system instances.
-
#each_statement(&ruby_block) ⇒ Object
Iterates over the statements.
-
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
-
#explicit_types! ⇒ Object
Explicit the types conversions in the scope.
-
#extract_declares! ⇒ Object
Extract the declares from the scope and returns them into an array.
-
#get_by_name(name) ⇒ Object
Find an inner object by +name+.
-
#has_event? ⇒ Boolean
Tells if there is any event.
-
#hash ⇒ Object
Hash function.
-
#initialize(block) ⇒ Behavior
constructor
Creates a new behavior executing +block+.
-
#last_statement ⇒ Object
Returns the last statement.
-
#map_events!(&ruby_block) ⇒ Object
Maps on the events.
-
#mixblocks2seq! ⇒ Object
Converts the par sub blocks to seq if they are not full par.
-
#on_edge? ⇒ Boolean
Tells if there is a positive or negative edge event.
-
#on_event?(*events) ⇒ Boolean
Tells if it is activated on one of +events+.
-
#parent_system ⇒ Object
Gets the parent system, i.e., the parent of the top scope.
-
#replace_names!(former, nname) ⇒ Object
Replaces recursively +former+ name by +nname+ until it is redeclared.
-
#reverse_each_statement(&ruby_block) ⇒ Object
Reverse iterates over the statements.
-
#set_block!(block) ⇒ Object
Sets the block.
-
#to_c(res, level = 0, time = false) ⇒ Object
Generates the text of the equivalent HDLRuby code.
-
#to_ch(res) ⇒ Object
Generates the content of the h file.
-
#to_hdr(level = 0, timed = false) ⇒ Object
Generates the text of the equivalent hdr text.
-
#to_high ⇒ Object
Creates a new high behavior.
-
#to_upper_space! ⇒ Object
Moves the declarations to the upper namespace.
-
#to_vhdl(level = 0) ⇒ Object
Generates the text of the equivalent HDLRuby::High code.
-
#top_scope ⇒ Object
Gets the top scope, i.e.
-
#with_boolean! ⇒ Object
Converts to a variable-compatible system.
-
#with_var!(upper = nil) ⇒ Object
Converts to a variable-compatible behavior.
Methods included from Low2Symbol
Methods included from Hparent
#hierarchy, #no_parent!, #scope
Constructor Details
#initialize(block) ⇒ Behavior
Creates a new behavior executing +block+.
2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 |
# File 'lib/HDLRuby/hruby_low.rb', line 2192 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 |
Instance Attribute Details
#block ⇒ Object
The block executed by the behavior.
2189 2190 2191 |
# File 'lib/HDLRuby/hruby_low.rb', line 2189 def block @block end |
Instance Method Details
#add_event(event) ⇒ Object
Adds an +event+ to the sensitivity list.
2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 |
# File 'lib/HDLRuby/hruby_low.rb', line 2253 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 |
#blocks2seq! ⇒ Object
Converts the par sub blocks to seq.
62 63 64 65 66 |
# File 'lib/HDLRuby/hruby_low2seq.rb', line 62 def blocks2seq! # Converts the block to seq. self.block.to_seq! return self end |
#delete_event!(event) ⇒ Object
Deletes a event.
400 401 402 403 404 405 406 407 408 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 400 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 |
#each_block(&ruby_block) ⇒ Object
Iterates over the blocks.
2293 2294 2295 2296 2297 2298 2299 |
# File 'lib/HDLRuby/hruby_low.rb', line 2293 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 |
#each_block_deep(&ruby_block) ⇒ Object
Iterates over all the blocks of the system type and its system instances.
2303 2304 2305 2306 2307 2308 2309 |
# File 'lib/HDLRuby/hruby_low.rb', line 2303 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 |
#each_deep(&ruby_block) ⇒ Object
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 |
# File 'lib/HDLRuby/hruby_low.rb', line 2340 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 |
#each_event(&ruby_block) ⇒ Object
Iterates over the events of the sensitivity list.
Returns an enumerator if no ruby block is given.
2267 2268 2269 2270 2271 2272 |
# File 'lib/HDLRuby/hruby_low.rb', line 2267 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 |
#each_node_deep(&ruby_block) ⇒ Object
Iterates over all the nodes of the system type and its system instances.
2313 2314 2315 2316 2317 2318 2319 |
# File 'lib/HDLRuby/hruby_low.rb', line 2313 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 |
#each_statement(&ruby_block) ⇒ Object
Iterates over the statements.
Returns an enumerator if no ruby block is given.
2326 2327 2328 |
# File 'lib/HDLRuby/hruby_low.rb', line 2326 def each_statement(&ruby_block) @block.each_statement(&ruby_block) end |
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 |
# File 'lib/HDLRuby/hruby_low.rb', line 2233 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_types! ⇒ Object
Explicit the types conversions in the scope.
46 47 48 49 50 |
# 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_declares! ⇒ Object
Extract the declares from the scope and returns them into an array.
NOTE: do not recurse into the sub scopes or behaviors!
445 446 447 448 |
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 445 def extract_declares! # Recurse on the block. return self.block.extract_declares! end |
#get_by_name(name) ⇒ Object
Find an inner object by +name+. NOTE: return nil if not found.
65 66 67 68 69 70 |
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 65 def get_by_name(name) if (self.block.name == name.to_sym) then return self.block end return self.block.get_by_name(name) end |
#has_event? ⇒ Boolean
Tells if there is any event.
2275 2276 2277 |
# File 'lib/HDLRuby/hruby_low.rb', line 2275 def has_event? return !@events.empty? end |
#hash ⇒ Object
Hash function.
2246 2247 2248 |
# File 'lib/HDLRuby/hruby_low.rb', line 2246 def hash return [@events,@block].hash end |
#last_statement ⇒ Object
Returns the last statement.
2354 2355 2356 |
# File 'lib/HDLRuby/hruby_low.rb', line 2354 def last_statement @block.last_statement end |
#map_events!(&ruby_block) ⇒ Object
Maps on the events.
391 392 393 394 395 396 397 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 391 def map_events!(&ruby_block) @events.map! do |event| event = ruby_block.call(event) event.parent = self unless event.parent event end end |
#mixblocks2seq! ⇒ Object
Converts the par sub blocks to seq if they are not full par.
69 70 71 72 73 74 75 |
# 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 |
#on_edge? ⇒ Boolean
Tells if there is a positive or negative edge event.
2285 2286 2287 2288 2289 2290 |
# File 'lib/HDLRuby/hruby_low.rb', line 2285 def on_edge? @events.each do |event| return true if event.on_edge? end return false end |
#on_event?(*events) ⇒ Boolean
Tells if it is activated on one of +events+.
2280 2281 2282 |
# File 'lib/HDLRuby/hruby_low.rb', line 2280 def on_event?(*events) @events.any? { |ev0| events.any? { |ev1| ev0.eql?(ev1) } } end |
#parent_system ⇒ Object
Gets the parent system, i.e., the parent of the top scope.
2364 2365 2366 |
# File 'lib/HDLRuby/hruby_low.rb', line 2364 def parent_system return self.top_scope.parent end |
#replace_names!(former, nname) ⇒ Object
Replaces recursively +former+ name by +nname+ until it is redeclared.
451 452 453 454 |
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 451 def replace_names!(former,nname) # Recurse on the block. self.block.replace_names!(former,nname) end |
#reverse_each_statement(&ruby_block) ⇒ Object
Reverse iterates over the statements.
Returns an enumerator if no ruby block is given.
2333 2334 2335 |
# File 'lib/HDLRuby/hruby_low.rb', line 2333 def reverse_each_statement(&ruby_block) @block.reverse_each_statement(&ruby_block) end |
#set_block!(block) ⇒ Object
Sets the block.
386 387 388 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 386 def set_block!(block) self.block = block end |
#to_c(res, level = 0, time = false) ⇒ Object
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. def to_c(level = 0, time = false)
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 661 def to_c(res, 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)" res << Low2C.obj_name(self.parent) << ";\n" else res << "behavior->owner = NULL;\n" end # Set the behavior as not enabled. */ res << " " * (level+1)*3 res << "behavior->enabled = 0;\n" # 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" # Set the active time to 0. res << " " * (level+1)*3 res << "behavior->active_time = 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 } # Remove the inner signals from the list. self.block.each_inner do |inner| refs.delete_if {|r| r.name == inner.name } end # 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)," res << "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" res << "behavior->events[#{i}] = " event.to_c(res) res << ";\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 sigad = "" event.ref.resolve.to_c_signal(sigad) # 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}," res << "#{sigad}->num_#{field}*sizeof(Object));\n" res << "#{sigad}->#{field}[#{sigad}->num_#{field}-1] = " res << "(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 |
#to_ch(res) ⇒ Object
Generates the content of the h file. def to_ch
794 795 796 797 798 799 800 801 802 803 804 805 806 807 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 794 def to_ch(res) # 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 self.block.to_ch(res) return res; end |
#to_hdr(level = 0, timed = false) ⇒ Object
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.
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# 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 |
#to_high ⇒ Object
Creates a new high behavior.
130 131 132 133 134 135 136 |
# 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 |
#to_upper_space! ⇒ Object
Moves the declarations to the upper namespace.
437 438 439 440 |
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 437 def to_upper_space! # Recurse on the block. self.block.to_upper_space! end |
#to_vhdl(level = 0) ⇒ Object
Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 |
# 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 |
#top_scope ⇒ Object
Gets the top scope, i.e. the first scope of the current system.
2359 2360 2361 |
# File 'lib/HDLRuby/hruby_low.rb', line 2359 def top_scope return parent.top_scope end |
#with_boolean! ⇒ Object
Converts to a variable-compatible system.
NOTE: the result is the same Behaviour.
74 75 76 |
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 74 def with_boolean! self.each_statement { |statement| statement.with_boolean! } end |
#with_var!(upper = nil) ⇒ Object
Converts to a variable-compatible behavior.
NOTE: the result is the same systemT.
45 46 47 48 49 |
# 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 |