Class: HDLRuby::Low::Transmit

Inherits:
Statement
  • Object
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_bool2select.rb,
lib/HDLRuby/hruby_low_without_concat.rb,
lib/HDLRuby/hruby_low_without_select.rb

Overview

Extends the Transmit class with functionality for converting select expressions to case statements.

Direct Known Subclasses

High::Transmit, Connection

Constant Summary

Constants included from Low2Symbol

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

Instance Attribute Summary collapse

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods inherited from Statement

#add_blocks_code, #block, #blocks2seq!, #break_types!, #delete_unless!, #extract_declares!, #mix?, #replace_names!, #to_upper_space!, #top_block, #top_scope, #with_boolean!

Methods included from Low2Symbol

#to_sym

Constructor Details

#initialize(left, right) ⇒ Transmit

Creates a new transmission from a +right+ expression to a +left+ reference.



2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
# File 'lib/HDLRuby/hruby_low.rb', line 2608

def initialize(left,right)
    # Check and set the left reference.
    unless left.is_a?(Ref)
        raise AnyError,
             "Invalid class for a reference (left value): #{left.class}"
    end
    @left = left
    # and set its parent.
    left.parent = self
    # Check and set the right expression.
    unless right.is_a?(Expression)
        raise AnyError, "Invalid class for an expression (right value): #{right.class}"
    end
    @right = right
    # and set its parent.
    right.parent = self
end

Instance Attribute Details

#leftObject (readonly)

The left reference.



2601
2602
2603
# File 'lib/HDLRuby/hruby_low.rb', line 2601

def left
  @left
end

#rightObject (readonly)

The right expression.



2604
2605
2606
# File 'lib/HDLRuby/hruby_low.rb', line 2604

def right
  @right
end

Instance Method Details

#boolean_in_assign2select!Object

Converts booleans in assignments to select operators.



56
57
58
59
60
61
62
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 56

def boolean_in_assign2select!
    # Apply on the left value.
    self.set_left!(self.left.boolean_in_assign2select)
    # Apply on the right value.
    self.set_right!(self.right.boolean_in_assign2select)
    return self
end

#break_concat_assignsObject

Break the assignments to concats.

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



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 81

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_block = self.top_block
            top_scope = top_block.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)
            # Is a default value required to avoid latch generation?
            unless top_block.parent.each_event.
                    find {|ev| ev.type!=:change} then
                # Yes, generate it.
                top_block.insert_statement!(0,
                    Transmit.new(aux.clone,Value.new(aux.type,0)))
            end
            # 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)))
                else
                    # Multi-bits.
                    # Compute the type of the right value.
                    rtype = TypeVector.new(:"",aux.type.base,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

#cloneObject

Clones the transmit (deeply)



2640
2641
2642
# File 'lib/HDLRuby/hruby_low.rb', line 2640

def clone
    return Transmit.new(@left.clone, @right.clone)
end

#each_block(&ruby_block) ⇒ Object

Iterates over the sub blocks.



2676
2677
2678
2679
2680
2681
# File 'lib/HDLRuby/hruby_low.rb', line 2676

def each_block(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block) unless ruby_block
    # A ruby block?
    # Nothing to do.
end

#each_block_deep(&ruby_block) ⇒ Object

Iterates over all the blocks contained in the current block.



2684
2685
2686
2687
2688
2689
# File 'lib/HDLRuby/hruby_low.rb', line 2684

def each_block_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block_deep) unless ruby_block
    # A ruby block?
    # Nothing to do.
end

#each_node(&ruby_block) ⇒ Object Also known as: each_expression

Iterates over the children if any.



2645
2646
2647
2648
2649
2650
2651
# File 'lib/HDLRuby/hruby_low.rb', line 2645

def each_node(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_node) unless ruby_block
    # A ruby block? Apply it on the children.
    ruby_block.call(@left)
    ruby_block.call(@right)
end

#each_node_deep(&ruby_block) ⇒ Object

Iterates over the nodes deeply if any.



2656
2657
2658
2659
2660
2661
2662
2663
2664
# File 'lib/HDLRuby/hruby_low.rb', line 2656

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
    @left.each_node_deep(&ruby_block)
    @right.each_node_deep(&ruby_block)
end

#each_statement_deep(&ruby_block) ⇒ Object

Iterates over all the stamements of the block and its sub blocks.



2667
2668
2669
2670
2671
2672
2673
# File 'lib/HDLRuby/hruby_low.rb', line 2667

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)
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


2627
2628
2629
2630
2631
2632
# File 'lib/HDLRuby/hruby_low.rb', line 2627

def eql?(obj)
    return false unless obj.is_a?(Transmit)
    return false unless @left.eql?(obj.left)
    return false unless @right.eql?(obj.right)
    return true
end

#explicit_types!Object

Explicit the types conversions in the statement.



82
83
84
85
86
87
88
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 82

