class HDLRuby::Low::If
Describes an if statement.
Describes an if statement.
Extends the If
class with generation of C text.
Extends the If
class with generation of hdr text.
Add the conversion to high.
Extends the If
class with functionality for converting par block to seq.
Extends the If
class with generation of HDLRuby::High
text.
Extends the If
class with functionality for converting booleans in assignments to select operators.
Extends the If
class with functionality for extracting expressions from cast.
Extends the If
class with functionality for breaking assingments to concats.
Extends the If
class with fixing of types and constants.
Describes an if statement.
Extends the If
class with separation between signals and variables.
Extends the If
class with functionality for moving the declarations to the upper namespace.
Extends the If
class with functionality for breaking assingments to concats.
Extends the If
class with functionality for converting select expressions to case statements.
Used to transrate if. Enhance If
with generation of verilog code.
Attributes
The condition
The yes and no statements
The yes and no statements
Public Class Methods
Creates a new if statement with a condition
and a yes
and no
blocks.
# File lib/HDLRuby/hruby_low.rb, line 3049 def initialize(condition, yes, no = nil) # Check and set the condition. unless condition.is_a?(Expression) raise AnyError, "Invalid class for a condition: #{condition.class}" end super() @condition = condition # And set its parent. condition.parent = self # Check and set the yes statement. unless yes.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{yes.class}" end @yes = yes # And set its parent. yes.parent = self # Check and set the yes statement. if no and !no.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{no.class}" end @no = no # And set its parent. no.parent = self if no # Initialize the list of alternative if statements (elsif) @noifs = [] end
Public Instance Methods
Adds an alternative if statement (elsif) testing next_cond
and executing next_yes
when the condition is met.
# File lib/HDLRuby/hruby_low.rb, line 3132 def add_noif(next_cond, next_yes) # Check the condition. unless next_cond.is_a?(Expression) raise AnyError, "Invalid class for a condition: #{next_cond.class}" end # And set its parent. next_cond.parent = self # Check yes statement. unless next_yes.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{next_yes.class}" end # And set its parent. next_yes.parent = self # Add the statement. @noifs << [next_cond,next_yes] end
Converts the par sub blocks to seq.
# File lib/HDLRuby/hruby_low2seq.rb, line 102 def blocks2seq! # Convert each sub block. # If block. self.yes.blocks2seq! # Elsif blocks self.each_noif do |cond, stmnt| stmnt.blocks2seq! end # Else block if any. self.no.blocks2seq! if self.no return self end
Converts booleans in assignments to select operators.
# File lib/HDLRuby/hruby_low_bool2select.rb, line 84 def boolean_in_assign2select! # No need to apply on condition! # # Apply on the condition. # self.set_condition!(self.condition.boolean_in_assign2select) # Apply on the yes. self.yes.boolean_in_assign2select! # Apply on the noifs. @noifs.map! do |cond,stmnt| # No need to apply on condition! # [cond.boolean_in_assign2select,stmnt.boolean_in_assign2select!] [cond,stmnt.boolean_in_assign2select!] end # Apply on the no if any. self.no.boolean_in_assign2select! if self.no return self end
Extracts the expressions from the casts.
# File lib/HDLRuby/hruby_low_casts_without_expression.rb, line 85 def casts_without_expression! # Apply on the condition. self.set_condition!(self.condition.casts_without_expression) # Apply on the yes. self.yes.casts_without_expression! # Apply on the noifs. @noifs.map! do |cond,stmnt| [cond.casts_without_expression,stmnt.casts_without_expression!] end # Apply on the no if any. self.no.casts_without_expression! if self.no return self end
Clones the If
(deeply)
# File lib/HDLRuby/hruby_low.rb, line 3259 def clone # Duplicate the if. res = If.new(@condition.clone, @yes.clone, @no ? @no.clone : nil) # Duplicate the alternate ifs @noifs.each do |next_cond,next_yes| res.add_noif(next_cond.clone,next_yes.clone) end return res end
Deletes an alternate if.
# File lib/HDLRuby/hruby_low_mutable.rb, line 726 def delete_noif!(noif) if @noifs.include?(noif) then # The noif is present, delete it. @noifs.delete(noif) # And remove its parent. noif.parent = nil end noif end
Removes the signals and corresponding assignments whose name is not in keep
.
# File lib/HDLRuby/hruby_low_cleanup.rb, line 128 def delete_unless!(keep) # Recurse on the sub statements. # Yes. self.yes.delete_unless!(keep) # Noifs. self.each_noif { |cond,stmnt| stmnt.delete_unless!(keep) } # No if any. self.no.delete_unless!(keep) if self.no end
Iterates over the sub blocks.
# File lib/HDLRuby/hruby_low.rb, line 3211 def each_block(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block) unless ruby_block # A ruby block? # Apply it on the yes, the alternate ifs and the no blocks. ruby_block.call(@yes) if @yes.is_a?(Block) @noifs.each do |next_cond,next_yes| ruby_block.call(next_yes) if next_yes.is_a?(Block) end ruby_block.call(@no) if @no.is_a?(Block) end
Iterates over all the blocks contained in the current block.
# File lib/HDLRuby/hruby_low.rb, line 3239 def each_block_deep(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_block_deep) unless ruby_block # A ruby block? # Apply it on the yes, the alternate ifs and the no blocks. @yes.each_block_deep(&ruby_block) @noifs.each do |next_cond,next_yes| next_yes.each_block_deep(&ruby_block) end # @no.each_block_deep(&ruby_block) if @no.is_a?(Block) @no.each_block_deep(&ruby_block) if @no end
Iterates over each object deeply.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 3081 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 condition. self.condition.each_deep(&ruby_block) # Then apply on the yes. self.yes.each_deep(&ruby_block) # The apply on the no. self.no.each_deep(&ruby_block) # Then apply on the alternate ifs. self.each_noif do |cond,stmnt| cond.each_deep(&ruby_block) stmnt.each_deep(&ruby_block) end end
Iterates over the children (including the condition).
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 3180 def each_node(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_node) unless ruby_block # A ruby block? # Appy it on the children. ruby_block.call(@condition) ruby_block.call(@yes) self.each_noif do |next_cond,next_yes| ruby_block.call(next_cond) ruby_block.call(next_yes) end ruby_block.call(@no) if @no end
Iterates over the nodes deeply if any.
# File lib/HDLRuby/hruby_low.rb, line 3195 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 @condition.each_node_deep(&ruby_block) @yes.each_node_deep(&ruby_block) self.each_noif do |next_cond,next_yes| next_cond.each_node_deep(&ruby_block) next_yes.each_node_deep(&ruby_block) end @no.each_node_deep(&ruby_block) if @no end
Iterates over the alternate if statements (elsif).
# File lib/HDLRuby/hruby_low.rb, line 3152 def each_noif(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_noif) unless ruby_block # A ruby block? # Appy it on the alternate if statements. @noifs.each do |next_cond,next_yes| yield(next_cond,next_yes) end end
Iterates over each sub statement if any.
Returns an enumerator if no ruby block is given.
# File lib/HDLRuby/hruby_low.rb, line 3165 def each_statement(&ruby_block) # No ruby block? Return an enumerator. return to_enum(:each_statement) unless ruby_block # A ruby block? # Appy it on the statement children. ruby_block.call(@yes) self.each_noif do |next_cond,next_yes| ruby_block.call(next_yes) end ruby_block.call(@no) if @no end
Iterates over all the stamements of the block and its sub blocks.
# File lib/HDLRuby/hruby_low.rb, line 3224 def each_statement_deep(&ruby_block) # No ruby statement? Return an enumerator. return to_enum(:each_statement_deep) unless ruby_block # A ruby block? # Apply it on self. ruby_block.call(self) # And recurse on the alternate ifs and the no statements. @yes.each_statement_deep(&ruby_block) @noifs.each do |next_cond,next_yes| next_yes.each_statement_deep(&ruby_block) end @no.each_statement_deep(&ruby_block) if @no.is_a?(Block) end
Comparison for hash: structural comparison.
# File lib/HDLRuby/hruby_low.rb, line 3100 def eql?(obj) return false unless obj.is_a?(If) return false unless @condition.eql?(obj.condition) return false unless @yes.eql?(obj.yes) return false unless @no.eql?(obj.no) return true end
Explicit the types conversions in the if.
# File lib/HDLRuby/hruby_low_fix_types.rb, line 110 def explicit_types! # Recurse on the condition: it must be a Bit. self.set_condition!(self.condition.explicit_types(Bit)) # Recurse on the yes block. self.yes.explicit_types! # Recruse on the alternative ifs, the conditions must be Bit. self.map_noifs! do |cond,block| [ cond.explicit_types(Bit), block.explicit_types! ] end # Recurse on the no block. self.no.explicit_types! if self.no return self end
Extract the declares from the scope and returns them into an array.
NOTE: do not recurse into the sub scopes or behaviors!
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 533 def extract_declares! # The extracted declares. decls = [] # Recurse on the sub blocks. # Yes. decls << self.yes.extract_declares! # Noifs. decls << self.each_noif.map do |cond,stmnt| stmnt.extract_declares! end # No if any. decls << self.no.extract_declares! if self.no # Returns the extracted declares. return decls end
Extract the Select
expressions.
NOTE: work on the condition only.
# File lib/HDLRuby/hruby_low_without_select.rb, line 186 def extract_selects! selects = [] self.set_condition!(self.condition.extract_selects_to!(selects)) return selects end
Hash
function.
# File lib/HDLRuby/hruby_low.rb, line 3109 def hash return [@condition,@yes,@no].hash end
Maps on the children (including the condition).
# File lib/HDLRuby/hruby_low_mutable.rb, line 748 def map_nodes!(&ruby_block) @condition = ruby_block.call(@condition) @yes = ruby_block.call(@yes) self.map_noifs! do |cond,stmnt| [ruby_block.call(cond), ruby_block.call(stmnt)] end # @noifs.map! do |cond,stmnt| # cond = ruby_block.call(cond) # stmnt = ruby_block.call(stmnt) # cond.parent = self unless cond.parent # stmnt.parent = self unless stmnt.parent # [cond,stmnt] # end @no = ruby_block.call(@no) if @no end
Maps on the noifs.
# File lib/HDLRuby/hruby_low_mutable.rb, line 737 def map_noifs!(&ruby_block) @noifs.map! do |cond,stmnt| cond,stmnt = ruby_block.call(cond,stmnt) # cond, stmnt = ruby_block.call(cond), ruby_block.call(stmnt) cond.parent = self unless cond.parent stmnt.parent = self unless stmnt.parent [cond,stmnt] end end
Tell if there is a mix block. mode
is the mode of the upper block.
# File lib/HDLRuby/hruby_low2seq.rb, line 117 def mix?(mode = nil) # Check each sub block. # If block. return true if self.yes.mix?(mode) # Elsif blocks self.each_noif do |cond, stmnt| return true if stmnt.mix?(mode) end # Else block if any. true if self.no && self.no.mix?(mode) end
Sets the no block.
No shoud only be set once, but this is not checked here for sake of flexibility.
# File lib/HDLRuby/hruby_low.rb, line 3117 def no=(no) # if @no != nil then # raise AnyError, "No already set in if statement." # end # Actually better not lock no here. # Check and set the yes statement. unless no.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{no.class}" end @no = no # And set its parent. no.parent = self end
Converts par blocks within seq blocks to seq blocks.
# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 62 def par_in_seq2seq! self.yes.par_in_seq2seq! self.each_noif do |cond,blk| blk.par_in_seq2seq! end self.no.par_in_seq2seq! if self.no end
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.
# File lib/HDLRuby/hruby_low_mutable.rb, line 770 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 condition? rep = node2rep[self.condition] if rep then # Yes, do it. rep = rep.clone node = self.condition # node.set_parent!(nil) self.set_condition!(rep) # And register the replacement. res[node] = rep end return res end
Replaces recursively former
name by nname
until it is redeclared.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 550 def replace_names!(former,nname) # Recurse on the condition. self.condition.replace_names!(former,nname) # Recurse on the yes. self.yes.replace_names!(former,nname) # Recurse on the alternate ifs. self.each_noif do |cond,stmnt| cond.replace_names!(former,nname) stmnt.replace_names!(former,nname) end # Recurse on the no if any. self.no.replace_names!(former,nname) if self.no end
Sets the condition.
# File lib/HDLRuby/hruby_low_mutable.rb, line 692 def set_condition!(condition) # Check and set the condition. unless condition.is_a?(Expression) raise AnyError, "Invalid class for a condition: #{condition.class}" end @condition = condition # And set its parent. condition.parent = self end
Sets the no block.
# File lib/HDLRuby/hruby_low_mutable.rb, line 715 def set_no!(no) # Check and set the yes statement. if no and !no.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{no.class}" end @no = no # And set its parent. no.parent = self if no end
Sets the yes block.
# File lib/HDLRuby/hruby_low_mutable.rb, line 704 def set_yes!(yes) # Check and set the yes statement. unless yes.is_a?(Statement) raise AnyError, "Invalid class for a statement: #{yes.class}" end @yes = yes # And set its parent. yes.parent = self end
Generates the C text of the equivalent HDLRuby
code. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2c.rb, line 1169 def to_c(level = 0) # The result string. res = " " * level*3 # Compute the condition. res << "{\n" res << " " * (level+1)*3 res << "Value cond = " << self.condition.to_c(level+1) << ";\n" # Ensure the condition is testable. res << " " * (level+1)*3 res << "if (is_defined_value(cond)) {\n" # The condition is testable. res << " " * (level+2)*3 res << "if (value2integer(cond)) {\n" # Generate the yes part. res << self.yes.to_c(level+3) res << " " * level*3 res << "}\n" # Generate the alternate if parts. self.each_noif do |cond,stmnt| res << " " * level*3 res << "else if (value2integer(" << cond.to_c(level+1) << ")) {\n" res << stmnt.to_c(level+1) res << " " * level*3 res << "}\n" end # Generate the no part if any. if self.no then res << " " * level*3 res << "else {\n" << self.no.to_c(level+1) res << " " * level*3 res << "}\n" end # Close the if. res << " " * (level+1)*3 res << "}\n" res << " " * (level)*3 res << "}\n" # Return the result. return res end
Generates the content of the h file.
# File lib/HDLRuby/hruby_low2c.rb, line 1211 def to_ch res = "" # Recurse on the sub statements. res << self.yes.to_ch self.each_noif do |cond,stmnt| res << stmnt.to_ch end res << self.no.to_ch if self.no return res end
Generates the text of the equivalent hdr text. level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2hdr.rb, line 350 def to_hdr(level = 0) # The result string. res = " " * (level*3) # Generate the test. res << "hif " << self.condition.to_hdr(level) << " do\n" # Generate the yes part. res << self.yes.to_hdr(level+1) res << " " * (level*3) << "end\n" # Generate the alternate if parts. self.each_noif do |cond,stmnt| res << " " * (level*3) res << "helsif " << cond.to_hdr(level) << " do\n" res << stmnt.to_hdr(level+1) res << " " * (level*3) << "end\n" end # Generate the no part if any. if self.no then res << " " * (level*3) res << "helse do\n" << self.no.to_hdr(level+1) res << " " * (level*3) << "end\n" end # Return the result. return res end
Creates a new high if statement.
# File lib/HDLRuby/hruby_low2high.rb, line 252 def to_high # Is there a no? if self.no then # Yes, create a new if statement with it. res = HDLRuby::High::If.new(self.condition.to_high, self.yes.to_high,self.no.to_high) else # No, create a new if statement without it. res = HDLRuby::High::If.new(self.condition.to_high, self.yes.to_high) end # Add the noifs if any. self.each_noif do |cond,stmnt| res.add_noif(cond.to_high,stmt.to_high) end return res end
Convert the block to seq.
# File lib/HDLRuby/hruby_low_without_parinseq.rb, line 71 def to_seq! self.to_seq! self.each_noif do |cond,blk| blk.to_seq! end self.no.to_seq! if self.no end
Moves the declarations to the upper namespace.
# File lib/HDLRuby/hruby_low_without_namespace.rb, line 520 def to_upper_space! # Recurse on the sub blocks. # Yes. self.yes.to_upper_space! # Noifs. self.each_noif {|cond,stmnt| stmnt.to_upper_space! } # No if any. self.no.to_upper_space! if self.no end
# Converts the system to Verilog
code. def to_verilog
(mode = nil) Converts to Verilog
code, checking adding 'spc' spaces at the begining of each line.
# File lib/HDLRuby/hruby_verilog.rb, line 1490 def to_verilog(spc = 3) $blocking = false result = " " * spc # Indented based on space_count. result << "if (#{self.condition.to_verilog}) " # Check if there is yes (if) and output yes or less. if self.respond_to? (:yes) result << self.yes.to_verilog(spc) end # If noif (else if) exists, it outputs it. # Since noif is directly under, respond_to is unnecessary. self.each_noif do |condition, block| result << "\n#{" "*spc}else if (#{condition.to_verilog}) " result << block.to_verilog(spc) end # Check if there is no (else) and output no or less. if self.no.respond_to?(:mode) result << "\n#{" " * spc}else " result << self.no.to_verilog(spc) end return result end
Generates the text of the equivalent HDLRuby::High
code. vars
is the list of the variables and level
is the hierachical level of the object.
# File lib/HDLRuby/hruby_low2vhd.rb, line 935 def to_vhdl(vars,level = 0) # The result string. res = " " * (level*3) # Generate the test. res << "if (" << Low2VHDL.to_boolean(self.condition) << ") then\n" # Generate the yes part. res << self.yes.to_vhdl(vars,level+1) # Generate the alternate if parts. self.each_noif do |cond,stmnt| res << " " * (level*3) # res << "elsif (" << cond.to_vhdl(level) << ") then\n" res << "elsif (" << Low2VHDL.to_boolean(cond) << ") then\n" res << stmnt.to_vhdl(vars,level+1) end # Generate the no part if any. if self.no then res << " " * (level*3) res << "else\n" << self.no.to_vhdl(vars,level+1) end # Close the if. res << " " * (level*3) res << "end if;\n" # Return the result. return res end
Tell if the statement includes a signal whose name is one of names
. NOTE: for the if check only the condition.
# File lib/HDLRuby/hruby_low.rb, line 3254 def use_name?(*names) return @condition.use_name?(*name) end
Converts to a variable-compatible if where upper
is the upper block if any.
NOTE: the result is a new if.
# File lib/HDLRuby/hruby_low_with_var.rb, line 271 def with_var(upper = nil) # Treat the sub nodes. # Condition. ncond = self.condition.clone # Yes. nyes =self.yes.with_var(upper) # Noifs. noifs = self.each_noif.map do |cond,stmnt| [cond.clone,stmnt.with_var(upper)] end # No. nno = self.no ? self.no.with_var(upper) : nil # Create the resulting If. res= If.new(ncond,nyes, nno) noifs.each do |cond,stmnt| res.add_noif(cond,stmnt) end return res end