Class: HDLRuby::Low::Connection

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

Overview

Describes a connection.

NOTE: eventhough a connection is semantically different from a transmission, it has a common structure. Therefore, it is described as a subclass of a transmit.

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 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!, #signal2subs!, #to_c, #to_hdr, #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, #each_statement, #explicit_types!, #extract_declares!, #mix?, #par_in_seq2seq!, #replace_expressions!, #replace_names!, #scope, #to_c, #to_ch, #to_hdr, #to_seq!, #to_upper_space!, #to_vhdl, #use_name?, #with_boolean!

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

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

Instance Method Details

#array_connection(left, right) ⇒ Object

Method used for array.



1686
1687
1688
1689
1690
1691
1692
1693
1694
# File 'lib/HDLRuby/hruby_verilog.rb', line 1686

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.



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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 251

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(:par)
            # 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)


4706
4707
4708
4709
# File 'lib/HDLRuby/hruby_low.rb', line 4706

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

#hashObject

Hash function.



4712
4713
4714
# File 'lib/HDLRuby/hruby_low.rb', line 4712

def hash
    return super
end

#parent_systemObject

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



4727
4728
4729
# File 'lib/HDLRuby/hruby_low.rb', line 4727

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.



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
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1276

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_highObject

Creates a new high connection.



393
394
395
396
# File 'lib/HDLRuby/hruby_low2high.rb', line 393

def to_high
    return HDLRuby::High::Connection.new(self.left.to_high,
                                         self.right.to_high)
end

#to_verilogObject



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
1729
1730
1731
1732
1733
1734
1735
1736
# File 'lib/HDLRuby/hruby_verilog.rb', line 1696

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:



4717
4718
4719
# File 'lib/HDLRuby/hruby_low.rb', line 4717

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.



4722
4723
4724
# File 'lib/HDLRuby/hruby_low.rb', line 4722

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