Class: HDLRuby::Low::Connection

Inherits:
Transmit show all
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_without_concat.rb

Overview

Extends the Connection class with functionality for breaking assingments to concats.

Direct Known Subclasses

High::Connection

Constant Summary

Constants included from Low2Symbol

Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable

Instance Attribute Summary

Attributes inherited from Transmit

#left, #right

Attributes included from Hdecorator

#hdr_id

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Transmit

#boolean_in_assign2select!, #casts_without_expression!, #clone, #each_block, #each_block_deep, #each_deep, #each_node, #each_node_deep, #each_statement_deep, #explicit_types!, #extract_selects!, #initialize, #map_nodes!, #replace_expressions!, #set_left!, #set_right!, #to_c, #to_high, #to_vhdl, #use_name?

Methods inherited from Statement

#add_blocks_code, #add_make_block, #behavior, #block, #blocks2seq!, #break_types!, #clone, #delete_related!, #delete_unless!, #each_deep, #explicit_types!, #extract_declares!, #mix?, #par_in_seq2seq!, #replace_expressions!, #replace_names!, #scope, #to_c, #to_ch, #to_high, #to_seq!, #to_upper_space!, #to_vhdl, #use_name?, #with_boolean!

Methods included from Low2Symbol

#to_sym

Methods included from Hdecorator

decorate_parent_id, dump, each, each_with_property, get, included, load, #properties

Methods included from Hparent

#scope

Constructor Details

This class inherits a constructor from HDLRuby::Low::Transmit

Instance Method Details

#array_connection(left, right) ⇒ Object

Method used for array.



1644
1645
1646
1647
1648
1649
1650
1651
1652
# File 'lib/HDLRuby/hruby_verilog.rb', line 1644

def array_connection(left,right)
    expression = right.each_expression.to_a
    result = ""
    expression[0..-2].each do |expression|
        result << "   assign #{left.to_verilog}[#{expression.content.to_s}] = #{expression.to_verilog};\n"
    end
    result << "   assign #{left.to_verilog}[#{expression.last.content.to_s}] = #{expression.last.to_verilog};\n"
    return result
end

#break_concat_assignsObject

Break the assignments to concats.

NOTE: when breaking generates a new Block containing the broken assignments.



225
226
227
228
229
230
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 225

def break_concat_assigns
    # puts "break_concat_assigns with self=#{self}"
    # Is the left value a RefConcat?
    self.left.each_node_deep do |node|
        if node.is_a?(RefConcat) then
            # Yes, must break. Create the resulting sequential
            # block that will contain the new assignements.
            block = Block.new(:seq)
            # Create an intermediate signal for storing the
            # right value. Put it in the top scope.
            top_scope = self.top_scope
            aux = top_scope.add_inner(
                SignalI.new(HDLRuby.uniq_name,self.right.type) )
            # puts "new signal: #{aux.name}"
            aux = RefName.new(aux.type,RefThis.new,aux.name)
            # Set a default value to avoid latch generation.
            block.insert_statement!(0,
                    Transmit.new(aux.clone,Value.new(aux.type,0)))
            # Replace the concat in the copy of the left value.
            if left.eql?(node) then
                # node was the top of left, replace here.
                nleft = aux
            else
                # node was inside left, replace within left.
                nleft = self.left.clone
                nleft.each_node_deep do |ref|
                    ref.map_nodes! do |sub|
                        sub.eql?(node) ? aux.clone : sub
                    end
                end
            end
            # Recreate the transmit and add it to the block.
            block.add_statement(
                Transmit.new(nleft,self.right.clone) )
            # And assign its part to each reference of the
            # concat.
            pos = 0
            node.each_ref.reverse_each do |ref|
                # Compute the range to assign.
                range = ref.type.width-1+pos .. pos
                # Single or multi-bit range?
                sbit = range.first == range.last
                # Convert the range to an HDLRuby range for 
                # using is the resulting statement.
                # Create and add the statement.
                if sbit then
                    # Single bit.
                    # Generate the index.
                    idx = Value.new(Integer,range.first)
                    # Generate the assignment.
                    block.add_statement(
                        Transmit.new(ref.clone,
                        # RefIndex.new(aux.type.base, aux.clone, idx)))
                        RefIndex.new(bit, aux.clone, idx)))
                else
                    # Multi-bits.
                    # Compute the type of the right value.
                    # rtype = TypeVector.new(:"",aux.type.base,range)
                    rtype = TypeVector.new(:"",bit,range)
                    # Generate the range.
                    range = Value.new(Integer,range.first) ..
                            Value.new(Integer,range.last)
                    # Generate the assignment.
                    block.add_statement(
                        Transmit.new(ref.clone,
                        RefRange.new(rtype, aux.clone, range)))
                end
                pos += ref.type.width
            end
            # puts "Resulting block=#{block.to_vhdl}"
            # Return the resulting block
            return block
        end
    end
    # No, nothing to do.
    return self
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


