Class: HDLRuby::Low::Behavior
- Inherits:
-
Base::Behavior
- Object
- Base::Behavior
- HDLRuby::Low::Behavior
- Includes:
- Hdecorator, Hparent, Low2Symbol
- Defined in:
- lib/HDLRuby/hruby_db.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.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_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 Hdecorator
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.
-
#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(level = 0, time = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code.
-
#to_ch ⇒ Object
Generates the content of the h file.
-
#to_high(level = 0, timed = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code.
-
#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 Hdecorator
decorate_parent_id, dump, each, each_with_property, get, included, load, #properties
Methods included from Hparent
Constructor Details
#initialize(block) ⇒ Behavior
Creates a new behavior executing +block+.
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 |
# File 'lib/HDLRuby/hruby_low.rb', line 2082 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.
2079 2080 2081 |
# File 'lib/HDLRuby/hruby_low.rb', line 2079 def block @block end |
Instance Method Details
#add_event(event) ⇒ Object
Adds an +event+ to the sensitivity list.
2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 |
# File 'lib/HDLRuby/hruby_low.rb', line 2143 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.
388 389 390 391 392 393 394 395 396 |
# 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 |
#each_block(&ruby_block) ⇒ Object
Iterates over the blocks.
2183 2184 2185 2186 2187 2188 2189 |
# File 'lib/HDLRuby/hruby_low.rb', line 2183 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.
2193 2194 2195 2196 2197 2198 2199 |
# File 'lib/HDLRuby/hruby_low.rb', line 2193 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.
2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 |
# File 'lib/HDLRuby/hruby_low.rb', line 2230 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.
2157 2158 2159 2160 2161 2162 |
# File 'lib/HDLRuby/hruby_low.rb', line 2157 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.
2203 2204 2205 2206 2207 2208 2209 |
# File 'lib/HDLRuby/hruby_low.rb', line 2203 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.
2216 2217 2218 |
# File 'lib/HDLRuby/hruby_low.rb', line 2216 def each_statement(&ruby_block) @block.each_statement(&ruby_block) end |
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 |
# File 'lib/HDLRuby/hruby_low.rb', line 2123 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!
438 439 440 441 |
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 438 def extract_declares! # Recurse on the block. return self.block.extract_declares! end |
#has_event? ⇒ Boolean
Tells if there is any event.
2165 2166 2167 |
# File 'lib/HDLRuby/hruby_low.rb', line 2165 def has_event? return !@events.empty? end |
#hash ⇒ Object
Hash function.
2136 2137 2138 |
# File 'lib/HDLRuby/hruby_low.rb', line 2136 def hash return [@events,@block].hash end |
#last_statement ⇒ Object
Returns the last statement.
2244 2245 2246 |
# File 'lib/HDLRuby/hruby_low.rb', line 2244 def last_statement @block.last_statement end |
#map_events!(&ruby_block) ⇒ Object
Maps on the events.
379 380 381 382 383 384 385 |
# 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 |
#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.
2175 2176 2177 2178 2179 2180 |
# File 'lib/HDLRuby/hruby_low.rb', line 2175 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+.
2170 2171 2172 |
# File 'lib/HDLRuby/hruby_low.rb', line 2170 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.
2254 2255 2256 |
# File 'lib/HDLRuby/hruby_low.rb', line 2254 def parent_system return self.top_scope.parent end |
#replace_names!(former, nname) ⇒ Object
Replaces recursively +former+ name by +nname+ until it is redeclared.
444 445 446 447 |
# 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_each_statement(&ruby_block) ⇒ Object
Reverse iterates over the statements.
Returns an enumerator if no ruby block is given.
2223 2224 2225 |
# File 'lib/HDLRuby/hruby_low.rb', line 2223 def reverse_each_statement(&ruby_block) @block.reverse_each_statement(&ruby_block) end |
#set_block!(block) ⇒ Object
Sets the block.
374 375 376 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 374 def set_block!(block) self.block = block end |
#to_c(level = 0, time = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object and +time+ is a flag telling if the behavior is timed or not.
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 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 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 579 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 |
#to_ch ⇒ Object
Generates the content of the h file.
694 695 696 697 698 699 700 701 702 703 704 705 706 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 694 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 |
#to_high(level = 0, timed = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code. +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_low2high.rb', line 251 def to_high(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_high(level) end.join(", ") res << " )" end res << " do\n" # Generate the content. res << self.block.to_high(level+1,false) # Close the behavior. res << " " * (level*3) << "end\n" # Return the result. return res end |
#to_upper_space! ⇒ Object
Moves the declarations to the upper namespace.
430 431 432 433 |
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 430 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.
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 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 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 738 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.
2249 2250 2251 |
# File 'lib/HDLRuby/hruby_low.rb', line 2249 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 |