def createTMRCirc(ckt): out = sa.scheme_alt() out.__inputs__ = ckt.__inputs__ out.__outputs__ = ckt.__outputs__ # Делаем 3 копии схемы for copy in range(1,4): for el in ckt.__elements__: el1 = "{}_COPY_{}".format(el, copy) data = ckt.__elements__[el] eltype = data[0] lst = [] for d in data[1]: if d not in ckt.__inputs__: lst.append("{}_COPY_{}".format(d, copy)) else: lst.append(d) out.__elements__[el1] = (eltype, lst) # Элемент голосования на каждом выходе for o in ckt.__outputs__: out.__elements__["{}_AND1".format(o)] = ('AND', ["{}_COPY_1".format(o), "{}_COPY_2".format(o)]) out.__elements__["{}_AND2".format(o)] = ('AND', ["{}_COPY_2".format(o), "{}_COPY_3".format(o)]) out.__elements__["{}_AND3".format(o)] = ('AND', ["{}_COPY_1".format(o), "{}_COPY_3".format(o)]) out.__elements__["{}_OR1".format(o)] = ('OR', ["{}_AND1".format(o), "{}_AND2".format(o)]) out.__elements__[o] = ('OR', ["{}_AND3".format(o), "{}_OR1".format(o)]) return out
def subscheme_by_inputs(scheme, nodes): sub = sa.scheme_alt() sub.__inputs__ = copy.copy(nodes) interarr = copy.copy(nodes) input_nodes = [] while interarr != []: label = interarr.pop() if (label in scheme.__outputs__) & (label not in sub.__outputs__): sub.__outputs__.append(label) for element in scheme.__elements__: if label in scheme.__elements__[element][1]: sub.__elements__[element] = copy.deepcopy(scheme.__elements__[element]) input_nodes.append(sub.__elements__[element][1][0]) if sub.__elements__[element][0] not in ["INV", "BUF", "VCC", "GND"]: input_nodes.append(sub.__elements__[element][1][1]) interarr.append(element) for input in input_nodes: if input not in sub.all_labels(): sub.__inputs__.append(input) return sub
def createSubckt_method3(q, ckt): sckt = sa.scheme_alt() for i in ckt.__inputs__: sckt.__inputs__.append(i) for o in ckt.__outputs__: sckt.__outputs__.append(o) # Делаем подходящую структуру данных merge = createMergeStructure(q, ckt) # Ищем самые часто встречающиеся пары и заменяем их # Приоритет парам либо с отрицаниями, либо без них # Цикл заканчивается когда все термы сжимаются до одного элемента num = 0 while (1): uniqueList = getUniqueNames(merge) total = len(uniqueList) # Создаем проверочный массив check = [0] * total for i in range(total): check[i] = [0] * total # Считаем пары for i in range(0, total): for j in range(i+1, total): n1 = uniqueList[i] n2 = uniqueList[j] check[i][j] = 0 for o in merge: for term in merge[o]: if term.count(n1) > 0 and term.count(n2) > 0: check[i][j] = check[i][j] + 1 # Выбираем случайную пару count = 0 for i in range(0, total): for j in range(i+1, total): if check[i][j] > 0: count += 1 if count == 0: break numPair = random.randint(0, count-1) count = 0 for i in range(0, total): for j in range(i+1, total): if check[i][j] > 0: if count == numPair: n1 = uniqueList[i] n2 = uniqueList[j] break count += 1 newname = "INT_{0}".format(num) num = num + 1 if (n1[0] != '!' and n2[0] != '!'): sckt.__elements__[newname] = ('AND', [n1, n2]) elif (n1[0] == '!' and n2[0] == '!'): sckt.__elements__[newname] = ('NOR', [n1[1:], n2[1:]]) elif (n1[0] == '!'): newname1 = "INT_{0}".format(num) num = num + 1 if random.randint(0, 1) == 0: sckt.__elements__[newname1] = ('INV', [n1[1:]]) sckt.__elements__[newname] = ('AND', [newname1, n2]) else: sckt.__elements__[newname1] = ('INV', [n2]) sckt.__elements__[newname] = ('NOR', [newname1, n1[1:]]) elif (n2[0] == '!'): newname1 = "INT_{0}".format(num) num = num + 1 if random.randint(0, 1) == 0: sckt.__elements__[newname1] = ('INV', [n2[1:]]) sckt.__elements__[newname] = ('AND', [newname1, n1]) else: sckt.__elements__[newname1] = ('INV', [n1]) sckt.__elements__[newname] = ('NOR', [newname1, n2[1:]]) # Заменяем пары в термах for o in merge: for term in merge[o]: if term.count(n1) > 0 and term.count(n2) > 0: term.remove(n1) term.remove(n2) term.append(newname) # Цикл, который попарно объединяет термы в рамках каждого выхода while (1): uniqueList = getUniqueNames(merge) total = len(uniqueList) # Создаем проверочный массив check = [0] * total for i in range(total): check[i] = [0] * total # Считаем пары (надо проверить какая пара чаще встречается среди всех выходов) for i in range(0, total): for j in range(i+1, total): n1 = uniqueList[i] n2 = uniqueList[j] check[i][j] = 0 for o in merge: flag = 0 for term in merge[o]: if term.count(n1) > 0: flag = flag + 1 for term in merge[o]: if term.count(n2) > 0: flag = flag + 1 if flag == 2: check[i][j] = check[i][j] + 1 # Выбираем случайную пару count = 0 for i in range(0, total): for j in range(i+1, total): if check[i][j] > 0: count += 1 if count == 0: break numPair = random.randint(0, count-1) count = 0 for i in range(0, total): for j in range(i+1, total): if check[i][j] > 0: if count == numPair: n1 = uniqueList[i] n2 = uniqueList[j] break count += 1 # Если пары ещё есть добавляем элемент в схемы и заменяем пару в списке на один элемент newname = "INT_{0}".format(num) num = num + 1 if (n1[0] != '!' and n2[0] != '!'): sckt.__elements__[newname] = ('OR', [n1, n2]) elif (n1[0] == '!' and n2[0] == '!'): sckt.__elements__[newname] = ('NAND', [n1[1:], n2[1:]]) elif (n1[0] == '!'): newname1 = "INT_{0}".format(num) num = num + 1 if random.randint(0, 1) == 0: sckt.__elements__[newname1] = ('INV', [n1[1:]]) sckt.__elements__[newname] = ('OR', [newname1, n2]) else: sckt.__elements__[newname1] = ('INV', [n2]) sckt.__elements__[newname] = ('NAND', [newname1, n1[1:]]) elif (n2[0] == '!'): newname1 = "INT_{0}".format(num) num = num + 1 if random.randint(0, 1) == 0: sckt.__elements__[newname1] = ('INV', [n2[1:]]) sckt.__elements__[newname] = ('OR', [newname1, n1]) else: sckt.__elements__[newname1] = ('INV', [n1]) sckt.__elements__[newname] = ('NAND', [newname1, n2[1:]]) # Заменяем пары в термах for o in merge: flag = 0 for term in merge[o]: if term.count(n1) > 0: flag = flag + 1 if term.count(n2) > 0: flag = flag + 1 if (flag == 2): for term in merge[o]: if term.count(n1) > 0: term.remove(n1) continue if term.count(n2) > 0: term.remove(n2) continue merge[o].append([newname]) # Чистим список от пустых записей for o in merge: for term in merge[o]: while (merge[o].count([]) > 0): merge[o].remove([]) # Теперь требуется заменить имена промежуточных узлов на имена реальных выходов for o in merge: find = merge[o][0][0] replace = o # Сначала меняем в поле ключей if find in sckt.__elements__: sckt.__elements__[replace] = sckt.__elements__[find] del sckt.__elements__[find] # Затем меняем в элементах for el in sckt.__elements__: lst = sckt.__elements__[el][1] for key,i in enumerate(lst): if i == find: lst[key] = replace # Фикс для случая когда у нас несколько выходов имеют единую логическую функцию (и часть выходов пропала при замене) # В этом случае добавляем буферы fix_happened = 0 for o in merge: if o not in sckt.__elements__: flag = 0 for el in sckt.__elements__: lst = sckt.__elements__[el][1] for key,i in enumerate(lst): if i == o: flag += 1 if flag == 0: f1 = merge[o][0][0] fname = '' for o1 in merge: if o1 in sckt.__elements__: f2 = merge[o1][0][0] if f1 == f2: fname = o1 if fname == '': print('Some unexpected error here') break sckt.__elements__[o] = ('BUF', [fname]) fix_happened += 1 # Фикс для случая когда выход полностью повторяет вход или его инверсию (и он теряется) # Необходимо добавить буфер типа (BUF вход выход) или (INV вход выход) for o in merge: if (len(merge[o]) == 1) & (len(merge[o][0]) == 1): if (merge[o][0][0][0] != '!') & (merge[o][0][0] in ckt.__inputs__): sckt.__elements__[o] = ('BUF', merge[o][0]) if (merge[o][0][0][0] == '!') & (merge[o][0][0][1:] in ckt.__inputs__): sckt.__elements__[o] = ('INV', [merge[o][0][0][1:]]) return sckt
def get_random_subcircuit(cir, limit=3, type=0): new = sa.scheme_alt() # Выбираем начальный элемент с которого начнем ветвление start = random.randint(0, cir.elements()-1) node = cir.element_labels()[start] cell = cir.__elements__[node] # Добавляем элемент в схему new.__outputs__.append(copy.deepcopy(node)) new.__inputs__ = copy.deepcopy(cell[1]) new.__elements__[node] = copy.deepcopy(cell) # Цикл пока не закончится ветвление while 1: # Выбираем случайный вход в схему (узел и ячейку подключенные к нему) inpnum = random.randint(0, new.inputs()-1) node = new.__inputs__[inpnum] # Если выбранный вход является входным в схему, то завершаем цикл if cir.__inputs__.count(node) > 0: break cell = cir.__elements__[node] # Удаляем из списка входов текущий и добавляем все входы от Cell try: new.__inputs__.remove(node) except: new.print_circuit_in_file(os.path.join(get_project_directory(), "temp", "debug1.txt")) cir.print_circuit_in_file(os.path.join(get_project_directory(), "temp", "debug2.txt")) exit(0) for inp in cell[1]: if new.__inputs__.count(inp) == 0: new.__inputs__.append(copy.deepcopy(inp)) # Добавляем ячейку в список элементов new.__elements__[node] = copy.deepcopy(cell) # Поскольку к узлу могут быть привязаны входы других элементов, # мы также должны добавить эти элементы в нашу подсхему for el in cir.__elements__: val = cir.__elements__[el] for i in val[1]: if i == node: if (el not in new.__elements__): # добавляем входы найденного элемента которых ещё не было v1 = cir.__elements__[el] for j in v1[1]: if new.__inputs__.count(j) == 0: if new.__outputs__.count(j) == 0: if j not in new.__elements__: new.__inputs__.append(copy.copy(j)) # добавляем выходы найденного элемента которых ещё не было if new.__outputs__.count(el) == 0: new.__outputs__.append(copy.deepcopy(el)) # добавляем сам найденный элемент new.__elements__[el] = copy.deepcopy(val) # если в списке входов оказался выход добавленного элемента удаляем if new.__inputs__.count(el) > 0: new.__inputs__.remove(el) # В некоторых условиях вход и выход могут стать рядовыми узлами подсхемы # Удаляем элемент из списка входов если он является выходом одного из элементов for i in new.__inputs__: if i in new.__elements__: new.__inputs__.remove(i) # Удаляем элемент из списка выходов если он является входом одного из элементов # Так делать нельзя так как от него могут идти связи к другим элементам большой схемы! if 0: for o in new.__outputs__: flag = 0 for el in new.__elements__: val = new.__elements__[el] for i in val[1]: if i == o: new.__outputs__.remove(o) flag = 1 break if flag == 1: break if type == 0: if new.elements() >= limit: break else: if new.inputs() >= limit: break # В некоторых условиях промежуточные узлы могут оказаться выходами основной схемы. # В этом случае их надо добавить в список выходов для подсхемы for o in cir.__outputs__: if o not in new.__outputs__: if o in new.__elements__: new.__outputs__.append(copy.deepcopy(o)) return new