もう'17年から、ボーッとopコード4bit固定、16種類のCPUを考えてるですが、
UMA向けの模型、AN式誘導機を優先するため、またもペンディングします。
特に割り込み周りが出来てなです。
いつ再開するかは未定。
現在の仕様はこんなカンジ。
--
================
= OP16 マイコン 仕様書
================ NAFuMA
= レジスタ
================
PC/16 Program Counter
基本的にアドレスが大きい方に1づつ進む
本機はハーバードアーキテクチャーなので、
プログラムカウンタが指すのは、プログラムメモリ
*(書き込みでは特殊な振る舞いをするので、後序する
ACM/16 Accumulator
データの一時保管レジスタ。
Immidiate値、DataMemoryAddress,ALUIn0,ALUOut0などは
このレジスタを経由する。
アドレスを割り付けるかもしれいないが、
意味のある動作はできないだろう。
DP/16 DataPointer
データスタックのポインタ。
RP/16 ReturnPointer
SubRoutineの帰還アドレスや、Nesting変数などを
格納するReturnStackのポインタ。
本機では、DataとReturn値のポンタを分ける。
IRQ/15 IRQ vector
割り込みのベクターを保持するレジスタ。
MSB[15]bitは、IRQ[14:0]のORであり、
irc OPCodeでは、MSBをチェックしている。
USRがRTLを作り込んで実現する。
RD/16 ReadData
read値を一時保管するレジスタ。
アドレスは割り付けるかもしれないが、
有意味のデータは得られないだろう
OPC/4 OP Code
OP Codeがラッチされている。
この値がマイクロプログラムのコードとして解釈される。
解釈なしに、コードがそのまま入る。
OPR/4 OPeRand
OPerandがラッチされ、ALUに、モードとして供給される。
どのタイミングで更新されるかはTBD中。
RED/1 Read Do
DataMemory Readのセマフォ。どの様に推移させるかはTBD中。
WTD/1 Write Do
DataMemory Writeのセマフォ。どの様に推移させるかはTBD中。
PRA/16 PGMEM Adress
PRD/16 PGMEM Data
(adressは未決定)
GPIO/???16bit x (256-16)word.
peripheralの専有アドレスは、TBD。
というか、userがRTLでコードして決めることになるが、
専有が小さい場合、システム寄りの場合、$0010~$01FFを推奨。
逆にVRAMやDMAを要するようなbufferの場合、$C000以上の高位が良いだろう。
インタープリターを実装する場合は、その中間か
- ステータスレジスタ
本機にステータスレジスタはありません。
これは割り込み処理の単純化に配慮したものです。
ステータスレジスタが必要な場合、スタックを消費して実現してください。
= OPecode
================
コード予約語は小文字とする。ユーザ定義は大文字(RTLコードではない。)
OPCode 別名 意味 動作
------------------------------------------------------------------------------
. dup dup push push (A|B C D -- A B|B D)
. drp drop pop pop (A B|C D -- A|B B D)
. dpi > DPinc DataPointer inc1 (A B|C D -- A B D|C)
. dpd < DPdec nip DataPointer dec1 (A B|C D -- A |C B D)
. nan nand nand (A B|C D -- A|~(B&C) B D)
. add + add (A B|C D -- A|(B+C) B D)
. bol bool booling (A B|C D -- A B | ( (C != 0)? -1 :0) B D)
. lda load Address (A B|Adr D -- A B|@Adr)
. sta store Address (A B Dat|Adr D -- A |B Dat D) @Adr<=Dat
. cal call call (A B|Adr -- A|B)(R: -- PC+1)PC<=Adr
. ret return (R:Rt --) PC<=Rt
. irq Interupt Check *** TBD ***
. li1 LDI1 load imidiate 1word (A B|C D -- A B C |{12'd0,D0} D)
. li4 LDI4 load imidiate 4word (A B|C D -- A B C |{D0,D1,D2,D3} D)
. al1 ALU21 ALU result store 1 (A B|C D -- A|ALU0 B D)
. al2 ALU22 ALU result store 2 (A B|C D -- A ALU0|ALU1 C D)
------------------------------------------------------------------------------
* OPCodeの値はTBD irqが0だけ決まってる。
* 動作説明の説明
(P3 P2 P1 |ACM P0 -- P3 P2 |P1 P1 P0)
(処理前のDataスタック,ACM -- 処理後のDataスタック,ACM)
|ACM |の右がACMの値
P0=@DP P0はDP(データポインタの示す値)
P1=@(DP-1) P1はDP-1の示す値
DPは積む(push)で1増える。
P2=@(DP-2)
P3=@(DP-3)
- DPの指すアドレスは、基本的に|ACMの一つ右。(例外もある。)
(R:Adr -- )
(R:処理前リターンポインタの
================
= al1 (ALU21)
================
// and or nor xor xnor
// inhb sub
// bitc bset bclr
// eq ge gr
// jadr
oprand 意味 動作
AND_ : an and {YYs0} = DATs1_i & DATs0_i ;
OR_ : orr or {YYs0} = DATs1_i | DATs0_i ;
NOR_ : norr nor {YYs0} = ~(DATs1_i | DATs0_i) ;
XOR_ : eor xor {YYs0} = DATs1_i ^ DATs0_i ;
XNOR_ : enor xnor {YYs0} = ~(DATs1_i ^ DATs0_i) ;
INHB_ : inhb inhbit(禁止) //(AB --A&(~boolB))
{YYs0} = (DATs0_i!=0) 0 : DATs1_i ;
SUB_ : sub 引き算 {YYs0} = DATs1_i - DATs0_i;
BITC_ : btc bit chek
{YYs0} = 1&(DATs1_i>>DATs0_i[3:0]);
BSET_ : bst bit set // DATs1_iの[DATs0_i]のbitを1にsetする。
{YYs0} = DATs1_i | (1<<DATs0_i[3:0]);
BCLR_ : bcr bit clear //DATs1_iの[BITs0_i]bit を 0にclearする
{YYs0} = DATs1_i&(~(1<<DATs0_i[3:0]));
EQ_ : eq 一致 //(DATs0_i==DATs1_i)なら-1。でなければ0を返す
{YYs0} = (DATs1_i==DATs0_i)?-1:0;
GR_ : gr 大きい //(DATs1_i>DATs0_i)なら-1。でなければ0を返す
{YYs0} = (DATs1_i>DATs0_i)?-1:0;
GE_ : ge 大きいかか同じ //(DATs1_i>=DATs0_i)なら-1。でなければ0を返す
{YYs0} = (DATs1_i>=DATs0_i)?-1:0;
JADR_ : jad jdgがFalseなら-1、でなければADRを返す。JPフィルタの補助
//(jdg ADR -- ADR/-1)
{YYs0} = (DATs1_i!=0)?DATs0_i : -1;
and,orなどは、verlogの予約語なので、oprandには避けている
================
= al2 (ALU22)
================
// ALU22
// sw neg neg32
// sub abs abs32 sadd ssub add12
// swp mul sft ssft maxmin smaxmin
// MSB lsb
//
// notはdup nan で実現。2wordなので、ALU22を使うメリットがない。
sw SWP_: {YYs1,YYs0}=
{DATs0_i,DATs1_i};//SW_=5'h10
NEG_:`b {YYs0} = -(DATs0_i);
YYs1=DATs1_i;
`e
NEGS32_: {YYs1,YYs0} = -{16'h0,DATs0_i} ;
ABS_:`b YYs0=(DATs0_i[15])?(-DATs0_i):DATs0 ;
YYs1=DATs1_i;
`e
ABS32_: {YYs1,YYs0} =
(DATs1_i[15])
? (-{DATs1_i,DATs0_i})
: {DATs1_i,DATs0_i}
;
SADD_: {YYs1,YYs0}=
{{16{DATs1_i[15]}},DATs1_i}
+ {{16{DATs0_i[15]}},DATs0_i}
;
SSUB_: {YYs1,YYs0}=
{{16{DATs1_i[15]}},DATs1_i}
- {{16{DATs0_i[15]}},DATs0_i}
;
ADD12_: {YYs1,YYs0}=
{16'h0,DATs1_i}
+{16'h0,DATs0_i}
;
SUB12_:
{YYs1,YYs0}=
{16'h0,DATs1_i}
-{16'h0,DATs0_i}
;
MSB_:`b YYs0= 1 & (DATs0_i>>15) ;
YYs1= DATs1_i;
`e
MUL_: {YYs1,YYs0}=
{16'h0,DATs0_i} * {16h0,DATs1_i};
SFT_: {YYs1,YYs0}=
{16'h0,DATs1_i}<<DATs0_i;
SSFT_: {YYs1,YYs0}=
{{16{DATs1_i[15]}},DATs1_i}<<DATs0_i;
MAXMIN_: {YYs1,YYs0}=
(DATs1_i>=DATs0_i)
? {DATs1_i,DATs0_i}
: {DATs0_i,DATs1_i}
}
SMAXMIN_: {YYs1,YYs0}=
({~DATs1_i[15],DATs1_i[14:0]}
>`{DATs0_i[15],DATs0_i[14:0]})
? {DATs1_i,DATs0_i}
: {DATs0_i,DATs1_i}
;
MUL_: {YYs1,YYs0}=
{16'h0,DATs1_i}*{16'h0,DATs0}
;
================
= shortened(短縮)subroutine
================
- Shortened(短縮)subroutine は
li1 <entry> cal の3wordで呼び出せる 16種類のサブルーチン郡。
- まだ絞りきれてない
- ソフトウエアのみで変更可能。
// LDS(pick)STS SEL N_GET
// ROT RROT TUCK RROL
// OVER TUKN ROLL
// DFOR DNEXT RJP RCAL
// FLT ZIP MAP REDUCE LEN
// JRCL
// N_GET i_GET n_GET m_get j_get
// LDS (A Ofs -- A Var)//7
{dup,nan,li,DP_,add,lda,ret}
// STS (A DAT ops -- A)//7
{dup,nan,li,DP_,add,sta.ret} //15
// SEL (A F Jdg T -- A sel)
{sw,dup //(A F T J J
,<,sw,> //(A F J T J
,nan //(A F J T'
,sw,nip,sw,bst //(A T' F J
,dup,nan
,nan
,nan,ret}
//RJP (A Ofs -- A)(R:Rt -- Ofs+PC)
{li,RP_,li,1_,add,lda //(A ofs Rt
,add,li,RP_,li,1_,add,lda,sta,ret}
================
= PCの動作
================
- 本機のPCの動作は
- 特殊条件ジャンプ
PCには16'hFFFFは書き込めず、
PCはPC+1にincrementされる。
これによって、jadと組み合わせることで、条件ジャンプを可能にしている。
<例> num が <cmp number>なら <ADR>にジャンプ (num -- )
li4 <cmp number> al1 eq li4 <adr> al1 jad li1 <PC> sta
- 短縮サブルーチン用アドレス変換
adr $0000-$000Fは、それそれ$0080,$0088,$0090,$0098..$00F8に直接転送される。
これによって、adr$0000-$000Fはそれぞれ8wordのjump命令などを実装でき、
短縮サブルーチンエントリーとして使える。
- 通常のサブルーチンcall
li4 A3 A2 A1 A0 cal //6word必要だが
- 短縮エントリーcall
li1 <short subRoutine Entry> cal //3wordで済む。
Z80の RST命令に近い。
- マッパー(未実装
$4000アドレス単位にマッパを持ち、
RTL実装で、自動ページ切り替えができればと考えてる。
mappa1->mappa2->mappa14->mappa13の様に任意にマッパが切り替わるが、
PCから見た見かけのアドレスは、$4000内にとどまる。様なやつ
- システムの0ページのみは固定。
- マッパサイズは$4000,$2000にするべきか迷い中。(0ページを実装で変えたいため)
================
= irc
================
- 本機では、1OPCでスタックを扱い切れない。
スタック処理の途中で割り込みが入ると、
割り込んだ側がスタックを破壊してしまう。
このため、毎OPCごとに割り込みを受け付ける処理は行えない
何か割り込み処理を行うために、ircコードをリザーブしている。
- 今はTBDだが、ircコマンドで、アプリ側がポーリングすることにするか?
(プリエンプティブは諦める型
================
= Dataメモリアクセス
================
================
= Prgメモリアクセス
================
- 構成
- その1
データRAMの上位にPRG メモリを配置する。
PGMEM_RE (ADR -- dat)
li 15 al1 bst lda
PGMEM_WT (dat Adr --)
li 15 al1 bst sta
- 問題
- 32k Wordしかアクセスできない
- アクセスにマッパを考える?
- 逆にDataMemが32kWは多分問題ない。
- マッパが大変になる
- その2
PRG mem アクセスレジスタを介してアクセス。
PGRMEM_RE (ADR -- dat)
li1 PGA sta li1 PGD lda
PGMEM_WT (DAT ADR --)
li1 PGA sta li1 PGD sta
- 問題
- FFを32bit消費する。
- HW 的にwaitをどうとるか考える必要がある。
- ちょっと遅い(そうでもないか?
- むしろ クロック単位のdlyを吸収しやすいか?
- 貴重な最初16アドレスを2コマも使う
- プログラムの転送
- ランダムアクセス
================
= メモリー
================
- DataもProgも16bit wordとする。
= Prog MEM
前詰めに配置する。
- Prgとしてのアクセス
- PC(Program Counter)による read opc フェッチ
PCからのアクセスは、上位14bitで16bitアドレスを選択する。
下2bitで4bit word select
- PC write
PCによるアクセスwriteはない。
書き込むのには、Dataとしてアクセスする。(staコマンド)
- Data としてのアクセス
- Read
16bit アドレスでアクセス
- write
16bit アドレスでのアクセス
= Data Mem
0ページ目はレジスタをアサインしているので、そこだけは避ける。
プログラムと供給するときは???
- Read
一般的なアクセス
- Write
一般的なアクセス
- opcフェッチ
Data Memのスタートアドレス設定によっては、
PCでアクセスできない。イメージにするべきかは???
--