Class: HDLRuby::Low::Block

Inherits:
Statement
  • Object
show all
Includes:
ForceName
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_low2seq.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_verilog.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_cleanup.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_resolve.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/hruby_low_with_var.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_parinseq.rb,
lib/HDLRuby/hruby_low_without_namespace.rb,
lib/HDLRuby/hruby_low_without_subsignals.rb,
lib/HDLRuby/hruby_low_casts_without_expression.rb

Overview

Extends the Block class with functionality for extracting expressions from cast.

Direct Known Subclasses

High::Block, TimeBlock

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 included from ForceName

#extend_name!, #force_name!

Methods inherited from Statement

#behavior, #block, #break_types!, #parent_system, #scope, #top_block, #top_scope, #use_name?, #with_boolean!

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

#initialize(mode, name = :"") ⇒ Block

Creates a new +mode+ sort of block with possible +name+.



4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
# File 'lib/HDLRuby/hruby_low.rb', line 4415

def initialize(mode, name = :"")
    super()
    # puts "new block with mode=#{mode} and name=#{name}"
    # Check and set the type.
    @mode = mode.to_sym
    # Check and set the name.
    @name = name.to_sym
    # Initializes the list of inner statements.
    # @inners = {}
    @inners = HashName.new
    # Initializes the list of statements.
    @statements = []
end

Instance Attribute Details

#modeObject (readonly)

The execution mode of the block.



4409
4410
4411
# File 'lib/HDLRuby/hruby_low.rb', line 4409

def mode
  @mode
end

#nameObject (readonly)

The name of the block if any



4412
4413
4414
# File 'lib/HDLRuby/hruby_low.rb', line 4412

def name
  @name
end

Instance Method Details

#add_blocks_code(res, level) ⇒ Object

Adds the c code of the blocks to +res+ at +level+



1940
1941
1942
1943
1944
# File 'lib/HDLRuby/hruby_low2c.rb', line 1940

def add_blocks_code(res,level)
    # res << self.to_c_code(level)
    self.to_c_code(res,level)
    return res
end

#add_inner(signal) ⇒ Object

Adds inner signal +signal+.



4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
# File 'lib/HDLRuby/hruby_low.rb', line 4473

def add_inner(signal)
    # puts "add inner=#{signal.name} in block=#{self}"
    # Check and add the signal.
    unless signal.is_a?(SignalI)
        raise AnyError,
              "Invalid class for a signal instance: #{signal.class}"
    end
    # if @inners.include?(signal) then
    #     raise AnyError, "SignalI #{signal.name} already present."
    # end
    # Set its parent.
    signal.parent = self
    # And add it
    @inners.add(signal)
end

#add_make_block(res, level) ⇒ Object

Adds the creation of the blocks to +res+ at +level+.



1947
1948
1949
1950
# File 'lib/HDLRuby/hruby_low2c.rb', line 1947

def add_make_block(res,level)
    res << " " * level*3
    res << Low2C.make_name(self) << "();\n"
end

#add_statement(statement) ⇒ Object

Adds a +statement+.

NOTE: TimeWait is not supported unless for TimeBlock objects.



4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
# File 'lib/HDLRuby/hruby_low.rb', line 4523

def add_statement(statement)
    unless statement.is_a?(Statement) then
        raise AnyError,
              "Invalid class for a statement: #{statement.class}"
    end
    if statement.is_a?(TimeWait) then
        raise AnyError,
              "Timed statements are not supported in common blocks."
    end
    @statements << statement
    # And set its parent.
    statement.parent = self
    statement
end

#add_variable(name, type) ⇒ Object

Adds variable +name+ with +type+.



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

def add_variable(name,type)
    # Ensure name is a symbol.
    name = name.to_sym
    # Declares the variable as an inner.
    inner = add_inner(SignalI.new(name,type))
    # And register it as a variable.
    variables[name] = inner 
end

#att_sharp(left, att = "'") ⇒ Object

A method that takes a variable from the sent left side and adds "att".



1405
1406
1407
1408
1409
# File 'lib/HDLRuby/hruby_verilog.rb', line 1405

def att_sharp(left,att = "'")
    new_left = search_refname(left, att)

    return new_left
end

#att_signal(left, att = "'") ⇒ Object

Generate a signal for the variable to which "'" or "#" is added.



1396
1397
1398
1399
1400
1401
1402
# File 'lib/HDLRuby/hruby_verilog.rb', line 1396

def att_signal(left,att = "'")
    this_name = res_name(left)
    new_name = RefName.new(this_name.type, this_name.ref.clone, this_name.name.to_s + att)
    new_signal = SignalI.new(new_name.name,new_name.type)

    return new_signal
end

#blocks2seq!Object

Converts the par sub blocks to seq.



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

def blocks2seq!
    # First recurse on each statement.
    self.each_statement { |stmnt| stmnt.blocks2seq! }
    # If the block is already seq, nothing more to do.
    return self if self.mode == :seq
    # IF the block contains one or less transmit statement,
    # simply change its mode.
    if self.each_statement.count { |stmnt| stmnt.is_a?(Transmit) } <= 1
        self.set_mode!(:par)
        return self
    end
    # Gather the left values of the assignments.
    lvalues = self.each_statement.select do |stmnt|
        stmnt.is_a?(Transmit)
    end.map { |trans| trans.left }
    # Gather the right values inside the whole block.
    rvalues = self.each_node_deep.select do |node|
        node.is_a?(Expression) and node.rightvalue?
    end
    # Keep the left value that are reused.
    lvalues = lvalues & rvalues
    # Create new inner variable for replacing them.
    nvalues = []
    lvalues.each do |lvalue|
        # Create the replacing variable.
        nvalues << nvalue = self.add_inner(
            SignalI.new(HDLRuby.uniq_name,lvalue.type))
        # Replace it.
        ref = RefName.new(lvalue.type, RefThis.new, nvalues[-1].name)
        lvalue.parent.set_left!(ref)
        # And reassign it at the end of the block.
        lvalue.parent = nil
        assign = Transmit.new(lvalue,ref.clone)
        self.add_statement(assign)
    end
    return self
end

#boolean_in_assign2select!Object

Converts booleans in assignments to select operators.



175
176
177
178
179
# File 'lib/HDLRuby/hruby_low_bool2select.rb', line 175

def boolean_in_assign2select!
    # Apply on each statement.
    self.each_statement(&:boolean_in_assign2select!)
    return self
end

#break_concat_assigns!Object

Breaks the assignments to concats.

NOTE: work on the direct sub statement only, not deeply.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 123

def break_concat_assigns!
    # puts "breack_concat_assigns! with block=#{self} with #{self.each_statement.count} statements"
    # Check each transmit.
    self.each_statement.to_a.each_with_index do |stmnt|
        # puts "stmnt=#{stmnt}"
        if stmnt.is_a?(Transmit) then
            # Transmit, breaking may be necessary.
            nstmnt = stmnt.break_concat_assigns
            if nstmnt.is_a?(Block) then
                # The transmit has been broken, remove the former
                # version and add the generated block as a behavior.
                # self.set_statement!(i,nstmnt)
                self.replace_statement!(stmnt,nstmnt)
                # puts "nstmnt.parent=#{nstmnt.parent}"
            end
        end
    end
    return self
end

#casts_without_expression!Object

Extracts the expressions from the casts.



160
161
162
163
164
# File 'lib/HDLRuby/hruby_low_casts_without_expression.rb', line 160

def casts_without_expression!
    # Apply on each statement.
    self.each_statement(&:casts_without_expression!)
    return self
end

#change_branch(block) ⇒ Object



1305
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
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
# File 'lib/HDLRuby/hruby_verilog.rb', line 1305

def change_branch(block)
    flat  = Block.new(self.mode,"")     # Store the expression until if is found.
    trans = Block.new(self.mode,"")     # A block that stores the expression after if is found.
    new_block = Block.new(self.mode,"") # Block storing each converted expression.

    has_branch = false                  # It is true if there is an if in the block.
    more_has_branch = false             # It is true if there are two or more if in the block.

    # Search each expression for if.
    block.each_statement do |statement|
        if (has_branch)
            trans.add_statement(statement.clone)
            if statement.is_a?(If) || statement.is_a?(Case) then
                more_has_branch = true
            end        
        else
            if statement.is_a?(If) || statement.is_a?(Case) then
                flat.add_statement(statement.clone)     
                has_branch = true          
            else
                flat.add_statement(statement.clone)
            end
        end
    end

    # If there are two or more if, recursively process if.
    if(more_has_branch) then
        conversion_block = change_branch(trans)
    else
        conversion_block = trans.clone
    end

    # Store "trans" contents for "if" and "case" in "flat".
    flat.each_statement do |statement|
        # Since case statements include defaulu and when, we store the expressions saved in each case.
        if statement.is_a?(Case) then
            if statement.default.is_a?(Block)
                new_default = statement.default.clone 
                conversion_block.each_statement do |smt|
                    new_default.add_statement(smt.clone)
                end         
            end

            new_statement = Case.new(statement.value.clone,statement.default ? new_default.clone : nil,[])

            statement.each_when do |whens|
                new_when = whens.clone

                conversion_block.each_statement do |smt|
                    new_when.statement.add_statement(smt.clone)
                end      
                new_statement.add_when(new_when.clone)
            end

            new_block.add_statement(new_statement.clone)
            # Because there are yes, no and noifs in the if statement, store the expression saved in each.
        elsif statement.is_a?(If) then
            new_yes = statement.yes.clone
            conversion_block.each_statement do |smt|
                new_yes.add_statement(smt.clone)
            end

            if statement.no.is_a? (Block) then
                new_no = statement.no.clone
                conversion_block.each_statement do |smt|
                    new_no.add_statement(smt.clone)
                end
            end

            # Make new if with converted yes and no.
            new_statement = If.new(statement.condition.clone,new_yes.clone,statement.no ? new_no.clone : nil)


            statement.each_noif do |condition, block|
                new_noif = block.clone
                conversion_block.each_statement do |smt|
                    new_noif.add_statement(smt.clone)
                end
                new_statement.add_noif(condition.clone,new_noif.clone)
            end
            # Add the new statement (if) created to flat.
            new_block.add_statement(new_statement.clone)
        else
            new_block.add_statement(statement.clone)
        end
    end

    return new_block # Return block after conversion.
