SSブログ
English Version

SuperSimpleController(その4)ALUの検討 [OriginalCPU]

 前回の記事で今回検討中のオリジナルCPUのブロック図を書いてALUの機能指定ビット数を3bitから4bitに増やしたことを書きましたが、この状態でも今回使うUV-EPROM(M27C322:2M x 16bit)の半分しか使っていません。
 もったいないので加減算とシフト命令にキャリーフラグ付きのものを加えることにしました。

 手法としては至って簡単でIR(インストラクションレジスタ)からALUに渡している4bitの機能指定ビットの上位にキャリーフラグを追加して機能指定ビットを5bitにするだけです。回路図の抜粋が下図になります。

オリジナルCPU回路のALU部抜粋


 機能指定ビットに対する機能も下表のように見直しました。キャリーが0の場合と1の場合の2面必要になるのでM27C322の容量すべてを使用することになります。下表の2項演算子の演算順序はインテル系のアセンブラと同じです。
 CP(コンペア)ではレジスタを変更する必要が無いのでALUの出力はゼロとし、レジスタをゼロクリアする時に利用することにしました。

No.addresscontents
000000h - 0FFFFhR0
110000h - 1FFFFhAND R0,R1
220000h - 2FFFFhOR R0,R1
330000h - 3FFFFhXOR R0,R1
440000h - 4FFFFhADD R0,R1
550000h - 5FFFFhADC R0,R1
660000h - 6FFFFhSUB R0,R1
770000h - 7FFFFhSBC R0,R1
880000h - 8FFFFhSHL R0 (shift left)
990000h - 9FFFFhSHLC R0 (shift left with carry)
AA0000h - AFFFFhSHR R0 (shift right)
BB0000h - BFFFFhSHRC R0 (shift right with carry)
CC0000h - CFFFFhDEC R0
DD0000h - DFFFFhINC R0
EE0000h - EFFFFhCP R0,R1 (output is zero)
FF0000h - FFFFFhR1
★変更 2021/02/13
 マシン語構成の検討からの反映で機能指定ビットのアサインを変更


 UV-EPROMの書込みはTL866II Plusを使用しています。
 このROMライタはM27C4096の容量までしか対応していない(これより大きいものは40ピンソケットでは足りない)のでM27C322まで対応しているM27C4096変換アダプタを使って書き込んでいます。

TL866II Plusでの書込み状況


 書き込み中の画面キャプチャを参考に貼っておきます。
 今回使用しているROMはST社のもので、TL866でのROMタイプはuPD27C4096を選択しています(他のいくつかのメーカーのM27C4096でも試しましたがNECのuPDタイプで書込みができました)
 赤のワーニングマーカー?が表示されますがライト及びリード操作で問題は発生しませんでした。

TL866II Plusでの書込み画面(書き込み中)


 今回使用しているM27C322はM27C4096の8倍の容量なので、8回に分けて書込み操作をする必要があります。下図が書込み終了後の画面表示例で各処理の所要時間が表示れさており、書込みには138秒かかっています。
 書込み操作は8回必要になるので全体で20分程度の時間がかかります。

TL866II Plusでの書込み画面(書き込み完了時)


 肝心のALU内に格納するデータについてですが、作成するのが面倒かもと思っていましたが、割合簡単にサクッとできました。
 TL866はHEXファイルの他にバイナリファイルも読込めるので、1回の書込みサイズに分割したバイナリファイルを生成するツールを作成しました。
 機能と生成ファイルとの関係は関数テーブルで保持することで管理しています。ソースファイルも貼っておきます。

Simple8Z ALUデータ生成プログラム(C言語)
/**************************** Simple8Z ALU data generator made by skyriver V0.04 2021/03/13 add Cf to R1 V0.03 2021/02/12 ****************************/ #include <stdio.h> #define FNAME "ALU4_%03d.bin" #define FlagZ 0x01 #define FlagC 0x02 void IncR0( FILE * ); void DecR0( FILE * ); void ShlR0( FILE * ); void ShlCR0( FILE * ); void ShrR0( FILE * ); void ShrCR0( FILE * ); void And( FILE * ); void Or( FILE * ); void Xor( FILE * ); void Add( FILE * ); void Adc( FILE * ); void Sub( FILE * ); void Sbc( FILE * ); void Cp( FILE * ); void R0( FILE * ); void R1( FILE * ); char Buf[ 128 ]; void (*func[])( FILE * ) = { R0, And, Or, Xor , Add, Add, Sub, Sub , ShlR0, ShlR0,ShrR0, ShrR0 , DecR0, IncR0, Cp, R1 , R0, And, Or, Xor , Add, Adc, Sub, Sbc , ShlR0,ShlCR0,ShrR0,ShrCR0 , DecR0, IncR0, Cp, R1 }; #define FuncNum ( sizeof(func) / sizeof( void(*)() ) ) #define ROM_BLK 4 // How many functions in a Rom block void DecR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 -1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void IncR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 + 1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void Add( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 + r1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void Adc( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 + r1 + 1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void Sub( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 - r1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void Sbc( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 - r1 - 1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void ShlR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 << 1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void ShlCR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = ( r0 << 1 ) | 0x01; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void ShrR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 >> 1; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((r0 & 1) == 0 ? 0 : FlagC), fp ); } } void ShrCR0( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = ( r0 >> 1) | 0x80; putc( (char)ans, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((r0 & 1) == 0 ? 0 : FlagC), fp ); } } void And( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 & r1; putc( (char)ans, fp ); putc( ans == 0 ? FlagZ : 0, fp ); } } void Or( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 | r1; putc( (char)ans, fp ); putc( ans == 0 ? FlagZ : 0, fp ); } } void Xor( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 ^ r1; putc( (char)ans, fp ); putc( ans == 0 ? FlagZ : 0, fp ); } } void Cp( FILE *fp ) { int adr, r0, r1, ans; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0 - r1; putc( 0, fp ); putc( ((char)ans == 0 ? FlagZ : 0) | ((ans & 0x0100) == 0 ? 0 : FlagC), fp ); } } void R0( FILE *fp ) { int adr, r0, r1, ans;; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r0; putc( (char)ans, fp ); putc( ans == 0 ? FlagZ : 0, fp ); } } void R1( FILE *fp ) { int adr, r0, r1, ans;; for( adr = 0; adr < 0x10000; adr++ ) { r0 = adr & 0xff; r1 = ( adr & 0xff00 ) >> 8; ans = r1; putc( (char)ans, fp ); putc( FlagC | ( ans == 0 ? FlagZ : 0 ), fp ); // add Cf } } int main( int argc, char *argv[] ) { FILE *fp; int i,j; int fidx = 0; for( i = 0; i < (FuncNum / ROM_BLK); i++ ) { sprintf( Buf, FNAME, i ); if( ( fp = fopen( Buf, "wb" ) ) == NULL ) { fprintf( stderr, "can not open %s\n", Buf ); break; } else { for( j = 0; j < ROM_BLK; j++ ) { func[ fidx++ ]( fp ); } fclose( fp ); fprintf( stderr, "%s is generated\n", Buf ); } } return( 0 ); }
★変更 2021/03/13
 R1()でCFをセットするように変更
★変更 2021/02/13
 機能指定ビットのアサインの変更に伴いソースをアップデート



[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。