Class: HDLRuby::Low::Binary
- Inherits:
-
Operation
- Object
- Base::Expression
- Expression
- Operation
- HDLRuby::Low::Binary
- 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_low2vhd.rb,
lib/HDLRuby/hruby_verilog.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_fix_types.rb,
lib/HDLRuby/hruby_low_with_bool.rb,
lib/HDLRuby/hruby_low_bool2select.rb,
lib/HDLRuby/hruby_low_casts_without_expression.rb
Overview
Extends the Binary class with functionality for extracting expressions from cast.
Direct Known Subclasses
Constant Summary
Constants included from Low2Symbol
Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable
Instance Attribute Summary collapse
-
#left ⇒ Object
readonly
The left child.
-
#right ⇒ Object
readonly
The right child.
Attributes inherited from Operation
Attributes inherited from Expression
Attributes included from Hparent
Instance Method Summary collapse
-
#boolean? ⇒ Boolean
Tells if the expression is boolean.
-
#boolean_in_assign2select ⇒ Object
Converts booleans in assignments to select operators.
-
#casts_without_expression ⇒ Object
Extracts the expressions from the casts.
-
#clone ⇒ Object
Clones the binary operator (deeply).
-
#each_deep(&ruby_block) ⇒ Object
Iterates over each object deeply.
-
#each_node(&ruby_block) ⇒ Object
(also: #each_expression)
Iterates over the expression children if any.
-
#each_node_deep(&ruby_block) ⇒ Object
Iterates over the nodes deeply if any.
-
#each_ref_deep(&ruby_block) ⇒ Object
Iterates over all the references encountered in the expression.
-
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
-
#explicit_types(type = nil) ⇒ Object
Explicit the types conversions in the binary operation where +type+ is the expected type of the condition if any.
-
#hash ⇒ Object
Hash function.
-
#immutable? ⇒ Boolean
Tells if the expression is immutable (cannot be written.).
-
#initialize(type, operator, left, right) ⇒ Binary
constructor
Creates a new binary expression with +type+ applying +operator+ on +left+ and +right+ children expressions.
-
#map_nodes!(&ruby_block) ⇒ Object
Maps on the child.
-
#replace_expressions!(node2rep) ⇒ Object
Replaces sub expressions using +node2rep+ table indicating the node to replace and the corresponding replacement.
-
#set_left!(left) ⇒ Object
Sets the left.
-
#set_right!(right) ⇒ Object
Sets the right.
-
#to_c(level = 0) ⇒ Object
Generates the C text of the equivalent HDLRuby code.
-
#to_change(mode) ⇒ Object
Method called when two or more expression terms are present.
-
#to_hdr(level = 0) ⇒ Object
Generates the text of the equivalent hdr text.
-
#to_high ⇒ Object
Creates a new high binary expression.
-
#to_verilog ⇒ Object
Converts the system to Verilog code.
-
#to_vhdl(level = 0, std_logic = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code.
-
#use_name?(*names) ⇒ Boolean
Tell if the expression includes a signal whose name is one of +names+.
Methods inherited from Operation
Methods inherited from Expression
#break_types!, #extract_selects_to!, #leftvalue?, #replace_names!, #rightvalue?, #set_type!, #statement
Methods included from Low2Symbol
Methods included from Hparent
Constructor Details
#initialize(type, operator, left, right) ⇒ Binary
Creates a new binary expression with +type+ applying +operator+ on +left+ and +right+ children expressions. def initialize(operator,left,right)
4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 |
# File 'lib/HDLRuby/hruby_low.rb', line 4778 def initialize(type,operator,left,right) # Initialize as a general operation. super(type,operator) # Check and set the children. unless left.is_a?(Expression) raise AnyError, "Invalid class for an expression: #{left.class}" end unless right.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{right.class}" end @left = left @right = right # And set their parents. left.parent = right.parent = self end |
Instance Attribute Details
#left ⇒ Object (readonly)
The left child.
4770 4771 4772 |
# File 'lib/HDLRuby/hruby_low.rb', line 4770 def left @left end |
#right ⇒ Object (readonly)
The right child.
4773 4774 4775 |
# File 'lib/HDLRuby/hruby_low.rb', line 4773 def right @right end |
Instance Method Details
#boolean? ⇒ Boolean
Tells if the expression is boolean.
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 116 def boolean? case(self.operator) when :==,:!=,:>,:<,:>=,:<= then # Comparison, it is a boolean. return true when :&,:|,:^ then # AND, OR or XOR, boolean if both subs are boolean. return self.left.boolean? && self.right.boolean? else # Other cases: not boolean. return false end end |
#boolean_in_assign2select ⇒ Object
Converts booleans in assignments to select operators.
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 211 def boolean_in_assign2select # Recurse on the sub nodes. nleft = self.left.boolean_in_assign2select nright = self.right.boolean_in_assign2select # Is it a comparison but the parent is not a boolean? # or a transmit to a boolean. if [:==,:>,:<,:>=,:<=].include?(self.operator) && ( (self.parent.is_a?(Expression) && !self.parent.type.boolean?) || (self.parent.is_a?(Transmit) && !self.parent.left.type.boolean?)) then # Yes, create a select. nself = Binary.new(self.type,self.operator,nleft,nright) # return Select.new(self.type, "?", nself, return Select.new(HDLRuby::Low::Bit, "?", nself, # Value.new(self.type,1), Value.new(self.type,0) ) Value.new(HDLRuby::Low::Bit,0), Value.new(HDLRuby::Low::Bit,1) ) # Value.new(HDLRuby::Low::Boolean,0), # Value.new(HDLRuby::Low::Boolean,1) ) else # No return it as is. # self.set_left!(nleft) # self.set_right!(nright) # return self return Binary.new(self.type,self.operator,nleft,nright) end end |
#casts_without_expression ⇒ Object
Extracts the expressions from the casts.
238 239 240 241 242 243 |
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 238 def casts_without_expression # Recurse on the sub nodes. return Binary.new(self.type,self.operator, self.left.casts_without_expression, self.right.casts_without_expression) end |
#clone ⇒ Object
Clones the binary operator (deeply)
4874 4875 4876 4877 |
# File 'lib/HDLRuby/hruby_low.rb', line 4874 def clone return Binary.new(@type, self.operator, @left.clone, @right.clone) end |
#each_deep(&ruby_block) ⇒ Object
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 |
# File 'lib/HDLRuby/hruby_low.rb', line 4803 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 the type. self.type.each_deep(&ruby_block) # Then apply on the left. self.left.each_deep(&ruby_block) # Then apply on the right. self.right.each_deep(&ruby_block) end |
#each_node(&ruby_block) ⇒ Object Also known as: each_expression
Iterates over the expression children if any.
4833 4834 4835 4836 4837 4838 4839 |
# File 'lib/HDLRuby/hruby_low.rb', line 4833 def each_node(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node) unless ruby_block # A ruby block? Apply it on the children. ruby_block.call(@left) ruby_block.call(@right) end |
#each_node_deep(&ruby_block) ⇒ Object
Iterates over the nodes deeply if any.
4844 4845 4846 4847 4848 4849 4850 4851 4852 |
# File 'lib/HDLRuby/hruby_low.rb', line 4844 def each_node_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node_deep) unless ruby_block # A ruby block? First apply it to current. ruby_block.call(self) # And recurse on the children. @left.each_node_deep(&ruby_block) @right.each_node_deep(&ruby_block) end |
#each_ref_deep(&ruby_block) ⇒ Object
Iterates over all the references encountered in the expression.
NOTE: do not iterate inside the references.
4857 4858 4859 4860 4861 4862 4863 4864 4865 |
# File 'lib/HDLRuby/hruby_low.rb', line 4857 def each_ref_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_ref_deep) unless ruby_block # puts "each_ref_deep for Binary" # A ruby block? # Recurse on the children. @left.each_ref_deep(&ruby_block) @right.each_ref_deep(&ruby_block) end |
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
4817 4818 4819 4820 4821 4822 4823 4824 4825 |
# File 'lib/HDLRuby/hruby_low.rb', line 4817 def eql?(obj) # General comparison. return false unless super(obj) # Specific comparison. return false unless obj.is_a?(Binary) return false unless @left.eql?(obj.left) return false unless @right.eql?(obj.right) return true end |
#explicit_types(type = nil) ⇒ Object
Explicit the types conversions in the binary operation where +type+ is the expected type of the condition if any.
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 269 def explicit_types(type = nil) # Find the larger child type. ctype = self.left.type.width > self.right.type.width ? self.left.type : self.right.type # Recurse on the children: match the larger type. op = Binary.new(self.type,self.operator, self.left.explicit_types(ctype), self.right.explicit_types(ctype)) # Does the type match the operation? if type && !self.type.eql?(type) then # No create a cast. return Cast.new(type,op) else # Yes, return the operation as is. return op end end |
#hash ⇒ Object
Hash function.
4828 4829 4830 |
# File 'lib/HDLRuby/hruby_low.rb', line 4828 def hash return [super,@left,@right].hash end |
#immutable? ⇒ Boolean
Tells if the expression is immutable (cannot be written.)
4795 4796 4797 4798 |
# File 'lib/HDLRuby/hruby_low.rb', line 4795 def immutable? # Immutable if both children are immutable. return left.immutable? && right.immutable? end |
#map_nodes!(&ruby_block) ⇒ Object
Maps on the child.
1491 1492 1493 1494 1495 1496 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1491 def map_nodes!(&ruby_block) @left = ruby_block.call(@left) @left.parent = self unless @left.parent @right = ruby_block.call(@right) @right.parent = self unless @right.parent end |
#replace_expressions!(node2rep) ⇒ Object
Replaces sub expressions using +node2rep+ table indicating the node to replace and the corresponding replacement. Returns the actually replaced nodes and their corresponding replacement.
NOTE: the replacement is duplicated.
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1504 def replace_expressions!(node2rep) # First recurse on the children. res = self.left.replace_expressions!(node2rep) res.merge!(self.right.replace_expressions!(node2rep)) # Is there a replacement to do on the left? rep = node2rep[self.left] if rep then # Yes, do it. rep = rep.clone node = self.left # node.set_parent!(nil) self.set_left!(rep) # And register the replacement. res[node] = rep end # Is there a replacement to do on the right? rep = node2rep[self.right] if rep then # Yes, do it. rep = rep.clone node = self.right # node.set_parent!(nil) self.set_right!(rep) # And register the replacement. res[node] = rep end return res end |
#set_left!(left) ⇒ Object
Sets the left.
1469 1470 1471 1472 1473 1474 1475 1476 1477 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1469 def set_left!(left) # Check and set the left. unless left.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{left.class}" end @left = left # And set its parent. left.parent = self end |
#set_right!(right) ⇒ Object
Sets the right.
1480 1481 1482 1483 1484 1485 1486 1487 1488 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1480 def set_right!(right) # Check and set the right. unless right.is_a?(Expression) raise AnyError,"Invalid class for an expression: #{right.class}" end @right = right # And set its parent. right.parent = self end |
#to_c(level = 0) ⇒ Object
Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object.
1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 1699 def to_c(level = 0) # res = " " * (level*3) res = "({\n" # Overrides the upper src0, src1 and dst... # And allocates a new value for dst. res << (" " * ((level+1)*3)) res << "Value src0,src1,dst = get_value();\n" # Save the state of the value pool. res << (" " * ((level+1)*3)) res << "unsigned int pool_state = get_value_pos();\n" # Compute the left. res << (" " * ((level+1)*3)) res << "src0 = #{self.left.to_c(level+2)};\n" # Compute the right. res << (" " * ((level+1)*3)) res << "src1 = #{self.right.to_c(level+2)};\n" res << (" " * ((level+1)*3)) # Compute the current binary operation. case self.operator when :+ then res += "dst = add_value(src0,src1,dst);\n" when :- then res += "dst = sub_value(src0,src1,dst);\n" when :* then res += "dst = mul_value(src0,src1,dst);\n" when :/ then res += "dst = div_value(src0,src1,dst);\n" when :% then res += "dst = mod_value(src0,src1,dst);\n" when :** then res += "dst = pow_value(src0,src1,dst);\n" when :& then res += "dst = and_value(src0,src1,dst);\n" when :| then res += "dst = or_value(src0,src1,dst);\n" when :^ then res += "dst = xor_value(src0,src1,dst);\n" when :<<,:ls then res += "dst = shift_left_value(src0,src1,dst);\n" when :>>,:rs then res += "dst = shift_right_value(src0,src1,dst);\n" when :lr then res += "dst = rotate_left_value(src0,src1,dst);\n" when :rr then res += "dst = rotate_right_value(src0,src1,dst);\n" when :== then res += "dst = equal_value(src0,src1,dst);\n" + "dst = reduce_or_value(dst,dst);" when :!= then # res += "dst = not_equal_value(src0,src1,dst);\n" res += "dst = xor_value(src0,src1,dst);\n" + "dst = reduce_or_value(dst,dst);" when :> then res += "dst = greater_value(src0,src1,dst);\n" when :< then res += "dst = lesser_value(src0,src1,dst);\n" when :>= then res += "dst = greater_equal_value(src0,src1,dst);\n" when :<= then res += "dst = lesser_equal_value(src0,src1,dst);\n" else raise "Invalid binary operator: #{self.operator}." end # Restore the state of the value pool. res << (" " * ((level+1)*3)) res << "set_value_pos(pool_state);\n" # Close the computation. res << (" " * (level*3)) res << "dst; })" return res end |
#to_change(mode) ⇒ Object
Method called when two or more expression terms are present. When translating par into seq mode = seq, when translating seq to par mode = par. Search recursively and replace if hash matches identifier.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 71 def to_change(mode) # Recursively search the left side and the right side, check the identifier and replace it. if self.left.is_a? (Binary) then # If there is an expression on the left side of the right side, to_chang is executed again. left = self.left.to_change(mode) else # If you need to replace the variable, replace it. Otherwise we will get a clone. if $fm.fm_par.has_key?(self.left.to_verilog) && mode == :par then left = $fm.fm_par["#{self.left.to_verilog}"] elsif $fm.fm_seq.has_key?(self.left.to_verilog) && mode == :seq then left = $fm.fm_seq["#{self.left.to_verilog}"] else left = self.left.clone end end if self.right.is_a? (Binary) then # Recursively search the right side and the right side, check the identifier and replace it. right = self.right.to_change(mode) else # If you need to replace the variable, replace it. Otherwise we will get a clone. if $fm.fm_par.has_key?(self.right.to_verilog) && mode == :par then right = $fm.fm_par["#{self.right.to_verilog}"] elsif $fm.fm_seq.has_key?(self.right.to_verilog) && mode == :seq then right = $fm.fm_seq["#{self.right.to_verilog}"] else right = self.right.clone end end # After confirmation, we create and return an expression. return Binary.new(self.type,self.operator,left.clone,right.clone) end |
#to_hdr(level = 0) ⇒ Object
Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.
599 600 601 602 |
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 599 def to_hdr(level = 0) return "(" + self.left.to_hdr(level) + self.operator.to_s + self.right.to_hdr(level) + ")" end |
#to_high ⇒ Object
Creates a new high binary expression.
426 427 428 429 430 |
# File 'lib/HDLRuby/hruby_low2high.rb', line 426 def to_high return HDLRuby::High::Binary.new(self.type.to_high,self.operator, self.left.to_high, self.right.to_high) end |
#to_verilog ⇒ Object
Converts the system to Verilog code.
64 65 66 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 64 def to_verilog return "(#{self.left.to_verilog} #{self.operator} #{self.right.to_verilog})" end |
#to_vhdl(level = 0, std_logic = false) ⇒ Object
Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object. +std_logic+ tells if std_logic computation is to be done.
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1273 def to_vhdl(level = 0, std_logic = false) # Shifts/rotate require function call. if [:<<, :>>, :ls, :rs, :lr, :rr].include?(self.operator) then # Generate the function name. case self.operator when :<<, :ls func = "shift_left" when :>>, :rs func = "shift_right" when :lr func = "rotate_left" when :rr function = "rotate_right" else raise AnyError, "Internal unexpected error." end res = Low2VHDL.unarith_cast(self) + "(#{func}(" + Low2VHDL.to_arith(self.left) + "," + Low2VHDL.to_arith(self.right) + "))" res += "(0)" if std_logic # Force std_logic if required. return res end # Usual operators. # Generate the operator string. case self.operator when :& # puts "self.left.to_vhdl=#{self.left.to_vhdl}" # puts "self.right.to_vhdl=#{self.right.to_vhdl}" # puts "self.left.type=#{self.left.type.to_vhdl}" # puts "self.right.type=#{self.right.type.to_vhdl}" # puts "self.type=#{self.type.to_vhdl}" opr = " and " when :| opr = " or " when :^ opr = " xor " when :== opr = " = " when :!= opr = " /= " else opr = self.operator.to_s end # Is the operator arithmetic? if [:+, :-, :*, :/, :%].include?(self.operator) then # Yes, type conversion my be required by VHDL standard. res = "#{Low2VHDL.unarith_cast(self)}(" + Low2VHDL.to_arith(self.left) + opr + Low2VHDL.to_arith(self.right) + ")" res += "(0)" if std_logic # Force std_logic if required. return res # Is it a comparison ? elsif [:>, :<, :>=, :<=, :==, :!=].include?(self.operator) then # Generate comparison operation return "(" + self.left.to_vhdl(level) + opr + Low2VHDL.to_type(self.left.type,self.right) + ")" else # No, simply generate the binary operation if std_logic then return "(" + self.left.to_vhdl(level,std_logic) + opr + self.right.to_vhdl(level,std_logic) + ")" else return "(" + self.left.to_vhdl(level) + opr + Low2VHDL.to_type(self.left.type,self.right) + ")" end end end |
#use_name?(*names) ⇒ Boolean
Tell if the expression includes a signal whose name is one of +names+.
4868 4869 4870 4871 |
# File 'lib/HDLRuby/hruby_low.rb', line 4868 def use_name?(*names) # Recurse on the left and the right. return @left.use_name?(*names) || @right.use_name?(*names) end |