nedoPC.org

Community for electronics hobbyists, established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 24 Jun 2024 09:22



Reply to topic  [ 38 posts ]  Go to page Previous  1, 2, 3  Next
Возможные микроархитектуры для 3niti alpha/beta 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Наверное для начала можно микропрограммную машину вообще двоичной сделать, взяв за основу идеи из темы Микрокодовое ядро на ПЗУ (2010), а в качестве памяти для регистров можно задействовать несколько TTL-чипов 74189 (или military style 54F189) - это память 16x4 (как К155РУ2, но выходы не ОК, а с третьим состоянием):

Attachment:
Screenshot from 2024-05-29 21-35-08.png
Screenshot from 2024-05-29 21-35-08.png [ 32.09 KiB | Viewed 770 times ]
(также всё ещё можно найти вариант с неинвертированными выходами 74F219)

Причём 4 адреса займут регистры - DPn, DPo, DPp и TP (9 тритов потребуют 6 корпусов, чтобы была возможность независимо обращаться к их третям и также появится контроль ошибок), а остальные 12 адресов можно отдать под стек! :o

При этом указатель стека SP станет двоичным и потребует только 4 бита, но вместе с тем отвяжется от основной памяти и не сможет быть установлен или считан...

P.S. Так как это будет своего рода машина Тьюринга (каждая микроинструкция будет в самой себе содержать адрес следующей микроинструкции), то такую микроархитектуру можно назвать Turandot ( типа ассоциация на Ternary Turing ; )

P.P.S. Поясню за контроль ошибок - каждый трит у нас будет представляться двумя битами т.е. одна 4-битная микросхема памяти покроет 2 трита, а они у нас в триады объединены т.е. 2 микросхемы покроют одну триаду плюс ещё останется трит, который можно отдать под контроль целостности данных (контроль ошибок) - т.е. наряду с тем, что можно будет отслеживать если 2 бита где-либо стали оба в 1 одновременно (что заведомо считается некорректной комбинацией), будет ещё трит "трёшности" ( т.к. слово "чётность" тут не подойдёт ; ) который может представлять из себя младший трит суммы трёх тритов триады данных:
Code:
NNN -> -3 -> NO -> O
NNO -> -2 -> NP -> P
NNP -> -1 -> ON -> N
NON -> -2 -> NP -> P
NOO -> -1 -> ON -> N
NOP ->  0 -> OO -> O
NPN -> -1 -> ON -> N
NPO ->  0 -> OO -> O
NPP -> +1 -> OP -> P
ONN -> -2 -> NP -> P
ONO -> -1 -> ON -> N
ONP ->  0 -> OO -> O
OON -> -1 -> ON -> N
OOO ->  0 -> OO -> O
OOP -> +1 -> OP -> P
OPN ->  0 -> OO -> O
OPO -> +1 -> OP -> P
OPP -> +2 -> PN -> N
PNN -> -1 -> ON -> N
PNO ->  0 -> OO -> O
PNP -> +1 -> OP -> P
PON ->  0 -> OO -> O
POO -> +1 -> OP -> P
POP -> +2 -> PN -> N
PPN -> +1 -> OP -> P
PPO -> +2 -> PN -> N
PPP -> +3 -> PO -> O

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

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


29 May 2024 21:40
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
В качестве памяти микропрограмм для Turandot возьмём одну микруху РФ2 на 2КБ (2716), которые можно разбить на пополам - скажем там можно держать стабильную и экспериментальную версии микрокода (по 1КБ каждая), переключая их джампером перед включением устройства. Каждый килобайт можно поделить на четвёрки байтов, получив 256 таких блоков по 32 бит в каждом - получается длина микроинструкции может быть до 32 бит и количество адресуемых микроинструкций будет 256 т.е. нам надо 8 бит для адресации (и соответственно 8 бит внутри каждой 32-битной инструкции будет отдано под адрес следующей микроинструкции в микропрограмме). Каждая микроинструкция будет вычитываться в 4 захода (или меньше, если дальнейшая вычитка ненужна - например адрес следующей микроинструкции можно держать в последнем байте и если выполнение микропрограммы надо прекратить, то переход будет на O|T0 в любом случае и четвёртый байт с произвольным адресом перехода можно уже не вычитывать). Каждый вычитанный байт будет защёлкиваться в 8-битном регистре, постепенно строя всю 32-битную микроинструкцию. Раз уж и в управлении микрокодом мы перешли в двоичную плоскость, то и количество тактов выполнения микроинструкции можно сделать не кратным трём (и даже более того - количество тактов может варьироваться в зависимости от типа микроинструкции).