end

#cloneObject

Clones (deeply)



4639
4640
4641
4642
4643
4644
4645
4646
4647
# File 'lib/HDLRuby/hruby_low.rb', line 4639

def clone
    # Creates the new block.
    nblock = Block.new(self.mode,self.name)
    # Duplicate its content.
    self.each_statement do |statement|
        nblock.add_statement(statement.clone)
    end
    return nblock
end

#delete_inner!(signal) ⇒ Object

Deletes an inner.



1131
1132
1133
1134
1135
1136
1137
1138
1139
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1131

def delete_inner!(signal)
    if @inners.key?(signal.name) then
        # The signal is present, delete it. 
        @inners.delete(signal.name)
        # And remove its parent.
        signal.parent = nil
    end
    signal
end

#delete_related!(*names) ⇒ Object

Deletes the elements related to one of +names+: either they have one of the names or they use an element with these names. NOTE: only delete actual instantiated elements, types or systemTs are left as is.



1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1263

def delete_related!(*names)
    # Delete the inner signals whose name are in names.
    @inners.delete_if { |sig| names.include?(sig.name) }
    # Recurse on the statements.
    @statements.each do |statement|
        statement.delete_related!(*names)
    end
    # Delete the statements that contain signals whose name are
    # in names.
    @statements.delete_if { |statement| statement.use_name?(*names) }
end

#delete_statement!(statement) ⇒ Object

Deletes a statement.



1201
1202
1203
1204
1205
1206
1207
1208
1209
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1201

def delete_statement!(statement)
    if @statements.include?(statement) then
        # Statement is present, delete it.
        @statements.delete(statement)
        # And remove its parent.
        statement.parent = nil
    end
    statement
end

#delete_unless!(keep) ⇒ Object

Removes the signals and corresponding assignments whose name is not in +keep+.



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/HDLRuby/hruby_low_cleanup.rb', line 172

def delete_unless!(keep)
    # Delete the unecessary inner signals.
    self.each_inner.to_a.each do |inner|
        self.delete_inner!(inner) unless keep.include?(inner.name)
    end

    # Recurse on the sub statements.
    self.each_statement {|stmnt| stmnt.delete_unless!(keep) }

    # Delete the unecessary assignments.
    self.each_statement.to_a.each do |stmnt|
        if stmnt.is_a?(Transmit) &&
             !stmnt.left.each_node_deep.any? { |node| 
            node.is_a?(RefName) && keep.include?(node.name) } then
            self.delete_statement!(stmnt)
        end
    end
end

#do_flat(mode = nil) ⇒ Object



780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
# File 'lib/HDLRuby/hruby_verilog.rb', line 780

def do_flat(mode = nil)
    flat  = Block.new(self.mode,"")   # Block between lower layers when converting.
    trans = Block.new(self.mode,"")   # The block used for converting itself.
    replase = Block.new(self.mode,"") # block to be used for further conversion in case of if statement.
    list = []
    rep_list = []

    # If there is a block inside the statement it is not the lowest layer. If there is, it is the lowest layer.      
    if (self.each_statement.find {|stmnt| stmnt.is_a?(Block)} || (self.each_statement.find {|stmnt| stmnt.is_a?(If)}) || (self.each_statement.find {|stmnt| stmnt.is_a?(Case)}))then
        # In the case of seq, the lower layer is par. Isolate fm_par so that it is not crosstalked.
        if(self.mode == :seq) then
            fm_buckup = FmI.fm_par.clone
            FmI.fm_par.clear()

            new_block = change_branch(self)
        else
            new_block = self.clone      
        end

        # Process for each statement.
        new_block.each_statement do |statement|
            # If statement is If, convert yes, no, noif and add them to flat.
            if statement.is_a?(Case) then
                if(self.mode == :seq) then
                    fm_buckup_if = FmI.fm_par.clone
                end

                if statement.default.is_a?(Block)
                    default = statement.default.flatten    
                    new_default = Block.new(default.mode,"")

                    default.each_statement do |statement|
                        new_default.add_statement(statement.clone)
                    end     
                end


                new_statement = Case.new(statement.value.clone,statement.default ? new_default.clone : nil,[])

                statement.each_when do |whens|
                    if(self.mode == :seq) then
                        fm_buckup_if.each_key do |key|
                            FmI.fm_par[key] = fm_buckup_if[key]
                        end
                    end

                    when_smt = whens.statement.flatten
                    new_when = When.new(whens.match.clone,when_smt.clone)
                    new_statement.add_when(new_when.clone)
                end
                flat.add_statement(new_statement)

            elsif statement.is_a?(If) then
                if(self.mode == :seq) then
                    fm_buckup_if = FmI.fm_par.clone
                end

                # Since yes always exist, convert without confirming.
                new_yes = statement.yes.flatten

                # I do not know whether no (else) exists, so convert it if it is confirmed.
                if statement.no.is_a? (Block) then

                    if(self.mode == :seq) then
                        fm_buckup_if.each_key do |key|
                            FmI.fm_par[key] = fm_buckup_if[key]
                        end
                    end

                    new_no = statement.no.flatten
                end
                # Create a new if statement with converted yes and no.
                new_statement = If.new(statement.condition.clone,new_yes.clone,statement.no ? new_no.clone : nil)

                # Since I do not know whether there is noifs (elsif), I convert it and add it if it is confirmed.
                statement.each_noif do |condition, block|
                    if(self.mode == :seq) then
                        fm_buckup_if.each_key do |key|
                            FmI.fm_par[key] = fm_buckup_if[key]
                        end
                    end

                    new_noif = block.flatten         
                    new_statement.add_noif(condition.clone,new_noif.clone)
                end
                # Add the new statement (if statement) created to flat.
                flat.add_statement(new_statement.clone)

                # If statement is Transmit, record the expression in fm_par and add the expression to flat as it is.
            elsif statement.is_a?(Transmit) then
                if(self.mode == :seq) then
                    FmI.fm_par["#{statement.left.to_verilog}"] = statement.right.clone
                end

                flat.add_statement(statement.clone)
                # If statement is Block, convert it with do_flat and add the returned expression and variable to flat respectively.

            elsif statement.is_a?(Block) then
                smt = statement.do_flat(self.mode)
                # If smt has inner, check it separately and add it if it's convenient.
                smt.each_inner do |inner|
                    if self.mode == :seq then
                        unless (list.include?(inner.name.to_s)) then
                            list << inner.name.to_s
                            flat.add_inner(inner.clone)
                        end
                    else
                        unless (list.include?(inner.name.to_s)) then
                            if(inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                flat.add_inner(inner.clone) # It was new_block. why?
                            end
                        end            
                    end
                end
                # If it is seq, the expression after conversion is also likely to be used, so record the expression.
                smt.each_statement do |tmt|
                    if self.mode == :seq then
                        FmI.fm_par["#{tmt.left.to_verilog}"] = tmt.right.clone
                    end
                    flat.add_statement(tmt.clone)
                end         
            end
        end

        # Overwrite to restore fm_par which was quarantined.
        if(self.mode == :seq) then
            FmI.fm_par.clear()
            fm_buckup.each_key do |key|
                FmI.fm_par[key] = fm_buckup[key]
            end
        end



        # Since it is a middle tier itself, it performs flat transformation, shifts inner, and returns the result.
        trans = flat.to_conversion(mode)


        # Write an expression that assigns an identifier that added # to an identifier that has not added.
        trans.each_statement do |statement|
            replase.add_statement(statement.clone)
            if statement.is_a?(If)
                FmI.rep_sharp.each_key do |key|
                    new_statement = Transmit.new(key.clone,FmI.rep_sharp[key].clone)
                    replase.add_statement(new_statement.clone)
                end
                FmI.rep_sharp.clear() # Deactivate rep that has become obsolete.
            end
        end

        # Extract the inner left in flat and add it to replase.
        flat.each_inner do |inner|
            replase.add_inner(inner.clone)
        end

        # Extract the inner left in trans and add it to replase.
        trans.each_inner do |inner|
            replase.add_inner(inner.clone)
        end

        return replase

        # Processing when there is no block (reaching the bottom layer).
    else
        # Since it is the lowest layer, it does not smooth but converts itself and returns it.
        flat = self.to_conversion(mode)
        return flat
    end
end

#each_block(&ruby_block) ⇒ Object

Iterates over the sub blocks.



4589
4590
4591
4592
4593
4594
4595
4596
4597
# File 'lib/HDLRuby/hruby_low.rb', line 4589

def each_block(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block) unless ruby_block
    # A ruby block?
    # Apply it on each statement which contains blocks.
    self.each_statement do |statement|
        ruby_block.call(statement) if statement.is_a?(Block)
    end
end

#each_block_deep(&ruby_block) ⇒ Object

Iterates over all the blocks contained in the current block.



4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
# File 'lib/HDLRuby/hruby_low.rb', line 4600

def each_block_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_block_deep) unless ruby_block
    # A ruby block?
    # Apply it on self.
    ruby_block.call(self)
    # And apply it on each statement which contains blocks.
    self.each_statement do |statement|
        statement.each_block_deep(&ruby_block)
    end
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
# File 'lib/HDLRuby/hruby_low.rb', line 4432

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 inners.
    self.each_inner do |inner|
        inner.each_deep(&ruby_block)
    end
    # Then apply on the statements.
    self.each_statement do |stmnt|
        stmnt.each_deep(&ruby_block)
    end
