Class: HDLRuby::Low::Transmit

Inherits:
Statement show all
Defined in:
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_viz.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_bool2select.rb,
lib/HDLRuby/hruby_low_without_concat.rb,
lib/HDLRuby/hruby_low_without_select.rb,
lib/HDLRuby/hruby_low_without_namespace.rb,
lib/HDLRuby/hruby_low_without_subsignals.rb,
lib/HDLRuby/hruby_low_casts_without_expression.rb

Overview

Decribes a transmission statement.

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, #add_make_block, #behavior, #block, #blocks2seq!, #break_types!, #delete_related!, #delete_unless!, #each_statement, #extract_declares!, #mix?, #par_in_seq2seq!, #parent_system, #replace_names!, #scope, #to_ch, #to_seq!, #to_upper_space!, #top_block, #top_scope, #with_boolean!

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#absolute_ref, #hierarchy, #no_parent!, #scope

Constructor Details

#initialize(left, right) ⇒ Transmit

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



3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
# File 'lib/HDLRuby/hruby_low.rb', line 3354

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
    super()
    @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.



3347
3348
3349
# File 'lib/HDLRuby/hruby_low.rb', line 3347

def left
  @left
end

#rightObject (readonly)

The right expression.



3350
3351
3352
# File 'lib/HDLRuby/hruby_low.rb', line 3350

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.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 157

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) )
            aux = RefName.new(aux.type,RefThis.new,aux.name)
            # Is a default value required to avoid latch generation?
            unless top_block.is_a?(TimeBlock) ||
                   top_block.parent.each_event.
                    # find {|ev| ev.type!=:change} then
                    find {|ev| ev.type!=:anyedge} 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)))
                        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
            # Return the resulting block
            # puts "new block=#{block}"
            return block
        end
    end
    # No, nothing to do.
    return self
end

#casts_without_expression!Object

Extracts the expressions from the casts.



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

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

#cloneObject

Clones the transmit (deeply)



3401
3402
3403
# File 'lib/HDLRuby/hruby_low.rb', line 3401

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

#each_block(&ruby_block) ⇒ Object

Iterates over the sub blocks.



3437
3438
3439
3440
3441
3442
# File 'lib/HDLRuby/hruby_low.rb', line 3437

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.



3445
3446
3447
3448
3449
3450
# File 'lib/HDLRuby/hruby_low.rb', line 3445

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_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
# File 'lib/HDLRuby/hruby_low.rb', line 3376

def each_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_deep) unless ruby_block
    # A ruby block? First apply it to current.
    ruby_block.call(self)
    # Then apply on the left.
    self.left.each_deep(&ruby_block)
    # Then apply on the right.
    self.right.each_deep(&ruby_block)
end

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

Iterates over the children if any.



3406
3407
3408
3409
3410
3411
3412
# File 'lib/HDLRuby/hruby_low.rb', line 3406

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.



3417
3418
3419
3420
3421
3422
3423
3424
3425
# File 'lib/HDLRuby/hruby_low.rb', line 3417

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.



3428
3429
3430
3431
3432
3433
3434
# File 'lib/HDLRuby/hruby_low.rb', line 3428

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)


3388
3389
3390
3391
3392
3393
# File 'lib/HDLRuby/hruby_low.rb', line 3388

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.



88
89
90
91
92
93
94
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 88

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.



163
164
165
166
167
168
# File 'lib/HDLRuby/hruby_low_without_select.rb', line 163

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

#fix_scope_refnames!(scopes) ⇒ Object

Fix the references names using scopes given in +scopes + list (they are marked to be deleted).



531
532
533
534
535
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 531

def fix_scope_refnames!(scopes)
    self.set_left!(self.left.fix_scope_refnames!(scopes))
    self.set_right!(self.right.fix_scope_refnames!(scopes))
    return self
end

#hashObject

Hash function.



3396
3397
3398
# File 'lib/HDLRuby/hruby_low.rb', line 3396

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

#map_nodes!(&ruby_block) ⇒ Object Also known as: map_expressions!

Maps on the children.



570
571
572
573
574
575
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 570

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.



586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 586

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.



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

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.



559
560
561
562
563
564
565
566
567
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 559

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

#signal2subs!Object

Decompose the hierarchical signals in the statements.



137
138
139
140
141
142
# File 'lib/HDLRuby/hruby_low_without_subsignals.rb', line 137

def signal2subs!
    # Recurse on the left and right.
    self.set_left!(self.left.signal2subs!)
    self.set_right!(self.right.signal2subs!)
    return self
end

#to_c(res, level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby code.

+level+ is the hierachical level of the object.

def to_c(level = 0)

def to_c(res,level = 0) # Save the state of the value pool. # res = (" " * ((level)*3)) res << (" " * ((level)*3)) res << " 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(res,level) # res << "," # self.left.to_c_signal(res,level) # res << ");\n" # else # # Assignment inside a signal (RefIndex or RefRange). # res << "transmit_to_signal_range#seq(" # self.right.to_c(res,level) # res << "," # self.left.to_c_signal(res,level) # res << ");\n" # ### Why twice ??? # res << "transmit_to_signal_range#seq(" # self.right.to_c(res,level) # res << "," # self.left.to_c_signal(res,level) # res << ");\n" # end # Generate the assignment. if (self.left.is_a?(RefName)) then # Generate the right value. self.right.to_c(res,level+1) # Direct assignment to a signal, simple transmission. res << (" " * ((level+1)*3)) res << "transmit_to_signal#seq(d," # Generate the left value (target signal). self.left.to_c_signal(res,level+1) res << ");\n" else # Generate the right value. self.right.to_c(res,level+1) # Assignment inside a signal (RefIndex or RefRange). res << "transmit_to_signal_range#seq(d," # Generate the left value (target signal). self.left.to_c_signal(res,level+1) res << ");\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 Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)



1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
# File 'lib/HDLRuby/hruby_low2c.rb', line 1439

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

#to_hdr(level = 0) ⇒ Object

Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.



344
345
346
347
348
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 344

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

#to_highObject

Creates a new high transmit statement.



261
262
263
264
# File 'lib/HDLRuby/hruby_low2high.rb', line 261

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

#to_verilog(spc = 3) ⇒ Object

Converts the system to Verilog code.



226
227
228
229
230
# File 'lib/HDLRuby/hruby_verilog.rb', line 226

def to_verilog(spc = 3)
    # Determine blocking assignment or nonblocking substitution from mode and return it.
    code = "#{" " * spc}#{self.left.to_verilog} #{self.block.mode == :seq ? "=" : "<="} #{self.right.to_verilog};"
    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.



914
915
916
917
918
919
920
921
922
923
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 914

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

#to_viz_node(parent) ⇒ Object

Converts the transmit to a Viz flow node under +parent+.



4623
4624
4625
4626
4627
4628
4629
# File 'lib/HDLRuby/hruby_viz.rb', line 4623

def to_viz_node(parent)
  node = HDLRuby::Viz::Node.new(:assign,parent)
  # And generate the left and right children.
  self.left.to_viz_node(node)
  self.right.to_viz_node(node)
  return node
end

#use_name?(*names) ⇒ Boolean

Tell if the statement includes a signal whose name is one of +names+.

Returns:

  • (Boolean)


3453
3454
3455
# File 'lib/HDLRuby/hruby_low.rb', line 3453

def use_name?(*names)
    return @left.use_name?(*names) || @right.use_name?(*names)
end