nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 16:32



Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Ternary computer TRINITY-2004 (instruction set) 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Some draft architecture of ternary machine that may be built practically, designed by me 3 years ago (Dec 2004):

Ternary computer TRINITY will have data bus with width 3 trits (triad). Every trit can be in one of 3 state: N (-1), O (0), P (+1). 1 triad can be in one of 27 states: from NNN (-13) to PPP (+13).

TRINITY will have linear memory where address bus will have width 9 trits (in current prototype I plan to use only 8 trits - highest trit will be always 0). Memory itself will be regular "binary" chips (2 bits per 1 trit), because ternary memory is not yet available and it's almost impossible to create one "manually" using "flip-flap-flops". Address space is divided to 3 parts:
-3280...-1094: space for peripheral devices (ternary or binary);
-1093...+1093: space for ROM with basic system program;
+1094...+3280: space for RAM with user program/data.

There are 9 directly available registers:
-4 Dn: triad from memory by address DPn (see below);
-3 Do: triad from memory by address DPo (see below);
-2 Dp: triad from memory by address DPp (see below);
-1 F: flag register (ASF-AccumulatorSignFlag, DPF-DataPointerFlag, BCF-BorrowCarryFlag);
0 A: accumulator register;
+1 B: auxiliary register;
+2 Dl: lower triad of data pointer;
+3 Dm: middle triad of data pointer;
+4 Dh: higher triad of data pointer.
Data pointer actually is set of 3 9-trits data pointer register, available through Dl/Dm/Dh and multiplexed by flag DPF and we may name that 9-trit registers DPn, DPo, DPp.
Register PC (program counter) is not available directly.

Command set has 3 groups of commands: load register A from other register (P??), save register A to other register (N??) and other commands (O??):
ONN - SLA: shift register A to the left through flag BCF;
ONO - ADD: add A with B and BCF, save result to A and BCF;
ONP - SRA: shift register A to the right through flag BCF:
OON - LAN #: load A by immediate triad;
OOO - ADN #: add A with immediate triad and BCF, save result to A and BCF;
OOP - OPA #: unary "tritwise" operation over register A (function set by immediate triad);
OPN - LDP # # #: load to current data pointer (D2 D1 D0) immediate 3 triads;
OPO - JMP # # #: jump to address set by immediate 3 triads (put it ot register PC: Pl Pm Ph);
OPP - OPB # # #: binary "tritwise" operation over registers A and B, save result to A (function set by 3 immediate triads).
Flag ASF always has sign (-1, 0, +1) of accumulator A value.
Command of loading register A is written as LAr (P??), where r is name of source register.
Command of saving regster A is written as SAr (N??), where r is name of destination register.
You can see that we have couple of nonsense commands there (SAA - save A to A and LAA - load A from A). Instead of it on the same opcodes we will have 2 new ones:
POO - LPD: load PC from D (Pl=Dl, Pm=Dm, Ph=Dh);
NOO - SPD: save PC to D (Dl=Pl, Dm=Pm, Dh=Ph).


29 Dec 2007 14:41
Profile WWW
Maniac

Joined: 17 Sep 2012 13:36
Posts: 277
Location: 81.170.128.52
Reply with quote
Interesting architecture...


29 Dec 2007 15:43
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
eudoxie wrote:
Interesting architecture...


Design has a few problems, but I didn't have enough time to fix it...


29 Dec 2007 22:27
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Implementation of ternary conditional branch:

Code:
; set pointers for ternary branch
LAN #ONO ; load A from number (O is zero)
SAF ; save A to F
LDP PointerN ; set address for N
LAN #OOO ; load A from number
SAF ; save A to F
LDP PointerO ; set address for O
LAN #OPO ; load A from number
SAF ; save A to F
LDP PointerP ; set address for P


Code:
; this is conditional branch by ASF state:
LAF ; load A from F
SRA ; shift A right (put ASF to DPF)
SAF ; save A to F
LPD ; load P from D (load true pointer)


Code:
; this is conditional branch by BCF state:
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)


29 Dec 2007 22:34
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Call subroutine with saving return address in 9-trit register DPo (available in 3-trit registers Dl/Dm/Dh if DPF=O):

Code:
LAN #OOO
SAF ; set DPo
LDP return_adr ; load data pointer
JMP subprg_adr ; call subprogram
return_adr:


Return from subprogram to address saved in DPo:

Code:
LAN #OOO
SAF ; set DPo
LPD ; load P from D


Full return stack implementation is much more heavy...


29 Dec 2007 22:46
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Some words about universal operations OPA and OPB:

Operation OPA #ttt may describe ANY unary "tritwise" operation over accumulator A. For example:
OPA #OOO means set A to 0 (N -> O, O -> O, P -> O);
OPA #PON means ternary inversion or negation (N -> P, O -> O, P -> N);
OPA #OPN means "Shift Up" (N -> O, O -> P, P -> N);
OPA #NOP means "No Operation" (N -> N, O -> O, P -> P).