У нас могут быть как минимум 4 варианта перехода на следующую микроинструкцию:
  • 00 - нормальный по адресу O|T0 (обычный переход на новую микропрограмму в соответствии с кодом базовой инструкции 3niti);
  • 01 - особый по адресу P|T1 если старший трит T1 равен N (для реализации новых инструкций 3niti beta кодируемых как JMP Nxx), в противном случае переход должен осуществляться по непосредственному адресу из четвёртого байта микроинструкции;
  • 10 - сложный, когда после вычитки 3 триад аргумента для JMP мы должны пойти на микропрограмму CALL, если аргумент получился отрицательным (в соответствии со спецификацией 3niti beta) - в этом случае переход должен осуществляться по непосредственному адресу из четвёртого байта микроинструкции, причём PC не должен модифицироваться (возможно для этого придётся отвести один бит в более ранних флагах микроинструкции) - если же адрес оказался положительным (или нулевым), то PC должен будет измениться в соответствии с кодом (в случае JMP это будет код PC=DP) и далее пойдёт вычитка следующей инструкции T0 и переход на адрес O|T0 для продолжения работы по программе;
  • 11 - непосредственный, когда адрес перескока берётся из четвёртого байта микроинструкции.
Для варианта 00 вычитка четвёртого байта микроинструкции может вообще не производиться, а вот в остальных трёх случаях наверное вычитка всех 32 битов будет обязательна. Простые микропрграммы копирующие из регистра в регистр (A,B,L,M,H) должны умещаться в одну микроинструкцию и заканчиваться раньше т.к. вычитка четвёртого байта из памяти микропрограмм будет ненужна - т.е. будет что-то типа такого:
  1. прочитать триаду с шины данных (нужный PC к этому моменту уже должен быть подключен к шине адреса) и защёлкнуть её в регистре T0;
  2. сформировать адрес микропрограммы (в общем случае это O|T0) и защёлкнуть первый байт микроинструкции в регистре I0;
  3. подключить регистр источник и регистр приёмник к внутренней шине данных и защёлкнуть второй байт микроинструкции в регистре I1;
  4. осуществить строб записи для сохранения необходимых данных и если надо флагов, а также обновить PC (в общем случае инкрементировать) и защёлкнуть третий байт микроинструкции в регистре I2, сохранив при этом способ перескока для следующего цикла;
  5. опционально защёлкнуть четвёртый байт микроинструкции в регистре I3, если способ перескока этого требует (иначе этот шаг может быть пропущен).
По-идее, получается, что следующий цикл может использовать регистры I2 и I3 оставшиеся от предыдущего цикла (в самом начале там должны быть нули), чтобы понять как адресовать память микропрограмм для вычитки следующей микроинструкции...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


02 Jun 2024 23:30
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Цикл чтения РФ2 по карточке 450нс т.е. длительность простейшей инструкции копирования из регистра в регистр может составлять 1.8мкс или 555555 операций в секунду при тактовой частоте 2.222 МГц - для круглого счёта за целевую частоту можно принять 2 МГц...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


03 Jun 2024 08:07
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Для упрощения можно принять, что в первом такте всегда читаем с шины по адресу PC и всегда в T0

Копирование в 3-м и 4-м тактах цикла может происходить из триады:
0000 - на шине данных по адресу DPn (виртуальный регистр N)
0001 - на шине данных по адресу DPo (виртуальный регистр O)
0010 - на шине данных по адресу DPp (виртуальный регистр P)
0011 - регистр F
0100 - регистр A
0101 - регистр B
0110 - регистр H (старшая триада текущего DPx)
0111 - регистр M (средняя триада текущего DPx)
1000 - регистр L (младшая триада текущего DPx)
1001 - регистр T0
1010 - выход OPA(A,T1)
1011 - выход OPB(A,B,T1,T2,T3)
1100 - выход сумматора (который всегда складывает A и T1)
1101 - регистр A сдвинутый влево через флаг BCF
1110 - регистр A сдвинутый вправо через флаг BCF
1111 - сюда можно поместить особые случаи, которые можно кодировать следующими 4-мя битами
в триаду:
0000 - на шине данных по адресу DPn (виртуальный регистр N)
0001 - на шине данных по адресу DPo (виртуальный регистр O)
0010 - на шине данных по адресу DPp (виртуальный регистр P)
0011 - регистр F
0100 - регистр A
0101 - регистр B
0110 - регистр H (старшая триада текущего DPx)
0111 - регистр M (средняя триада текущего DPx)
1000 - регистр L (младшая триада текущего DPx)
1001 - регистр A и флаг BCF
1010 - регистр A и флаг RSF
1011 - регистр A и оба флага BCF и RSF
1100 - вывод на выходной регистр GPIO
1101 - регистр T1 (старшая триада регистра TP)
1110 - регистр T2 (средняя триада регистра TP)
1111 - регистр T3 (младшая триада регистра TP)
(не все комбинации источников и приёмников на практике возможны - например нельзя скопировать из L в T1 или из N в H)
либо из 9 тритов в 9 тритов:
- из PC в текущий DP (с инкрементом?)
- из текущего DP в PC
- из TP в PC
- из TP в PC с инверсией
- из PC в [SP] с инкрементом
- из [SP] в PC
(источник внутри 74189 это текущий DP, TP с инверсией или без и [SP] в PC либо PC в 74189 c выбранным DP и [SP])

