2020年7月12日日曜日

Z8002にMMUを その1

MMUについて考えていきます。

Z8001にはZ8010というMMUが準備されていますが、Z8002にはつなげられないため、必然的に自作することになります。今回はUNIX V6を動かそうとしているので、DECのPDP-11のメモリ管理機構を参考にします。ネットの情報と「はじめてのOSコードリーディング」を読んだところでは、ざっと下のような感じです。
  • 64kバイトの物理アドレスは、8つのセグメントに分割されている
  • セグメントの最大サイズは8kバイト
  • 各セグメントは、64バイト単位でサイズが可変できる
  • 各セグメントは、物理アドレスの64バイト境界にマップできる
  • カーネルとユーザで空間を分離できる
  • 命令とデータの空間が分離できる
  • セグメント毎に読み込み専用に指定できる
完全に同じものを作るのは難しそうなので、次のように単純化します。
  • セグメントサイズは固定
  • セグメントの物理アドレスへのマッピングはセグメントサイズ境界に揃える
  • 読み込み専用指定は実装しない
  • カーネルとユーザで空間は分離する
  • 命令とデータで空間は分離する
セグメントのサイズは、4kバイト固定にします。マッピングテーブルに高速SRAMを使ったアドレス変換回路を組むのですが、高速SRAMのデータバスは8ビットなので、セグメントサイズを4kバイトにすると、上位8ビット + 下位12ビットでちょうど1Mバイトのメモリを扱うことができます。

セグメントのマッピング位置をセグメントサイズ境界に揃えると、メモリの使用に無駄が多くなりそうですが、PDP-11のように細かくしようとするとセグメント情報を記録するマップが大きくなってしまいます。また、加算回路が必要になるためアドレスが確定するまでの遅延が大きくなり配線量も増えるので諦めます。その分、セグメントサイズを4kバイトに小さくすることにします。

読み込み専用指定は、テキストセグメントへの書き込み禁止などの保護のために使うのでしょうか。今回は設定できなくても特に問題はないと思うので省略します。

カーネルとユーザ空間の分離は、Z8000がシステムとノーマルモードを持っており、どちらで動作しているか信号を出しているので実装できそうです。

命令とデータの空間分離は、Z8000では64kバイトしかアドレス空間がないので、プロセスが使えるメモリを増やすために有用です。これも信号が出ているので実装してみます。

2020年6月27日土曜日

Zilog Z8002でUNIX

CP/M-8000の移植が終わってから何もやってなかったのですが、注文していたZ8002が届いたので再始動します。

このZ8002でUNIX V6を動かすのが次の目標です。

ZilogのZEUSとかOnyx SystemsのC8002とか、Z8000でUNIXを動かしている製品があったので、不可能ではないのは確かです。ネット検索してみましたが、趣味でZ8000でUNIXを動かした人はいないようなので、挑みがいもあります。CP/M-8000よりかなりハードルが高いのは確かですが、また1年か2年越しで達成したいと思います。なんせ趣味なので気長にゆっくり楽しめれば、それでOKです。
ちなみに、私は、Linuxは使いますがUNIXの経験は全くありません。OSの中身を勉強するにも良い機会になると期待しています。

CPUをZ8001からZ8002に切り替えた理由ですが、Z8001のセグメントモードはいろいろと効率が悪いと感じたからです。Z8000のアドレス空間は基本64kバイトです。Z8001ではセグメントを導入し、128セグメント×64kバイトで8Mバイトまで拡張しています。
Z8001では、1セグメントは64kバイトしかないのにアドレスを表すには4バイト必要だったり、即値アドレスを読み込むのに1サイクル余分に必要になったりと無駄が多い気がしてなりません。Z8000のアーキテクチャだと、これらの無駄がないノンセグメントなZ8002の方が素直で扱いやすい気がします。

UNIX V6を動かすに必要なメモリ容量ははっきりわからないのですが、V6が開発されていたPDP-11では256kバイトか4Mバイト扱えたそうなので、最低256kバイトのメモリは必要になりそうです。
64kバイト以上のメモリをZ8002で扱うには、アドレス空間を拡張するMMUを外付けする必要が出てくるので、まずはこの辺りから始めます。

2020年5月16日土曜日

CP/M-8000公開

Z8001ボードにインストラクションとデータのメモリ空間を分離する機能の追加と、CP/M-8000のBIOSの対応を行いました。これで、アセンブラやCコンパイラなど、すべてのコマンドが使えるようになっています。


回路図とBIOSのコードをGitHUbに上げました。

https://github.com/4sun5bu/Z8001MB

今後、CP/M-8000を移植したい人が現れるかはわかりませんが、役に立つと思います。

2020年4月29日水曜日

CP/M-8000の移植とその先へ