end

#each_inner(&ruby_block) ⇒ Object Also known as: each_signal

Iterates over the inner signals.

Returns an enumerator if no ruby block is given.



4492
4493
4494
4495
4496
4497
# File 'lib/HDLRuby/hruby_low.rb', line 4492

def each_inner(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_inner) unless ruby_block
    # A ruby block? Apply it on each inner signal instance.
    @inners.each(&ruby_block)
end

#each_node_deep(&ruby_block) ⇒ Object

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



4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
# File 'lib/HDLRuby/hruby_low.rb', line 4626

def each_node_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_node_deep) unless ruby_block
    # A ruby block?
    # Apply it on current.
    ruby_block.call(self)
    # And apply it on each statement deeply.
    self.each_statement do |stmnt|
        stmnt.each_node_deep(&ruby_block)
    end
end

#each_signal_deep(&ruby_block) ⇒ Object

Iterates over all the signals of the block and its sub block's ones.



4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
# File 'lib/HDLRuby/hruby_low.rb', line 4508

def each_signal_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_signal_deep) unless ruby_block
    # A ruby block?
    # First, apply on the signals of the block.
    self.each_signal(&ruby_block)
    # Then apply on each sub block. 
    self.each_block_deep do |block|
        block.each_signal_deep(&ruby_block)
    end
end

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

Iterates over the statements.

Returns an enumerator if no ruby block is given.



4564
4565
4566
4567
4568
4569
# File 'lib/HDLRuby/hruby_low.rb', line 4564

def each_statement(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_statement) unless ruby_block
    # A ruby block? Apply it on each statement.
    @statements.each(&ruby_block)
end

#each_statement_deep(&ruby_block) ⇒ Object

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



4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
# File 'lib/HDLRuby/hruby_low.rb', line 4613

def each_statement_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_statement_deep) unless ruby_block
    # A ruby block?
    # Apply it on current.
    ruby_block.call(self)
    # And apply it on each statement deeply.
    self.each_statement do |statement|
        statement.each_statement_deep(&ruby_block)
    end
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
# File 'lib/HDLRuby/hruby_low.rb', line 4448

def eql?(obj)
    return false unless obj.is_a?(Block)
    return false unless @mode.eql?(obj.mode)
    return false unless @name.eql?(obj.name)
    idx = 0
    obj.each_inner do |inner|
        return false unless @inners[inner.name].eql?(inner)
        idx += 1
    end
    return false unless idx == @inners.size
    idx = 0
    obj.each_statement do |statement|
        return false unless @statements[idx].eql?(statement)
        idx += 1
    end
    return false unless idx == @statements.size
    return true
end

#explicit_types!Object

Explicit the types conversions in the block.



196
197
198
199
200
# File 'lib/HDLRuby/hruby_low_fix_types.rb', line 196

def explicit_types!
    # Recurse on the statements.
    self.each_statement(&:explicit_types!)
    return self
end

#extract_declares!Object

Extract the declares from the scope and returns them into an array.

NOTE: do not recurse into the sub scopes or behaviors!



693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 693

def extract_declares!
    # Ensure there is a name.
    self.force_name!
    # The extracted declares.
    decls = []
    # Extract the inners.
    self.each_inner {|inner| decls << inner }
    decls.each {|inner| self.delete_inner!(inner) }
    # Renames them with the current level.
    decls.each do |inner|
        former = inner.name
        self.extend_name!(inner)
        self.replace_names_subs!(former,inner.name)
    end
    # Returns the extracted declares.
    return decls
end

#extract_from_externals!(stmnt, sym2var) ⇒ Object

Extract the variables corresponding to external signals from block-based statement +stmnt+, and put the extraction result is table +sym2var+ that associate variable with corresponding signal name.



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

def extract_from_externals!(stmnt,sym2var)
    if (stmnt.is_a?(Block)) then
        # Block case, gather its declared and signals variables.
        vars = {}
        sigs = {}
        stmnt.each_inner do |inner|
            if variable_name?(inner.name) then
                vars[inner.name] = inner
            else
                sigs[inner.name] = inner
            end
        end
        # Select the variables that correspond to external signals.
        vars.each do |name,inner|
            sym = var_name2sym(name)
            unless sigs.key?(sym) then
                # The variable correspond to an external signal,
                # extract it.
                sym2var[sym] = inner
                stmnt.delete_inner(inner)
            end
        end
    elsif
        # Other case, recurse on the sub blocks.
        stmnt.each_block do |block|
            extract_from_externals!(block,sym2var)
        end
    end
end

#flatten(mode = nil) ⇒ Object

Process top layer of Block. Determine whether there is a block under block and convert it.



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
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
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/HDLRuby/hruby_verilog.rb', line 317