Получается, что чтение-запись в виртуальные регистры N,O,P тоже может занимать 4 такта!

P.S. Сохранение PC происходит в самом конце цикла в любом случае - нам просто надо включать правильный источник данных:
000 - старое значение PC (если надо потоптаться на месте выполняя длинную микропрограмму)
001 - троично инкрементированное значение PC (в большинстве случаев)
010 - значение из TP (для реализации JMP)
011 - инвертированное значение из TP (для реализации CALL)
100 - слово адресуемое 4-битным указателем SP (для реализации RET)
101 - текущий DP (для реализации LPCD)
110 - заранее введённый специальный адрес прерывания INTERRUPT
111 - заранее введённый специальный адрес ошибки ERROR
А копирование из PC в [SP] (для CALL) или из PC в DP (для SPCD) может включаться своими собственными флагами в микроинструкции:
00 - PC никуда не копируется
01 - копировать PC в DP
10 - копировать PC в [SP]
11 - специальный случай для копирования PC в PC если TP<0 (работает в паре со сложным перескоком)
(одновременное изменение PC и копирование старого значения PC куда-либо ещё вполне возможно т.к. оно будет происходить в разных линейках троичных триггеров, но только не в том случае, когда и источником, и приёмником является микросхема памяти 74189)

P.P.S. Ещё надо задавать постинкремент или предекремент 4-битного регистра SP - нужно выбрать какую-то микруху-счётчик из серии 4000 и прямо управлять её входами беря биты микроинструкции. Первый байт микроинструкции I0 полностью отдаётся под кодирование источника (4 бита) и приёмника (4 бита) при однотриадном копировании. Второй байт I1 будет содержать 2 бита определяющий приёмник для опционального копирования PC (DP или [SP]), 3 бита для кодирования источника для записи PC и как минимум 2 бита для кодирования постинкремента или предекремента SP (зависит от выбранной микрухи для хранения SP). Из третьего байта I2 нам по сути нужны будут только 2 бита, которые задают способ перескока (для их хранения нужны будут триггеры, которые сбрасываются в ноль при старте устройства) и четвёртый опциональный байт I3 будет содержать адрес следующей микроинструкции в микропрограмме...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


03 Jun 2024 21:52
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Итак, получается, что почти все однотриадные инструкции (копирование между регистрами и сдвиги RLA и RRA) занимают одну укороченную микроинструкцию, которая выполняется за 4 такта, а вот ADD похоже уходит в 9 тактов (там по ходу надо будет скопировать B в T1 т.к. сумматор всегда складывает A и T1)

2-триадные инструкции:
LAI # - загрузка регистра A следующей триадой - 9 тактов (2 микроинструкции)
ADI # - сложение A со следующей триадой - 14 тактов (3 микроинструкции)
OPA # - унарная троичная операция - 14 тактов (3 микроинструкции)

4-триадные инструкции:
LDI ### - загрузка текущего DP cледующими тремя триадами - 24 такта (5 микроинструкций)
OPB ### - бинарная троичная операция - 24 такта (5 микроинструкций)
JMP ### (обычный джамп на положительный адрес) - 25 тактов или больше (т.к. может потребоваться больше 5 микроинструкций в связи с тем, что там придётся выделять особые случаи - см. ниже)

Особые инструкции из расширения 3niti beta будут сильно потяжелее (надо написать симулятор Turandot, чтобы отладить эти микропрограммы):
CALL ### (JMP с отрицательным 3-триадным аргументом)
RET (JMP NNN)
и т.д.

P.S. На самом деле все особые инструкции будут обрабатываться в одной большой и ветвистой микропрграмме JMP, которая может закончиться после 4 полных микроинструкций (в случае перехода на положительный адрес) либо пойдёт на обработку особых случаев.

P.P.S. По идее уже сейчас можно кодировать особые пользовательские инструкции (со свободными кодами JMP NPN или JMP NPO например), которые будут выполняться 14 тактов (за 3 микроинструкции) и будут скажем делать какое-то необычное действие, например сохранять регистр флагов F в регистре B или складывать A с кодом следующей инструкции...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


04 Jun 2024 01:11
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Для упрощения можно принять, что в первом такте всегда читаем с шины по адресу PC и всегда в T0
А можно добавить в I2 ещё 2 бита и кодировать ими то, куда мы будем записывать триаду с шины данных - в T0,T1,T2 или T3.
Это должно сэкономить одну микроинструкцию (5 тактов) в некоторых длинных командах!
Или оставить это улучшение на потом?
т.к. это надо делать вместе с возможностью инкрементировать PC в середине микроинструкции, а не только в конце...
P.S. либо с возможностью укоротить выполнение некоторых микроинструкций перескочив с вычитки I0 сразу на I3...
P.P.S. отложу эти оптимизации на будущую версию Turnadot-II :roll:
P.P.P.S. А потом появится чисто троичная микроархитектура Troglodyte и суперскалярная микроархитектура Tutankhamun...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


