Внедрение 8-битного сумматора в python - PullRequest
1 голос
/ 24 марта 2020

Я реализовал 8-битный сумматор в python следующим образом:

from gates import AND, OR, XOR
from utils import number_to_binary, binary_to_number

def EightBitAdder(s1='110101', s2='00010', carry_in=0):
    # Limit to 8 bits
    s1 = s1[-8:].zfill(8)
    s2 = s2[-8:].zfill(8)
    s_out = ''
    carry_out = None
    for i in range(8):
        bit_1 = int(s1[8-1-i])
        bit_2 = int(s2[8-1-i])
        carry_in = carry_out if (carry_out is not None) else carry_in
        value_out = XOR(carry_in, XOR(bit_1, bit_2))
        carry_out = OR(AND(bit_1, bit_2), AND(bit_1, carry_in), AND(bit_2, carry_in))
        s_out = str(int(value_out)) + s_out
    print ("  %s (%s) \n+ %s (%s) \n= %s (%s)  -- Carry %s" % (s1, binary_to_number(s1), s2, binary_to_number(s2), s_out, binary_to_number(s_out), int(carry_in)))
    return (s_out, int(carry_out))

Для меня поразительно, что "ворота" будут оценивать лениво, поэтому они не будут возвращать 1/0 если я не позвоню int(), и кажется, что в 8-битном сумматоре огромное количество вентилей. Например:

enter image description here

Я где-то совершаю ошибку (или избыточность) где-то в оценке переноса / выведения стоимости, или делает основание c 8-битный сумматор действительно имеет столько ворот ??

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Если реализовано напрямую, в полном сумматоре есть столько ворот. Рассматривали ли вы использование составных вентилей, таких как 8-битные примитивы или использование полусуммера ? У меня нет непосредственного опыта, но я не думаю, что полные сумматоры реализуются непосредственно с примитивами на практике, вместо этого они, вероятно, используют эти промежуточные части.

Вторая глава nand2tetris охватывает подход наполовину сумматора, который, если вы примените к своему коду, позволяет сделать небольшое упрощение:

        carry_in = carry_out if (carry_out is not None) else carry_in
        value_out = XOR(carry_in, XOR(bit_1, bit_2))
        carry_out = OR(AND(bit_1, bit_2), AND(bit_1, carry_in), AND(bit_2, carry_in))

можно вместо этого записать в виде:

        carry_in = carry_out if (carry_out is not None) else carry_in
        half_sum = XOR(bit_1, bit_2)
        half_carry = AND(bit_1, bit_2)
        full_sum = XOR(carry_in, half_sum)
        full_carry = AND(half_sum, carry_in)
        value_out = full_sum
        carry_out = OR(half_carry, full_carry)

Это уменьшает число Ворота за итерацию от 6 до 5, так что это должно уменьшить ваш вывод на 1/6. Тем не менее, я бы порекомендовал поместить это в отдельные ворота, поскольку половинный сумматор полезен независимо.

0 голосов
/ 25 марта 2020

В реальном сумматоре вентили соединены в график, где выход гейта может использоваться как вход для нескольких других.

Вы записываете выход как выражение, где выход ворот можно использовать только в одном месте.

Это достигается путем копирования всего выражения для каждого вывода во все места, которые оно использует. Вы делаете это в каждой итерации - carry_in используется один раз для получения значения и 3 раза для создания следующего переноса.

Размер выражения переноса умножается на 3 в каждой итерации, приводя к экспоненте Взрыв в количестве используемых вами операторов.

Вероятно, вы должны генерировать свои выходные данные в другой форме, которая может сохранить график гейта, например, stati c одиночное назначение: https://en.wikipedia.org/wiki/Static_single_assignment_form

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...