Operation OPB Tn To Tp may describe ANY binary "tritwise" operation over accumulator A and auxiliary register B. Rule for every trit in A: if trit value in register B is N then choose Tn, if trit value in register B is O then choose To, if trit value in register B is P then choose Tp, then use chosen triad as for OPA operation (lower trit for N, middle trit for O, higher trit for P). For example, using OPB for masking of flag BCF in F:

Code:
LAN #NNP
SAB ; set B to #NNP (mask for BCF)
LAF ; load A from F
OPB #NNN #NOO #NOP ; operation MIN (ternary AND)


After that BCF will keep its value, but other trits will set to N.


29 Dec 2007 23:06
Profile WWW
Maniac

Joined: 17 Sep 2012 13:36
Posts: 277
Location: 81.170.128.52
Reply with quote
Shaos wrote:
eudoxie wrote:
Interesting architecture...


Design has a few problems, but I didn't have enough time to fix it...


It's a bit claustrophobic, with the small data units. You can't store very much information with only 27 states, and storing in several data units creates overhead; which would be a problem in general purpose applications.

Though, I can imagine special purpose applications, like signal processing, where this sort of machine could be very useful.


30 Dec 2007 08:19
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
eudoxie wrote:

It's a bit claustrophobic, with the small data units. You can't store very much information with only 27 states, and storing in several data units creates overhead; which would be a problem in general purpose applications.

Though, I can imagine special purpose applications, like signal processing, where this sort of machine could be very useful.


Yes, it's kind of minimalistic, but main idea is ability almost for everyone to build this machine at home :)


30 Dec 2007 10:15
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Shaos wrote:
Call subroutine with saving return address in 9-trit register DPo (available in 3-trit registers Dl/Dm/Dh if DPF=O):

Code:
LAN #OOO
SAF ; set DPo
LDP return_adr ; load data pointer
JMP subprg_adr ; call subprogram
return_adr:


Return from subprogram to address saved in DPo:

Code:
LAN #OOO
SAF ; set DPo
LPD ; load P from D


Full return stack implementation is much more heavy...


I simply translated it in English from my Russian message from Dec 2004. No time to check correctness...

Lets use stack of return addresses with depth 9 (27 triads).
Stack pointer will move from xxx xxx PPP to xxx xxx NNN (only Dl changed).
Stack pointer may be DPp, so first initialization is 7 triads:
Code:
LDN #OPO
SAF ; set DPp
LDP StackAddress ; xxx xxx NNN (trick NNN-1=PPP)


Call subroutine macro (47 triads):
Code:
LDN #OOO
SAF ; set DPo
LDP ReturnAddress ; any address

LDN #OPO
SAF ; set DPp
LADl
ADN -1
SADl
LDN #OOO
SAF ; set DPo
LADl
SADp

LDN #OPO
SAF ; set DPp
LADl
ADN -1
SADl
LDN #OOO
SAF ; set DPo
LADm
SADp

LDN #OPO
SAF ; set DPp
LADl
ADN -1
SADl
LDN #OOO
SAF ; set DPo
LADh
SADp

JMP SubprogramAddress

ReturnAddress:

 ...


Return from subroutine macro (40 triads):
Code:
 ...

LDN #OOO
SAF ; set DPo
LADp
SADh
LDN #OPO
SAF ; set DPp
LADl
ADN 1
SADl

LDN #OOO
SAF ; set DPo
LADp
SADm
LDN #OPO
SAF ; set DPp
LADl
ADN 1
SADl

LDN #OOO
SAF ; set DPo
LADp
SADl
LDN #OPO
SAF ; set DPp
LADl
ADN 1
SADl

LDN #OOO
SAF ; set DPo
LPD ; load P from D


30 Dec 2007 10:43
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
I have an idea about renaming registers to do names 1-character:

-4 N: triad from memory addressed by DPn (see below);
-3 O: triad from memory addressed by DPo (see below);
-2 P: triad from memory addressed by DPp (see below);
-1 F: flag register (see below);
0 A: accumulator register;
+1 B: auxiliary register;
+2 L: lower triad of current DP register (see below);
+3 M: middle triad of current DP register (see below);
+4 H: higher triad of current DP register (see below);

Register F is set of 3 flags:
Higher trit: ASF (Accumulator Sign Flag)
Middle trit: DPF (Data Pointer Flag)
Lower trit: BCF (Borrow Carry Flag)

There are 3 9-trit DP (data pointer) registers - DPn, DPo, DPp, available through L/M/H when flag DPF has corresponding value (N, O, P).

To separate meanings of P and PC we need to rename opcodes #POO and #NOO to LPCD and SPCD respectively. We need to rename opcodes #ONN and #ONP to RLA and RRA respectively ('R'otate instead of 'S'hift). Also we need to rename opcodes #OON, #OOO and #OPN to LAI, ADI and LDI respectively ('I'mmediate).