def explicit_types!
    # Recurse on the left and the right.
    self.set_left!(self.left.explicit_types)
    # The right have to match the left type.
    self.set_right!(self.right.explicit_types(self.left.type))
    return self
end

#extract_selects!Object

Extract the Select expressions.



130
131
132
133
134
135
# File 'lib/HDLRuby/hruby_low_without_select.rb', line 130

def extract_selects!
    selects = []
    self.set_left!(self.left.extract_selects_to!(selects))
    self.set_right!(self.right.extract_selects_to!(selects))
    return selects
end

#hashObject

Hash function.



2635
2636
2637
# File 'lib/HDLRuby/hruby_low.rb', line 2635

def hash
    return [@left,@right].hash
end

#map_nodes!(&ruby_block) ⇒ Object

Maps on the children.



549
550
551
552
553
554
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 549

def map_nodes!(&ruby_block)
    @left = ruby_block.call(@left)
    left.parent = self unless left.parent
    @right = ruby_block.call(@right)
    right.parent = self unless right.parent
end

#replace_expressions!(node2rep) ⇒ Object

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.



562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 562

def replace_expressions!(node2rep)
    # First recurse on the children.
    res = self.left.replace_expressions!(node2rep)
    res.merge!(self.right.replace_expressions!(node2rep))
    # Is there a replacement to do on the left?
    rep = node2rep[self.left]
    if rep then
        # Yes, do it.
        rep = rep.clone
        node = self.left
        # node.set_parent!(nil)
        self.set_left!(rep)
        # And register the replacement.
        res[node] = rep
    end
    # Is there a replacement to do on 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)
        # And register the replacement.
        res[node] = rep
    end

    return res
end

#set_left!(left) ⇒ Object

Sets the left.



526
527
528
529
530
531
532
533
534
535
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 526

def set_left!(left)
    # Check and set the left reference.
    unless left.is_a?(Ref)
        raise AnyError,
             "Invalid class for a reference (left value): #{left.class}"
    end
    @left = left
    # and set its parent.
    left.parent = self
end

#set_right!(right) ⇒ Object

Sets the right.



538
539
540
541
542
543
544
545
546
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 538

def set_right!(right)
    # Check and set the right expression.
    unless right.is_a?(Expression)
        raise AnyError, "Invalid class for an expression (right value): #{right.class}"
    end
    @right = right
    # and set its parent.
    right.parent = self
end

#to_c(level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.



1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
# File 'lib/HDLRuby/hruby_low2c.rb', line 1064

def to_c(level = 0)
    # Save the state of the value pool.
    res = (" " * ((level)*3))
    res << "{\n"
    res << (" " * ((level+1)*3))
    res << "unsigned int pool_state = get_value_pos();\n"
    # Perform the copy and the touching only if the new content
    # is different.
    res << (" " * ((level+1)*3))
    # Is it a sequential execution model?
    seq = self.block.mode == :seq ? "_seq" : ""
    # Generate the assignment.
    if (self.left.is_a?(RefName)) then
        # Direct assignment to a signal, simple transmission.
        res << "transmit_to_signal#{seq}(#{self.right.to_c(level)},"+
            "#{self.left.to_c_signal(level)});\n"
    else
        # Assignment inside a signal (RefIndex or RefRange).
        res << "transmit_to_signal_range#{seq}(#{self.right.to_c(level)},"+
            "#{self.left.to_c_signal(level)});\n"
    end
    # Restore the value pool state.
    res << (" " * ((level+1)*3))
    res << "set_value_pos(pool_state);\n"
    res << (" " * ((level)*3))
    res << "}\n"
    return res
end

#to_high(level = 0) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.



338
339
340
341
342
# File 'lib/HDLRuby/hruby_low2high.rb', line 338

def to_high(level = 0)
    return " " * (level*3) + 
           self.left.to_high(level) + " <= " +
           self.right.to_high(level) + "\n"
end

#to_verilog(mode = nil) ⇒ Object

Converts the system to Verilog code.



95
96
97
98
99
# File 'lib/HDLRuby/hruby_verilog.rb', line 95

def to_verilog(mode = nil)
    # Determine blocking assignment or nonblocking substitution from mode and return it.
    code = "#{self.left.to_verilog} #{mode == "seq" ? "=" : "<="} #{self.right.to_verilog};\n"
    return code
end

#to_vhdl(vars, level = 0) ⇒ Object

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.



864
865
866
867
868
869
870
871
872
873
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 864

def to_vhdl(vars,level = 0)
    # Generate the assign operator.
    assign = vars.any? do |var|
        self.left.respond_to?(:name) && var.name == self.left.name 
    end ? " := " : " <= "
    # Generate the assignment.
    return " " * (level*3) + 
           self.left.to_vhdl(level) + assign +
           Low2VHDL.to_type(self.left.type,self.right) + ";\n"
end