04 Jun 2024 21:06
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Ещё надо задавать постинкремент или предекремент 4-битного регистра SP - нужно выбрать какую-то микруху-счётчик из серии 4000 и прямо управлять её входами беря биты микроинструкции...и как минимум 2 бита для кодирования постинкремента или предекремента SP (зависит от выбранной микрухи для хранения SP).
Это может быть 74HC193 например (не 4000 серия конечно, но всё-таки CMOS - советский аналог есть только в ТТЛ вроде - К155ИЕ7):

Attachment:
Screenshot from 2024-06-04 22-36-28.png
Screenshot from 2024-06-04 22-36-28.png [ 61.27 KiB | Viewed 510 times ]

LOAD будет по RESET-у схемы происходить сразу устанавливая начальный SP в 0100 (а MASTER RESET самой микрухи не будет использоваться и будет посажен на землю). Cчёт будет происходить путём установки соответствующего бита в 0 в одной микроинструкции и затем возвращения его в 1 в следующей - соответственно постинкремент надо делать по CALL/PUSH в конце соответствующей микропрограммы (после записи в [SP]), а предекремент надо делать по RET/POP в начале соответствующей микропрограммы (перед чтением из [SP]). После 12 пушей стек залезет на DPo и это можно считать "фичей" (точно также поп после ресета вернёт T1,T2,T3, которые хранятся по адресу 0011)...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


04 Jun 2024 22:57
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Копирование в 3-м и 4-м тактах цикла может происходить из триады:
0000 - на шине данных по адресу DPn (виртуальный регистр N)
0001 - на шине данных по адресу DPo (виртуальный регистр O)
0010 - на шине данных по адресу DPp (виртуальный регистр P)
0011 - регистр F
0100 - регистр A
0101 - регистр B
0110 - регистр H (старшая триада текущего DPx)
0111 - регистр M (средняя триада текущего DPx)
1000 - регистр L (младшая триада текущего DPx)
1001 - регистр T0
1010 - выход OPA(A,T1)
1011 - выход OPB(A,B,T1,T2,T3)
1100 - выход сумматора (который всегда складывает A и T1)
1101 - регистр A сдвинутый влево через флаг BCF
1110 - регистр A сдвинутый вправо через флаг BCF
1111 - сюда можно поместить особые случаи, которые можно кодировать следующими 4-мя битами
Получается тут можно закодировать 16 особых случаев, например включив туда вот эти 4:
Shaos wrote:
А копирование из PC в [SP] (для CALL) или из PC в DP (для SPCD) может включаться своими собственными флагами в микроинструкции:
00 - PC никуда не копируется
01 - копировать PC в DP
10 - копировать PC в [SP]
11 - специальный случай для копирования PC в PC если TP<0 (работает в паре со сложным перескоком)
Также до кучи можно накидать "особых случаев" по копированию наиболее полезных констант в регистр T1:

1111 1000 - записать OOO
1111 1001 - записать OOP
1111 1010 - записать OON
1111 1011 - записать NNN
1111 1100 - записать PPP
1111 1101 - записать POO
1111 1110 - записать NOO
1111 1111 - записать PON (это например если надо будет сделать инверсию A через OPA по ходу пьесы)

P.S. А также покрыть несколько пока ненужных, но потенциально полезных случаев:

1111 0100 - скопировать содержимое SP в регистр A в троичном виде
1111 0101 - скопировать T1 в A
1111 0110 - скопировать T2 в A
1111 0111 - скопировать T3 в A

P.P.S. Либо сделать особый случай 1111 0100 универсальным чтением из внешнего 3-тритного порта к которому кроме всего прочего может быть подключена плата переводящая 4-битный указатель стека в 3-тритное значение. Ещё я выше добавил в копирование триад возможность выводить на некий внешний 3-тритный порт что даст нам некое подобие троичного GPIO. Также на выход могут уходить свободные биты микроинструкции из I1 - один бит может взводить внешний триггер, а другой бит - сбрасывать (и также этот триггер или триггеры могут сбрасываться при старте компа) - в общем случае оно будет зажигать или гасить некий индикаторный светодиод (или светодиоды)...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


05 Jun 2024 09:03
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Один из возможных "лёгких" способов преобразования состояния 4-битного счётчика SP в троичный вид (3 трита):

