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_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

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 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_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.



1638
1639
1640
1641
1642
1643
1644
1645
1646
# File 'lib/HDLRuby/hruby_verilog.rb', line 1638

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)


4532
4533
4534
4535
# File 'lib/HDLRuby/hruby_low.rb', line 4532

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

#hashObject

Hash function.



4538
4539
4540
# File 'lib/HDLRuby/hruby_low.rb', line 4538

def hash
    return super
end

#parent_systemObject

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



4553
4554
4555
# File 'lib/HDLRuby/hruby_low.rb', line 4553

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.



1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1306

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.



364
365
366
367
# File 'lib/HDLRuby/hruby_low2high.rb', line 364

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

#to_verilogObject



1648
1649
1650
1651
1652
1653
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 1648

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:



4543
4544
4545
# File 'lib/HDLRuby/hruby_low.rb', line 4543

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.



4548
4549
4550
# File 'lib/HDLRuby/hruby_low.rb', line 4548

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