暫くCP/M-8000のBIOSを書いていたのですが、ほぼ終わりました。
現在、CFに書き込んだCP/Mのディスクイメージから起動できるようになっています。コマンドも実行可能で、下はSTATを実行した例です。


CP/Mのことをほとんど知らないのに移植に挑んだのが原因ですが、Disk I/Oの部分を書くのにかなり手間取りました。いかに役に立ったサイトのリンクを載せておきます。
  • John Elliott氏のCP/M Main Page : CP/M全般の情報が集められています。ファイルシステムの構造やBIOSの情報が役に立ちました。
  • Grant Searle氏のGrant's homebuilt electronics : CP/MのドライブをCFに対応させるアイデアや、ディスクフォーマットの決め方を参考にさせてもらいました。その他の情報も盛りだくさんです。
  • neko Javaさん?のCP/Mコーナー : CP/Mのディスクイメージの作成方法の情報があります。

ここまでで「CP/M-8000の移植はできた」と言っていいとは思うのですが、実は問題があります。トランジェントコマンドの多くが、インストラクションとデータのメモリ空間が分けられるハードウェアを要求することです。
Z8001は8MBのアドレス空間を持ってはいますが、64kBのセグメントに分割されています。コマンドはノンセグメンテッドのコードで書かれているため、利用できるメモリー空間が64kBに制限されてしまいます。それを補うためインストラクションとデータとを別々の空間に置き、128kBまで扱えるようにしているのです。

今回作ったCPUボードでは空間の分離には対応していないので、殆どのコマンドが実行できません。EDやASすら実行できなので、テキストを入力してアセンブルすることすらできず正直何もできません。

動かないコマンドがあることは、移植を開始した早い段階で気づいていましたが、「移植できるのか」という技術的なことにしか興味がなかったので目をつむっていました。せっかくここまで来たので、ハードウェアを改造してインストラクションとデータ空間を分けられるようにしていきます。

2020年4月19日日曜日

CP/M-8000 目覚める

ここ暫くCP/M-8000のBIOSの実装を続けてきたのですが、やっとプロンプトが表示されるところまで来ました。まだプロンプトの表示が変で、謎の"1#"が表示されてはいますが、ビルトインコマンドをタイプすると実行できることを確認できました。
完全にBIOSが実装できておらず、特にディスクI/Oがまだ未実装なので何もできませんが、ゴールデンウィークを中に実装を進めるつもりです。


The Unofficial CP/M Web site には、「CP/M-8000を移植するには、CP/Mが動作するOlibetti-M20上でビルドすることを検討しろ」と書かれていたのですが、オブジェクトファイルをCOFFに変換するツールができたことで、LinuxやWindows上でクロス開発できるようになりました。LinuxやWindows上では高機能な開発環境が使えるので、作業がかなり楽になります。
このあと、私以外にCP/M-8000を移植しようとする人が現れるのかはわかりませんが、ものずきな人のために情報をまとめて公開していくつもりです。

2020年3月14日土曜日

XOUT to COFF 変換

ここ暫く作業を続けていた、CP/M-8000のXOUTファイルをCOFFに変換するツールができたので、まとめてGitHubで公開することにします。

xoutulis (GitHub)

当初、いつものようにCで書いていたのですが途中で行き詰ってしまい、気分転換と自分の勉強を兼ねてGoで書き直しました。Goでかいた最初のアプリになるので、かなり変なことをしているかもしれませんが、とりあえず動きます。

公開するツールは、XOUTからCOFFに変換する xout2coff と、ライブラリファイルをXOUTファイルに分割する xarch です。

使い方は単純で、GOPATHをxoututils/ に通して、そのディレクトリで、
$ go build xout2coff
$ go build xarch
とコマンドを打つと、それぞれビルドされて xoututils/ にコマンドができます。
$ xarch libXXX.a
で、ライブラリの展開。

$ xout2coff XXX.rel
で、COFFへのファイル変換ができます。

これで、CP/M-8000をLinuxやWindows上でクロス開発できるようになりました。今はOlivetti M20用のBIOSを読んで、自作Z8001ボード用に書き直す作業に入っています。

2019年11月4日月曜日

ATmega164PのJTAGを禁止する

初期状態のATmega164PのPC2 - PC5 は、JTAGに割り当てられているため、そのままでは入出力に使えません。これらのピンを入出力で使うには、JTAGを禁止する必要があります。
ネット上ではソフト的に禁止する方法が見つかるのですが、試したてみたものの、うまく行きませんでした。

ハード的にJTAGを禁止するには、ヒューズビットの上位バイトのbit6を1に書き換えます。
私の手持ちの石の上位バイトは0x99でしたので、これを0xD9に書き換えます。
AVR ISP mkIIを使ってavrdudeで書き換える場合だと、
avrdude -c avrisp2 -P usb -p m164p -U hfuse:w:0xD9:m 

ヒューズビットの設定を間違えると最悪起動しなくなることもあるので、注意が必要です。