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_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 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_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 Hparent
Constructor Details
#initialize(block) ⇒ Behavior
Creates a new behavior executing +block+.
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 |
# File 'lib/HDLRuby/hruby_low.rb', line 1985 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.
1982 1983 1984 |
# File 'lib/HDLRuby/hruby_low.rb', line 1982 def block @block end |
Instance Method Details
#add_event(event) ⇒ Object
Adds an +event+ to the sensitivity list.
2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 |
# File 'lib/HDLRuby/hruby_low.rb', line 2043 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.
2083 2084 2085 2086 2087 2088 2089 |
# File 'lib/HDLRuby/hruby_low.rb', line 2083 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.
2093 2094 2095 2096 2097 2098 2099 |
# File 'lib/HDLRuby/hruby_low.rb', line 2093 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_event(&ruby_block) ⇒ Object
Iterates over the events of the sensitivity list.
Returns an enumerator if no ruby block is given.
2057 2058 2059 2060 2061 2062 |
# File 'lib/HDLRuby/hruby_low.rb', line 2057 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.
2103 2104 2105 2106 2107 2108 2109 |
# File 'lib/HDLRuby/hruby_low.rb', line 2103 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.
2116 2117 2118 |
# File 'lib/HDLRuby/hruby_low.rb', line 2116 def each_statement(&ruby_block) @block.each_statement(&ruby_block) end |
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 |
# File 'lib/HDLRuby/hruby_low.rb', line 2023 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.
2065 2066 2067 |
# File 'lib/HDLRuby/hruby_low.rb', line 2065 def has_event? return !@events.empty? end |
#hash ⇒ Object
Hash function.
2036 2037 2038 |
# File 'lib/HDLRuby/hruby_low.rb', line 2036 def hash return [@events,@block].hash end |
#last_statement ⇒ Object
Returns the last statement.
2128 2129 2130 |
# File 'lib/HDLRuby/hruby_low.rb', line 2128 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.
2075 2076 2077 2078 2079 2080 |
# File 'lib/HDLRuby/hruby_low.rb', line 2075 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+.
2070 2071 2072 |
# File 'lib/HDLRuby/hruby_low.rb', line 2070 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.
2138 2139 2140 |
# File 'lib/HDLRuby/hruby_low.rb', line 2138 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.
2123 2124 2125 |
# File 'lib/HDLRuby/hruby_low.rb', line 2123 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.
578 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 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 578 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.
693 694 695 696 697 698 699 700 701 702 703 704 705 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 693 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.
2133 2134 2135 |
# File 'lib/HDLRuby/hruby_low.rb', line 2133 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 |