Class: HDLRuby::Low::Binary
- Inherits:
-
Operation
- Object
- Expression
- Operation
- HDLRuby::Low::Binary
- Defined in:
- 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
Describes an binary operation.
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
(also: #map_expressions!)
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(res, level = 0) ⇒ Object
return res end 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!, #fix_scope_refnames!, #leftvalue?, #replace_names!, #rightvalue?, #set_type!, #signal2subs!, #statement, #to_c_expr, #to_viz_names
Methods included from Low2Symbol
Methods included from Hparent
#absolute_ref, #hierarchy, #no_parent!, #scope
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)
5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 |
# File 'lib/HDLRuby/hruby_low.rb', line 5394 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.
5386 5387 5388 |
# File 'lib/HDLRuby/hruby_low.rb', line 5386 def left @left end |
#right ⇒ Object (readonly)
The right child.
5389 5390 5391 |
# File 'lib/HDLRuby/hruby_low.rb', line 5389 def right @right end |
Instance Method Details
#boolean? ⇒ Boolean
Tells if the expression is boolean.
131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 131 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.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 231 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.
247 248 249 250 251 252 253 254 255 |
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 247 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) self.set_left!(self.left.casts_without_expression!) self.set_right!(self.right.casts_without_expression!) return self end |
#clone ⇒ Object
Clones the binary operator (deeply)
5490 5491 5492 5493 |
# File 'lib/HDLRuby/hruby_low.rb', line 5490 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.
5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 |
# File 'lib/HDLRuby/hruby_low.rb', line 5419 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.
5449 5450 5451 5452 5453 5454 5455 |
# File 'lib/HDLRuby/hruby_low.rb', line 5449 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.
5460 5461 5462 5463 5464 5465 5466 5467 5468 |
# File 'lib/HDLRuby/hruby_low.rb', line 5460 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.
5473 5474 5475 5476 5477 5478 5479 5480 5481 |
# File 'lib/HDLRuby/hruby_low.rb', line 5473 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.
5433 5434 5435 5436 5437 5438 5439 5440 5441 |
# File 'lib/HDLRuby/hruby_low.rb', line 5433 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.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 311 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.
5444 5445 5446 |
# File 'lib/HDLRuby/hruby_low.rb', line 5444 def hash return [super,@left,@right].hash end |
#immutable? ⇒ Boolean
Tells if the expression is immutable (cannot be written.)
5411 5412 5413 5414 |
# File 'lib/HDLRuby/hruby_low.rb', line 5411 def immutable? # Immutable if both children are immutable. return left.immutable? && right.immutable? end |
#map_nodes!(&ruby_block) ⇒ Object Also known as: map_expressions!
Maps on the child.
1465 1466 1467 1468 1469 1470 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1465 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.
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1480 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.
1443 1444 1445 1446 1447 1448 1449 1450 1451 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1443 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.
1454 1455 1456 1457 1458 1459 1460 1461 1462 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1454 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(res, level = 0) ⇒ Object
return res end Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)
2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 2545 def to_c(res, level = 0) # Save the value pool state. res << (" " * (level*3)) << "PV;\n" # Generate the left computation. self.left.to_c(res,level) # Generate the right computation. self.right.to_c(res,level) # Generate the binary. res << (" " * (level*3)) res << "binary(" # Set the operation. case self.operator when :+ then res << "&add_value" when :- then res << "&sub_value" when :* then res << "&mul_value" when :/ then res << "&div_value" when :% then res << "&mod_value" when :** then res << "&pow_value" when :& then res << "&and_value" when :| then res << "&or_value" when :^ then res << "&xor_value" when :<<,:ls then res << "&shift_left_value" when :>>,:rs then res << "&shift_right_value" when :lr then res << "&rotate_left_value" when :rr then res << "&rotate_right_value" when :== then res << "&equal_value_c" when :!= then res << "¬_equal_value_c" when :> then res << "&greater_value" when :< then res << "&lesser_value" when :>= then res << "&greater_equal_value" when :<= then res << "&lesser_equal_value" else raise "Invalid binary operator: #{self.operator}." end # Close the computation. res << ");\n" # Restore the value pool state. res << (" " * (level*3)) << "RV;\n" 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.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 188 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 FmI.fm_par.has_key?(self.left.to_verilog) && mode == :par then left = FmI.fm_par["#{self.left.to_verilog}"] elsif FmI.fm_seq.has_key?(self.left.to_verilog) && mode == :seq then left = FmI.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 FmI.fm_par.has_key?(self.right.to_verilog) && mode == :par then right = FmI.fm_par["#{self.right.to_verilog}"] elsif FmI.fm_seq.has_key?(self.right.to_verilog) && mode == :seq then right = FmI.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.
617 618 619 620 |
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 617 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.
460 461 462 463 464 |
# File 'lib/HDLRuby/hruby_low2high.rb', line 460 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.
171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 171 def to_verilog # In HDLRuby if on term is signed and the other is not, the # computation is signed. if self.left.type.signed? and self.right.type.unsigned? then return "(#{self.left.to_verilog} #{self.operator} " + "$signed({1'b0,#{self.right.to_verilog}}))" elsif self.left.type.unsigned? and right.type.signed? then return "($signed({1'b0,#{self.left.to_verilog}})" + " #{self.operator} #{self.right.to_verilog})" else return "(#{self.left.to_verilog} #{self.operator} #{self.right.to_verilog})" end 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.
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 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1313 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+.
5484 5485 5486 5487 |
# File 'lib/HDLRuby/hruby_low.rb', line 5484 def use_name?(*names) # Recurse on the left and the right. return @left.use_name?(*names) || @right.use_name?(*names) end |