/******************************************
* (C)Copyright by N.T.T 1993(unpublished) *
* All rights are reserved.                *
******************************************/
%i <r256_8.h>
%i <r256_8.cir>
%i <inc8.h>
%i <inc8.cir>
%i <cla8.h>
%i <cla8.cir>

%d LDAI 0x80    /* a <- op2 */
%d LDAX 0x01    /* a <- (x) */
%d STAX 0x02    /* (x) <- a */
%d LDXI 0x83    /* x <- op2 */
%d LDXM 0x84    /* x <- (op2) */
%d STXM 0x85    /* (op2) <- x */
%d INX  0x06    /* x <- x + 1 */
%d SEC  0x07    /* c <- 1 */
%d CLC  0x08    /* c <- 0 */
%d ROLA 0x09    /* c || a <- a || c */
%d COMA 0x0a    /* a <- ^ a */
%d ADCX 0x0b    /* a <- a + (x) + c */
%d ANDX 0x0c    /* a <- a & (x) */
%d BC   0x8d    /* if (c) pc <- op2 */
%d IN   0x0e    /* a <- dti */
%d OUT  0x0f    /* dto <- a */

declare cpu {
    input    dti<8> ;
    output   dto<8> ;
    output   adrs<8> ;
    instrout memory_read;
    instrout memory_write;
    instrin  start ;
}

module top {
    instrin   start;
    output    dto<8>;
    output    adrs<8>;
    cpu       cpu;
    r256_8    ram;
    instruct start cpu.start();
    instruct cpu.memory_read cpu.dti = ram.read(cpu.adrs).dout ;
    instruct cpu.memory_write ram.write(cpu.adrs,cpu.dto);
}

module cpu {
    input    dti<8> ;
    output   dto<8> ;
    output   adrs<8> ;
    instrout memory_read ;
    instrout memory_write;
    instrin  start ;
    reg_wr   pc<8> ;
    reg      a<8> ;
    reg      x<8> ;
    reg      c ;
    reg      op1<8> ;
    reg      op2<8> ;
    reg      md<8> ;
    inc8     inc ;
    cla8     cla ;
    instr_arg memory_read(adrs);
    instr_arg memory_write(adrs,dto);
    stage_name if {
        task ift() ;
    }
    stage_name exec {
        task ext() ;
    }
    instruct start generate if.ift();
    stage if {
        state_name  fetch1 ;
        state_name  fetch2 ;
        first_state fetch1 ;
        state fetch1 par {
            op1 := memory_read(pc).dti ;
            pc := inc.do(pc).out ;
            any {
                dti<7> : goto fetch2 ;
                else : relay exec.ext() ;
            }
        }
        state fetch2 par {
            op2 := memory_read(pc).dti ;
            pc := inc.do(pc).out ;
            goto fetch1 ;
            relay exec.ext() ;
        }
    }
    stage exec {
        state_name  exec1 ;
        state_name  exec2 ;
        first_state exec1 ;
        state exec1 any {
            (op1 == ADCX) | (op1 == ANDX) : par {
                generate if.ift() ;
                goto exec2 ;
                md := memory_read(x).dti ;
            }
            else : par {
                relay if.ift() ;
                any {
                    op1 == LDAI    : a  := op2 ;
                    op1 == LDAX    : a  := memory_read(x).dti ;
                    op1 == STAX    : memory_write(x,a) ;
                    op1 == LDXI    : x  := op2;
                    op1 == LDXM    : x  := memory_read(op2).dti ;
                    op1 == STXM    : memory_write(op2,x) ;
                    op1 == INX     : x  := cla.do(0b1,x,0x00).out ;
                    op1 == SEC     : c  := 0b1 ;
                    op1 == CLC     : c  := 0b0 ;
                    op1 == ROLA    : par { a := (a || c)<7:0> ; c := a<7> ; }
                    op1 == COMA    : a  := ^a ;
                   (op1 == BC) & c : pc := op2 ;
                    op1 == IN      : a  := dti ;
                    op1 == OUT     : dto = a ;
                }
            }
        }
        state exec2 par {
            goto exec1 ;
            finish ;
            any {
                op1 == ADCX : a := cla.do(c,a,md).out ;
                op1 == ANDX : a := a & md ;
            }
        }
    }
}
