class BlifUtils::Netlist

Public Class Methods

new() click to toggle source
# File lib/blifutils/netlist.rb, line 586
def initialize
        @models = []
end

Public Instance Methods

add_model(model) click to toggle source
# File lib/blifutils/netlist.rb, line 611
def add_model (model)
        if include?(model.name) then
                abort "ERROR: Model \"#{model.name}\" is already defined in the model collection"
        end
        @models << model
        self
end
add_model_to_front(model) click to toggle source
# File lib/blifutils/netlist.rb, line 620
def add_model_to_front (model)
        if include?(model.name) then
                abort "ERROR: Model \"#{model.name}\" is already defined in the model collection".ligth_red
        end
        @models.unshift(model)
        self
end
analyze() click to toggle source
# File lib/blifutils/netlist.rb, line 653
def analyze
        str = "Model collection contains #{length} models\n"
        @models.each{|model| str += model.analyze}
        return str
end
clear() click to toggle source
# File lib/blifutils/netlist.rb, line 697
def clear
        @models = []
        self
end
create_simulation_file_for_model(modelName = nil, quiet: false) click to toggle source
# File lib/blifutils/simulator_generator.rb, line 55
def create_simulation_file_for_model (modelName = nil, quiet: false)
        modelName = first_model.name if modelName.nil?
        dedel = get_model_by_name(modelName)
        if dedel.nil?
                abort "ERROR: Model \"#{modelName}\" not found."
        end
        if dedel.is_self_contained? then
                model = dedel
        else
                model = flatten(modelName, false, quiet: quiet)
        end

        className = (model.name + '_simulation_class').gsub('_',' ').split.collect{|word| word.capitalize}.join
        gateArray = model.simulation_components_to_schedule_stack(withOutputGraphviz: false, quiet: quiet) # This array does not contain constants
        latchArray = model.components.select{|comp| comp.isLatch?}
        nbGates = gateArray.length
        nbLatches = latchArray.length
        nbNets = model.nets.length

        # Find inputs #
        simInputs = {} # {name -> [[net, index], ... ], ... }
        model.inputs.each do |iIO|
                iname = iIO.name
                match = iname.match(/(.*?)((\[(\d+)\])|(_(\d+)_))/)
                if match.nil? then
                        simInputs[iname] = [] if simInputs[iname].nil?
                        simInputs[iname] << [iIO.net, 0]
                else
                        unless match[4].nil? then
                                indNum = match[4].to_i
                        end
                        unless match[6].nil? then
                                indNum = match[6].to_i
                        end
                        simInputs[match[1]] = [] if simInputs[match[1]].nil?
                        simInputs[match[1]] << [iIO.net, indNum]
                end
        end
        simVectorInputs = [] # [[name, [net0, net1, ... ]], ... ]
        simInputs.each do |vectName, net_index_array|
                net_index_array.sort!{|net_indexA, net_indexB| net_indexA[1] <=> net_indexB[1]}
                simVectorInputs << [vectName, net_index_array.collect{|net_index| net_index[0]}]
        end

        # Find outputs #
        simOutputs = {} # {name -> [[net, index], ... ], ... }
        model.outputs.each do |iIO|
                oname = iIO.name
                match = oname.match(/(.*?)((\[(\d+)\])|(_(\d+)_))/)
                if match.nil? then
                        simOutputs[oname] = [] if simOutputs[oname].nil?
                        simOutputs[oname] << [iIO.net, 0]
                else
                        unless match[4].nil? then
                                indNum = match[4].to_i
                        end
                        unless match[6].nil? then
                                indNum = match[6].to_i
                        end
                        simOutputs[match[1]] = [] if simOutputs[match[1]].nil?
                        simOutputs[match[1]] << [iIO.net, indNum]
                end
        end
        simVectorOutputs = [] # [[name, [net0, net1, ... ]], ... ]
        simOutputs.each do |vectName, net_index_array|
                net_index_array.sort!{|net_indexA, net_indexB| net_indexA[1] <=> net_indexB[1]}
                simVectorOutputs << [vectName, net_index_array.collect{|net_index| net_index[0]}]
        end


        str = "/#{'*'*78}/\n\n\n"

        str += "class #{className} : public Model\n{\n" 
        str += "\tprivate:\n\n" 
        str += "\t\tstatic const unsigned int nbNets    = #{nbNets};\n"
        str += "\t\tstatic const unsigned int nbLatches = #{nbLatches};\n"
        str += "\t\tstatic const unsigned int nbGates   = #{nbGates};\n\n"
        str += "\t\tNet   *nets[nbNets];\n"
        str += "\t\tLatch *latches[nbLatches];\n"
        str += "\t\tGate  *gates[nbGates];\n\n"
        str += "\t\tbool   gateChanged[nbGates];\n\n"
        str += "\tpublic:\n\n"
        str += "\t\t#{className}();\n"
        str += "\t\t~#{className}();\n\n"
        simInputs.each do |key, val|
                val.each do |net_index|
                        ind = model.nets.index(net_index[0])
                        next if ind.nil?
                        str += "\t\tNet *INPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end};\n"
                end
        end
        str += "\n"
        simOutputs.each do |key, val|
                val.each do |net_index|
                        str += "\t\tNet *OUTPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end};\n"
                end
        end
        unless simVectorInputs.empty? then
                str += "\n"
                simVectorInputs.each do |simVectInput|
                        next if simVectInput[1].collect{|net| model.nets.index(net)}.include?(nil)
                        str += "\t\tBitVector *INPUT_VECTOR_#{simVectInput[0]};\n"
                end
        end
        unless simVectorOutputs.empty? then
                str += "\n"
                simVectorOutputs.each do |simVectOutput|
                        str += "\t\tBitVector *OUTPUT_VECTOR_#{simVectOutput[0]};\n"
                end
        end
        str += "\n\tprivate:\n\n\t\tvoid setConstants();\n"
        str += "};\n\n"

        str += "#{className}::#{className}() :\n"
        str += "\tModel(nbNets, nbLatches, nbGates)\n"
        str += "{\n"
        model.nets.each_with_index do |net, i|
                fanouts = []
                net.fanouts.each do |fanout| 
                        index = gateArray.index(fanout.target)
                        fanouts << index unless index.nil?
                end
                if fanouts.empty? then
                        str += "\tnets[#{i}] = new Net(NULL, 0, gateChanged);\n"
                else
                        str += "\tnets[#{i}] = new Net(new int[#{fanouts.length}] {#{fanouts.collect{|ind| ind.to_s}.join(', ')}}, #{fanouts.length}, gateChanged);\n"
                end
        end
        str += "\n"
        latchArray.each_with_index do |latch, i|
                str += "\tlatches[#{i}] = new Latch(nets[#{model.nets.index(latch.input)}], nets[#{model.nets.index(latch.output)}], #{latch.initValue != 1 ? '0' : '1'});\n"
        end
        str += "\n"
        gateArray.each_with_index do |gate, i|
                str += "\tgates[#{i}] = new Gate(new Net*[#{gate.inputs.length}]{#{gate.inputs.collect{|net| "nets[#{model.nets.index(net)}]"}.join(', ')}}, #{gate.inputs.length}, nets[#{model.nets.index(gate.output)}], new uint32_t[#{((2**gate.inputs.length)/32.0).ceil}]{#{gate.get_simulation_table}});\n"
        end
        str += "\n"
        str += "\tfor (unsigned int i(0); i < nbGates; i++) {\n\t\tgateChanged[i] = false;\n\t}\n"
        str += "\n"
        simInputs.each do |key, val|
                val.each do |net_index|
                        ind = model.nets.index(net_index[0])
                        next if ind.nil?
                        str += "\tINPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end} = nets[#{ind}];\n"
                end
        end
        str += "\n"
        simOutputs.each do |key, val|
                val.each do |net_index|
                        str += "\tOUTPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end} = nets[#{model.nets.index(net_index[0])}];\n"
                end
        end
        unless simVectorInputs.empty? then
                str += "\n"
                simVectorInputs.each do |simVectInput|
                        next if simVectInput[1].collect{|net| model.nets.index(net)}.include?(nil)
                        str += "\tINPUT_VECTOR_#{simVectInput[0]} = new BitVector(new Net*[#{simVectInput[1].length}]{#{simVectInput[1].collect{|net| "nets[#{model.nets.index(net)}]"}.join(', ')}}, #{simVectInput[1].length});\n"
                end
        end
        unless simVectorOutputs.empty? then
                str += "\n"
                simVectorOutputs.each do |simVectOutput|
                        str += "\tOUTPUT_VECTOR_#{simVectOutput[0]} = new BitVector(new Net*[#{simVectOutput[1].length}]{#{simVectOutput[1].collect{|net| "nets[#{model.nets.index(net)}]"}.join(', ')}}, #{simVectOutput[1].length});\n"
                end
        end
        str += "\n"
        str += "\tModel::setNets(nets);\n"
        str += "\tModel::setLatches(latches);\n"
        str += "\tModel::setGates(gates);\n"
        str += "\tModel::setChanges(gateChanged);\n"
        str += "}\n\n\n"

        str += "#{className}::~#{className}()\n"
        str += "{\n"
        str += "\tunsigned int i;\n\n"
        if nbNets > 0 then
                str += "\tfor (i = 0; i < nbNets; i++) {\n"
                str += "\t\tdelete nets[i];\n"
                str += "\t}\n\n"
        end
        if nbLatches > 0 then
                str += "\tfor (i = 0; i < nbLatches; i++) {\n"
                str += "\t\tdelete latches[i];\n"
                str += "\t}\n\n"
        end
        if nbGates > 0 then
                str += "\tfor (i = 0; i < nbGates; i++) {\n"
                str += "\t\tdelete gates[i];\n"
                str += "\t}\n"
        end
        unless simVectorInputs.empty? then
                str += "\n"
                simVectorInputs.each do |simVectInput|
                        next if simVectInput[1].collect{|net| model.nets.index(net)}.include?(nil)
                        str += "\tdelete INPUT_VECTOR_#{simVectInput[0]};\n"
                end
        end
        unless simVectorOutputs.empty? then
                str += "\n"
                simVectorOutputs.each do |simVectOutput|
                        str += "\tdelete OUTPUT_VECTOR_#{simVectOutput[0]};\n"
                end
        end
        str += "}\n\n\n"
        str += "void #{className}::setConstants()\n{\n"
        model.components.select{|comp| comp.isGate? and comp.is_constant?}.each do |cstGate|
                if cstGate.singleOutputCoverList.empty? or cstGate.singleOutputCoverList[0][1] == 0 then
                        str += "\tnets[#{model.nets.index(cstGate.output)}]->setValue(0);\n"
                else
                        str += "\tnets[#{model.nets.index(cstGate.output)}]->setValue(1);\n"
                end
                if cstGate.singleOutputCoverList.length > 1 and cstGate.singleOutputCoverList.collect{|ina_o| ina_o[1]}.uniq.length > 1 then
                        abort "ERROR: Bad constant definition in gate \"#{cstGate.output.name}\""
                end
        end
        str += "}\n\n"


        outFileName = model.name + '_cpp_sim.cc'
        File.write(outFileName, File.read(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'share', 'blimulator_cpp_classes.cc')) + str)
        puts "Written C++ simulation model in file \"#{outFileName}\"" unless quiet

        compileLine = "g++ -c -W -Wall -O3 -std=c++11 #{outFileName} -o #{File.basename(outFileName, '.cc')}.o"
        puts "Compiling model...\n#{compileLine}" unless quiet
        case system(compileLine)
        when nil then
                abort "ERROR: No g++ compiler found"
        when false then
                abort "An error occured during compilation"
        end


        ## Header ##
        hstr  = "class #{className} : public Model\n{\n" 
        hstr += "\tprivate:\n\n" 
        hstr += "\t\tstatic const unsigned int nbNets    = #{nbNets};\n"
        hstr += "\t\tstatic const unsigned int nbLatches = #{nbLatches};\n"
        hstr += "\t\tstatic const unsigned int nbGates   = #{nbGates};\n\n"
        hstr += "\t\tNet   *nets[nbNets];\n"
        hstr += "\t\tLatch *latches[nbLatches];\n"
        hstr += "\t\tGate  *gates[nbGates];\n\n"
        hstr += "\t\tbool   gateChanged[nbGates];\n\n"
        hstr += "\tpublic:\n\n"
        hstr += "\t\t#{className}();\n"
        hstr += "\t\t~#{className}();\n\n"
        simInputs.each do |key, val|
                val.each do |net_index|
                        ind = model.nets.index(net_index[0])
                        next if ind.nil?
                        hstr += "\t\tNet *INPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end};\n"
                end
        end
        hstr += "\n"
        simOutputs.each do |key, val|
                val.each do |net_index|
                        hstr += "\t\tNet *OUTPUT_NET_#{key}#{if val.length > 1 then "_#{net_index[1]}" end};\n"
                end
        end
        unless simVectorInputs.empty? then
                hstr += "\n"
                simVectorInputs.each do |simVectInput|
                        next if simVectInput[1].collect{|net| model.nets.index(net)}.include?(nil)
                        hstr += "\t\tBitVector *INPUT_VECTOR_#{simVectInput[0]};\n"
                end
        end
        unless simVectorOutputs.empty? then
                hstr += "\n"
                simVectorOutputs.each do |simVectOutput|
                        hstr += "\t\tBitVector *OUTPUT_VECTOR_#{simVectOutput[0]};\n"
                end
        end
        hstr += "\n\tprivate:\n\n\t\tvoid setConstants();\n"
        hstr += "};\n\n#endif /* #{model.name.upcase}_SIMULATION_HEADER_H */\n"

        hhstr = "#ifndef #{model.name.upcase}_SIMULATION_HEADER_H\n#define #{model.name.upcase}_SIMULATION_HEADER_H\n\n"
        outHeadername = model.name + '_cpp_header.hh'
        File.write(outHeadername, hhstr + File.read(File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'share', 'blimulator_cpp_classes.hh')) + hstr)

        puts "Written C++ model simulation header in file \"#{outHeadername}\"" unless quiet
        puts "Now you can write your testbench in a C++ file as 'testbench.cc' including '#include \"#{outHeadername}\"', then run:" unless quiet
        puts "g++ -W -Wall -O3 #{File.basename(outFileName, '.cc')}.o testbench.cc" unless quiet
end
create_vhdl_files(topLevelModuleName = nil) click to toggle source
# File lib/blifutils/blif_to_vhdl.rb, line 27
def create_vhdl_files (topLevelModuleName = nil)
        if topLevelModuleName then
                tLModel = get_model_by_name(topLevelModuleName)
        else
                tLModel = first_model
        end

        abort "ERROR: create_vhdl_file(#{topLevelModuleName}): cannot find top level model" if tLModel.nil?

        update_clocks()

        models.each do |model| 
                model.create_vhdl_file(model == tLModel)
        end
end
first_model() click to toggle source
# File lib/blifutils/netlist.rb, line 596
def first_model
        return @models[0]
end
flatten(modelName = nil, withOutputBuffers = true, quiet: false) click to toggle source
# File lib/blifutils/netlist.rb, line 677
def flatten (modelName = nil, withOutputBuffers = true, quiet: false)
        modelName = first_model.name if modelName.nil?
        dedel = get_model_by_name(modelName)
        if dedel.nil?
                abort "ERROR: Model \"#{modelName}\" not found."
        end
        if dedel.is_self_contained? then
                return dedel.clone
        end
        ####################################
        update_clocks()
        ####################################
        flattenedModel = flatten_model_recursive(modelName, [], quiet: quiet)
        flattenedModel.remove_buffers
        flattenedModel.rename_nets
        flattenedModel.add_output_buffers if withOutputBuffers
        return flattenedModel
end
get_model_by_name(name) click to toggle source
# File lib/blifutils/netlist.rb, line 648
def get_model_by_name (name)
        return @models.select{|mod| mod.name == name}[0]
end
include?(model) click to toggle source
# File lib/blifutils/netlist.rb, line 629
def include? (model)
        if model.class == String then
                return model_names.include?(model)
        elsif model.class == BlifUtils::Netlist::Model then
                return @models.include?(model)
        end
end
length() click to toggle source
# File lib/blifutils/netlist.rb, line 601
def length
        return @models.length
end
model_names() click to toggle source
# File lib/blifutils/netlist.rb, line 606
def model_names
        return @models.collect{|mod| mod.name}
end
models() click to toggle source
# File lib/blifutils/netlist.rb, line 591
def models
        return @models
end
remove_model(model) click to toggle source
# File lib/blifutils/netlist.rb, line 638
def remove_model (model)
        if model.class == String then
                @models.delete_if{|momo| momo.name == model}
        elsif model.class == BlifUtils::Netlist::Model then
                @models.delete(model)
        end
        self
end
remove_unused_models() click to toggle source
# File lib/blifutils/netlist.rb, line 660
def remove_unused_models
        used_models = []
        find_used_models_recursive(used_models, first_model)
        model_names.each do |modName|
                unless used_models.include?(modName) then
                        remove_model(modName)
                end
        end
        self
end
to_blif() click to toggle source
# File lib/blifutils/netlist.rb, line 672
def to_blif
        return @models.collect{|mod| mod.to_blif}.join("\n")
end
update_clocks() click to toggle source
# File lib/blifutils/netlist.rb, line 703
def update_clocks
        @models.each do |model|
                update_clocks_for_model_recursive(model)
        end
        self
end

Private Instance Methods

find_used_models_recursive(used_models, model) click to toggle source
# File lib/blifutils/netlist.rb, line 763
def find_used_models_recursive (used_models, model)
        return if used_models.include?(model.name)
        used_models << model.name
        model.components.select{|comp| comp.isSubcircuit?}.collect{|subc| subc.modelName}.uniq.each do |modname|
                find_used_models_recursive(used_models, get_model_by_name(modname))
        end
end
flatten_model_recursive(modelName, parentModelList, quiet: false) click to toggle source
# File lib/blifutils/netlist.rb, line 772
def flatten_model_recursive (modelName, parentModelList, quiet: false)
        puts "Flattening model \"#{modelName}\"" unless quiet
        # Retreive the model to be flattened
        originalModToFlatten = get_model_by_name(modelName)
        if originalModToFlatten.nil? then
                errStr = "ERROR: The model collection does not contains a model named \"#{modelName}\"."
                unless parentModelList.empty? then
                        instancierFileName = get_model_by_name(parentModelList[-1][0]).originFileName
                        errStr += "\n       Model \"#{modelName}\" is referenced in model \"#{parentModelList[-1]}\""
                end
                abort errStr
        end
        if originalModToFlatten.isBlackBox then
                abort "ERROR: Cannot flatten black box \"#{originalModToFlatten.name}\""
        end

        # Check that there is no recursive instanciation of the same model (would get infinite loop)
        if parentModelList.include?(modelName) then
                errStr = "ERROR: Recursive reference of model \"#{modelName}\".\n       Reference stack:\n"
                parentModelList.each{|pmn| errStr += "        #{pmn}\n"}
                abort errStr
        end

        # Clone it to get a new object copy to work with
        currentModel = originalModToFlatten.clone

        # Loop on each sub circuits in the current model
        currentModel.components.select{|comp| comp.isSubcircuit?}.each do |subckt|
                next if get_model_by_name(subckt.modelName).isBlackBox

                # Get a flatten clone of the referenced model
                instanciatedModel = flatten_model_recursive(subckt.modelName, parentModelList + [currentModel.name], quiet: quiet)

                # Merge the inputs #
                instanciatedModel.inputs.each do |fio|
                        # Find the IO aio whose formal corresponds to fio #
                        actualIOindex = subckt.inputFormalAcutalList.index{|iaio| iaio.name == fio.name}
                        if actualIOindex.nil? then
                                abort "ERROR: In model \"#{currentModel.name}\": in reference to model \"#{instanciatedModel.name}\": input \"#{fio.name}\" is not driven."
                        end
                        aio = subckt.inputFormalAcutalList[actualIOindex]
                        # aio.net -> fio.net
                        newBuffer = BlifUtils::Netlist::LogicGate.new([aio.net], fio.net, [[[1], 1]])
                        aFanoutIndexToDelete = aio.net.fanouts.index{|fanout| fanout.target == subckt and fanout.index == actualIOindex}
                        #####################################################################################
                        raise "Cannot find actual fanout to delete for input" if aFanoutIndexToDelete.nil?
                        aio.net.fanouts[aFanoutIndexToDelete].target = newBuffer
                        aio.net.fanouts[aFanoutIndexToDelete].index = 0
                        fio.net.driver = newBuffer
                        fio.net.isInput = false
                        currentModel.components << newBuffer
                        #####################################################################################
                        #unless aFanoutIndexToDelete.nil? then
                        #  aio.net.fanouts[aFanoutIndexToDelete].target = newBuffer
                        #  aio.net.fanouts[aFanoutIndexToDelete].index = 0
                        #  fio.net.driver = newBuffer
                        #  fio.net.isInput = false
                        #  currentModel.components << newBuffer
                        #end
                        #####################################################################################
                end

                # Merge the outputs #
                instanciatedModel.outputs.each_with_index do |fio, oind|
                        # Find the IO aio whose formal corresponds to fio #
                        actualIOindex = subckt.outputFormalAcutalList.index{|iaio| iaio.name == fio.name}
                        if actualIOindex.nil? then
                                abort "ERROR: In model \"#{currentModel.name}\": in reference to model \"#{instanciatedModel.name}\": output \"#{fio.name}\" has no fanout."
                        end
                        aio = subckt.outputFormalAcutalList[actualIOindex]
                        # fio.net -> aio.net
                        newBuffer = BlifUtils::Netlist::LogicGate.new([fio.net], aio.net, [[[1], 1]])
                        fFanoutIndexToDelete = fio.net.fanouts.index{|fanout| fanout.target == :output and fanout.index == oind}
                        raise "Cannot find actual fanout to delete for output" if fFanoutIndexToDelete.nil?
                        fio.net.fanouts[fFanoutIndexToDelete].target = newBuffer
                        fio.net.fanouts[fFanoutIndexToDelete].index = 0
                        aio.net.driver = newBuffer
                        fio.net.isOutput = false
                        currentModel.components << newBuffer
                end

                currentModel.components.delete(subckt)
                currentModel.components += instanciatedModel.components
                currentModel.nets += instanciatedModel.nets
        end

        return currentModel
end
update_clocks_for_model_recursive(model) click to toggle source
# File lib/blifutils/netlist.rb, line 714
def update_clocks_for_model_recursive (model)
        childrenClocks = []
        model.components.select{|comp| comp.isSubcircuit?}.each do |subckt|
                referencedModel = get_model_by_name(subckt.modelName)
                if referencedModel.nil? then
                        STDERR.puts "WARNING: update_clocks(): Model \"#{subckt.modelName}\" referenced from model \"#{model.name}\" is not is the model collection,\n         cannot determine if it uses any clock."
                        next
                end
                if referencedModel.isBlackBox then
                        STDERR.puts "WARNING: update_clocks(): Model \"#{subckt.modelName}\" referenced from model \"#{model.name}\" is a black box,\n         cannot determine if it uses any clock."
                        next
                end
                update_clocks_for_model_recursive(referencedModel)
                childrenClocks += referencedModel.clocks
        end
        childrenClocks.uniq!
        childrenClocks.each do |clkname|
                model.clocks << clkname unless model.clocks.include?(clkname)
        end
        model.clocks.each do |clkname|
                next if model.inputs.collect{|io| io.name}.include?(clkname)
                newClkNet = BlifUtils::Netlist::Net.new(clkname, nil, [], true, false)
                newClkIo = BlifUtils::Netlist::IO.new(clkname, newClkNet)
                model.inputs.unshift(newClkIo)
        end

        model.components.select{|comp| comp.isSubcircuit?}.each do |subckt|
                referencedModel = get_model_by_name(subckt.modelName)
                next if referencedModel.nil? or referencedModel.isBlackBox
                referencedModel.clocks.each do |clkname|
                        unless (subckt.inputFormalAcutalList.collect{|io| io.name} + subckt.outputFormalAcutalList.collect{|io| io.name}).include?(clkname) then
                                actualClkNet = model.inputs.find{|io| io.name == clkname}.net
                                actualClkNet.fanouts << BlifUtils::Netlist::Fanout.new(subckt, 0)
                                newIo = BlifUtils::Netlist::IO.new(clkname, actualClkNet)

                                subckt.inputFormalAcutalList.each_with_index do |io, i|
                                        net = io.net
                                        fanout = net.fanouts.find{|fnt| fnt.target == subckt and fnt.index == i}
                                        raise "Trouve pas le fanout de l'IO net:#{io.net.name} name:#{io.name} de la reference:#{subckt.modelName} depuis:#{model.name}" if fanout.nil?
                                        fanout.index += 1
                                end

                                subckt.inputFormalAcutalList.unshift(newIo)
                        end
                end
        end
end