350 likes | 419 Views
Explore how Ternary CPUs work and how Python facilitates their design process. Learn about base-2 and base-3 systems, signed numbers, encoding information, and defining Tribbles and Trytes. Discover floating points in base-3 and the 3ISA Ternary Architecture. Join Cesare Di Mauro at PyCon X 2019 to delve into the fascinating world of Ternary CPUs.
E N D
Ternary CPUs: how they work and how Python helps designing one Cesare Di Mauro PyCon X – Florence May 2019 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
In the beginning it was… binary! Computers use a binary numeral system (two symbols) • Two symbols that may represent: • 0, 1 • False, True • Off, On • -, + Numbers: 11001002 1·26 + 1·25 + 0·24 + 0·23 + 1·22 + 0·21 + 0·20 6410 + 3210 + 410 + 210 10010 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Information in base-2 Commonly defined conventions Bit: one binary digit 0 or 1, False or True, etc. 3 bits: one octal digit 0002 = 08 = 010, …, 1112 = 78 = 010 4 bits: one nibble one hex (hexadecimal) digit 00002 = 016 = 010, …, 11112 = F8 = 1510 8 bits: one byte 000000002 = 010, …, 111111112 = 25510 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Integers in base-2 Signed numbers: two’s complement 10010 = 011001002 -10010 = 100111002 8 bits: one byte unsigned: 0..255 signed: -128..127 16 bits: two bytes unsigned: 0..65535 signed: -32768..32767 32 bits: four bytes unsigned: 0..4294967295 signed: -2147483648..2147483647 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Now it’s ternary time! A ternary numeral system uses three symbols • Three symbols may represent: • 0, 1, 2 • -1, 0, 1 • -, 0, + • False, True, Unknown Numbers: 102013 1·34 + 0·33 + 2·32 + 0·31 + 1·30 8110 + 1810 + 110 10010 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Encoding information in base-3 Three symbols = one ternary digit = one trit 0 or 1 or 2, -1 or 0 or 1, - or 0 or +, etc. Three symbols ≠ +50% over two symbols (base-2)! Encoded information = = 1.5849625… bits Example: two trits = 32 = 9 symbols vs three bits = 23 = 8 symbols Two trits ≠ three bits: we have one more symbol available! Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Signed numbers in base-3* Trit: one ternary digit 0 or 1 or 2, -1 or 0 or 1, - or 0 or +, etc. 3 trits: one tribble 33 == 27 symbols Balanced Ternary: -, 0, and + are shortcuts for -1, 0, and +1. Example: -0+ = (-1)·32 + 0·31 + 1·30 = -9 + 1 = -8 *http://homepage.divms.uiowa.edu/~jones/ternary/numbers.shtml Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Defining the “Tribble” Same as base-2: defining conventions 3 trits: one tribble 33 = 27 symbols 0003 = 010, …, 2223 = 2610 From Hexadecimal (base-16) to Heptavintimal (base-27) 0123456789ABCDEFGHKMNPRTVXZ* Heptavintimal “pack” more information when representing ternary numbers/data; similar to hexadecimal vs binary. Example: 20 trits are represented by 7 tribbles (hept digits). *http://homepage.divms.uiowa.edu/~jones/ternary/hept.shtml Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Defining the “Tryte” Possible choices for the byte equivalent: 5, 6, or 9 trits. 5 trits: -13 symbols* losing some information unsigned: 0..242 signed: -121..121 6 trits: +473 symbols* much more information unsigned: 0..728 signed: -364..364 9 trits: +19427 symbols* way more information! unsigned: 0..19682 signed: -9841..9841 My personal choice: 1 tryte = 5 trits. Closely matches a byte. *Compared to one byte Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Integers in base-3 5 trits: one tryte unsigned: 0..242 signed: -121..121 Reference: ±10010 10 trits: two trytes unsigned: 0..59048 signed: -29524..29524 Reference: ±10,00010 20 trits: four trytes unsigned: 0..3486784400 signed: -1743392200..1743392200 Reference: ±1,000,000,00010 Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Floating points in base-3 fp20 1 tryte for exponent -121..121 (in base-3! Wider range) 3 trytes for mantissa & sign 6-7 decimal digits* 20-trits float in base-3 ≈ 32-bit float in base-2 fp40 7 trits for exponent -1093..1093 (in base-3! Wider range) 33 trits for mantissa & sign 15-16 decimal digits* 40-trits float in base-3 ≈ 64-bit float in base-2 *A bit less information is available, due to a slightly small mantissa range, and the sign which is encoded into the mantissa. Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The 3ISA – Ternary Architecture Like almost all modern ISAs: it’s a N-RISC* Not-Reduced Instruction Set Architecture (more CISC-like) • Many instructions (and room for more) • Not only “simple” instructions (even multi-cycles ones) • Variable-length opcodes • 2 trytes minimum (10 trits. Then 15, 20, 25, etc.) • Base ISA is fixed-length: 4 trytes (20 trits) • Load & store • Feature-complete: “integer” (scalar), FPU, vector/SIMD • *https://www2.eecs.berkeley.edu/Pubs/TechRpts/1982/CSD-82-106.pdf Pag.2 “Design goals for RISC I” Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The 3ISA opcodes structure Compact opcodes (Integer) 2 trytes (10 trits) 3 trytes (15 trits) Standard/base opcodes (Integer, FPU) Implemented 4 trytes (20 trits) Vector (SIMD with masks. Like Intel’s AVX-512) opcodes 5 trytes (25 trits) Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
General specs • 27 General purpose registers R0..R26. • R0 fixed to zero (not writable fault raised). • R1 used as a stack pointer (PUSH/POP instructions). • R26 used as link register (CALL instructions). • GP registers are either 20 or 40 trits (4 or 8 trytes). • 1 PC (Program Counter) register (20 or 40 trits). • 1 F (Flags) register (20 or 40 trits). User-mode. • Note: the architecture is little-endian (LSTrit/Tryte first). Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Float and vector registers • 27 FPU & Vector registers F0..F26 or V0..V26. • Shared (e.g.: F0 = lower part of V0). • 10, 20, 40, or 80 trits FPU registers (depending on the supported maximum floating point precision). • Roughly equivalent to fp16, fp32, fp64, fp128 in base-2. • Minimum vector registers size = maximum FPU registers size. • Maximum vector size depends on specific implementation (e.g. ISA is variable-length & length-agnostic). Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Instructions groups • Quaternary (3 sources, 1 destination)* • Ternary (2 sources, 1 destination)* • Binary (1 source, 1 destination)* • Unary (1 source or destination) • User mode & privilege mode • Calls (jump & link using R26) • Conditional jumps (up to 27 conditions), cmp regs & jump • Load & Store (one address mode: base reg + offset) • Loads with immediate. Load immediate from PC • *Support quick immediate as the last source Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Ternary (diadic) instructions Most are common: Arithmetic ADD, ADDC, SUB, SUBC Shift/rotate SHL, SHR, SAR, ROL, ROR, RCL, RCR Logical ones are quite different*: TMIN Ternary AND, TMAX Ternary OR TANTIMIN Ternary Antimin (NAND) TANTIMAX Ternary Antimax (NOR) TXOR Ternary XOR New ones*: TSUM, TANY, TEQUAL, TCONS *http://homepage.divms.uiowa.edu/~jones/ternary/logic.shtml Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Binary (monadic) instructions Some are common: MOV, CMP, TEST Logical ones (NOT, specifically) are quite different*: STI Standard Ternary Inverter NTI Negative Ternary Inverter PTI Positive Ternary Inverter New ones*: ISUNK Is Unknown, ISFALSE Is False, ISTRUE Is True SHIFTD Shift Down, SHIFTU Shift Up ROTD Rotate Down, ROTU Rotate Up SWAPN Swap Negative, SWAPP Swap Positive *http://homepage.divms.uiowa.edu/~jones/ternary/logic.shtml Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The 3ISA assembler specs • Supports: • all 3ISA (integer) instructions • directives (ORG, EQU, SET, PRINT) • labels and local labels (e.g. internal to subroutines) • comments • data constant & storage definition • expressions with classic unary (+, -, ~) and binary (<<, >>, &, !, ^, *, /, %, +, -, =, <, >, <>, <=, >=) operators • decimal, binary, octal, hexadecimal literals • single quoted and double quoted strings Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
3ISA assembly example • L2NextEQU l2 + 4PRINTL2NextL2SizeSET L2 - Labelcmpjs r14,r26,L2loadl r2,-(@5-2+2*5)loadh r2,$Dloadpc r2,%100 load5 r3,[r4,13] store5 r3,[r4,-81] loadu5 r3,[r4,243]DC.T 'A'L0DC.T 1, $f, 'A'DS.L 5 • StartORG 12.LocalLabel:PRINT.LocalLabelPRINT *add r1,r2,r3; Commentmov r1,r2cmp r1,r2 call r1add r1,r2,-4mov r1,-4cmp r1,-4Label: call l2 call r13,13L2jz Label Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Building the assembler: ANTLR • ANTLR (ANother Tool for Language Recognition) • https://www.antlr.org • Parser generator for: • lexer • (language) syntax parser • AST (Abstract Syntax Tree) Tree walker • A single grammar for all parsers! • Parsers generated for several languages (Python included) Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The ANTLR grammar for 3ISA • grammarasm3isa;options{language= Python2; // Generated code for Python.}module // This is the main/start rule.: (line? NEWLINE)+;line: directive| compound_instruction| standalone_label| standalone_comment;standalone_label: label ':’; • comment: ~NEWLINE*;standalone_comment: ('*' | ';') comment;label: SYMBOL {self.define_label($SYMBOL)}; // Embedded Python code. Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
ANTLRWorks2: an ANTLR tool ANTLRWorks2 is an IDE to help develop ANTLR grammars http://tunnelvisionlabs.com/products/demo/antlrworks It can generate syntax diagrams for rules Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The generated object file The object file: a pure sequence of trits?!? Representing trits on a binary system: - 002 0 012 + 102 Space wasted (e.g.: 112 not used): 1 trit 2 bits. 1 tryte 10 bits. Object file sequence of bytes Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Testing assembler and emulator • Assembler testing goals: • Check ternary (the expected one) • Check stdout (expected) • Emulator testing goals: • Initialize the emulator state • Check conditions all times (invariants) • Check final state (post-conditions) • Assembler and emulator goals: • Same assembly code for assembler and emulator • More complex test scenarios Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Beautiful testing with Python class TernaryTests(BaseTest):@expected_ternary('++----0+00+-000---++')@expected_output('')@init(r2=2, r3=3)@postconditions(r2=2, r3=3, exception=WriteToR0)def test_write_to_r0(self):"""add r0,r2,r3"""@expected_ternary('++----0+00+-00+---++')@init(r2=2, r3=3)@invariants(r2=2, r3=3)@postconditions(r1=5, r2=2, r3=3, pc=4, f=9)def test_add(self):"""add r1,r2,r3""" No code: “just” simple, explicit, readable declarations… Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
How the trick works • @expected_ternary('++----0+00+-000---++')@expected_output('') • @init(r2=2, r3=3)@invariants(r2=2, r3=3)@postconditions(r1=5, r2=2, r3=3, pc=4, f=9) • Decorators collect all requirements • args or kwargs are stored in test method • Requirements used & checked by “test executor” @postconditions(r2=2, r3=3, exception=WriteToR0) Exceptions can be trapped and checked Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Reusing standard Python features • class TernaryTests(BaseTest):def test_add(self):"""add r1,r2,r3""" Doc string 3ISA assembly source code Doc string is compiled and used (run) by “test executor” class EmulatorTests(BaseTest):@postconditions()deftest_init(self):assertlen(self.emulator.memory) == 0, "The emulator memoryisnotempty!" Method code extra, more complex, conditions Method code is executed by “test executor” after emulator execution and post-condition checks. Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Testing framework limits • Emulator’s memory status not yet testable on invariants and post-conditions checks. • Assembler should be run as separate process (and killed on timeout) to avoid deadlocks (e.g.: compilation never completes). • Same issue for emulator (e.g: never-ending loops). • Invariants checks totally own emulator’s single-step execution. Single-step cannot be used/tested by per-se • Assembler’s stderr not intercepted/collected and checked. Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Conclusion • PROs • Better code density 20 trits≈ 32 bits for opcodes • Better data density5/10/20 trits≈ 8/16/32 bits for data • Much less wiring (and chip area)* • Better power consumption • CONs • Effort to convert/adapt existing software • New encodings needed (e.g.: ASCII, UTF-8, RGB, etc.) • Interfacing with existing binary world • Possible lower frequencies reached for chips (3 states) • * http://homepage.divms.uiowa.edu/~jones/ternary/ Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Bibliography / references The Ternary Manifesto by Douglas W. Jones THE UNIVERSITY OF IOWA Department of Computer Science http://homepage.divms.uiowa.edu/~jones/ternary/ Ternary Computer System Project By Claudio La Rosa (thanks for involving me!) http://www.ternary-computing.com https://www.facebook.com/Ternary-Computer-System-1959288864198262/ Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
The first ternary computer board Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one
Q&A Cesare Di Mauro – PyCon X Ternary CPUs: how they work and how Python helps designing one