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_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
Overview
Extends the Binary class with functionality for converting booleans in assignments to select operators.
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.
-
#clone ⇒ Object
Clones the binary operator (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.
-
#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::High code.
-
#to_change(mode) ⇒ Object
Method called when two or more expression terms are present.
-
#to_high(level = 0) ⇒ Object
Generates the text of the equivalent HDLRuby::High code.
-
#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)
4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 |
# File 'lib/HDLRuby/hruby_low.rb', line 4175 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.
4167 4168 4169 |
# File 'lib/HDLRuby/hruby_low.rb', line 4167 def left @left end |
#right ⇒ Object (readonly)
The right child.
4170 4171 4172 |
# File 'lib/HDLRuby/hruby_low.rb', line 4170 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.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 197 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 |
#clone ⇒ Object
Clones the binary operator (deeply)
4249 4250 4251 4252 |
# File 'lib/HDLRuby/hruby_low.rb', line 4249 def clone return Binary.new(@type, self.operator, @left.clone, @right.clone) end |
#each_node(&ruby_block) ⇒ Object Also known as: each_expression
Iterates over the expression children if any.
4208 4209 4210 4211 4212 4213 4214 |
# File 'lib/HDLRuby/hruby_low.rb', line 4208 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.
4219 4220 4221 4222 4223 4224 4225 4226 4227 |
# File 'lib/HDLRuby/hruby_low.rb', line 4219 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.
4232 4233 4234 4235 4236 4237 4238 4239 4240 |
# File 'lib/HDLRuby/hruby_low.rb', line 4232 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.
4192 4193 4194 4195 4196 4197 4198 4199 4200 |
# File 'lib/HDLRuby/hruby_low.rb', line 4192 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.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 255 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.
4203 4204 4205 |
# File 'lib/HDLRuby/hruby_low.rb', line 4203 def hash return [super,@left,@right].hash end |
#map_nodes!(&ruby_block) ⇒ Object
Maps on the child.
1421 1422 1423 1424 1425 1426 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1421 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.
1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1434 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.
1399 1400 1401 1402 1403 1404 1405 1406 1407 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1399 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.
1410 1411 1412 1413 1414 1415 1416 1417 1418 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1410 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::High code. +level+ is the hierachical level of the object.
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 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 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 1656 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.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 63 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_high(level = 0) ⇒ Object
Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.
599 600 601 602 |
# File 'lib/HDLRuby/hruby_low2high.rb', line 599 def to_high(level = 0) return "(" + self.left.to_high(level) + self.operator.to_s + self.right.to_high(level) + ")" end |
#to_verilog ⇒ Object
Converts the system to Verilog code.
56 57 58 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 56 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.
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 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 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1249 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+.
4243 4244 4245 4246 |
# File 'lib/HDLRuby/hruby_low.rb', line 4243 def use_name?(*names) # Recurse on the left and the right. return @left.use_name?(*names) || @right.use_name?(*names) end |