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!, #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.



1665
1666
1667
1668
1669
1670
1671
1672
1673
# File 'lib/HDLRuby/hruby_verilog.rb', line 1665

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.



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

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.



1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1317

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



1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
# File 'lib/HDLRuby/hruby_verilog.rb', line 1675

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