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



4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
# File 'lib/HDLRuby/hruby_low.rb', line 4241

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.



4235
4236
4237
# File 'lib/HDLRuby/hruby_low.rb', line 4235

def mode
  @mode
end

#nameObject (readonly)

The name of the block if any



4238
4239
4240
# File 'lib/HDLRuby/hruby_low.rb', line 4238

def name
  @name
end

Instance Method Details

#add_blocks_code(res, level) ⇒ Object

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



1829
1830
1831
1832
1833
# File 'lib/HDLRuby/hruby_low2c.rb', line 1829

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



4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
# File 'lib/HDLRuby/hruby_low.rb', line 4299

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



1836
1837
1838
1839
# File 'lib/HDLRuby/hruby_low2c.rb', line 1836

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.



4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
# File 'lib/HDLRuby/hruby_low.rb', line 4349

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



1403
1404
1405
1406
1407
# File 'lib/HDLRuby/hruby_verilog.rb', line 1403

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.



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

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.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/HDLRuby/hruby_low_without_concat.rb', line 109

def break_concat_assigns!
    # Check each transmit.
    self.each_statement.each.with_index do |stmnt,i|
        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)
            end
        end
    end
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



1303
1304
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 1303

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)



4465
4466
4467
4468
4469
4470
4471
4472
4473
# File 'lib/HDLRuby/hruby_low.rb', line 4465

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.



1124
1125
1126
1127
1128
1129
1130
1131
1132
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1124

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.



1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1252

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.



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

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



778
779
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 778

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.



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

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.



4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
# File 'lib/HDLRuby/hruby_low.rb', line 4426

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.



4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
# File 'lib/HDLRuby/hruby_low.rb', line 4258

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.



4318
4319
4320
4321
4322
4323
# File 'lib/HDLRuby/hruby_low.rb', line 4318

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.



4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
# File 'lib/HDLRuby/hruby_low.rb', line 4452

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.



4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
# File 'lib/HDLRuby/hruby_low.rb', line 4334

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.



4390
4391
4392
4393
4394
4395
# File 'lib/HDLRuby/hruby_low.rb', line 4390

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.



4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
# File 'lib/HDLRuby/hruby_low.rb', line 4439

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)


4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
# File 'lib/HDLRuby/hruby_low.rb', line 4274

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.



315
316
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 315

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



4327
4328
4329
4330
# File 'lib/HDLRuby/hruby_low.rb', line 4327

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.



4294
4295
4296
# File 'lib/HDLRuby/hruby_low.rb', line 4294

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

#insert_statement!(idx, stmnt) ⇒ Object

Inserts statement *stmnt+ at index +idx+.



1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1135

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.



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

def last_statement
    return @statements[-1]
end

#map_inners!(&ruby_block) ⇒ Object

Maps on the inners.



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

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.



1179
1180
1181
1182
1183
1184
1185
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1179

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.



4383
4384
4385
# File 'lib/HDLRuby/hruby_low.rb', line 4383

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.



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

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

#repeat_to_verilog!Object

Extract and convert to verilog the TimeRepeat statements. NOTE: work only on the current level of the block (should be called through each_block_deep).



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/HDLRuby/hruby_verilog.rb', line 260

def repeat_to_verilog!
    code = ""
    # Gather the TimeRepeat statements.
    repeats = self.each_statement.find_all { |st| st.is_a?(TimeRepeat) }
    # Remove them from the block.
    repeats.each { |st| self.delete_statement!(st) }
    # Generate them separately in timed always processes.
    repeats.each do |st|
        code << "   always #{st.delay.to_verilog} begin\n"

        # Perform "scheduling" using the method "flatten".
        block = st.statement.flatten(st.statement.mode.to_s)

        # Declaration of "inner" part within "always".
        block.each_inner do |inner|
            # if regs.include?(inner.name) then
            if HDLRuby::Low::VERILOG_REGS.include?(inner.to_verilog) then
                code << "      reg"
            else
                code << "      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

        # Translate the block that finished scheduling.
        block.each_statement do |statement|
            code  << "\n      #{statement.to_verilog(block.mode.to_s)}"
        end

        FmI.fm_par.clear()

        code << "\n   end\n\n"
    end
    return code
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.



1206
1207
1208
1209
1210
1211
1212
1213
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1206

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.



1169
1170
1171
1172
1173
1174
1175
1176
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1169

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
end

#res_name(me) ⇒ Object

Recursively search, return Refname.



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

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.



4402
4403
4404
4405
4406
4407
# File 'lib/HDLRuby/hruby_low.rb', line 4402

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.



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

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.



1103
1104
1105
1106
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1103

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

#set_name!(name) ⇒ Object

Sets the name.



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

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



1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1150

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

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



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

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)



1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
# File 'lib/HDLRuby/hruby_low2c.rb', line 1844

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



1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
# File 'lib/HDLRuby/hruby_low2c.rb', line 1956

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



949
950
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
# File 'lib/HDLRuby/hruby_verilog.rb', line 949

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

def to_seq!
    if self.mode == :par then
        # Need to convert.
        # 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
                sig = SignalI.new(HDLRuby.uniq_name,left.type)
                self.add_inner(sig)
                diff = RefName.new(left.type,RefThis.new,sig.name)
                differeds << [left,diff]
                statement.set_left!(diff)
            end
        end
        # Adds the differed assignments.
        differeds.each do |left,diff|
            self.add_statement(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.



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

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.



4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
# File 'lib/HDLRuby/hruby_low.rb', line 4367

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