Троичный компьютер ТРИНИТИ-2004

Уравновешенная троичная система счисления - форум переехал с http://ternary.info

Moderator: haqreu

User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Проект "Троичный компьютер Trinity"

Post by Shaos »

Предлагается создать простейший троичный компьютер, состоящий из комбинированных аналогово-цифровых модулей с троичным интерфейсом. Для начала реализовать 3 трехтритных регистра и обкатать на них основные троичные алгоритмы. Имя "Trinity" как мне кажется может привлечь интерес к проекту со стороны матрицофилов после опубликования материалов по нему в интернете. Жду откликов :)

P.S. Под спойлером можно найти окончательную архитектуру 3niti alpha, оформившуюся к концу 2008 года:

 3niti alpha
Регистры:

-4 N: триада из ячейки памяти с адресом DPn (см. ниже);
-3 O: триада из ячейки памяти с адресом DPo (см. ниже);
-2 P: триада из ячейки памяти с адресом DPp (см. ниже);
-1 F: регистр флагов (см. ниже);
0 A: регистр аккумулятора;
+1 B: дополнительный регистр;
+2 L: младшая триада текущего регистра DP (см. ниже);
+3 M: средняя триада текущего регистра DP (см. ниже);
+4 H: старшая триада текущего регистра DP (см. ниже).

Регистр F состоит из 3 троичных флагов:
  • Старший трит: RSF (Result Sign Flag) - флаг знака результата
  • Средний трит: DPF (Data Pointer Flag) - флаг указателя данных
  • Младший трит: BCF (Borrow Carry Flag) - флаг переноса-заёма
Также существют три 9-тритовых регистра указателя данных (data pointer = DP) - DPn, DPo, DPp, доступные через имена регистров L/M/H когда флаг DPF имеет значение N, O, P соответственно.

Теневой регистр программного счётчика (program counter = PC) напрямую недоступен - только через команды копирования между PC и текущим DP.

Полный список команд:

#NNN (-13) SAN - сохранить регистр A в регистре N (ячейка памяти с адресом DPn);
#NNO (-12) SAO - сохранить регистр A в регистре O (ячейка памяти с адресом DPo);
#NNP (-11) SAP - сохранить регистр A в регистре P (ячейка памяти с адресом DPp);
#NON (-10) SAF - сохранить регистр A в регистре F;
#NOO (-9) SPCD - сохранить PC в текущем регистре DP;
#NOP (-8) SAB - сохранить регистр A в регистре B;
#NPN (-7) SAL - сохранить регистр A в регистре L (младшая триада текущего DP);
#NPO (-6) SAM - сохранить регистр A в регистре M (средняя триада текущего DP);
#NPP (-5) SAH - сохранить регистр A в регистре H (старшая триада текущего DP);
#ONN (-4) RLA - сдвинуть регистр A влево через флаг BCF;
#ONO (-3) ADD - сложить регистр A с регистром B и флагом BCF, сохранить результат в A и флаге BCF, установить флаг знака RSF;
#ONP (-2) RRA - сдвинуть регистр A вправо через флаг BCF;
#OON (-1) LAI # - загрузить регистр A данными из триады идущей следом;
#OOO (0) ADI # - сложить регистр A с данными из триады идущей следом и флагом BCF, сохранить результат в регистре A и флаге BCF, установить флаг знака RSF;
#OOP (1) OPA # - выполнить унарную потритовую операцию над регистром A (функция устанавливается данными из триады идущей следом), установить флаг знака RSF;
#OPN (2) LDI # # # - загрузить текущий регистр DP данными из 3 триад идущих следом (старшая, средняя, младшая);
#OPO (3) JMP # # # - передать управление на адрес, взятый из 3 триад идущих следом (старшая, средняя, младшая);
#OPP (4) OPB # # # - выполнить бинарную потритовую операцию над регистрами A и B, сохранить результат в регистре A (функция устанавливается данными из 3 триад идущих следом), установить флаг знака RSF;
#PNN (5) LAN - загрузить регистр A из регистра N (ячейка памяти с адресом DPn);
#PNO (6) LAO - загрузить регистр A из регистра O (ячейка памяти с адресом DPo);
#PNP (7) LAP - загрузить регистр A из регистра P (ячейка памяти с адресом DPp);
#PON (8) LAF - загрузить регистр A из регистра F;
#POO (9) LPCD - загрузить PC из текущего регистра DP;
#POP (10) LAB - загрузить регистр A из регистра B;
#PPN (11) LAL - загрузить регистр A из регистра L (младшая триада текущего DP);
#PPO (12) LAM - загрузить регистр A из регистра M (средняя триада текущего DP);
#PPP (13) LAH - загрузить регистр A из регистра H (старшая триада текущего DP).

