Class: HDLRuby::Low::Select
- Inherits:
-
Operation
- Object
- Expression
- Operation
- HDLRuby::Low::Select
- 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 a selection operation (generalization of the ternary operator).
NOTE: choice is using the value of +select+ as an index.
Direct Known Subclasses
Constant Summary
Constants included from Low2Symbol
Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable
Instance Attribute Summary collapse
-
#select ⇒ Object
readonly
The selection child (connection).
Attributes inherited from Operation
Attributes inherited from Expression
Attributes included from Hparent
Instance Method Summary collapse
-
#add_choice(choice) ⇒ Object
Adds a +choice+.
-
#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 select (deeply).
-
#delete_choice!(choice) ⇒ Object
Deletes a choice.
-
#each_choice(&ruby_block) ⇒ Object
Iterates over the choices.
-
#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 selection where +type+ is the expected type of the condition if any.
-
#get_choice(index) ⇒ Object
Gets a choice by +index+.
-
#hash ⇒ Object
Hash function.
-
#immutable? ⇒ Boolean
Tells if the expression is immutable (cannot be written.).
-
#initialize(type, operator, select, *choices) ⇒ Select
constructor
Creates a new operator with +type+ selecting from the value of +select+ one of the +choices+.
-
#map_choices!(&ruby_block) ⇒ Object
Maps on the choices.
-
#map_nodes!(&ruby_block) ⇒ Object
(also: #map_expressions!)
Maps on the children.
-
#replace_expressions!(node2rep) ⇒ Object
Replaces sub expressions using +node2rep+ table indicating the node to replace and the corresponding replacement.
-
#set_select!(select) ⇒ Object
Sets the select.
-
#to_c(res, level = 0) ⇒ Object
Generates the C text of the equivalent HDLRuby code.
-
#to_hdr(level = 0) ⇒ Object
Generates the text of the equivalent hdr text.
-
#to_high ⇒ Object
Creates a new high select 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
Methods included from Low2Symbol
Methods included from Hparent
#absolute_ref, #hierarchy, #no_parent!, #scope
Constructor Details
#initialize(type, operator, select, *choices) ⇒ Select
Creates a new operator with +type+ selecting from the value of +select+ one of the +choices+. def initialize(operator,select,*choices)
5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 |
# File 'lib/HDLRuby/hruby_low.rb', line 5506 def initialize(type,operator,select,*choices) # Initialize as a general operation. # super(operator) super(type,operator) # Check and set the selection. unless select.is_a?(Expression) raise AnyError, "Invalid class for an expression: #{select.class}" end @select = select # And set its parent. select.parent = self # Check and set the choices. @choices = [] choices.each do |choice| self.add_choice(choice) end end |
Instance Attribute Details
#select ⇒ Object (readonly)
The selection child (connection).
5501 5502 5503 |
# File 'lib/HDLRuby/hruby_low.rb', line 5501 def select @select end |
Instance Method Details
#add_choice(choice) ⇒ Object
Adds a +choice+.
5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 |
# File 'lib/HDLRuby/hruby_low.rb', line 5574 def add_choice(choice) unless choice.is_a?(Expression) raise AnyError, "Invalid class for an expression: #{choice.class}" end # Set the parent of the choice. choice.parent = self # And add it. @choices << choice choice end |
#boolean? ⇒ Boolean
Tells if the expression is boolean.
152 153 154 155 |
# File 'lib/HDLRuby/hruby_low_with_bool.rb', line 152 def boolean? # Boolean if all the choices are boolean. return !self.each_choice.any? {|c| !c.boolean? } end |
#boolean_in_assign2select ⇒ Object
Converts booleans in assignments to select operators.
265 266 267 268 269 270 271 272 273 |
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 265 def boolean_in_assign2select # Recurse on the sub node. return Select.new(self.type,"?", self.select.boolean_in_assign2select, *self.each_choice.map do |choice| choice.boolean_in_assign2select end ) return self end |
#casts_without_expression! ⇒ Object
Extracts the expressions from the casts.
265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 265 def casts_without_expression! # Recurse on the sub node. # return Select.new(self.type,"?", # self.select.casts_without_expression, # *self.each_choice.map do |choice| # choice.casts_without_expression # end ) self.set_select!(self.select.casts_without_expression!) self.map_choices! { |choice| choice.casts_without_expression! } return self end |
#clone ⇒ Object
Clones the select (deeply)
5647 5648 5649 5650 |
# File 'lib/HDLRuby/hruby_low.rb', line 5647 def clone return Select.new(@type, self.operator, @select.clone, *@choices.map {|choice| choice.clone } ) end |
#delete_choice!(choice) ⇒ Object
Deletes a choice.
1537 1538 1539 1540 1541 1542 1543 1544 1545 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1537 def delete_choice!(choice) if @choices.include?(choice) then # The choice is present, delete it. @choices.delete(choice) # And remove its parent. choice.parent = nil end choice end |
#each_choice(&ruby_block) ⇒ Object
Iterates over the choices.
Returns an enumerator if no ruby block is given.
5589 5590 5591 5592 5593 5594 |
# File 'lib/HDLRuby/hruby_low.rb', line 5589 def each_choice(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_choice) unless ruby_block # A ruby block? Apply it on each choice. @choices.each(&ruby_block) end |
#each_deep(&ruby_block) ⇒ Object
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 |
# File 'lib/HDLRuby/hruby_low.rb', line 5537 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 select. self.select.each_deep(&ruby_block) # Then apply on the choices. self.each_choice do |choice| choice.each_deep(&ruby_block) end end |
#each_node(&ruby_block) ⇒ Object Also known as: each_expression
Iterates over the expression children if any.
5602 5603 5604 5605 5606 5607 5608 |
# File 'lib/HDLRuby/hruby_low.rb', line 5602 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(@select) @choices.each(&ruby_block) end |
#each_node_deep(&ruby_block) ⇒ Object
Iterates over the nodes deeply if any.
5613 5614 5615 5616 5617 5618 5619 5620 5621 |
# File 'lib/HDLRuby/hruby_low.rb', line 5613 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. @select.each_node_deep(&ruby_block) @choices.each { |choice| choice.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.
5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 |
# File 'lib/HDLRuby/hruby_low.rb', line 5626 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 Select" # A ruby block? # Recurse on the children. self.select.each_ref_deep(&ruby_block) self.each_choice do |choice| choice.each_ref_deep(&ruby_block) end end |
#eql?(obj) ⇒ Boolean
Comparison for hash: structural comparison.
5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 |
# File 'lib/HDLRuby/hruby_low.rb', line 5553 def eql?(obj) # General comparison. return false unless super(obj) # Specific comparison. return false unless obj.is_a?(Select) return false unless @select.eql?(obj.select) idx = 0 obj.each_choice do |choice| return false unless @choices[idx].eql?(choice) idx += 1 end return false unless idx == @choices.size return true end |
#explicit_types(type = nil) ⇒ Object
Explicit the types conversions in the selection where +type+ is the expected type of the condition if any.
336 337 338 339 340 341 342 |
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 336 def explicit_types(type = nil) # If there is no type to match, use the one of the selection. type = self.type unless type # Each choice child must match the type. return Select.new(type,self.operator,self.select.clone, *self.each_choice.map { |choice| choice.explicit_types(type)}) end |
#get_choice(index) ⇒ Object
Gets a choice by +index+.
5597 5598 5599 |
# File 'lib/HDLRuby/hruby_low.rb', line 5597 def get_choice(index) return @choices[index] end |
#hash ⇒ Object
Hash function.
5569 5570 5571 |
# File 'lib/HDLRuby/hruby_low.rb', line 5569 def hash return [super,@select,@choices].hash end |
#immutable? ⇒ Boolean
Tells if the expression is immutable (cannot be written.)
5526 5527 5528 5529 5530 5531 5532 |
# File 'lib/HDLRuby/hruby_low.rb', line 5526 def immutable? # Immutable if children are all immutable. return self.select.constant && self.each_choice.reduce(true) do |r,c| r && c.immutable? end end |
#map_choices!(&ruby_block) ⇒ Object
Maps on the choices.
1528 1529 1530 1531 1532 1533 1534 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1528 def map_choices!(&ruby_block) @choices.map! do |choice| choice = ruby_block.call(choice) choice.parent = self unless choice.parent choice end end |
#map_nodes!(&ruby_block) ⇒ Object Also known as: map_expressions!
Maps on the children.
1548 1549 1550 1551 1552 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1548 def map_nodes!(&ruby_block) @select = ruby_block.call(@select) @select.parent = self unless @select.parent map_choices!(&ruby_block) 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.
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1562 def replace_expressions!(node2rep) # First recurse on the children. res = {} self.each_node do |node| res.merge!(node.replace_expressions!(node2rep)) end # Is there a replacement to do on the select? rep = node2rep[self.select] if rep then # Yes, do it. rep = rep.clone node = self.select # node.set_parent!(nil) self.set_select!(rep) # And register the replacement. res[node] = rep end # Is there a replacement of on a choice. self.map_choices! do |choice| rep = node2rep[choice] if rep then # Yes, do it. rep = rep.clone node = choice # node.set_parent!(nil) # And register the replacement. res[node] = rep rep else choice end end return res end |
#set_select!(select) ⇒ Object
Sets the select.
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 |
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1516 def set_select!(select) # Check and set the selection. unless select.is_a?(Expression) raise AnyError, "Invalid class for an expression: #{select.class}" end @select = select # And set its parent. select.parent = self end |
#to_c(res, level = 0) ⇒ Object
Generates the C text of the equivalent HDLRuby code.
+level+ is the hierachical level of the object.
def to_c(level = 0)
def to_c(res,level = 0) # Gather the possible selection choices. expressions = self.each_choice.to_a # Create the resulting string. # res = "( res << "({\n" # Overrides the upper sel, src0, src1, ..., and dst... # And allocates a new value for dst. res << (" " * ((level+1)*3)) res << "Value sel;\n" res << (" " * ((level+1)*3)) res << "Value " res << expressions.size.times.map do |i| "src#{i" end.join(",") res << ";\n" res << (" " * ((level+1)*3)) res << "Value 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 selection. res << (" " * ((level+1)*3)) # res << "sel = #HDLRuby::Low::Select.selfself.selectself.select.to_c(level+2);\n" res << "sel = " self.select.to_c(res,level+2) res << ";\n" # Compute each choice expression. expressions.each_with_index do |expr,i| res << (" " * ((level+1)*3)) # res << "src#i = #HDLRuby::Low::Select.exprexpr.to_c(level+2);\n" res << "src#i = " expr.to_c(res,level+2) res << ";\n" end # Compute the resulting selection. res << (" " * ((level+1)*3)) res << "select_value(sel,dst,#HDLRuby::Low::Select.expressionsexpressions.size," # res << "#{ |i| "src#{i" }.join(",")}" res << expressions.size.times.map { |i| "src#i" }.join(",") res << ");\n" # 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 Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object.
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 |
# File 'lib/HDLRuby/hruby_low2c.rb', line 2665 def to_c(res,level = 0) # Save the value pool state. res << (" " * (level*3)) << "PV;\n" # Gather the possible selection choices. expressions = self.each_choice.to_a # Create the resulting string. # Compute the selection. self.select.to_c(res,level) # Compute each choice expression. expressions.each_with_index do |expr,i| expr.to_c(res,level) end # Compute the resulting selection. res << (" " * (level*3)) res << "hselect(#{expressions.size});\n" # Restore the value pool state. res << (" " * (level*3)) << "RV;\n" return res end |
#to_hdr(level = 0) ⇒ Object
Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.
629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 629 def to_hdr(level = 0) # The resulting string. res = "" # Generate the header. res << "mux(" + self.select.to_hdr(level) << ", " # Generate the choices res << self.each_choice.map do |choice| choice.to_hdr(level+1) end.join(", ") # Close the select. res << ")" # Return the resulting string. return res end |
#to_high ⇒ Object
Creates a new high select expression.
472 473 474 475 476 |
# File 'lib/HDLRuby/hruby_low2high.rb', line 472 def to_high return HDLRuby::High::Select(self.type.to_high,self.operator, self.select.to_high, self.each_choice.map { |ch| ch.to_high }) end |
#to_verilog ⇒ Object
Converts the system to Verilog code.
1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 |
# File 'lib/HDLRuby/hruby_verilog.rb', line 1627 def to_verilog # Outputs the first and second choices (choice (0) and choice (1)). # return "#{self.select.to_verilog} == 1 #{self.operator} #{self.get_choice(0).to_verilog} : #{self.get_choice(1).to_verilog}" res = "" sels = self.select.to_verilog @choices[0..-2].each_with_index do |choice,i| res << "#{sels} == #{i} ? #{choice.to_verilog} : " end res << @choices[-1].to_verilog return res 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.
NOTE: assumes the existance of the mux function.
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 |
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1390 def to_vhdl(level = 0, std_logic = false) # The resulting string. res = "" # The number of arguments. num = @choices.size # Generate the header. res << "#{Low2VHDL.mux_name(self.type.to_vhdl(level),num)}(" + self.select.to_vhdl(level) << ", " # Generate the choices res << self.each_choice.map do |choice| choice.to_vhdl(level+1) end.join(", ") # Close the select. res << ")" # Return the resulting string. return res end |
#use_name?(*names) ⇒ Boolean
Tell if the expression includes a signal whose name is one of +names+.
5639 5640 5641 5642 5643 5644 |
# File 'lib/HDLRuby/hruby_low.rb', line 5639 def use_name?(*names) # Recurse on the select. return true if @select.use_name?(*names) # Recurse on the choices. return @choices.any? { |choice| choice.use_name?(*names) } end |