2020年7月30日木曜日

Z8002にMMUを その2

今回作るMMUは、高速SRAMをマッピングテーブに使った回路になり、下の図のような構成になります。


Z8002のアドレス下位12ビットは、そのまま物理アドレスの下位12bitとしてメモリに渡します。Z8002のアドレス上位4bitは高速SRAMのアドレスに入れ、読み出されるデータ8bitを物理アドレスの上位8bitとします。これで合計20bit( 1Mバイト分)のアドレスに変換します。

アドレス変換を行うには、高速SRAMにマッピングデータを書き込む必要があるので、マルチプレクサとバッファをつけます。高速SRAMは0xC000からのI/O空間に置きアクセスします。マルチプレクサは、変換する仮想アドレスの上位4ビットとI/Oアクセスするアドレスを切り替えるために使います。バッファは、高速SRAMをデータバスに接続するために必要です。

本当は、アドレスの上位4ビットをバイパスするために、高速SRAMとメモリの間にさらにマルチプレクサを追加したいのですが、部品と配線量が増えるので見送ります。これはCPUリセット後に高速SRAMを初期化するまでの間、MMUを無効にしておくために必要なのですが、単純に高速SRAMを非アクティブにしおいて データバスをプルダウンすることにします。このため上位8ビットが0に固定され、MMUが初期化されるまでの間はメモリの先頭の4kバイトしかアクセスできなくなってしまいます。

いま気づいている点は、
  • ページがマップされていない状態を設定できない
  • ページごとに書き込み禁止を設定できない
  • ページに書き込みがあったか記録できない
などですが、実現するには高速SRAMを追加する必要があります。これらの機能がどれくらい必要なのか判断がつかないので、MMUは最小限の構成にしておいて、とりあえず動かすことを優先します。


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バイトしかアドレス空間がないので、プロセスが使えるメモリを増やすために有用です。これも信号が出ているので実装してみます。