- разбиваем счётчик на две половины по 2 бита в каждой (старшая пара и младшая пара)
- в каждой половине комбинации 00, 01 и 10 превращаются в O, P и N соответственно, формируя средний и младший триты ответа (старший трит по умолчанию берётся O)
- если младшая пара это 11, то младший трит считается N, а в старшем трите пишем P
- если старшая пара это 11, то средний трит считается N и в старшем трите пишем N
- если обе пары это 11 (т.е. значение счётчика 1111), то результирующей триадой принимаем PPP
Code:
0000 -> OOO (0)
0001 -> OOP (+1)
0010 -> OON (-1)
0011 -> PON (+8)
0100 -> OPO (+3)
0101 -> OPP (+4)
0110 -> OPN (+2)
0111 -> PPN (+11)
1000 -> ONO (-3)
1001 -> ONP (-2)
1010 -> ONN (-4)
1011 -> PNN (+5)
1100 -> NNO (-12)
1101 -> NNP (-11)
1110 -> NNN (-13)
1111 -> PPP (+13)
и затем программно можно будет восстановить изначальное значение по таблице:
Code:
NNN (-13) -> 1110 (14)
NNO (-12) -> 1100 (12)
NNP (-11) -> 1101 (13)
NON (-10) -> ERROR
NOO (-9)  -> ERROR
NOP (-8)  -> ERROR
NPN (-7)  -> ERROR
NPO (-6)  -> ERROR
NPP (-5)  -> ERROR
ONN (-4)  -> 1010 (10)
ONO (-3)  -> 1000 (8)
ONP (-2)  -> 1001 (9)
OON (-1)  -> 0010 (2)
OOO (0)   -> 0000 (0)
OOP (+1)  -> 0001 (1)
OPN (+2)  -> 0110 (6)
OPO (+3)  -> 0100 (4)
OPP (+4)  -> 0101 (5)
PNN (+5)  -> 1011 (11)
PNO (+6)  -> ERROR
PNP (+7)  -> ERROR
PON (+8)  -> 0011 (3)
POO (+9)  -> ERROR
POP (+10) -> ERROR
PPN (+11) -> 0111 (7)
PPO (+12) -> ERROR
PPP (+13) -> 1111 (15)


P.S. Напомню, что начальное значение SP предполагается быть 4 и оно будет увеличиваться при пушах и уменьшаться при попах - по идее ради упрощения восприятия можно выводить глубину стека вместо конкретного значения SP т.е. SP-4, которое вначале будет 0, потом 1, потом 2 и т.д. вплоть до 11 вместо 15 и далее (с переполнением) 12 вместо 0, 13 вместо 1, -13 вместо 2 и -12 вместо 3 (эти последние 4 значения указателя стека будут "наползать" на DPo, DPp, DPn и TP соответственно) - или это наоборот всех запутает?

P.P.S. Можно наверное отдельную отладочную плату сделать если уж на то пошло, которая будет превращать 4 бита в 3 трита как надо (без упрощений) ну или выводить на 7-сегментный индикатор прямо из двоичного вида...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


05 Jun 2024 21:52
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Также до кучи можно накидать "особых случаев" по копированию наиболее полезных констант в регистр T1:

1111 1000 - записать OOO
1111 1001 - записать OOP
1111 1010 - записать OON
1111 1011 - записать NNN
1111 1100 - записать PPP
1111 1101 - записать POO
1111 1110 - записать NOO
1111 1111 - записать PON (это например если надо будет сделать инверсию A через OPA по ходу пьесы)

Остальные комбинации можно получить операциями сложения:
Code:
NNN (-13) -> есть
NNO (-12) -> NNN+OOP BCF=O
NNP (-11) -> NNN+OOP BCF=P
NON (-10) -> NOO+OON BCF=O
NOO (-9)  -> есть
NOP (-8)  -> NOO+OOP BCF=O или OPA(PON,PON)
NPN (-7)  -> NOO+OOP BCF=P
NPO (-6)  -> NNN+PON BCF=N
NPP (-5)  -> NNN+POO BCF=N
ONN (-4)  -> NNN+POO BCF=O
ONO (-3)  -> OON+OON BCF=N
ONP (-2)  -> OON+OON BCF=O
OON (-1)  -> есть
OOO (0)   -> есть
OOP (+1)  -> есть
OPN (+2)  -> OOP+OOP BCF=O
OPO (+3)  -> OOP+OOP BCF=P
OPP (+4)  -> PPP+NOO BCF=O
PNN (+5)  -> PPP+NOO BCF=P
PNO (+6)  -> PON+OON BCF=N
PNP (+7)  -> PON+OON BCF=O
PON (+8)  -> есть
POO (+9)  -> есть
POP (+10) -> POO+OOP BCF=O
PPN (+11) -> POO+OOP BCF=P
PPO (+12) -> PPP+OON BCF=O
PPP (+13) -> есть

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