См. http://ternary.info/wiki/index.php?n=Alpha.InstructionSet

Самый старый архив этой вики-странички на вебархиве с описанием системы команд 3niti alpha датируется 1 июля 2009 года:
https://web.archive.org/web/20090701024237/http://www.3niti.org/wiki/index.php?n=Alpha.InstructionSet

P.P.S. В апреле 2023 года сложилось расширение этой архитектуры под названием 3niti beta: viewtopic.php?p=169510#p169510
Я тут за главного - если что шлите мыло на me собака shaos точка net
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Re: Проект "Троичный компьютер Trinity"

Post by Mac Buster »

Shaos wrote:Предлагается создать простейший троичный компьютер, состоящий из комбинированных аналогово-цифровых модулей с троичным интерфейсом. Для начала реализовать 3 трехтритных регистра и обкатать на них основные троичные алгоритмы. Имя "Trinity" как мне кажется может привлечь интерес к проекту со стороны матрицофилов после опубликования материалов по нему в интернете. Жду откликов :)
Поддерживаю! Готов обсудить конкретные вопросы архитектуры ;)
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Вот мои предложения. Итак - все 3-тритное. И данные, и команды. Каждый трит может принимать состояние -1 (N), 0 (O) или +1(P). Имеем 9 регистров (возможно не все сначала будут реализованы):

Code: Select all

CS #NN (-4) Code Segment
PC #NO (-3) Program Counter
OP #NP (-2) Operator =[CS:PC] (?)
RF #ON (-1) Register F (RSF-ResultSignFlag|reserv|BCF-BorrowCarryFlag)
RA #OO (0) Register A (Accumulator)
RB #OP (1) Register B
RD #PN (2) Data =[DS:DP]
DP #PO (3) Data Pointer
DS #PP (4) Data Segment
Как видно адресуем мы только 27 ячеек памяти за раз, чтобы иметь больше памяти используется сегментация - еще 27 сегментов, итого 729 ячеек памяти - для начала неплохо, а потом можно и расшириться ;)
Операции делятся на три большие группы:
Код #Nxx - скопировать аккумулятор в регистр (SVArr)
Код #Oxx - отдельные операции
Код #Pxx - скопировать регистр в аккумулятор (LDArr)
Отдельные операции по отдельности:

Code: Select all

SAR #ONN (1-cell) Shift Accumulator Right using BCF
ADD #ONO (1-cell) Addition A=A+B+BCF
SAL #ONP (1-cell) Shift Accumulator Left using BCF
LCA t #OON #xxx (2-cell) Load Constant to Accumulator
NOP t #OOO #xxx (2-cell) Not Operation and Wait 't' ticks (?)
OPA t #OOP #xxx (2-cell) Operation (see below)
JRS tN tO tP #OPN #xxx #yyy #zzz (4-cell) Jump if RSF (N-xxx,O-yyy,P-zzz)
JMP tR tS tA #OPO #xxx #yyy #zzz (4-cell) Long Jump (tN=0, tS=Segment, tA=Address)
JBC tN tO tP #OPP #xxx #yyy #zzz (4-cell) Jump if BCF (N-xxx,O-yyy,P-zzz)
Отдельно по поводу спецоперации OPA - эта команда покрывает все возможные побитовые (потритовые) операции, т.к. задает во второй ячейке правила преобразования каждого трита регистра A: левый трит задает результат операции, если трит был равен N, средний трит задает результат операции, если трит был равен O, правый трит задает результат операции, если трит был равен P. Например:
OPA #OOO - все триты регистра A принимают значение 0
OPA #PON - регистр A инвертируется (A=-A)
OPA #OPN - совершить над регистром A потритовую операцию "Shift Up" (см. http://www.trinary.cc)
и так далее. После каждого изменения аккумулятора меняются флаги RSF и BCF.

