
Комментарии 5
В целом подумал, подумал, и, кажется, примерно определился.
Википедия, здоровья сему справочнику, указывает в качестве рекорда полного сумматора на КМОП 24 транзистора. Это сумматор, реализованный как один логический элемент «полный сумматор». С, так сказать, полным сокращением всех «лишних членов уравнений».
А вот если из отдельных элементов, то лучше классического «nine-NAND» никто не придумал (ну серьёзно, где ещё можно проверить это вот «не придумали ли за сто лет ещё чего-то», как не на Википедии?) 9 NAND — это 36 транзисторов на КМОП, разница невелика. Но!
С такого сумматора можно снимать с промежуточных участков операции «MOV» (очевидно; просто взяли вход и дело с концом), «XOR» (даже не нужен вход «запрет внутреннего переноса» — просто берём в нужном месте, где этот самый перенос ещё не встрял в результат), «ADD/ADC» (одна и та же команда, просто можем подать на первый перенос флаг переноса, а можем — ноль) и таки «NAND». Да, «Мух» потребуется приличный, ну да как без них, без мухов-то. Что ещё хуже по транзисторам, лишний муховый вход или лишняя логика. Муховый вход обычно дешевле. А вот с 24-транзисторного практически ничего дополнительного снять нельзя…
Итого: поскольку NAND A, A имеет ещё какой великий смысл, подменять нужно только операнд для MOV. Поэтому подаём на вход АЛУ строго выбранный операнд, а вот у второго муха (который выбирает, какие именно результаты взять с АЛУ — окончательную сумму или что-то промежуточное) входы, отвечающие за MOV, пропускаем через дополнительный мух, который подсовывает на них P в тех случаях, если операнд у нас A. Он вносит дополнительную задержку только на входах, реализующих MOV — а туда хоть часы с кукушкой можно поставить, там запас по времени относительно других операций конский.
Избавившись от лагов и обеспечив забесплатно важнейшую команду MOV A, P (у нас же только P можно грузить константой прямо из микрокода, командой SCN! Перекладывать её в аккумулятор — важнейшая операция), позаботимся о бедном NAND A, A. Тут я хочу ввернуть изящный хак: добавить ещё один флаг «NEG» и при NAND A, A всегда ставить его в единицу, а вот флаг переноса — не обнулять, а сохранять текущий (любые другие команды, модифицирующие флаги, обнуляют NEG). И команду ADD слегка модифицировать: на первый вход переноса подаётся не 0, а флаг NEG.
Поясняю: берём младший байт вычитаемого из срамы, инвертируем, NEG взводится. Берём младший байт уменьшаемого из срамы, делаем ADD. Получается сложение уменьшаемого с инверсией вычитаемого плюс единичка — то есть нормальное человеческое вычитание в дополнительном коде. Теперь у нас есть нормальный флаг переноса из младшего байта и младший байт разности. Кладём его в сраму, берём второй байт вычитаемого. Инвертируем, флаг переноса не меняется. Берём второй байт уменьшаемого, делаем ADC. Он учитывает реальный перенос из младшего байта, как и подобает ADC — а вот NEG игнорирует. Перебирая вот так вот байты, производим вычитание «на лету», не храня нигде в сраме допкод вычитаемого. Ну, и как выше говорил, чтобы не мешать нормальной работе ADD, любые другие операции, кроме NAND A, A, NEG обнуляют.
Флаг переноса для всех NAND, кроме NAND A, A, можно использовать для быстрой проверки флагов: он может означать не то, что результат у нас 1 ??? ???, а то, что он у нас 111 111. То есть в несколько извращённом, но крайне полезном смысле «вот ещё бы одна единичка, и был бы перенос». Всё равно реальных переносов в NAND, ясен пень, не бывает — а вот кинуть в P маску с единичкой в нужном бите и через NAND A, P быстро проверить, единичка ли в этом бите аккумулятора, штука архиполезная. Но перенос, зараза, из сумматора вылезает последним, так что надо бы подумать, что это от нас потребует по быстродействию и по лишним транзисторам. Есть ощущение, что копейки, но надо смотреть по месту. В случае простого AND это был бы, конечно, флаг нулевого результата, но переход от AND к NAND нам эту халяву прикрыл…
Чем-то напонило Programmable I/O (PIO) контроллер, встроенный в Raspberry PI PICO: такой же крохотный размер памяти для его программы и минималисткий набор инструкций.
«И питать прямо от 12 вольт, а не от 3.3»
Ох, помню... Сначала 155 серия, ей строго 5 вольт подавай. Впрочем, на практике и от батарейки на 4,5 тоже работало. Потом 561, сколько же различной несложной автоматики на ней делали. От 3 до 15 вольт. А как пошла мода пихать что-нибудь 8051-совсестимое куда ни попадя - потребовало снова строго 5, стабильных. Казалось шагом назад.
В целом подумал, подумал, и, кажется, примерно определился.
Википедия, здоровья сему справочнику, указывает в качестве рекорда полного сумматора на КМОП 24 транзистора. Это сумматор, реализованный как один логический элемент «полный сумматор». С, так сказать, полным сокращением всех «лишних членов уравнений».
А вот если из отдельных элементов, то лучше классического «nine-NAND» никто не придумал (ну серьёзно, где ещё можно проверить это вот «не придумали ли за сто лет ещё чего-то», как не на Википедии?) 9 NAND — это 36 транзисторов на КМОП, разница невелика. Но!
С такого сумматора можно снимать с промежуточных участков операции «MOV» (очевидно; просто взяли вход и дело с концом), «XOR» (даже не нужен вход «запрет внутреннего переноса» — просто берём в нужном месте, где этот самый перенос ещё не встрял в результат), «ADD/ADC» (одна и та же команда, просто можем подать на первый перенос флаг переноса, а можем — ноль) и таки «NAND». Да, «Мух» потребуется приличный, ну да как без них, без мухов-то. Что ещё хуже по транзисторам, лишний муховый вход или лишняя логика. Муховый вход обычно дешевле. А вот с 24-транзисторного практически ничего дополнительного снять нельзя…
Итого: поскольку NAND A, A имеет ещё какой великий смысл, подменять нужно только операнд для MOV. Поэтому подаём на вход АЛУ строго выбранный операнд, а вот у второго муха (который выбирает, какие именно результаты взять с АЛУ — окончательную сумму или что-то промежуточное) входы, отвечающие за MOV, пропускаем через дополнительный мух, который подсовывает на них P в тех случаях, если операнд у нас A. Он вносит дополнительную задержку только на входах, реализующих MOV — а туда хоть часы с кукушкой можно поставить, там запас по времени относительно других операций конский.
Избавившись от лагов и обеспечив забесплатно важнейшую команду MOV A, P (у нас же только P можно грузить константой прямо из микрокода, командой SCN! Перекладывать её в аккумулятор — важнейшая операция), позаботимся о бедном NAND A, A. Тут я хочу ввернуть изящный хак: добавить ещё один флаг «NEG» и при NAND A, A всегда ставить его в единицу, а вот флаг переноса — не обнулять, а сохранять текущий (любые другие команды, модифицирующие флаги, обнуляют NEG). И команду ADD слегка модифицировать: на первый вход переноса подаётся не 0, а флаг NEG.
Поясняю: берём младший байт вычитаемого из срамы, инвертируем, NEG взводится. Берём младший байт уменьшаемого из срамы, делаем ADD. Получается сложение уменьшаемого с инверсией вычитаемого плюс единичка — то есть нормальное человеческое вычитание в дополнительном коде. Теперь у нас есть нормальный флаг переноса из младшего байта и младший байт разности. Кладём его в сраму, берём второй байт вычитаемого. Инвертируем, флаг переноса не меняется. Берём второй байт уменьшаемого, делаем ADC. Он учитывает реальный перенос из младшего байта, как и подобает ADC — а вот NEG игнорирует. Перебирая вот так вот байты, производим вычитание «на лету», не храня нигде в сраме допкод вычитаемого. Ну, и как выше говорил, чтобы не мешать нормальной работе ADD, любые другие операции, кроме NAND A, A, NEG обнуляют.
Флаг переноса для всех NAND, кроме NAND A, A, можно использовать для быстрой проверки флагов: он может означать не то, что результат у нас 1 ??? ???, а то, что он у нас 111 111. То есть в несколько извращённом, но крайне полезном смысле «вот ещё бы одна единичка, и был бы перенос». Всё равно реальных переносов в NAND, ясен пень, не бывает — а вот кинуть в P маску с единичкой в нужном бите и через NAND A, P быстро проверить, единичка ли в этом бите аккумулятора, штука архиполезная. Но перенос, зараза, из сумматора вылезает последним, так что надо бы подумать, что это от нас потребует по быстродействию и по лишним транзисторам. Есть ощущение, что копейки, но надо смотреть по месту. В случае простого AND это был бы, конечно, флаг нулевого результата, но переход от AND к NAND нам эту халяву прикрыл…
Шестибитный процессор без единой картинки