4091
4092
4093
4094
# File 'lib/HDLRuby/hruby_low.rb', line 4091

def eql?(obj)
    return false unless obj.is_a?(Connection)
    return super(obj)
end

#hashObject

Hash function.



4097
4098
4099
# File 'lib/HDLRuby/hruby_low.rb', line 4097

def hash
    return super
end

#parent_systemObject

Gets the parent system, i.e., the parent of the top scope.



4112
4113
4114
# File 'lib/HDLRuby/hruby_low.rb', line 4112

def parent_system
    return self.top_scope.parent
end

#reassign_expressions!(node2reassign) ⇒ Object

Replace node by corresponding replacement from +node2reassign+ that is a table whose entries are: +node+ the node to replace +rep+ the replacement of the node +ref+ the reference where to reassign the node.



1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1224

def reassign_expressions!(node2reassign)
    # Build the replacement table.
    node2rep = node2reassign.map {|n,r| [n,r[0]] }.to_h

    # Performs the replacements.
    node2rep_done = {} # The performed replacements.
    # Replace on the sons of the left.
    node2rep_done.merge!(self.left.replace_expressions!(node2rep))
    # Replace on the sons of the left.
    node2rep_done.merge!(self.right.replace_expressions!(node2rep))
    # Shall we replace 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)
        node2rep_done[node] = rep
    end

    # Assign the replaced nodes.
    node2rep_done.each do |node,rep|
        reassign = node2reassign[node][1].clone
        self.parent.add_connection(
            Connection.new(reassign,node.clone))
    end
end

#to_verilogObject



1654
1655
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 1654

def to_verilog
    # Decide whether to assign to array by if.
    # NOTICE: Now array assignment is done trough constant initialization, will be treated later.
    # if self.right.respond_to? (:each_expression) 
    #   array_connection(self.left,self.right);
    # else
    cnt = 0  # Use count.
    bit = -2 # Used to determine the bit width. Since there are 0 and default, -2.

    # Measure the number of choices on the right side (case statement if it is 3 or more).
    if self.right.respond_to? (:each_choice)
        choice = self.right.each_choice.to_a
        choice.each do |choice|
            bit += 1
        end
    end

    # Three or more choices.
    if (bit > 2)
        # The bit width is obtained by converting the bit into a binary number and obtaining the size.
        bit = bit.to_s(2).size

        # Create a case statement.
        result = "   begin\n"
        result << "      case(#{self.right.select.to_verilog})\n"
        # Output other than the last one in order.
        choice[0..-2].each do |choice|
            result << "         #{bit}'#{cnt}: #{self.left.to_verilog} = #{choice.to_verilog}\n"
            cnt += 1
        end
        # At the end, it becomes default because it needs default.
        result << "         default: #{self.left.to_verilog} = #{choice.last.to_verilog}\n"
        result << "      endcase\n"
        result << "   end\n"
        return result
    end

    # It is not a case so call it normally.
    return "   assign #{self.left.to_verilog} = #{self.right.to_verilog};\n"
    # end
end

#top_blockObject

Gets the top block, i.e. the first block of the current behavior.

Raises:



4102
4103
4104
# File 'lib/HDLRuby/hruby_low.rb', line 4102

def top_block
    raise AnyError, "Connections are not within blocks."
end

#top_scopeObject

Gets the top scope, i.e. the first scope of the current system.



4107
4108
4109
# File 'lib/HDLRuby/hruby_low.rb', line 4107

def top_scope
    return self.parent.is_a?(Scope) ? self.parent : self.parent.top_scope
end