06 Jun 2024 00:35
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Значит план такой:
1) Написать симулятор Turandot на C++ чтобы отладить микрокод
2) Сделать FPGA версию "3niti beta" на Turandot, дабы привлечь железячников-виртуалов
3) Начать потихоньку разводить платки для 3niti 4000, в котором будет железная реализация Turandot на рассыпухе и микросхемах памяти...

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


07 Jun 2024 06:59
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Shaos wrote:
Для упрощения можно принять, что в первом такте всегда читаем с шины по адресу PC и всегда в T0
А можно добавить в I2 ещё 2 бита и кодировать ими то, куда мы будем записывать триаду с шины данных - в T0,T1,T2 или T3.
Это должно сэкономить одну микроинструкцию (5 тактов) в некоторых длинных командах!
Или оставить это улучшение на потом?
т.к. это надо делать вместе с возможностью инкрементировать PC в середине микроинструкции, а не только в конце...
P.S. либо с возможностью укоротить выполнение некоторых микроинструкций перескочив с вычитки I0 сразу на I3...
P.P.S. отложу эти оптимизации на будущую версию Turnadot-II :roll:
Этот самый Turandot-II ещё можно будет научить изображать не только 3-тритные архитектуры, но и 6-тритные - те же Tunguska и Tryte-I. Для этого можно при чтении с внешней шины читать вторую триаду в новый 3-тритный регистр T0' (который можно поставить на место GPIO), а при записи во внешнюю шину использовать какой-то ещё свободно лежащий регистр. А памяти 16x4 которых 6 штук в параллель надо будет порезать не по 3 раза по 2, а 2 раза по 3 получив парные 6-тритные ячейки памяти представленные как 12-битные ячейки - всего получится 32 таких ячейки (а в Tryte-I напомню 26 6-тритных регистров, которые собраны парами)... Хотя нет - лучше всё таки ещё пару этих микрух памяти добавить, чтобы было 4 раза по 2 - ведь мы всё равно должны будем всё триадами считать...

P.S. Ещё в Turnadot-II надо будет добавить модификаторов микроинструкций, чтобы читать-писать из этого нового четвёртого слоя T4 вместо того же GPIO наряду с T0' (либо вместо T3, который может попеременно меняться местами с T4). Также нужно будет иметь возможность непосредственно писать в регистр SP (имитируя начальную загрузку адреса через LOAD с подменой битов, которые будут вводиться) и читать слово адресуемое SP в 4-триадный временный регистр снаружи (таковым может стать расширенный до 12 тритов PC - ведь именно такая шина адреса используется в обоих архитектурах Tryte-I и Tunguska). И наверное память микропрограмм надо увеличить и добавить ещё скажем 3 бита в третий байт микроинструкции I2, что позволить нарастить память микропрограмм до 8КБ - это должно помочь реализовать сложные системы команд типа Tunguska.

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


07 Jun 2024 17:50
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
У нас могут быть как минимум 4 варианта перехода на следующую микроинструкцию:
  • 00 - нормальный по адресу O|T0 (обычный переход на новую микропрограмму в соответствии с кодом базовой инструкции 3niti);
  • 01 - особый по адресу P|T1 если старший трит T1 равен N (для реализации новых инструкций 3niti beta кодируемых как JMP Nxx), в противном случае переход должен осуществляться по непосредственному адресу из четвёртого байта микроинструкции;
    ...
Придумал как сделать "особый" способ перескока в микропрограмме более универсальным - проверять старший трит регистра T1 на N (и перескакивать на P|T1) только если это была микроинструкция T0->T1!

Если же это была микроинструкция T0->T2, то проверять надо старший трит регистра T2 на равенство O (и перескакивать на P|T2 если так) - это чтобы отлавливать новые пользовательские инструкции типа JMP NPP Oxx (9 возможных инструкций, причём у них даже могут быть аргументы).

Во всех остальных случаях (включая T0->T3) надо проверять старший трит регистра T3 на равенство P (и перескакивать на P|T3) - это поможет отлавливать пользовательские инструкции типа JMP NPP yyy Pxx (если нужно - это ещё 9 инструкций у которых могут быть разные префиксы) т.е. это даст как минимум 9x9=81 новых инструкций, а также позволит реализовывать произвольное условное ветвление в сложных микропрограммах.

Перескок во всех этих случаях на адрес P|Tn позволит покрыть области 0100xxxx, 0101xxxx и 0110xxxx памяти микропрограмм (т.к. каждый раз мы проверяем на разное значение старшего трита - P,O,N), в то время как 00xxxxxx у нас отдано под старый набор команд (обычный перескок на O|T0), а зона 1xxxxxxx (вторая половина памяти) свободна для сложных микропрограмм пользователя т.к. произвольный переход по обычному способу может быть произведён на любой двоичный адрес в пределах памяти микропрограмм...

