自作3進CPU

【自作三進CPU】Libra the Processor の仕様

投稿日:2024-11-25 更新日:

現在進行形で作成中の自作三進CPU、愛称を Libra the Processor としました。(以下省略して Libra と書きます)

名前の由来は天秤座の英名 Libra です。平衡三進数は英語では Balanced Ternary といいますが、balance という単語は天秤という意味も持ちます。

このページでは実装の回路的な話はあまりせずに、プログラムを描いたりするうえで把握したい情報をまとめたいと思います。

アーキテクチャ

まずは Libra のアーキテクチャを簡単に説明します。Libra は大きく分けて以下の4つのユニットから構成されます。

  • ステートユニット
  • レジスタユニット
  • ALUユニット
  • メモリユニット

そしてすべてのユニットが一つの大きなバスに接続される形となっています。なお、すべてをバスに接続する形を採用したのは、それぞれのユニットを基板を分けて作ったときに接続しやすいようにという実装上の理由です。

4つのユニットがバスに接続されている図

次にそれぞれのユニットに含まれるものについて説明します。

ステートユニット

ステートユニットはCPUの状態を管理するためのユニットです。Libra はマルチサイクルプロセッサなので、各クロックにおいて命令のどの段階を実行しているかを state が表します。具体的な状態遷移についてはここでは省略します。

PC (プログラムカウンタ)は実行する命令のアドレスを表し、SP (スタックポインタ)はスタックトップのアドレスを表します。どちらも幅は5trit、初期値は-121 (0t#####)です。

sign は演算命令を行った際にその結果の符号が記憶されるレジスタです。条件付きジャンプに使用します。幅は1tritです。

レジスタユニット

Libra は3つの汎用レジスタを持ちます。Imm は即値命令を実行する際にメモリから読みだした即値を格納するレジスタで、自由にアクセスすることはできません。

A, B, C の3つのレジスタのうち、Aレジスタは特殊なレジスタで基本的にどの演算もオペランドの片方はAレジスタとなります。アキュムレータに近いですが、書き込み先はB, Cも選べるので微妙なところです。後述する ISA も併せて確認してください。

レジスタはすべて5tritです。

ALUユニット

ALUユニットは計算を行うユニットです。(ALUのUはUnitなのでALUユニットって表記は気持ち悪いですね。)記憶素子は持ちません。

ALUが実行できる演算は以下のとおりです。(すべて5trit幅)

  • ADD
  • SUB (NOT + ADD)
  • NOT
  • AND
  • OR
  • Shift Left (1trit)
  • Shift Right (1trit)

Shift Left の LST, Shift Right の MST には0が補充されます。

メモリユニット

Libra は命令メモリ、データメモリ、スタックと3つのメモリを持っています。アドレス空間はそれぞれ独立しています。

アドレス幅、データ幅ともに5tritです。

データメモリの121(0t11111)番地はMMIOとして使用する予定です。(変更の可能性あり)

ISA

Libra 用の命令セットを紹介します。ISAについてはあまり練れていないので、Libra the Processor 1号機が動いた後には改良することも考えています。

4~0の欄は機械語のコードです。どの命令も1ワードで表現しています。即値を使う命令は命令本体と即値で2ワードとなっています。

r, d は A, B, C のレジスタを表し、機械語ではA: 1, B: 0, C: #に対応します。

形式はアセンブリの引数を表しています。

命令説明sign変更命令長サイクル数43210形式
ANDd = A AND r131r11dDR
ORd = A OR r131r1#dDR
ADDd = A + r131r01dDR
MOVd = r131r00dDR
SUBd = A – r131r0#dDR
LDd = MEM[r]131r#1dDR
CMPA – r 131r#0R
STMEM[r] = A131r##R
SLd = A << 113011dD
NOTd = NOT A13010dD
SRd = A >> 1 1301#dD
ANDId = A AND imm250011dDI
ORId = A OR imm25001#dDI
ADDId = A + imm250001dDI
MOVId = imm250000dDI
LDId = MEM[imm]2500#1dDI
CMPIA – imm2500#0I
STIMEM[imm] = A2500##I
PUSHSTACK[SP] = A; SP++150#1N
POPSP–; d = STACK[SP]140##dD
JPC = imm25#11L
JPif (sign == 1) PC = imm25#1#1L
JZif (sign == 0) PC = imm25#0#1L
JNif (sign == #) PC = imm25###1L
CALLPUSH(PC+1); PC = imm27#10L
RETPC = POP();14##0N
HALTプロセッサ停止13#####N

特徴、注意点としては以下のような点が挙げられるでしょうか。

  • Aレジスタをオペランドの片方として使う
  • 書き込み先は自由に選べる
  • ST, PUSHはAレジスタからしか保存できない
  • 分岐はCMP + JZ (JP/JN) で行う
  • スタックへのアクセスはPUSH/POP, CALL/RET で行う。特にSPは直接触れない
  • MOVでもsignが変わってしまう(設計ミス)
  • CMPは引き算の結果の符号だけ使うが、オーバーフロー、アンダーフローしたときも下位5tritの値で符号を判断するので注意(設計ミス)

まだ私自身もこの命令セットでプログラムをほとんど書いたことがないので使い勝手が分かりません…

アセンブリ

アセンブリのサンプルとして適当に書いたプログラムを載せておきます。R形式だけ例がありませんが、まあ分かるでしょってことで。

記述の特徴としては以下の点があります。

  • コメントは //
  • 即値は10進法または0tのプレフィックスをつけた平衡三進法で記述
  • 即値の範囲は-121~121 (0t##### ~ 0t11111)
  • N形式は引数なし
  • L形式はラベル名を引数にとる

ツール

Libra the Processor を他の人にも触ってほしいという気持ちから、ツールをウェブで動かせるように作ったのでぜひ遊んでみてください。

-自作3進CPU

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

3進Dフリップフロップを作ってみた【自作3進CPU】

自作3進CPU計画の第2回です。 前回は NOT, NOR, NAND のゲートを作成しましたが、今回はフリップフロップ、すなわち記憶回路の作成に挑戦しました。   目次1 フリップフロップ …

3値論理回路を作ってみた【自作3進CPU】

かねてより温めていた計画である自作3進CPU計画の第1弾として、まずは基本的な論理回路を作ってみました。 2進数といえばコンピュータ、コンピュータといえば2進数というのが常識となっていますが、そんな常 …