/******************** MODULE INFO ****************************/ /* * File name : pop11.sfl * * AUTHOR : Yoshihiro Iida (3aepm001@keyaki.cc.u-tokai.ac.jp) * VERSION : 1.0 * DATE : Oct 16, 2003 * * Compiler : sfl2vl * Project : POP-11: PDP-11 compatible On Programmable chip * Functions : Control of POP-11 * * Copyright (c) Yoshihiro Iida, Tokai University, Shimizu Lab., Japan. (http://shimizu-lab.dt.u-tokai.ac.jp) This software is the property of Tokai University, Shimizu Lab., Japan. The POP-11 is free set of files; you can use it, redistribute it and/or modify it under the following terms: 1. You are not allowed to remove or modify this copyright notice and License paragraphs, even if parts of the software is used. 2. The improvements and/or extentions you make SHALL be available for the community under THIS license, source code included. Improvements or extentions, including adaptions to new architectures/languages, SHALL be reported and transmitted to Tokai University, Shimizu Lab., Japan. 3. You must cause the modified files to carry prominent notices stating that you changed the files, what you did and the date of changes. 4. You may NOT distribute this set of files under another license without explisit permission from Tokai University, Shimizu Lab., Japan. 5. This set of files is free, and distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You SHALL NOT use this software unless you accept to carry all risk and cost of defects or limitations. * * ------------ CHANGE RECORD ---------------- * Yoshihiro Iida (3aepm001@keyaki.cc.u-tokai.ac.jp) Sep 21, 2004: * First free version of this software published. * */ %i "define.sfl" %i "data11.sfl" %i "idc.sfl" %i "cnt4.sfl" declare pop11 { input dati<16>; output dato<16>; output adrs<16>; instrin irq_in, rdy, error, fault; instrout rd, wt; output byte; instrout int_ack; output pswout<16>; input psi<16>; instrin pswt; instrout inst; instr_arg pswt(psi); } module pop11 { input dati<16>; output dato<16>; output adrs<16>; instrin irq_in, rdy, error, fault; instrout rd, wt; output byte; instrout int_ack; input psi<16>; output pswout<16>; instrin pswt; instrout inst; instrself start; instrself ifrun, wback, svcall, read, write; instrself decop; instrself s0,s1,s2,s3,s4,s5,s6,s7,s8; data11 dp; idc id; cnt4 cnt; reg_wr st0; reg st1,st2; reg rsub; sel byte_sel; instr_arg write(byte_sel); instr_arg read(byte_sel); stage_name ifetch { task run(); task src_op(); task dst_op(); } stage_name ex { task tsk0(); task tsk1(); task tsk2(); task tsk3(); task tsk4(); task tsk5(); task tsk6(); task tsk7(); task tsk8(); } stage_name wb { task run(); } stage_name trap { task int_req(); task int_svc(); task trace(); } /* * Boot sequence */ par { st0 := 0b1; st1 := st0; st2 := st1; if((st2==0b0) & (st1==0b1)) start(); pswout = dp.psw; } instruct read par { rd(); adrs = dp.dba; if(RDY) dp.dbi = dati; byte = byte_sel; } instruct write par { wt(); dato = dp.dbo; adrs = dp.dba; byte = byte_sel; } instruct pswt par { dp.dbi = psi; dp.dbiPS(); } instruct start par { generate ifetch.run(); dp.setPCrom(); } /* * Decodes instruction, and instruct the instruction. */ instruct decop any { id.dclr: par { dp.dstALU1(); dp.clr(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dcom: par { dp.dstALU1(); dp.com(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dinc: par { dp.dstALU1(); dp.inc(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.ddec: par { dp.dstALU1(); dp.dec(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dneg: par { dp.dstALU1(); dp.neg(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dadc: par { dp.dstALU1(); dp.adc(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dsbc: par { dp.dstALU1(); dp.sbc(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dtst: par { dp.dstALU1(); dp.tst(); ifrun(); dp.ALUcc(); } id.dror: par { dp.dstALU1(); dp.ror(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.drol: par { dp.dstALU1(); dp.rol(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dasr: par { dp.dstALU1(); dp.asr(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dasl: par { dp.dstALU1(); dp.asl(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dsxt: par { dp.dstALU1(); dp.sxt(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dmov: par { dp.srcALU1(); dp.mov(); dp.ALUdst(); wback(); dp.ALUcc(); } id.dcmp: par { dp.srcALU1(); dp.dstALU2(); dp.cmp(); ifrun(); dp.ALUcc(); } id.dbit: par { dp.srcALU1(); dp.dstALU2(); dp.bit(); ifrun(); dp.ALUcc(); } id.dbic: par { dp.srcALU1(); dp.dstALU2(); dp.bic(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dbis: par { dp.srcALU1(); dp.dstALU2(); dp.bis(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dadd &^rsub: par { dp.srcALU1(); dp.dstALU2(); dp.add(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dadd & rsub: par { dp.srcALU2(); dp.dstALU1(); dp.sub(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dexor: par { dp.srcALU1(); dp.dstALU2(); dp.exor(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dswab: par { dp.dstALU1(); dp.swab(); dp.ALUdstb(); wback(); dp.ALUcc(); } id.dnop: par { ifrun(); } id.djmp: par { dp.adrPC(); ifrun(); } id.dbpt: par { dp.bpt(); svcall(); } id.diot: par { dp.iot(); svcall(); } id.demt: par { dp.emt(); svcall(); } id.dtrap: par { dp.svc(); svcall(); } id.dspl: par { ifrun(); dp.spl(); } id.dfloat: par { ifrun(); } /* Not implemented yet */ id.dreset: par { ifrun(); } /* Not implemented yet */ id.dhalt: par { } id.diwait: par { if( irq_in) ifrun(); if(^irq_in) s0(); } /* * Subtract One and Branch */ id.dsob: any { ex.tsk0: par { dp.regSEL2(); dp.selALU1(); dp.dec(); dp.ALUreg(); dp.setReg2(); dp.ccget(); if(^dp.alucc<2>) s1(); if( dp.alucc<2>) ifrun(); } ex.tsk1: par { dp.pcALU1(); dp.ofs6ALU2(); dp.sub(); dp.ALUpc(); ifrun(); } } /* * Mark */ id.dmark: any { ex.tsk0: par { dp.spALU1(); dp.ofs6ALU2(); dp.add(); dp.ALUsp(); dp.FPpc(); s1(); } ex.tsk1: par { read(WORD); dp.dbaSP(); if(^RDY) s1(); if(RDY) par { dp.dbiFP(); dp.spALU1(); dp.inc2(); dp.ALUsp(); ifrun(); } } } /* * Return Interrupt */ (id.drti | id.drtt): any { ex.tsk0: par { read(WORD); dp.dbaSP(); if(^RDY) s0(); if(RDY) par { dp.dbiPC(); dp.spALU1(); dp.inc2(); dp.ALUsp(); s1(); } } ex.tsk1: par { read(WORD); dp.dbaSP(); if(^RDY) s1(); if(RDY) par { dp.dbiPS(); dp.spALU1(); dp.inc2(); dp.ALUsp(); ifrun(); } } } /* * Jump Subroutine */ id.djsr: any { ex.tsk0: par { dp.spALU1(); dp.dec2(); dp.ALUsp(); s1(); } ex.tsk1: par { write(WORD); dp.regSEL2();dp.dboSEL(); dp.dbaSP(); if(^RDY) s1(); if(RDY) par { dp.PCreg(); dp.setReg2(); s2(); } } ex.tsk2: par { dp.adrPC(); ifrun(); } } /* * RTS: Return Subroutine */ id.drts: any { ex.tsk0: par { dp.regSEL(); dp.SELpc(); s1(); } ex.tsk1: par { read(WORD); dp.dbaSP(); if(^RDY) s1(); if(RDY) par { dp.dbiReg(); dp.setReg(); dp.spALU1(); dp.inc2(); dp.ALUsp(); ifrun(); } } } /* * MFPI: Move From Previous Instruction space */ MMU & id.dmfpi: any { ex.tsk0: par { dp.change_mode(); s1(); } ex.tsk1: par { if(/|dp.opc<5:3>) par { read(WORD); dp.dbaAdr(); if(error) dp.change_mode(); if(fault) dp.change_mode(); if(RDY) par { dp.change_mode(); dp.dbiDst(); s2(); } } if(^/|dp.opc<5:3>) par { dp.change_mode(); dp.regSEL(); dp.SELdst(); s2(); } } ex.tsk2: par { dp.spALU1(); dp.dec2(); dp.ALUsp(); s3(); } ex.tsk3: par { write(WORD); dp.dbaSP(); dp.dboDst(); if(RDY) par { dp.srcALU1(); dp.mmu(); dp.ALUcc(); ifrun(); } } } /* * MTPI: Move To Previous Instruction space */ MMU & id.dmtpi: any { ex.tsk0: par { read(WORD); dp.dbaSP(); if(RDY) par { dp.spALU1(); dp.inc2(); dp.ALUsp(); dp.change_mode(); dp.dbiSrc(); s1(); } } ex.tsk1: par { if(/|dp.opc<5:3>) par { write(WORD); dp.dbaAdr(); dp.dboSrc(); if(error) dp.change_mode(); if(fault) dp.change_mode(); if(RDY) par { dp.change_mode(); ifrun(); } } if(^/|dp.opc<5:3>) par { dp.change_mode(); dp.SRCreg(); dp.setReg(); ifrun(); } dp.srcALU1(); dp.mmu(); dp.ALUcc(); } } /* * MUL */ EIS & id.dmul: any { ex.tsk0: par { dp.clrADR(); s1(); } ex.tsk1: par { dp.mul(); if(^(cnt.out==0xf)) par { s1(); cnt.inc(); } if( (cnt.out==0xf)) par { s2(); cnt.rst(); } } ex.tsk2: par { if(dp.opc<6>) par { dp.SRCreg(); dp.setReg2(); dp.tstSRC(); ifrun(); } if(^dp.opc<6>) par { dp.ADRreg(); dp.setReg2(); dp.oddReg(); dp.tstSRCADR(); s3(); } } ex.tsk3: par { dp.SRCreg(); dp.setReg2(); ifrun(); } } /* * DIV */ EIS & id.ddiv: any { ex.tsk0: par { dp.div_ini0(); s1(); dp.oddReg(); } ex.tsk1: par { dp.regSEL2(); dp.SELadr(); s2(); } ex.tsk2: par { dp.div_ini1(); s3(); } ex.tsk3: par { dp.div_ini2(); s4(); } ex.tsk4: par { if(^dp.psw<1>) dp.div(); if(^dp.psw<1> &^(cnt.out==0xf)) par { s4(); cnt.inc(); } if(^dp.psw<1> & (cnt.out==0xf)) par { s5(); cnt.rst(); } if( dp.psw<1>) ifrun(); } ex.tsk5: par { dp.div(); dp.div_end(); if(^dp.psw<1>) s6(); if( dp.psw<1>) ifrun(); } ex.tsk6: par { if(^dp.psw<1>) par { dp.div_fin0(); s7(); } if( dp.psw<1>) ifrun(); } ex.tsk7: par { dp.div_fin1(); s8(); dp.SRCreg(); dp.setReg2(); dp.oddReg(); dp.tstSRC(); } ex.tsk8: par { dp.ADRreg(); dp.setReg2(); dp.adrALU1(); dp.tst(); dp.ALUcc(); ifrun(); } } /* * ASH */ EIS & id.dash: any { ex.tsk0: par { dp.ash(); if(dp.ashdone) s1(); if(^dp.ashdone) s0(); } ex.tsk1: par { dp.tstSRC(); dp.SRCreg(); dp.setReg2(); ifrun(); } } /* * ASHC */ EIS & id.dashc: any { ex.tsk0: par { dp.oddReg(); s1(); } ex.tsk1: par { dp.regSEL2(); dp.SELadr(); s2(); } ex.tsk2: par { dp.ashc(); if(dp.ashdone) s3(); if(^dp.ashdone) s2(); } ex.tsk3: par { dp.ADRreg(); dp.setReg2(); dp.oddReg(); s4(); } ex.tsk4: par { dp.SRCreg(); dp.setReg2(); dp.tstSRCADR(); ifrun(); } } }/* end of decop */ stage ifetch { state_name if0,id0,of0,of1,of2,of3,of4,cc0,br0; first_state if0; /* * Instruction fetch */ state if0 par { inst(); read(WORD); dp.dbaPC(); if(error) par { dp.buserr(); relay trap.int_svc(); } if(fault) par { dp.segerr(); relay trap.int_svc(); } if(RDY) par { dp.pcALU1(); dp.inc2(); dp.ALUpc(); dp.setopc(); goto id0; } } /* * Decodes instruction type */ state id0 par { id.do(dp.opc); if(id.sop) par { goto of1; relay ifetch.src_op(); dp.change_opr(); } if(id.dop) par { goto of1; relay ifetch.dst_op(); } if(id.rsd) par { goto of0; relay ifetch.dst_op(); dp.change_opr(); } if(id.nof) par { goto if0; relay ex.tsk0(); } if(id.cco) par { goto cc0; } if(id.bra) par { goto br0; } if(id.dadd) par { rsub := 0b0; } if(id.dsub) par { rsub := 0b1; dp.reset_byte(); } if(id.unused) par { goto if0; dp.err(); relay trap.int_svc(); } } /* * Condition Code operation */ state cc0 par { dp.ccset(); goto if0; if(^TRACE & irq_in) relay trap.int_req(); if(TRACE) par { dp.bpt(); relay trap.int_svc(); } } /* * Branch */ state br0 par { dp.cctaken(); if(dp.taken) par { dp.pcALU1(); dp.ofs8ALU2(); dp.add(); dp.ALUpc(); } goto if0; if(^TRACE & irq_in) relay trap.int_req(); if(TRACE) par { dp.bpt(); relay trap.int_svc(); } } /* * Register read without Addressing mode. */ state of0 par { dp.regSEL(); dp.SELsrc(); dp.change_opr(); goto of1; } /* * Mode check */ state of1 any { (MODE == 0b00): par { if(ifetch.dst_op) dp.SELdst(); if(ifetch.src_op) dp.SELsrc(); dp.regSEL(); any { (INDR): goto of4; (ifetch.dst_op &^INDR): par { goto if0; relay ex.tsk0(); } (ifetch.src_op &^INDR): par { goto of1; relay ifetch.dst_op(); dp.change_opr(); } } } (MODE == 0b01): par { dp.regSEL(); dp.selALU1(); dp.ALUreg(); dp.setReg(); if( BYTE &^(INDR|SPPC) ) dp.inc(); if(^BYTE | (INDR|SPPC) ) dp.inc2(); if(ifetch.dst_op) dp.SELdst(); if(ifetch.src_op) dp.SELsrc(); goto of3; } (MODE == 0b10): par { dp.regSEL(); dp.selALU1(); dp.ALUreg(); dp.setReg(); if( BYTE &^(INDR|SPPC) ) dp.dec(); if(^BYTE | (INDR|SPPC) ) dp.dec2(); if(ifetch.dst_op) dp.ALUdst(); if(ifetch.src_op) dp.ALUsrc(); goto of3; } (MODE == 0b11): par { read(WORD); dp.dbaPC(); if(error) par { goto if0; dp.buserr(); relay trap.int_svc(); } if(fault) par { goto if0; dp.segerr(); relay trap.int_svc(); } if(RDY) par { dp.pcALU1(); dp.inc2(); dp.ALUpc(); if(ifetch.dst_op) dp.dbiDst(); if(ifetch.src_op) dp.dbiSrc(); goto of2; } } } /* * Computes effective adress in index mode. */ state of2 par { dp.regSEL(); dp.selALU1(); dp.add(); if(ifetch.dst_op) par { dp.dstALU2(); dp.ALUdst(); } if(ifetch.src_op) par { dp.srcALU2(); dp.ALUsrc(); } goto of3; } /* * First step memory read. Used by Auto-inc,dec,index mode. */ state of3 par { if( INDR) read(WORD); if(^INDR) read(BYTE); if(ifetch.dst_op) dp.dbaDst(); if(ifetch.src_op) dp.dbaSrc(); if(error) par { goto if0; dp.buserr(); relay trap.int_svc(); } if(fault) par { goto if0; dp.segerr(); relay trap.int_svc(); } if(RDY) par { if(ifetch.dst_op) par { dp.dbiDst(); dp.DSTadr(); } if(ifetch.src_op) par { dp.dbiSrc(); dp.SRCadr(); } any { (INDR): goto of4; (ifetch.dst_op &^INDR): par { goto if0; relay ex.tsk0(); } (ifetch.src_op &^INDR): par { goto of1; relay ifetch.dst_op(); dp.change_opr(); } } } } /* * Deferred instruction */ state of4 any { ifetch.dst_op: par { read(BYTE); dp.dbaDst(); if(error) par { goto if0; dp.buserr(); relay trap.int_svc(); } if(fault) par { goto if0; dp.segerr(); relay trap.int_svc(); } if(RDY) par { dp.DSTadr(); dp.dbiDst(); goto if0; relay ex.tsk0(); } } ifetch.src_op: par { read(BYTE); dp.dbaSrc(); if(error) par { goto if0; dp.buserr(); relay trap.int_svc(); } if(fault) par { goto if0; dp.segerr(); relay trap.int_svc(); } if(RDY) par { dp.SRCadr(); dp.dbiSrc(); goto of1; relay ifetch.dst_op(); dp.change_opr(); } } } }/* end of if */ stage ex { par { decop(); id.do(dp.opc); any { ^(error | fault): any { s0: relay ex.tsk0(); s1: relay ex.tsk1(); s2: relay ex.tsk2(); s3: relay ex.tsk3(); s4: relay ex.tsk4(); s5: relay ex.tsk5(); s6: relay ex.tsk6(); s7: relay ex.tsk7(); s8: relay ex.tsk8(); } error: par { dp.buserr(); relay trap.int_svc(); } fault: par { dp.segerr(); relay trap.int_svc(); } wback: relay wb.run(); svcall: relay trap.int_svc(); (ifrun &^TRACE &^irq_in): relay ifetch.run(); (ifrun &^TRACE & irq_in): relay trap.int_req(); (ifrun & TRACE &^id.drtt): par { dp.bpt(); relay trap.int_svc(); } (ifrun & TRACE & id.drtt): relay ifetch.run(); /* else: finish; */ } } }/* end of ex */ stage wb { state_name wb_s0; first_state wb_s0; state wb_s0 par { if(/|dp.opc<5:3>) par { write(BYTE); dp.dboDst(); dp.dbaAdr(); if(RDY &^TRACE &^irq_in) relay ifetch.run(); if(RDY &^TRACE & irq_in) relay trap.int_req(); if(RDY & TRACE) par { dp.bpt(); relay trap.int_svc(); } if(error) par { dp.buserr(); relay trap.int_svc(); } if(fault) par { dp.segerr(); relay trap.int_svc(); } } if(^/|dp.opc<5:3>) par { dp.DSTreg(); dp.setReg(); if(^TRACE &^irq_in) relay ifetch.run(); if(^TRACE & irq_in) relay trap.int_req(); if( TRACE) par { dp.bpt(); relay trap.int_svc(); } } } }/* end of wb */ stage trap { state_name trap0,trap1,trap2,trap3,trap4; first_state trap0; /* * STATE 0 * read interrupt address vector, and move it to SRC register * zero clear op-code * change current mode to kernel mode after saving status * keep PC to ADR register and PS to DST register */ state trap0 par { if(trap.int_req) par { int_ack(); dp.dbi = dati; dp.dbiSrc(); } if(trap.int_svc) par { } dp.reset_byte(); dp.kernel_mode(); dp.save_stat(); goto trap1; } /* * STATE 1 * memory read with address vector to PC * increment address vector */ state trap1 par { read(WORD); dp.dbaSrc(); /* vector */ if(RDY) par { dp.dbiPC(); dp.srcALU1(); dp.inc2(); dp.ALUsrc(); goto trap2; } } /* STATE 2 * memory read with address vector to PS * decrement SP to ready to push PS */ state trap2 par { read(WORD); dp.dbaSrc(); /* vector +2 */ if(RDY) par { dp.vectorPS(); dp.spALU1(); dp.dec2(); dp.ALUsp(); goto trap3; } } /* * STATE 3 * push PS * decrement SP to ready to push PC */ state trap3 par { dp.dboDst(); dp.dbaSP(); write(BYTE); if(RDY) par { dp.spALU1(); dp.dec2(); dp.ALUsp(); goto trap4; } } /* * STATE 4 * push PC */ state trap4 par { dp.dboAdr(); dp.dbaSP(); write(BYTE); if(RDY) par { goto trap0; relay ifetch.run(); } } }/* end of trap */ }/* end of pop11 */