P.S. На самом деле под это дело можно просто больше битов отводить в I2 вплоть до указания того, с каким значением мы сравниваем старший трит - с N,O,P или их комбинацией (например переходить на адрес P|T3 если старший трит регистра T3 равен P или O иначе идти на адрес из I3).

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


07 Jun 2024 22:34
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Shaos wrote:
Копирование в 3-м и 4-м тактах цикла может происходить из триады:
0000 - на шине данных по адресу DPn (виртуальный регистр N)
0001 - на шине данных по адресу DPo (виртуальный регистр O)
0010 - на шине данных по адресу DPp (виртуальный регистр P)
0011 - регистр F
0100 - регистр A
0101 - регистр B
0110 - регистр H (старшая триада текущего DPx)
0111 - регистр M (средняя триада текущего DPx)
1000 - регистр L (младшая триада текущего DPx)
1001 - регистр T0
1010 - выход OPA(A,T1)
1011 - выход OPB(A,B,T1,T2,T3)
1100 - выход сумматора (который всегда складывает A и T1)
1101 - регистр A сдвинутый влево через флаг BCF
1110 - регистр A сдвинутый вправо через флаг BCF
1111 - сюда можно поместить особые случаи, которые можно кодировать следующими 4-мя битами
в триаду:
0000 - на шине данных по адресу DPn (виртуальный регистр N)
0001 - на шине данных по адресу DPo (виртуальный регистр O)
0010 - на шине данных по адресу DPp (виртуальный регистр P)
0011 - регистр F
0100 - регистр A
0101 - регистр B
0110 - регистр H (старшая триада текущего DPx)
0111 - регистр M (средняя триада текущего DPx)
1000 - регистр L (младшая триада текущего DPx)
1001 - регистр A и флаг BCF
1010 - регистр A и флаг RSF
1011 - регистр A и оба флага BCF и RSF
1100 - вывод на выходной регистр GPIO
1101 - регистр T1 (старшая триада регистра TP)
1110 - регистр T2 (средняя триада регистра TP)
1111 - регистр T3 (младшая триада регистра TP)
(не все комбинации источников и приёмников на практике возможны - например нельзя скопировать из L в T1 или из N в H)
Чего-то наверное много дополнительного декодирования тут придётся делать - наверное можно придумать какое-то более детальное разбиение на флаги, причём оставаясь в пределах тех же самых 8 бит?

Например 4-битный адрес микросхемы памяти 74189 будет подаваться и когда она приёмник, и когда она источник, и это всегда будет одно из нижеследующего (MEMADR):

00 - адрес будет выбран в зависимости от состояния младшего трита T0 (N:0010, O:0000, P:0001)
01 - адрес будет выбран в зависимости от состояния флага DPF (N:0010, O:0000, P:0001)
10 - адрес будет взят с 4-битного регистра SP (0000...1111)
11 - адрес будет установлен в 0011 (для выбора 9-тритного регистра TP)

Далее и по входу, и по выходу нужно будет мультиплексировать-демультиплексировать выходы и входы - если эта память является приёмником (DSTMUX):

00 - подключаем входы нулевого канала на внутреннюю шину, чтобы записать T1/H
01 - подключаем входы первого канала на внутреннюю шину, чтобы записать T2/M
10 - подключаем входы второго канала на внутреннюю шину, чтобы записать T3/L
11 - включает особые случаи

Если эта память является источником (SRCMUX):

00 - подключаем выходы нулевого канала на внутреннюю шину, чтобы прочитать T1/H
01 - подключаем выходы первого канала на внутреннюю шину, чтобы прочитать T2/M
10 - подключаем выходы третьего канала на внутреннюю шину, чтобы прочитать T3/L
11 - подключаем выходы операций на внутреннюю шину

Те же самые биты могут выбирать один из отдельно стоящих троичных регистров (DSTMUX или SRCMUX):

00 - регистр T0
01 - регистр F
10 - регистр A
11 - регистр B

Что является источником, а что приёмником (DIRECT):

00 - с регистра на шину (9-тритный адрес берётся с памяти)
01 - с шины на регистр (9-тритный адрес берётся с памяти)
10 - с регистра на память (сюда также подпадают особые случаи)
11 - с памяти на регистр (сюда также подпадают операции)

И ещё осталось повыбирать операции и действия с флагами, а битов больше нет...

P.S. Хотя операции можно попробовать воткнуть через память (см. выше, что добавлено жирным) и адресовать их теми же битами MEMADR, что и память и иногда учитывать код операции (T0):
00 - выход OPA(A,T1)
01 - выход OPB(A,B,T1,T2,T3)
10 - выход сумматора (который всегда складывает A и T1)
11 и T0.l==N - регистр A сдвинутый влево через флаг BCF
11 и T0.l==O - например значение SP в троичном виде (?)
11 и T0.l==P - регистр A сдвинутый вправо через флаг BCF
Особые случаи можно включать выбирая DIRECT=10 (с регистра на память), DSTMUX=11 (особые случаи) и кодируя действие через комбинацию MEMADR и SRCMEM (который тут не будет использоваться по назначению) - как раз получается 16 особых случаев (см. тут) - причём MEMADR будет корректно выбирать адресацию через DPF (01) или адресацию через SP (10) если SRCMEM будет нулевым.