So full set of opcodes is:
#NNN (-13) SAN - save register A to register N;
#NNO (-12) SAO - save register A to register O;
#NNP (-11) SAP - save register A to register P;
#NON (-10) SAF - save register A to register F;
#NOO (-9) SPCD - save PC (program counter) to current data pointer;
#NOP (-8) SAB - save register A to register B;
#NPN (-7) SAL - save register A to register L (lower triade of current data pointer);
#NPO (-6) SAM - save register A to register M (middle triade of current data pointer);
#NPP (-5) SAH - save register A to register H (higher triade of current data pointer);
#ONN (-4) RLA - rotate register A to the left through flag BCF;
#ONO (-3) ADD - add register A with B and flag BCF, save result to A and BCF;
#ONP (-2) RRA - rotate register A to the right through flag BCF;
#OON (-1) LAI # - load register A from immediate triad;
#OOO (0) ADI # - add register A with immediate triad and flag BCF, save result to A and BCF;
#OOP (1) OPA # - perform unary "tritwise" operation over register A (function set by immediate triad);
#OPN (2) LDI # # # - load current data pointer by immediate 3 triads (lower, middle, higher);
#OPO (3) JMP # # # - jump to address set by immediate 3 triads (put it to register PC: lower, middle, higher);
#OPP (4) OPB # # # - perform binary "tritwise" operation over registers A and B, save result to A (function set by immediate 3 triad);
#PNN (5) LAN - load register A from register N;
#PNO (6) LAO - load register A from register O;
#PNP (7) LAP - load register A from register P;
#PON (8) LAF - load register A from register F;
#POO (9) LPCD - load PC (program counter) from current data pointer;
#POP (10) LAB - load register A from register B;
#PPN (11) LAL - load register A from register L (lower triad of current data pointer);
#PPO (12) LAM - load register A from register M (middle triad of current data pointer);
#PPP (13) LAH - load register A from register H (higher triad of current data pointer);


Last edited by Shaos on 20 Sep 2012 20:43, edited 1 time in total.



30 Dec 2007 17:06
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Lets name this instruction set as "TRINITY-2004" (year of design)

It can be used as microcode for next generation of TRINITY processor!

1 trit - 3 values (N,O,P or -1,0,+1);
1 triad (3 trits) - 27 values;
1 tryte (6 trits, 2 triads) - 729 values;
1 tradr (9 trits, 3 triads) - 19 683 values;
1 trord (12 trits, 4 triads, 2 trytes) - 531 441 values;
1 truadr (18 trits, 6 triads, 3 trytes, 2 tradrs) - 387 420 489 values;
1 truble (24 trits, 8 triads, 4 trytes, 2 trords) - 282 429 536 481 values;

New words "tradr" and "trord" mean "ternary address" and "ternary word" respectively ;-)
New words "truadr" and "truble" mean "double ternary address" and "double ternary word" respectively :-D

P.S. And "tribble" must be 2 trits (3 tribbles = 1 tryte)


09 Jan 2008 06:35
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Another idea to rename "triad" (half of tryte) to "tribble" (like nibble that is half of byte) :-)


10 Jan 2008 18:40
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Idea about representation of floating point numbers: Lets take "truble" and divide it to 2 parts: 6-trit exponent and 18-trit fraction. By accuracy it is better than 32-bit "float", worse than 64-bit "double" and similar to 36-bit floating number in IBM System/360 from 1964 that had 9-bit sign and exponent and 27-bit fraction. Because of nature of balanced ternary numeric system we don't need "biasing" exponent. Also we don't need separate sign bit - we simply combine it with "hidden" most significant bit of fraction instead and it will be part of full 18-trit fraction. So range of exponent is from -364 to +364 (3^6/2) and fraction from -193710244 to +193710244 (3^18/2 that is max possible integer represented by this floating point format). To simplify formula for calculation number from representation we may simply forget about "fractional" nature of fraction and say F*3^E
8-)
P.S. here ^ means "power"


16 Jan 2008 20:18
Profile WWW
Retired

Joined: 03 Aug 2003 22:37
Posts: 1474
Location: Moscow
Reply with quote
So, let's take the representation as a basic representation of fractional numbers for ternary platform.


19 Jan 2008 04:07
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22412
Location: Silicon Valley
Reply with quote
Right now I think that ability to compare normalized floating point numbers as integers is good and to have it we should do "fraction" really fractional (-1 < F < 1): (F*3^18)*3^E = F*3^(18+E). In this case for example to do float from integer 193710244 (PPPPPPPPPPPPPPPPPP) we have to add exponent +18 (OOPNOO): OOPNOOPPPPPPPPPPPPPPPPPP (here fraction is O.PPPPPPPPPPPPPPPPPP). Also to represent 0.5 we will use OOOOOOPPPPPPPPPPPPPPPPPP (error is 0.00000000258).

P.S. But in case of integer "fraction" described in my previous post we still can use normalization as shifting to the left and comparison "normalized" floating point numbers as regular integers...


Last edited by Shaos on 20 Sep 2012 20:43, edited 1 time in total.



19 Jan 2008 15:41
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 21 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 4 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.