def flatten(mode = nil)
    if self.is_a?(TimeBlock) then
        new_block = TimeBlock.new(self.mode,"")
    else
        new_block  = Block.new(self.mode,"") # A new block to store the converted statement.
    end
    list = []                            # A list for confirming that variable declarations do not overlap.

    # Is block in the statement?
    if (self.each_statement.find {|stmnt| stmnt.is_a?(Block)}) then
        # Process for each type of statement in block.
        self.each_statement do |statement|
            # If statement is case, there is a block for each default and when, so translate each.      
            if statement.is_a?(Case) then
                if statement.default.is_a?(Block)
                    default = statement.default.flatten
                    new_default = Block.new(default.mode,"")

                    default.each_inner do |inner|          
                        # I read inner, but when I am par, I delete all '.
                        unless (list.include?(inner.name.to_s)) then
                            if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                new_block.add_inner(inner.clone)
                            end            
                        end
                    end

                    default.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || default.mode == :par then
                                # Prepare a new signal with the # on the variable on the left side using the att_signal method.
                                new_signal = att_signal(statement.left, "#")
                                # Check list and add new variables to inner if they do not duplicate.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                                new_default.add_statement(new_statement.clone)
                            else
                                new_default.add_statement(statement.clone)
                            end 
                        else
                            new_default.add_statement(statement.clone)
                        end
                    end     
                end

                new_statement = Case.new(statement.value.clone,statement.default ? new_default.clone : nil,[])

                statement.each_when do |whens|
                    when_smt = whens.statement.flatten
                    new_when_smt = Block.new(when_smt.mode,"")

                    when_smt.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || when_smt.mode == :par then
                                # # Prepare a new signal with the # on the variable on the left side using the att_signal method.
                                new_signal = att_signal(statement.left, "#")
                                # Check list and add new variables to inner if they do not duplicate.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_smt = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_smt.left
                                new_when_smt.add_statement(new_smt.clone)
                            else
                                new_when_smt.add_statement(statement.clone)
                            end 
                        else
                            new_when_smt.add_statement(statement.clone)
                        end
                    end

                    new_when = When.new(whens.match.clone,new_when_smt.clone)
                    new_statement.add_when(new_when.clone)
                end

                new_block.add_statement(new_statement)

                FmI.rep_sharp.each_key do |key|
                    new_smt = Transmit.new(key.clone,FmI.rep_sharp[key].clone)
                    new_block.add_statement(new_smt.clone)
                end
                FmI.rep_sharp.clear() # Deactivate rep that has become obsolete.

                # If the statement is if, there is a block for each of yes, no, noifs, so translate each.
            elsif statement.is_a?(If) then   
                yes = statement.yes.flatten       # Smooth yes of if statement. 
                new_yes = Block.new(yes.mode,"")  # New yes storage block

                yes.each_inner do |inner|          
                    # I read inner, but when I am par, I delete all '.
                    unless (list.include?(inner.name.to_s)) then
                        if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            new_block.add_inner(inner.clone)
                        end            
                    end
                end

                # Check the statements in "yes" in order.
                yes.each_statement do |statement|
                    # If statement is Transmit, it is an expression and should be processed.
                    if statement.is_a?(Transmit) then
                        # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                        unless (res_name(statement.left).name.to_s.include? "'") || yes.mode == :par then
                            # Prepare a new signal with the # on the variable on the left side using the att_signal method.
                            new_signal = att_signal(statement.left, "#")
                            # Check list and add new variables to inner if they do not duplicate.
                            unless (list.include?(new_signal.name.to_s)) then
                                list << new_signal.name.to_s
                                new_block.add_inner(new_signal)
                            end

                            new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                            FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                            new_yes.add_statement(new_statement.clone)


                            FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left

                        else
                            new_yes.add_statement(statement.clone)
                        end 
                    else
                        new_yes.add_statement(statement.clone)
                    end
                end

                # Confirm that "else" exists and convert it if it exists.
                # Because error occurs when trying to convert when "else" does not exist.
                if statement.no.is_a? (Block) then
                    no = statement.no.flatten
                    new_no = Block.new(no.mode,"")

                    no.each_inner do |inner|          
                        # I read inner, but when I am par, I delete all '.
                        unless (list.include?(inner.name.to_s)) then
                            if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                new_block.add_inner(inner.clone)
                            end            
                        end
                    end

                    no.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || yes.mode == :par then

                                new_signal = att_signal(statement.left, "#")

                                # Double declaration of existing variable can not be done, so it is excluded.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                                new_no.add_statement(new_statement.clone)
                            else
                                new_no.add_statement(statement.clone)
                            end 
                        else
                            new_no.add_statement(statement.clone)
                        end
                    end
                end

                # Rebuild the converted "if" as a new" statement (If)".
                new_statement = If.new(statement.condition.clone,new_yes.clone,statement.no ? new_no.clone : nil)

                # Just like "no", check if "noifs (elsif)" exists and if there is, take one by one and convert.
                # After that, add the converted "noif" to "If".
                statement.each_noif do |condition, block|
                    noif = block.flatten
                    new_noif = Block.new(noif.mode,"")

                    noif.each_inner do |inner|          
                        # I read inner, but when I am par, I delete all '.
                        unless (list.include?(inner.name.to_s)) then
                            if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                new_block.add_inner(inner.clone)
                            end            
                        end
                    end


                    noif.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || yes.mode == :par then

                                new_signal = att_signal(statement.left, "#")

                                # Double declaration of existing variable can not be done, so it is excluded.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                                new_noif.add_statement(new_statement.clone)
                            else
                                new_noif.add_statement(statement.clone)
                            end 
                        else
                            new_noif.add_statement(statement.clone)
                        end
                    end

                    new_statement.add_noif(condition.clone,new_noif.clone)
                end

                new_block.add_statement(new_statement.clone)

                FmI.rep_sharp.each_key do |key|
                    new_smt = Transmit.new(key.clone,FmI.rep_sharp[key].clone)
                    new_block.add_statement(new_smt.clone)
                end
                FmI.rep_sharp.clear() # Deactivate rep that has become obsolete.

                # Process when "statement" is "Transmit" (just expression).
                # Record the expression in fm_par used for par-> seq and add the expression to new_block which is the "new block".
            elsif statement.is_a?(Transmit) then
                if self.mode == :seq then
                    FmI.fm_par["#{statement.left.to_verilog}"] = statement.right
                end
                new_block.add_statement(statement.clone)

                # When statement is Block (lower layer exists).
                # Smooth the lower layer with do_flat.
                # Add the added variables (inner) and expressions (statement) to new_block, respectively.
            elsif statement.is_a?(Block) then
                smt = statement.do_flat(self.mode)

                smt.each_inner do |inner|         
                    # I read inner, but when I am par, I delete all '.
                    unless (list.include?(inner.name.to_s)) then
                        if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            new_block.add_inner(inner.clone)        
                        end
                    end
                end
                smt.each_statement do |tmt|
                    # Retrieve the RefName of the variable on the left side and store it in this_name.
                    if ((tmt.is_a? (Transmit)) && (self.mode == :seq)) then
                        FmI.fm_par["#{tmt.left.to_verilog}"] = tmt.right
                    end
                    new_block.add_statement(tmt.clone)           
                end
            else
                # Other statements are simply added as is.
                new_block.add_statement(statement.clone)
            end
        end

        return new_block # Return the new_block that completed the smoothing.

        # Processing when there is no block beneath.
        # Unlike ordinary "if" and "case" blocks come down, we check individually block under block.
    else
        self.each_statement do |statement|
            # If the if statement, convert it, otherwise add it as is
            if statement.is_a?(If) then
                # Since yes always exists, it is no problem even if it is converted as it is.
                yes = statement.yes.flatten 
                new_yes = Block.new(yes.mode,"")

                yes.each_inner do |inner|          
                    # I read inner, but when I am par, I delete all '.
                    unless (list.include?(inner.name.to_s)) then
                        if (yes.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            new_block.add_inner(inner.clone)
                        end            
                    end
                end

                # Check the statements in "yes" in order.
                yes.each_statement do |statement|
                    # If statement is Transmit, it is an expression and should be processed.
                    if statement.is_a?(Transmit) then
                        # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                        unless (res_name(statement.left).name.to_s.include? "'") || yes.mode == :par then
                            # Generate a new signal to return #.
                            new_signal = att_signal(statement.left, "#")

                            # Double declaration of existing variable can not be done, so it is excluded.
                            unless (list.include?(new_signal.name.to_s)) then
                                list << new_signal.name.to_s
                                new_block.add_inner(new_signal)
                            end

                            new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                            FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                            FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                            new_yes.add_statement(new_statement.clone)
                        else
                            new_yes.add_statement(statement.clone)
                        end 
                    else
                        new_yes.add_statement(statement.clone)
                    end
                end

                # Confirm that "else" exists and convert it if it exists.
                # Because error occurs when trying to convert when "else" does not exist.
                if statement.no.is_a? (Block) then          
                    no = statement.no.flatten
                    new_no = Block.new(no.mode,"")

                    no.each_inner do |inner|          
                        # I read inner, but when I am par, I delete all '.
                        unless (list.include?(inner.name.to_s)) then
                            if (no.mode == :seq) || (inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                new_block.add_inner(inner.clone)
                            end            
                        end
                    end

                    no.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || no.mode == :par then

                                new_signal = att_signal(statement.left, "#")

                                # Double declaration of existing variable can not be done, so it is excluded.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                                new_no.add_statement(new_statement.clone)
                            else
                                new_no.add_statement(statement.clone)
                            end 
                        else
                            new_no.add_statement(statement.clone)
                        end
                    end
                end
                # Rebuild the converted "if" as a new" statement (If)".
                new_statement = If.new(statement.condition.clone,new_yes.clone,statement.no ? new_no.clone : nil)
                # Just like "no", check if "noifs (elsif)" exists and if there is, take one by one and convert.
                # After that, add the converted "noif" to "If".
                statement.each_noif do |condition, block|

                    noif = block.flatten
                    new_noif = Block.new(noif.mode,"")

                    noif.each_inner do |inner|          
                        # I read inner, but when I am par, I delete all '.
                        unless (list.include?(inner.name.to_s)) then
                            if (noif.mode == :seq) || (inner.name.to_s.include? "#") then
                                list << inner.name.to_s
                                new_block.add_inner(inner.clone)
                            end            
                        end
                    end


                    noif.each_statement do |statement|
                        # If statement is Transmit, it is an expression and should be processed.
                        if statement.is_a?(Transmit) then
                            # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                            unless (res_name(statement.left).name.to_s.include? "'") || noif.mode == :par then

                                new_signal = att_signal(statement.left, "#")

                                # Double declaration of existing variable can not be done, so it is excluded.
                                unless (list.include?(new_signal.name.to_s)) then
                                    list << new_signal.name.to_s
                                    new_block.add_inner(new_signal)
                                end

                                new_statement = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                                FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                                FmI.fm_par["#{statement.left.to_verilog}"] = new_statement.left
                                new_noif.add_statement(new_statement.clone)
                            else
                                new_noif.add_statement(statement.clone)
                            end 
                        else
                            new_noif.add_statement(statement.clone)
                        end
                    end

                    new_statement.add_noif(condition.clone,new_noif.clone)
                end

                new_block.add_statement(new_statement.clone)

                FmI.rep_sharp.each_key do |key|
                    new_smt = Transmit.new(key.clone,FmI.rep_sharp[key].clone)
                    new_block.add_statement(new_smt.clone)
                end
                FmI.rep_sharp.clear() # Deactivate rep that has become obsolete.

            elsif statement.is_a?(Case) then
                if statement.default.is_a?(Block)
                    new_default = statement.default.flatten
                end

                new_statement = Case.new(statement.value.clone,statement.default ? new_default.clone : nil,[])
                statement.each_when do |whens|
                    new_when_statement = whens.statement.flatten
                    new_when = When.new(whens.match.clone,new_when_statement.clone)

                    new_statement.add_when(new_when.clone)
                end

                new_block.add_statement(new_statement)
            else          
                new_block.add_statement(statement.clone)
            end
        end    
        return new_block
    end
end

#get_by_name(name) ⇒ Object

Find an inner object by +name+. NOTE: return nil if not found.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/HDLRuby/hruby_low_resolve.rb', line 94

def get_by_name(name)
    # Ensure the name is a symbol.
    name = name.to_sym
    # Look in the signals.
    found = self.get_inner(name)
    return found if found
    # Check the sub blocks names.
    self.each_block do |block|
        # puts "block=#{block.name}"
        if (block.name == name) then
            return block
        end
    end
    return nil
end

#get_inner(name) ⇒ Object Also known as: get_signal

Gets an inner signal by +name+.



4501
4502
4503
4504
# File 'lib/HDLRuby/hruby_low.rb', line 4501

def get_inner(name)
    # puts "name=#{name}, inners=#{@inners.each_key.to_a}"
    return @inners[name.to_sym]
end

#get_variable(name) ⇒ Object

Gets a variable by +name+.



147
148
149
150
151
152
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 147

def get_variable(name)
    # Ensure name is a symbol.
    name = name.to_sym
    # Get the variable.
    return variables[name]
end

#hashObject

Hash function.



4468
4469
4470
# File 'lib/HDLRuby/hruby_low.rb', line 4468

def hash
    return [@mode,@name,@inners,@statements].hash
end

#insert_statement!(idx, stmnt) ⇒ Object

Inserts statement *stmnt+ at index +idx+.



1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1142

def insert_statement!(idx,stmnt)
    # Checks the index.
    if idx > @statements.size then
        raise AryError, "Index out of range: #{idx}"
    end
    # Checks the statement.
    unless stmnt.is_a?(Statement)
        raise AnyError, "Invalid type for a statement: #{stmnt.class}"
    end
    # Inserts the statement.
    @statements.insert(idx,stmnt)
    stmnt.parent = self
end

#last_statementObject

Returns the last statement.



4584
4585
4586
# File 'lib/HDLRuby/hruby_low.rb', line 4584

def last_statement
    return @statements[-1]
end

#map_inners!(&ruby_block) ⇒ Object

Maps on the inners.



1122
1123
1124
1125
1126
1127
1128
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1122

def map_inners!(&ruby_block)
    @inners.map! do |inner|
        inner = ruby_block.call(inner)
        inner.parent = self unless inner.parent
        inner
    end
end

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

Maps on the statements.



1190
1191
1192
1193
1194
1195
1196
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1190

def map_statements!(&ruby_block)
    @statements.map! do |stmnt|
        stmnt = ruby_block.call(stmnt)
        stmnt.parent = self unless stmnt.parent
        stmnt
    end
end

#mix?(mode = nil) ⇒ Boolean

Tell if there is a mix block. +mode+ is the mode of the upper block.

Returns:

  • (Boolean)


238
239
240
241
242
243
244
# File 'lib/HDLRuby/hruby_low2seq.rb', line 238

def mix?(mode = nil)
    # Check if different from mode block if any.
    return true if mode && self.type != mode
    # No difference with the upper block, maybe there is one within.
    # Check each statement.
    self.each_statement.any? { |stmt| stmnt.mix?(mode) }
end

#num_statementsObject

Gets the number of statements.



4557
4558
4559
# File 'lib/HDLRuby/hruby_low.rb', line 4557

def num_statements
    return @statements.size
end

#par_in_seq2seq!Object

Converts par blocks within seq blocks to seq blocks.



106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/HDLRuby/hruby_low_without_parinseq.rb', line 106

def par_in_seq2seq!
    # Recurse on the sub blocks.
    self.each_statement(&:par_in_seq2seq!)
    # Is the current block a seq block?
    if self.mode == :seq then
        # Yes, convert its inner par blocks to seq blocks.
        self.each_statement do |statement|
            if (statement.is_a?(Block)) then
                statement.to_seq! if statement.mode == :par
            end
        end
    end
    return self
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.



1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1231

def reassign_expressions!(node2reassign)
    # Build the replacement table.
    node2rep = node2reassign.map {|n,r| [n,r[0]] }.to_h

    # First recurse on the sub blocks.
    # self.each_block { |block| block.reassign_expressions!(node2rep) }
    self.each_block { |block| block.reassign_expressions!(node2reassign) }

    # Now work on the block.
    # Replace on the statements.
    self.map_statements! do |statement|
        # Do the replacement
        node2rep_done = statement.replace_expressions!(node2rep)
        # Assign the replaced nodes in a new block.
        unless node2rep_done.empty?
            blk = Block.new(:seq)
            node2rep_done.each do |node,rep|
                reassign = node2reassign[node][1].clone
                blk.add_statement(Transmit.new(reassign,node.clone))
            end
            blk.add_statement(statement.clone)
            blk
        else
            statement
        end
    end
end

#refs_by_variables!(stmnt, sym2var) ⇒ Object

Replaces the references by corresponding variables in +stmnt+ from +sym2var+ table.



115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 115

def refs_by_variables!(stmnt,sym2var)
    # First, recurse.
    if stmnt.respond_to?(:each_node) then
        stmnt.each_node {|elem| refs_by_variables!(elem,sym2var) }
    end
    # Now replace an element if required.
    if stmnt.respond_to?(:map_nodes!) then
        stmnt.map_nodes! do |elem| 
            var = sym2var[elem.to_sym]
            var ? var2ref(var) : elem
        end
    end
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.



1217
1218
1219
1220
1221
1222
1223
1224
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1217

def replace_expressions!(node2rep)
    res = {}
    # Recurse on the children.
    self.each_node do |node|
        res.merge!(node.replace_expressions!(node2rep))
    end
    return res
end

#replace_names!(former, nname) ⇒ Object

Replaces recursively +former+ name by +nname+ until it is redeclared.



720
721
722
723
724
725
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 720

def replace_names!(former,nname)
    # Stop here if the name is redeclared.
    return if self.each_inner.find {|inner| inner.name == former }
    # Recurse on the sub scopes and behaviors.
    replace_names_subs!(former,nname)
end

#replace_names_subs!(former, nname) ⇒ Object

Replaces recursively +former+ name by +nname+ until it is redeclared in the sub scopes and behaviors.



713
714
715
716
717
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 713

def replace_names_subs!(former,nname)
    self.each_statement do |stmnt|
        stmnt.replace_names!(former,nname)
    end
end

#replace_statement!(org, stmnt) ⇒ Object

Replaces statement +org+ by statement +stmnt+.

NOTE: does nothing if +org+ is not present.



1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1176

def replace_statement!(org,stmnt)
    # Checks the statement.
    unless stmnt.is_a?(Statement)
        raise AnyError, "Invalid type for a statement: #{stmnt.class}"
    end
    idx = @statements.index(org)
    # @statements[idx] = stmnt if idx
    if idx then
        @statements[idx] = stmnt
        stmnt.parent = self unless stmnt.parent
    end
end

#res_name(me) ⇒ Object

Recursively search, return Refname.



1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
# File 'lib/HDLRuby/hruby_verilog.rb', line 1427

def res_name(me)
    if me.is_a? (RefName) then
        return me
    else
        if me.ref.is_a? (RefName) then
            return RefName.new(me.ref.type, me.ref.ref.clone, me.ref.name.to_s)
        elsif me.ref.is_a? (RefIndex) then
            return res_name(me.ref)
        elsif me.ref.is_a? (RefRange) then
            return res_name(me.ref)
        end
    end
end

#reverse_each_statement(&ruby_block) ⇒ Object

Reverse iterates over the statements.

Returns an enumerator if no ruby block is given.



4576
4577
4578
4579
4580
4581
# File 'lib/HDLRuby/hruby_low.rb', line 4576

def reverse_each_statement(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:reverse_each_statement) unless ruby_block
    # A ruby block? Apply it on each statement.
    @statements.reverse_each(&ruby_block)
end

#search_refname(me, att = "'") ⇒ Object

Recursively search, add "att" to RefName and return.



1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
# File 'lib/HDLRuby/hruby_verilog.rb', line 1413

def search_refname(me,att = "'")
    if me.is_a? (RefName) then
        return RefName.new(me.type, me.ref.clone, me.name.to_s + att)
    elsif me.ref.is_a? (RefName) then
        return RefName.new(me.ref.type, me.ref.ref.clone, me.ref.name.to_s + att)
    elsif me.ref.is_a? (RefIndex) then
        return RefIndex.new(me.ref.type, search_refname(me.ref), me.ref.index.clone)
    elsif me.ref.is_a? (RefRange) then
        my_range = me.ref.range
        return RefRange.new(me.ref.type, search_refname(me.ref), my_range.first.clone..my_range.last.clone)
    end
end

#select2case!Object

Breaks the assignments to concats.

NOTE: work on the direct sub statement only, not deeply.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/HDLRuby/hruby_low_without_select.rb', line 134

def select2case!
    # Check each statement.
    self.map_statements! do |stmnt|
        # Skip blocks that are treated through recursion.
        next stmnt if stmnt.is_a?(Block)
        # Work on the statement.
        # Extract the Select expressions.
        selects = stmnt.extract_selects!
        if selects.any? then
            # Generate a sequential block containing the cases.
            blk = LowWithoutSelect.selects2block(selects)
            # Adds the statement to the block.
            blk.add_statement(stmnt.clone)
            stmnt = blk
        end
        stmnt 
    end
end

#set_mode!(mode) ⇒ Object

Sets the mode.



1110
1111
1112
1113
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1110

def set_mode!(mode)
    # Check and set the type.
    @mode = mode.to_sym
end

#set_name!(name) ⇒ Object

Sets the name.



1116
1117
1118
1119
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1116

def set_name!(name)
    # Check and set the name.
    @name = name.to_sym
end

#set_statement!(idx, stmnt) ⇒ Object

Sets statement +stmnt+ at index +idx+.



1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1157

def set_statement!(idx,stmnt)
    # Checks the index.
    if idx > @statements.size then
        raise AryError, "Index out of range: #{idx}"
    end
    # Checks the statement.
    unless stmnt.is_a?(Statement)
        raise AnyError, "Invalid type for a statement: #{stmnt.class}"
    end
    # Detach the previous statement if any.
    @statements[idx].parent = nil if @statements[idx]
    # Set the new statement.
    @statements[idx] = stmnt
    stmnt.parent = self
end

#signal2subs!Object

Decompose the hierarchical signals in the statements.



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

def signal2subs!
    # Recurse on the statments.
    self.map_statements! do |stmnt|
        stmnt.signal2subs!
    end
    return self
end

#sym2var_name(sym) ⇒ Object

Converts symbol +sym+ representing an HDLRuby reference to a variable name.



63
64
65
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 63

def sym2var_name(sym)
    return ("%" + sym.to_s).to_sym
end

#to_c(res, level = 0) ⇒ Object

Generates the execution of the block C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)



2058
2059
2060
2061
2062
2063
# File 'lib/HDLRuby/hruby_low2c.rb', line 2058

def to_c(res,level = 0)
    # res = " " * (level*3)
    res << " " * (level*3)
    res << Low2C.code_name(self) << "();\n"
    return res
end

#to_c_code(res, level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c_code(level = 0)



1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
# File 'lib/HDLRuby/hruby_low2c.rb', line 1955

def to_c_code(res,level = 0)
    # The resulting string.
    # res = ""
    # puts "generating self=#{self.object_id}"

    # Declare the global variable holding the block.
    res << "Block " << Low2C.obj_name(self) << ";\n\n"

    # Generate the c code of the sub blocks if any.
    self.each_statement do |stmnt|
        stmnt.add_blocks_code(res,level)
    end

    # Generate the execution function.
    res << " " * level*3
    res << "void " << Low2C.code_name(self) << "() {\n"
    res << " " * (level+1)*3
    # res << "Value l,r,d;\n"
    # res << " " * (level+1)*3
    # res << "unsigned long long i;\n"
    # res << "printf(\"Executing #{Low2C.code_name(self)}...\\n\");"
    # Generate the statements.
    self.each_statement do |stmnt|
        # res << stmnt.to_c(level+1)
        stmnt.to_c(res,level+1)
    end
    # Close the execution function.
    res << " " * level*3
    res << "}\n\n"


    # Generate the signals.
    # self.each_signal { |signal| res << signal.to_c(level) }
    self.each_signal { |signal| signal.to_c(res,level) }

    # The header of the block.
    res << " " * level*3
    res << "Block " << Low2C.make_name(self) << "() {\n"
    res << " " * (level+1)*3
    res << "Block block = malloc(sizeof(BlockS));\n"
    res << " " * (level+1)*3
    res << "block->kind = BLOCK;\n";

    # Sets the global variable of the block.
    res << "\n"
    res << " " * (level+1)*3
    res << Low2C.obj_name(self) << " = block;\n"

    # Set the owner if any.
    if self.parent then
        # Look for a block or behavior parent.
        true_parent = self.parent
        until true_parent.is_a?(Block) || true_parent.is_a?(Behavior)
               true_parent = true_parent.parent
        end
        # Set it as the real parent.
        res << " " * (level+1)*3
        res << "block->owner = (Object)" 
        res << Low2C.obj_name(true_parent) << ";\n"
    else
        res << "block->owner = NULL;\n"
    end

    # The name
    res << " " * (level+1)*3
    res << "block->name = \"#{self.name}\";\n"

    # Add the inner signals declaration.
    res << " " * (level+1)*3
    res << "block->num_inners = #{self.each_inner.to_a.size};\n"
    res << " " * (level+1)*3
    res << "block->inners = calloc(sizeof(SignalI)," +
           "block->num_inners);\n"
    self.each_inner.with_index do |inner,i|
        res << " " * (level+1)*3
        res << "block->inners[#{i}] = "
        res << Low2C.make_name(inner) << "();\n"
    end

    # Sets the execution function.
    res << " " * (level+1)*3
    res << "block->function = &" << Low2C.code_name(self) << ";\n"

    # Generate creation of the sub blocks.
    self.each_statement do |stmnt|
        stmnt.add_make_block(res,level+1)
    end

    # Generate the Returns of the result.
    res << "\n"
    res << " " * (level+1)*3
    res << "return block;\n"

    # Close the block.
    res << " " * level*3
    res << "};\n\n"
    return res
end

#to_ch(res) ⇒ Object

Generates the content of the h file. def to_ch



2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
# File 'lib/HDLRuby/hruby_low2c.rb', line 2067

def to_ch(res)
    # puts "to_ch for block=#{Low2C.obj_name(self)} with=#{self.each_inner.count} inners"
    # res = ""
    # Declare the global variable holding the block.
    res << "extern Block " << Low2C.obj_name(self) << ";\n\n"

    # Generate the access to the function making the block. */
    res << "extern Block " << Low2C.make_name(self) << "();\n\n"

    # Generate the accesses to the ports.
    # self.each_inner  { |inner|  res << inner.to_ch }
    self.each_inner  { |inner|  inner.to_ch(res) }

    # Recurse on the statements.
    # self.each_statement { |stmnt| res << stmnt.to_ch }
    self.each_statement { |stmnt| stmnt.to_ch(res) }

    return res
end

#to_conversion(mode = nil, rst = true, rep = true) ⇒ Object



951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
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
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 951

def to_conversion(mode = nil, rst = true, rep = true)
    flat = Block.new(mode,"")      # Block that stores results.
    new_yes = Block.new(mode,"")   # Block containing the new yes.
    new_no  = Block.new(mode,"")   # Block containing the new no.
    new_noif  = Block.new(mode,"") # Block containing the new noif.
    list = []

    if rst == false then
        fm_seq_backup = FmI.fm_seq.dup
    end

    # The statement is divided (since it is the lowest layer, there is only Transmit).
    self.each_statement do |statement|
        # Various processing is performed depending on the type of Transmit.
        # If the mode of the upper layer = its own mode, it compresses as it is.

        if(mode == self.mode) then        
            new_statement = statement.clone
            # In the case of an If statement, processing of if, else, elsif is performed.
        elsif statement.is_a?(Case) then

            if statement.default.is_a?(Block)
                rep_buckup = FmI.rep.dup
                FmI.rep.clear()
                default = statement.default.to_conversion(mode,false,false)
                FmI.rep.clear()
                rep_buckup.each_key do |key|
                    FmI.rep[key] = rep_buckup[key]
                end

                new_default = Block.new(default.mode,"")

                default.each_inner do |inner|          
                    # I read inner, but when I am par, I delete all '.
                    unless (list.include?(inner.name.to_s)) then
                        if (self.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            flat.add_inner(inner.clone)
                        end            
                    end
                end

                default.each_statement do |statement|
                    # If statement is Transmit, it is an expression and should be processed.
                    if statement.is_a?(Transmit) then
                        # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                        unless (res_name(statement.left).name.to_s.include? "'") || default.mode == :par then
                            # Prepare a new signal with the # on the variable on the left side using the att_signal method.
                            new_signal = att_signal(statement.left, "#")
                            # Check list and add new variables to inner if they do not duplicate.
                            unless (list.include?(new_signal.name.to_s)) then
                                list << new_signal.name.to_s
                                flat.add_inner(new_signal)
                            end

                            new_smt = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                            FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                            FmI.fm_par["#{statement.left.to_verilog}"] = new_smt.left
                            new_default.add_statement(new_smt.clone)
                        else
                            new_default.add_statement(statement.clone)
                        end 
                    else
                        new_default.add_statement(statement.clone)
                    end
                end     
            end


            new_statement = Case.new(statement.value.clone,statement.default ? new_default.clone : nil,[])

            statement.each_when do |whens|

                rep_buckup = FmI.rep.dup
                FmI.rep.clear()
                when_smt = whens.statement.to_conversion(mode,false,false)
                FmI.rep.clear()
                rep_buckup.each_key do |key|
                    FmI.rep[key] = rep_buckup[key]
                end

                new_when_smt = Block.new(when_smt.mode,"")

                when_smt.each_statement do |statement|
                    # If statement is Transmit, it is an expression and should be processed.
                    if statement.is_a?(Transmit) then
                        # If you add a # to the one with 'on the left side, the shape of the formula will collapse and it will be removed.
                        unless (res_name(statement.left).name.to_s.include? "'") || when_smt.mode == :par then
                            # Prepare a new signal with the # on the variable on the left side using the att_signal method.
                            new_signal = att_signal(statement.left, "#")
                            # Check list and add new variables to inner if they do not duplicate.
                            unless (list.include?(new_signal.name.to_s)) then
                                list << new_signal.name.to_s
                                flat.add_inner(new_signal)
                            end

                            new_smt = Transmit.new(search_refname(statement.left,"#"),statement.right.clone)

                            FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                            FmI.fm_par["#{statement.left.to_verilog}"] = new_smt.left
                            new_when_smt.add_statement(new_smt.clone)
                        else
                            new_when_smt.add_statement(statement.clone)
                        end 
                    else
                        new_when_smt.add_statement(statement.clone)
                    end
                end

                new_when = When.new(whens.match.clone,new_when_smt.clone)
                new_statement.add_when(new_when.clone)
            end

        elsif statement.is_a?(If) then

            rep_buckup = FmI.rep.dup
            FmI.rep.clear()
            yes = statement.yes.to_conversion(mode, false,false)
            FmI.rep.clear()
            rep_buckup.each_key do |key|
                FmI.rep[key] = rep_buckup[key]
            end

            yes.each_inner do |inner|
                unless (list.include?(inner.name.to_s)) then
                    if (yes.mode == :seq) || (inner.name.to_s.include? "#") then
                        list << inner.name.to_s
                        flat.add_inner(inner.clone) # It was new_block. why?
                    end            
                end
            end

            yes.each_statement do |smt|
                if(yes.mode == :seq) then
                    new_signal = att_signal(smt.left, "#")

                    unless (list.include?(new_signal.name.to_s)) then
                        list << new_signal.name.to_s
                        flat.add_inner(new_signal)
                    end

                    yes_statement = Transmit.new(search_refname(smt.left,"#"),smt.right.clone)

                    FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                    FmI.fm_par["#{smt.left.to_verilog}"] = yes_statement.left
                    new_yes.add_statement(yes_statement)
                else
                    new_yes.add_statement(smt.clone)
                end
            end

            if statement.no.is_a? (Block) then
                rep_buckup = FmI.rep.dup
                FmI.rep.clear()
                no = statement.no.to_conversion(mode,false,false)
                FmI.rep.clear()
                rep_buckup.each_key do |key|
                    FmI.rep[key] = rep_buckup[key]
                end

                no.each_inner do |inner|
                    unless (list.include?(inner.name.to_s)) then
                        if (no.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            flat.add_inner(inner.clone) # It was new_block. why?
                        end            
                    end
                end

                no.each_statement do |smt|
                    if(no.mode == :seq) then
                        new_signal = att_signal(smt.left, "#")

                        unless (list.include?(new_signal.name.to_s)) then
                            list << new_signal.name.to_s
                            flat.add_inner(new_signal)
                        end

                        no_statement = Transmit.new(search_refname(smt.left,"#"),smt.right.clone)

                        FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                        FmI.fm_par["#{smt.left.to_verilog}"] = no_statement.left
                        new_no.add_statement(no_statement)
                    else
                        new_no.add_statement(smt.clone)
                    end
                end
            end

            new_statement = If.new(statement.condition.clone,new_yes.clone,statement.no ? new_no.clone : nil)

            statement.each_noif do |condition, block|
                rep_buckup = FmI.rep.dup
                FmI.rep.clear()
                noif = block.to_conversion(mode,false,false)
                FmI.rep.clear()
                rep_buckup.each_key do |key|
                    FmI.rep[key] = rep_buckup[key]
                end

                noif.each_inner do |inner|
                    unless (list.include?(inner.name.to_s)) then
                        if (noif.mode == :seq) || (inner.name.to_s.include? "#") then
                            list << inner.name.to_s
                            flat.add_inner(inner.clone) # It was new_block. why?
                        end            
                    end
                end

                noif.each_statement do |smt|
                    if(noif.mode == :seq) then
                        new_signal = att_signal(smt.left, "#")

                        unless (list.include?(new_signal.name.to_s)) then
                            list << new_signal.name.to_s
                            flat.add_inner(new_signal)
                        end

                        noif_statement = Transmit.new(search_refname(smt.left,"#"),smt.right.clone)

                        FmI.rep_sharp[statement.left] = search_refname(statement.left,"#")

                        FmI.fm_par["#{smt.left.to_verilog}"] = noif_statement.left
                        new_noif.add_statement(no_statement)
                    else
                        new_noif.add_statement(smt.clone)
                    end
                end

                new_statement.add_noif(condition.clone,new_noif.clone)
            end

            # Otherwise, it is necessary to process par-> seq or seq-> par.
        else       
            # Make sure the right side is a formula (Binary).
            if statement.right.is_a?(Binary) then
                # Check the right side and the left side, and if they are variables, check the corresponding expressions and replace them.
                # If it is not a variable, it calls the method to be searched.
                if statement.right.left.is_a? (Ref) then               
                    if (mode == :par && self.mode == :seq) && FmI.fm_seq.has_key?(statement.right.left.to_verilog) then
                        statement_left = FmI.fm_seq["#{statement.right.left.to_verilog}"]
                    elsif (mode == :seq && self.mode == :par) && FmI.fm_par.has_key?(statement.right.left.to_verilog) then
                        statement_left = FmI.fm_par["#{statement.right.left.to_verilog}"]
                    else
                        statement_left = statement.right.left.clone
                    end
                elsif statement.right.left.is_a? (Binary) then  
                    statement_left = statement.right.left.to_change(self.mode)
                else
                    statement_left = statement.right.left.clone
                end

                if statement.right.right.is_a? (Ref) then
                    if (mode == :par && self.mode == :seq) && FmI.fm_seq.has_key?(statement.right.right.to_verilog) then
                        statement_right = FmI.fm_seq["#{statement.right.right.to_verilog}"]
                    elsif (mode == :seq && self.mode == :par) && FmI.fm_par.has_key?(statement.right.right.to_verilog) then
                        statement_right = FmI.fm_par["#{statement.right.right.to_verilog}"]
                    else
                        statement_right = statement.right.right.clone
                    end
                elsif statement.right.right.is_a? (Binary) then
                    statement_right = statement.right.right.to_change(self.mode)
                else
                    statement_right = statement.right.right.clone
                end   
                new_right = Binary.new(statement.right.type,statement.right.operator,statement_left.clone,statement_right.clone)
                # Confirm whether it is a variable.
            elsif statement.right.is_a?(Ref) then
                if (mode == :par && self.mode == :seq) && FmI.fm_seq.has_key?(statement.right.to_verilog) then
                    new_right = FmI.fm_seq["#{statement.right.to_verilog}"].clone
                elsif (mode == :seq && self.mode == :par) && FmI.fm_par.has_key?(statement.right.to_verilog) then
                    new_right = FmI.fm_par["#{statement.right.to_verilog}"].clone
                else
                    new_right = statement.right.clone
                end
                # Because it is not a number. Put it in as it is.
            else
                new_right = statement.right.clone
            end

            if (mode == :par && self.mode == :seq) then
                # Dock the existing left hand side and the replaced right hand side to create a new expression.
                # Record the expression after conversion to hash to continue seq-> par.
                new_statement = Transmit.new(statement.left.clone,new_right)
                FmI.fm_seq["#{statement.left.to_verilog}"] = new_right
            elsif (mode == :seq && self.mode == :par) && (rep) then
                unless (res_name(statement.left).name.to_s.include? "#")
                    # Search the variable on the left side and give 'to the name.
                    new_signal = att_signal(statement.left,"'")

                    unless (list.include?(new_signal.name.to_s)) then
                        list << new_signal.name.to_s
                        flat.add_inner(new_signal)
                    end

                    new_statement = Transmit.new(search_refname(statement.left,"'"),new_right)

                    FmI.rep[statement.left] = new_statement     
                end
            else
                new_statement = Transmit.new(statement.left.clone,new_right)
            end          
        end
        # Add the converted statement to flat (because par -> par or seq -> seq will be added until then).

        if new_statement.is_a?(Transmit) then
            unless (mode == :par && self.mode == :seq) && (res_name(new_statement.left).name.to_s.include? "'") then
                flat.add_statement(new_statement.clone)
            end
        else
            flat.add_statement(new_statement.clone)
        end

        if (rep)
            FmI.rep_sharp.each_key do |key|
                new_smt = Transmit.new(key.clone,FmI.rep_sharp[key].clone)
                flat.add_statement(new_smt.clone)
            end
            FmI.rep_sharp.clear() # Deactivate rep that has become obsolete.
        end
    end
    # Add an expression after paragraph based on rep.
    # A complement expression like x = x '.
    FmI.rep.each_key do |key|
        new_statement = Transmit.new(key.clone,FmI.rep[key].left.clone)
        flat.add_statement(new_statement.clone)
    end
    FmI.rep.clear() # Deactivate rep that has become obsolete.


    # Since seq -> par is the end, fm_par is deleted.
    if (mode == :par && self.mode == :seq) then
        FmI.fm_seq.clear()
    end

    # In case of if statement (when rst == false) you can not convert no or else if you delete the contents of fm_seq.
    # Therefore, in this case restore the backup to restore.
    # This means that it is necessary to erase fm_seq once obtained in the if statement once.
    if(rst == false) then
        FmI.fm_seq.clear()
        fm_seq_backup.each_key do |key|
            FmI.fm_seq[key] = fm_seq_backup[key]
        end
    end

    return flat # Return flat finished checking.
end

#to_hdr(level = 0, header = true, timed = false) ⇒ Object

Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object. +header+ tells if the header is to generate or not. +timed+ tells if its a timed block.



475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 475

def to_hdr(level = 0, header = true, timed = false)
    # The resulting string.
    res = ""
    # Generate the header if required.
    if header then
        if timed then
            res << " " * (level*3) << "timed "
        else
            res << " " * (level*3) << "#{self.mode} "
        end
        unless self.name.empty? then
            res << ":" << Low2HDR.hdr_decl_name(self.name) << " "
        end
        res << "do\n"
    end
    level = level + 1 if header
    # Generate the inners declaration.
    self.each_inner do |inner|
        res << " " * (level*3)
        res << inner.type.to_hdr(level) 
        res << ".inner :" << Low2HDR.hdr_decl_name(inner.name) << "\n"
    end
    # Generate the statements.
    self.each_statement do |stmnt|
        res << stmnt.to_hdr(level)
    end
    # Close the block.
    if header then
        res << " " * ((level-1)*3) << "end\n"
    end
    # Return the result.
    return res
end

#to_highObject

Creates a new high block statement.



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

def to_high
    # Create the new block statement.
    res = HDLRuby::High::Block.new(self.mode,self.name)
    # Add the statements.
    self.each_statement { |stmnt| res.add_statement(stmnt.to_high) }
    return res
end

#to_seq!Object

Convert the block to seq.



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

def to_seq!
    if self.mode == :par then
        # Need to convert.
        # Get which module is it.
        modul = self.is_a?(HDLRuby::High::Block) ? HDLRuby::High :
            HDLRuby::Low
        # First recurse on the sub blocks.
        self.each_statement(&:to_seq!)
        # Now replace each left value by a new signal for
        # differed assingment in seq.
        differeds = []
        self.each_statement do |statement|
            left = statement.left
            if statement.is_a?(Transmit) then
                if modul == HDLRuby::High then
                    sig = modul::SignalI.new(HDLRuby.uniq_name,left.type,:inner)
                    self.add_inner(sig)
                    puts "sig.parent=#{sig.parent}"
                    diff = modul::RefObject.new(modul::RefThis.new,sig)
                else
                    sig = modul::SignalI.new(HDLRuby.uniq_name,left.type)
                    self.add_inner(sig)
                    diff = modul::RefName.new(left.type,modul::RefThis.new,sig.name)
                end
                differeds << [left,diff]
                statement.set_left!(diff)
            end
        end
        # Adds the differed assignments.
        differeds.each do |left,diff|
            self.add_statement(modul::Transmit.new(left.clone,diff.clone))
        end
        # Change the mode.
        self.set_mode!(:seq)
    end
    return self
end

#to_upper_space!Object

Moves the declarations to the upper namespace.



679
680
681
682
683
684
685
686
687
688
# File 'lib/HDLRuby/hruby_low_without_namespace.rb', line 679

def to_upper_space!
    # Recurse on the statements.
    self.each_statement(&:to_upper_space!)

    # Extract the declares from the statements.
    decls = self.each_statement.map(&:extract_declares!)

    # Reinsert the extracted declares to self.
    decls.flatten.each { |decl| self.add_inner(decl) }
end

#to_verilog(spc = 3, vcdmodule = nil) ⇒ Object

Converts the system to Verilog code adding 'spc' spaces at the begining of each line. NOTE: if +vcdmodule+ is not nil add code for generating vcd file when simulating



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
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/HDLRuby/hruby_verilog.rb', line 198

def to_verilog(spc = 3, vcdmodule = nil)
    code = "begin"
    if self.name && !self.name.empty? then
        vname = name_to_verilog(self.name)
        code << " : #{vname}"
        # self.properties[:verilog_name] = vname
    end
    code << "\n" if block.each_inner.any?
    # Declaration of "inner" part within "always".
    block.each_inner do |inner|
        if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
            # code << "      reg"
            code << "#{" " * (spc+3)}reg"
        else
            code << "#{" " * (spc+3)}wire"
        end

        # Variable has "base", but if there is width etc, it is not in "base".
        # It is determined by an if.
        if inner.type.base? 
            if inner.type.base.base? 
                code << "#{inner.type.base.to_verilog} #{inner.to_verilog} #{inner.type.to_verilog}"
            else
                code << "#{inner.type.to_verilog} #{inner.to_verilog}"
            end
        else
            code << " #{inner.type.to_verilog}#{inner.to_verilog}"
        end
        if inner.value then
            # There is an initial value.
            code << " = #{inner.value.to_verilog}"
        end
        code << ";\n"
    end

    # Make the generation of vcd file if required.
    if vcdmodule then
        code << "\n#{" " * (spc+3)}$dumpfile(\"verilog_simulator.vcd\");"
        code << "\n#{" " * (spc+3)}$dumpvars(0,#{vcdmodule});\n"
    end

    # Translate the block that finished scheduling.
    block.each_statement do |statement|
        # puts "#{statement.to_verilog(spc+3)}"
        if statement.is_a?(Block) then
            code << "\n#{" " * (spc+3)}#{statement.to_verilog(spc+3)}"
        else
            code  << "\n#{statement.to_verilog(spc+3)}"
        end
    end
    # Close the block."
    code << "\n#{" "*spc}end"
    return code
end

#to_vhdl(vars, level = 0) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +vars+ is the list of variables and +level+ is the hierachical level of the object.

NOTE: only the statements are generated, the remaining is assumed to be handled by the upper scope.



1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1106

def to_vhdl(vars, level = 0)
    # The resulting string.
    res = ""
    # Generate the statements.
    self.each_statement do |stmnt|
        res << stmnt.to_vhdl(vars,level)
    end
    # Return the result.
    return res
end

#unshift_statement(statement) ⇒ Object

Adds a +statement+ and the begining of the block

NOTE: TimeWait is not supported unless for TimeBlock objects.



4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
# File 'lib/HDLRuby/hruby_low.rb', line 4541

def unshift_statement(statement)
    unless statement.is_a?(Statement) then
        raise AnyError,
              "Invalid class for a statement: #{statement.class}"
    end
    if statement.is_a?(TimeWait) then
        raise AnyError,
              "Timed statements are not supported in common blocks."
    end
    @statements.unshift(statement)
    # And set its parent.
    statement.parent = self
    statement
end

#var2ref(var) ⇒ Object

Converts a variable to a reference to it.



57
58
59
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 57

def var2ref(var)
    return RefName.new(var.type,RefThis.new,var.name)
end

#var_name2sym(name) ⇒ Object

Converts a variable +name+ to the symbol giving the corresponding HDLRuby reference.



69
70
71
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 69

def var_name2sym(name)
    return name[1..-1].to_sym
end

#variable_name?(name) ⇒ Boolean

Tell if a name is a variable one.

Returns:

  • (Boolean)


74
75
76
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 74

def variable_name?(name)
    name[0] == "%"
end

#variablesObject

Get access to the variables



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

def variables
    # Initializes the set of variables if required.
    @variables ||= {}
    return @variables
end

#with_var(upper = nil) ⇒ Object

Converts to a variable-compatible block where +upper+ is the upper block if any.

NOTE: the result is a new block.



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
240
241
242
243
244
245
246
# File 'lib/HDLRuby/hruby_low_with_var.rb', line 159

def with_var(upper = nil)
    # puts "with_var for #{self} with upper=#{upper}"
    # Recurse on the statements.
    new_stmnts = []
    self.each_statement do |stmnt|
        # Process stmnt
        if stmnt.respond_to?(:with_var) then
            # Can be converted
            stmnt = stmnt.with_var(self)
        else
            # Cannot be converted, simply clone.
            stmnt = stmnt.clone
        end
        # Adds the result.
        new_stmnts << stmnt
    end
    # Handle the cases that does not need directly a variable
    # convertion
    # Is the block a par?
    if self.mode == :par then
        # Yes, creates a new block with the new statements.
        block = Block.new(self.mode)
        self.each_inner { |inner| block.add_inner(inner.clone) }
        new_stmnts.each {|stmnt| block.add_statement(stmnt) }
        # Is the block within a seq?
        if upper && upper.mode == :seq then
            # Yes, converts to seq.
            # return self.to_seq
            return block.blocks2seq!
        end
        # No, simply return the block.
        # block = self.clone
        return block
    end

    # The block is a seq, convert it.
    # Treat the block
    sym2var = {} # The table of variable by corresponding signal name
    # Generate and replace the variables
    new_stmnts.each do |stmnt|
        unless stmnt.is_a?(Transmit) then
            # The statement is not a transmission, extract the
            # variables that correspond to external signals.
            extract_from_externals!(stmnt,sym2var)
        else 
            # Other case: transmission, the left value is to convert
            # to a variable, and the right values are to be updated
            # with the existing variables.
            # First convert the left value to the corresponding symbol.
            sym = stmnt.left.to_sym
            # puts "sym=#{sym}"
            var = sym2var[sym]
            unless var then
                var = SignalI.new(sym2var_name(sym),stmnt.left.type)
                sym2var[sym] = var
            end
            # Then replace the relevant references by corresponding
            # variables
            refs_by_variables!(stmnt,sym2var)
        end
    end
    # puts "sym2var=#{sym2var}"
    # Declare the variables in the top block.
    top = self.top_block
    # puts "top=#{top}"
    sym2var.each_value do |var|
        # puts "Adding var=#{var.name}"
        top.add_inner(var.clone) unless top.each_inner.find {|v| v.eql?(var) }
    end
    # Generate the new block.
    result = self.class.new(self.mode,self.name)
    # Adds the inner signals of current block.
    self.each_inner do |inner|
        result.add_inner(inner.clone)
    end
    # Adds the new statements.
    new_stmnts.each do |stmnt|
        result.add_statement(stmnt)
    end
    # Adds final statements assigning variables back to the orginal
    # signals.
    sym2var.each do |sym,var|
        result.add_statement(
            Transmit.new(sym.to_hdr.clone,var2ref(var)))
    end
    # End of the conversion.
    return result
end