А вот что делать с флагами? Или просто заполнять те флаги, какие надо для соответствующих операций?

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


09 Jun 2024 17:56
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22903
Location: Silicon Valley
Reply with quote
Итак, новый формат I0:

DIRECT (2 бита) - направление копирования с указанием источника и приёмника
DSTMUX (2 бита) - демультиплексирование приёмника
SRCMUX (2 бита) - мультиплексирование источника
MEMADR (2 бита) - адресация микросхем памяти, выдающих 9 тритов

Мультиплексирование/демультиплексирование приёмника и источника имеет смысл только при чтении или записи с регистров или памяти - в случае шины оно смысла не имеет и этот факт можно использовать, например если мы пишем на шину (DIRECT=00 с регистра на шину), то DSTMUX может добавить что-то ещё в приёмники, например другие регистры:

00 - запись в шину (тут MEMADR используется по прямому назначению)
01 - запись в регистр F
10 - запись в регистр A
11 - запись в регистр B (должен ли MEMADR включать запись в GPIO вместо регистра?)

(причём если мы пишем из F в F или из A в A или из B в B, то можно просто обнулять значение регистра)

А если читаем с шины (DIRECT=01 с шины на регистр), то SRCMUX может добавить что-то ещё в источники, например GPIO (а может сюда часть операций пенести, чтобы не вовлекать триты из самой троичной инструкции, хранимой в T0?):

00 - чтение с шины с A9=0 (тут MEMADR используется по прямому назначению)
01 - чтение с шины с A9=P (раcширение шины для устройств с большой памятью)
10 - чтение с шины с A9=N (раcширение шины для устройств с большой памятью)
11 - чтение из GPIO ???

По поводу особых случаев включаемых по DIRECT=10 (с регистра на память) - они могут выбираться 4-битной комбинацией SRCMUX и MEMADR:

0000 - PC никуда не копируется
0001 - копировать PC в DP
0010 - копировать PC в [SP]
0011 - специальный случай для копирования PC в PC если TP<0 (работает в паре со сложным перескоком)

Далее наверное имеет смысл больше внимания уделить константам, которые можно будет записать в регистр T1 (который также находится в памяти) - можно тут применить логику отроичивания 4-битного значения SP, но инвертировать второй бит:

0100 -> 0000 -> OOO
0101 -> 0001 -> OOP
0110 -> 0010 -> OON
0111 -> 0011 -> PON
1000 -> 1100 -> NNO
1001 -> 1101 -> NNP
1010 -> 1110 -> NNN
1011 -> 1111 -> PPP
1100 -> 1000 -> ONO
1101 -> 1001 -> ONP
1110 -> 1010 -> ONN
1111 -> 1011 -> PNN

Это неполный набор комбинаций для одной триады - чтобы получить полный надо будет в некоторых случаях применить унарную операцию:
Code:
NNN (-13) -> OK
NNO (-12) -> OK
NNP (-11) -> OK
NON (-10) -> OPA(ONO,ONO)
NOO (-9)  -> OPA(PNN,ONN)
NOP (-8)  -> OPA(PON,PON)
NPN (-7)  -> OPA(ONO,PNN)
NPO (-6)  -> OPA(ONP,PON) -> OPN & OPA(OPN,ONP)
NPP (-5)  -> OPA(PNN,PON)
ONN (-4)  -> OK
ONO (-3)  -> OK
ONP (-2)  -> OK
OON (-1)  -> OK
OOO (0)   -> OK
OOP (+1)  -> OK
OPN (+2)  -> OPA(ONP,PON)
OPO (+3)  -> OPA(ONO,PON)
OPP (+4)  -> OPA(ONN,PON)
PNN (+5)  -> OK
PNO (+6)  -> OPA(ONP,PON) -> OPN & OPA(OPN,OPN)
PNP (+7)  -> OPA(ONO,PNN) -> NPN & OPA(NPN,PON)
PON (+8)  -> OK
POO (+9)  -> OPA(OPP,OPO)
POP (+10) -> OPA(ONO,ONO) -> NON & OPA(NON,PON)
PPN (+11) -> OPA(NNP,PON)
PPO (+12) -> OPA(NNO,PON)
PPP (+13) -> OK

_________________
https://mastodon.social/@Shaos :dj:
https://www.youtube.com/@Shaos1973


10 Jun 2024 01:31
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 38 posts ]  Go to page Previous  1, 2, 3  Next

Who is online

Users browsing this forum: No registered users and 26 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.