На базе указателя данных DP теоретически возможно реализовать стек возвратов - будет время, напишу макросы.

Жду горячего обсуждения ;)

UPDATE: Флаг RSF до 2008 года назывался ASF (Accumulator Sign Flag) и это было поправлено
Last edited by Shaos on 14 Dec 2004 08:56, edited 1 time in total.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Shaos wrote: Отдельно по поводу спецоперации OPA - эта команда покрывает все возможные побитовые (потритовые) операции, т.к. задает во второй ячейке правила преобразования каждого трита регистра A: левый трит задает результат операции, если трит был равен N, средний трит задает результат операции, если трит был равен O, правый трит задает результат операции, если трит был равен P. Например:
OPA #OOO - все триты регистра A принимают значение 0
OPA #PON - регистр A инвертируется (A=-A)
OPA #OPN - совершить над регистром A потритовую операцию "Shift Up" (см. http://www.trinary.cc)
Только что заметил: OPA #NOP - это "нет операции" (оставить в регистре A все как есть и скушать у проца два цикла) :lol:

Т.е. команду NOP (#OOO) можно заменить чем-то другим
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Shaos wrote:
Shaos wrote: Отдельно по поводу спецоперации OPA - эта команда покрывает все возможные побитовые (потритовые) операции, т.к. задает во второй ячейке правила преобразования каждого трита регистра A: левый трит задает результат операции, если трит был равен N, средний трит задает результат операции, если трит был равен O, правый трит задает результат операции, если трит был равен P. Например:
OPA #OOO - все триты регистра A принимают значение 0
OPA #PON - регистр A инвертируется (A=-A)
OPA #OPN - совершить над регистром A потритовую операцию "Shift Up" (см. http://www.trinary.cc)
Только что заметил: OPA #NOP - это "нет операции" (оставить в регистре A все как есть и скушать у проца два цикла) :lol:

Т.е. команду NOP (#OOO) можно заменить чем-то другим
Например короткий безусловный jump со смещением (-13...+13)
Я тут за главного - если что шлите мыло на me собака shaos точка net
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Post by Mac Buster »

Shaos wrote:Отдельно по поводу спецоперации OPA
Сильно, я про такое не подумал :)
совершить над регистром A потритовую операцию "Shift Up" (см. http://www.trinary.cc)
Этот сайт снова недоступен :(
Т.е. команду NOP (#OOO) можно заменить чем-то другим. Например короткий безусловный jump со смещением (-13...+13)
Можно.
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Mac Buster wrote:
Shaos wrote:Отдельно по поводу спецоперации OPA
Сильно, я про такое не подумал :)
Давно такое хотел сделать - для бинарного процессора вообще предполагал разные операции над разными битами. Можно обкатать на тринарном когда одна и та же операция для всех - покрывает много чего :)
Mac Buster wrote:
совершить над регистром A потритовую операцию "Shift Up" (см. http://www.trinary.cc)
Этот сайт снова недоступен :(
У меня доступен - я автору письмо кастати написал, сообщил ему, что собираюсь написать Java-эмулятор его квадратиков ;)
Mac Buster wrote:
Т.е. команду NOP (#OOO) можно заменить чем-то другим. Например короткий безусловный jump со смещением (-13...+13)
Можно.
Ок - пусть будет так. Если смещение уходит за пределы сегмента - пока наверное будет исключение, а потом можно сделать аппаратное переключение в соседний сегмент.
Я тут за главного - если что шлите мыло на me собака shaos точка net
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Post by Mac Buster »

Я тут прикинул пару алгоритмов и пришёл к выводу что надо либо увеличить количество регистров общего назначения и сделать непрерывную модель памяти, либо вводить команды сравнения, сдвига, определения состояния отдельного трита и маскирования группы тритов. Иначе даже самые простае алгоритмы реализовать очень сложно.
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Mac Buster wrote:Я тут прикинул пару алгоритмов и пришёл к выводу что надо либо увеличить количество регистров общего назначения и сделать непрерывную модель памяти, либо вводить команды сравнения, сдвига, определения состояния отдельного трита и маскирования группы тритов. Иначе даже самые простае алгоритмы реализовать очень сложно.
Сдвиг есть. Сравнение - через вычитание (сложение с инвертированным слагаемым). Маскирование группы тритов - через произвольные потритовые операции.
Я тут за главного - если что шлите мыло на me собака shaos точка net
Mac Buster
Retired
Posts: 1474
Joined: 03 Aug 2003 22:37
Location: Moscow

Post by Mac Buster »

Shaos wrote:Сдвиг есть.
Он с переносом, а нам нужен без переноса ;)
Сравнение - через вычитание (сложение с инвертированным слагаемым).
Тогда придётся где-то прятать значение регистра а потом загружать его обратно.
Маскирование группы тритов - через произвольные потритовые операции.
Похоже я не совсем понял их работу.
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Новая модификация архитектуры. Память линейная, ширина адреса 9 тритов. В железяке предлагается использовать только 8 (старший трит всегда 0). Все что касается адресов будет реализована обычной бинарной КМОС или ТТЛ логикой (т.к. троичной памяти с троичной адресацией пока не существует, а на троичных триггерах флип-флап-флопах делать дороговато будет). Адресное пространство делится на три части:
-3280...-1094: диапазон внешних устройств (троичных или обычных);
-1093...+1093: диапазон ПЗУ с прошитой системой;
+1094...+3280: диапазон ОЗУ с программой пользователя.
Регистр PC непосредственно недоступен.
Итак, имеем 9 доступных регистров:
-4 Dn: триада из памяти по адресу DPn;
-3 Dz: триада из памяти по адресу DPz;
-2 Dp: триада из памяти по адресу DPp;
-1 F: регистр флагов (ASF-AccumulatorSignFlag,DPF-DataPointerFlag,BCF-BorrowCarryFlag);
0 A: регистр аккумулятора;
+1 B: вспомогательный регистр;
+2 D0: младшая триада указателя данных;
+3 D1: средняя триала указателя данных;
+4 D2: старшая триада указателя данных.
Под указателем данных на самом деле понимается ТРИ набора 9-тритовых регистров составляемых из D0/D1/D2, которые переключаются флагом DPF - в зависимости от значения флага будем называть их DPn, DPz, DPp.
Команды как и в прошлом случае делятся на три группы: загрузка регистра А из другого регистра (P??), сохранение регистра А в другой регистр (N??) и отдельные операции (Z??):
ZNN - SLA: сдвиг регистра A влево через флаг BCF;
ZNZ - ADD: сложение A и B с учетом BCF, результат в A и BCF;
ZNP - SRA: сдвиг регистра A вправо через флаг BCF:
ZZN - LAN #: загрузка A далее идушей триадой
ZZZ - ADN #: сложение A и далее идушей триады с учетом BCF, результат в A и BCF;
ZZP - OPA #: унарная потритовая операция над регистром A;
ZPN - LDP # # #: загрузка в текущий указатель данных 9 тритов (D2 D1 D0);
ZPZ - JMP # # #: загрузка в программный указатель 9 тритов (P2 P1 P0);
ZPP - OPB # # #: бинарная потритовая операция с регистрами A и B, результат в A.
Флаг ASF всегда содержит знак содержимого регистра A (-1, 0, +1).
Команда сохранения регистра A записывается как SAr, где r-имя регистра. Команда загрузки регистра A записывается как LAr, где r-имя регистра. Среди команд загрузки и сохранения регистра A есть пара бесполезных команд - сохранить регистр A в A и загрузить регистр A из A - вместо них по данным кодам будут выполнятся действия сохранения P в D и загрузки P из D, соответственно эти команды называются SPD и LPD.
Last edited by Shaos on 17 Dec 2004 23:57, edited 2 times in total.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Вот как реализуется тройной условный переход:

LAN #ZNZ ; load A from number (Z is zero)
SAF ; save A to F
LDP PointerN ; set address for N
LAN #ZZZ ; load A from number
SAF ; save A to F
LDP PointerZ ; set address for Z
LAN #ZPZ ; load A from number
SAF ; save A to F
LDP PointerP ; set address for P

Далее идут операции, изменяющие флаги ASF или BCF.

Чтобы осуществить условный переход по состоянию флага ASF делаем:

LAF ; load A from F
SRA ; shift A right (put ACF to DPF)
SAF ; save A to F
LPD ; load P from D (load true pointer)

Чтобы осуществить условный переход по состоянию флага BCF делаем:

LAF ; load A from F
SLA ; shift A left (put BCF to DPF)
SAF ; save A to F
LPD ; load P from D (load true pointer)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
cr0acker
God
Posts: 1078
Joined: 03 Feb 2003 13:53

Post by cr0acker »

Shaos wrote:Вот как реализуется тройной условный переход:

LAN #ZNZ ; load A from number (Z is zero)
SAF ; save A to F
LDP PointerN ; set address for N
LAN #ZZZ ; load A from number
SAF ; save A to F
LDP PointerZ ; set address for Z
LAN #ZPZ ; load A from number
SAF ; save A to F
LDP PointerP ; set address for P

Далее идут операции, изменяющие флаги ASF или BCF.

Чтобы осуществить условный переход по состоянию флага ASF делаем:

LAF ; load A from F
SRA ; shift A right (put ACF to DPF)
SAF ; save A to F
LPD ; load P from D (load true pointer)

Чтобы осуществить условный переход по состоянию флага BCF делаем:

LAF ; load A from F
SLA ; shift A left (put BCF to DPF)
SAF ; save A to F
LPD ; load P from D (load true pointer)
Это уже какой то пик:)
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

По поводу наименований значений тритов - предлагалось их называть N (-1), O (0), P (+1). Но я в одной статье увидел, что 0 обозначается Z, и это мне больше нравится, т.е. пусть будет N (-1), Z (0), P (+1).

Еще несколько макросов:

Переход к подпрограмме с сохранением адреса возврата в DPz (9-тритовый указатель данных при DPF=Z):

LAN #ZZZ
SAF ; set DPz
LDP return_adr ; load data pointer
JMP subprg_adr ; call subprogram
return_adr:

Возврат из подпрограммы по адресу, сохраненному в DPz:

LAN #ZZZ
SAF ; set DPz
LPD ; load P from D
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Post by Shaos »

Mac Buster wrote:
Shaos wrote:Сдвиг есть.
Он с переносом, а нам нужен без переноса ;)
Обнуляем перенос и двигаем :)
Mac Buster wrote:
Сравнение - через вычитание (сложение с инвертированным слагаемым).
Тогда придётся где-то прятать значение регистра а потом загружать его обратно.
Угу - прячем по указателю данных
Mac Buster wrote:
Маскирование группы тритов - через произвольные потритовые операции.
Похоже я не совсем понял их работу.
Да, для маскирования пришлось ввести бинарную потритовую операцию OPB Tn Tz Tp, где если трит регистра B равен N то берется триада Tn, если трит регистра B равен Z, то берется триада Tz и если трит регистра B равен P то берется триада Tp, и далее если трит регистра A равен N, то в качестве результата берется самый левый трит выбранной триады, если трит регистра A равен Z, то - средний трит, и если трит регистра A равен P, то - правый трит. Например маскирование трита BCF можно проделать так:

LAN #NNP
SAB ; set B to #NNP
LAF ; load A from B
OPB #NNN #NZZ #NZP ; operation MIN

при этом все лишние триты превратятся в N, а нужный (самый правый) сохранит свое значение
Last edited by Shaos on 17 Feb 2005 18:39, edited 1 time in total.
Я тут за главного - если что шлите мыло на me собака shaos точка net