Mano pdp8 BasicMano.cc
BasicMano.cc
// Basic Mano class // memory, registers and commands. #ifndef BASICMANO_CC #define BASICMANO_CC #ifndef INSTRUCTIONWORD_CC #include "InstructionWord.cc" #endif #ifndef STACK_CC #include "stack.cc" #endif #ifndef RAM_CC #include "RAM.cc" #endif #ifndef COUNTER_CC #include "counter.cc" #endif class BasicMano; ostream& operator << (ostream& OS, BasicMano &A); class BasicMano { // Main Memory RAM MainMemory; // Nine registers: InstructionWord InstructionWord_AC; // Accumulator InstructionWord InstructionWord_AR; // Address Register InstructionWord InstructionWord_DR; // Data Register InstructionWord InstructionWord_IR; // Instruction Register char OUTR; // Output Register char INPR; // Input Register unsigned int PC; // Program Counter InstructionWord InstructionWord_TR; // Temporary Register counter T_sequence_counter; // Using T_sequence_counter as a 0-15 counter, // dropped SC and the 4x16 decoder. // Seven flip-flops: short int I_flip_flop; short int S_flip_flop; short int E_flip_flop; short int R_flip_flop; short int IEN_flip_flop; short int FGI_flip_flop; short int FGO_flip_flop; // Control states short int D_flip_flop; // Indirection Control short int si_mIndirect; friend ostream& operator << (ostream& OS, BasicMano &A) { if( DEBUG ) cout << "Basic Mano: << 0 " << endl; OS << " Basic Mano Computer " << endl; OS << " Nine Registers" << endl; OS << " AC / Accumulator " << A.InstructionWord_AC << endl; OS << " AR / Address Register " << A.InstructionWord_AR << endl; OS << " DR / Data Register " << A.InstructionWord_DR << endl; OS << " INPR / Input Register" << A.INPR << endl; OS << " IR / Instruction Register" << A.InstructionWord_IR << endl; OS << " OUTR / Output Register" << A.OUTR << endl; OS << " PC / Program Counter" << A.PC << endl; OS << " SC / Sequence Counter" << A.T_sequence_counter << endl; OS << " TR / Temporary Register" << A.InstructionWord_TR << endl; OS << endl; OS << " Seven Flip-Flops" << endl; OS << " E " << A.E_flip_flop << endl; OS << " FGI " << A.FGI_flip_flop << endl; OS << " FGO " << A.FGO_flip_flop << endl; OS << " I " << A.I_flip_flop << endl; OS << " IEN " << A.IEN_flip_flop << endl; OS << " R " << A.R_flip_flop << endl; OS << " S " << A.S_flip_flop << endl; OS << endl; OS << " Control States" << endl; OS << " D " << A.D_flip_flop << endl; OS << endl; OS << " Main Memory" << endl; OS << A.MainMemory << endl; if( DEBUG ) cout << "Basic Mano: << 1 " << endl; return OS; } void Decode() { if( DEBUG ) cout << "Basic Mano: Decode 0 " << endl; D_flip_flop = InstructionWord_IR.getopcode(); } // end decode int Execute() { if( DEBUG ) cout << "Basic Mano: Execute 0 " << endl; T_sequence_counter++; if ( D_flip_flop == 7 ) return ExecuteRegIo(); else ExecuteMemRef(); return 1; } int ExecuteRegIo() { if( DEBUG ) cout << "Basic Mano: ExecuteRegIo 0 " << endl; if ( I_flip_flop && (T_sequence_counter.getcount() == 3)) { // execute I/O instruction switch ( InstructionWord_IR.getRcode() ) { case 1: IEN_flip_flop = 0; // IOF break; case 2: IEN_flip_flop =1; // ION break; case 4: if( FGO_flip_flop ) // SKO PC++; break; case 8: if( FGI_flip_flop ) // SKI PC++; break; case 16: OUTR = InstructionWord_AC.CellToDec(7); // OUT FGO_flip_flop = 0; break; case 32: InstructionWord_AC.DecToCell( (short) INPR ); // INP FGI_flip_flop = 0; break; default: ; } } if( (I_flip_flop == 0) && (T_sequence_counter.getcount() == 3)) { // execute register-reference instruction switch( InstructionWord_AR.getopcode() ) { case 0: S_flip_flop = 0; // HLT T_sequence_counter.clear(); return 0; break; case 1: if (E_flip_flop == 0) // SZE PC++; break; case 2: if( InstructionWord_AC.CellToDec() == 0) // SZA PC++; break; case 3: if( InstructionWord_AC.getIcode() ) // SNA PC++; break; case 4: if( InstructionWord_AC.getIcode() == 0 ) // SPA PC++; break; case 5: InstructionWord_AC.increment(); // INC break; case 6: InstructionWord_AC.circulateleft( E_flip_flop ); // CIL break; case 7: InstructionWord_AC.circulateright( E_flip_flop ); // CIR break; case 8: ~E_flip_flop; // CME break; case 9: InstructionWord_AC.COMPLEMENT(); // CMA break; case 10: E_flip_flop = 0; // CLE break; case 11: InstructionWord_AC.clear(); // CLA break; default: ; } } T_sequence_counter.clear(); return 1; } void ExecuteMemRef() { if( DEBUG ) cout << "Basic Mano: ExecuteMemRef 0 " << endl; if ( I_flip_flop && (T_sequence_counter.getcount() == 3)) { InstructionWord_AR = MainMemory.returncurrent(); // execute I/O } if ((I_flip_flop == 0) && (T_sequence_counter.getcount() == 3)) { // execute memory-reference switch ( D_flip_flop ) { case 0: { InstructionWord mem_Temp = MainMemory.returncurrent( ); // AND InstructionWord_AC.AND( mem_Temp ); } break; case 1: LoadDR(); // ADD InstructionWord_AC.ADD( InstructionWord_DR , E_flip_flop ); T_sequence_counter.clear(); break; case 2: LoadDR(); // LDA InstructionWord_AC = InstructionWord_DR; T_sequence_counter.clear(); break; case 3: { InstructionWord mem_Temp; // STA mem_Temp.setlocation( InstructionWord_AR.returndata() ); mem_Temp.setdata( InstructionWord_AC.returndata() ); MainMemory.LoadCell( mem_Temp ); T_sequence_counter.clear(); } break; case 4: PC = InstructionWord_AR.returndata(); // BUN T_sequence_counter.clear(); break; case 5: // BSA break; case 6: // ISZ T_sequence_counter.clear(); break; case 7: break; default: ; } } T_sequence_counter.clear(); } void Fetch() { if( DEBUG ) cout << "Basic Mano: Fetch 0 " << endl; if( LoadAR() && (T_sequence_counter.getcount() == 1) ) { if( DEBUG ) cout << "Basic Mano: Fetch 1 " << endl; MainMemory.locate( InstructionWord_AR ); InstructionWord_IR = MainMemory.returncurrent(); cout << "Basic Mano: Fetch 2, InstructionWord_IR is " << InstructionWord_IR << endl; PC++; T_sequence_counter++; } } short LoadAR() { if( DEBUG ) cout << "Basic Mano: LoadAR 0 " << endl; if( T_sequence_counter.getcount() ) return 0; InstructionWord_AR = PC; T_sequence_counter++; return 1; } void LoadDR() { if( DEBUG ) cout << "Basic Mano: LoadDR 0 " << endl; T_sequence_counter++; InstructionWord_DR = MainMemory.returncell( InstructionWord_AR ); } public: BasicMano() { OUTR = '\0'; INPR = '\0'; D_flip_flop = 0; I_flip_flop = 0; S_flip_flop = 0; E_flip_flop = 0; R_flip_flop = 0; IEN_flip_flop = 0; FGI_flip_flop = 0; FGO_flip_flop = 0; PC = 0; si_mIndirect = 0; } BasicMano(const BasicMano &V) { InstructionWord_AC = V.InstructionWord_AC; InstructionWord_AR = V.InstructionWord_AR; InstructionWord_DR = V.InstructionWord_DR; InstructionWord_IR = V.InstructionWord_IR; OUTR = V.OUTR; INPR = V.INPR; InstructionWord_TR = V.InstructionWord_TR; PC = V.PC; D_flip_flop = V.D_flip_flop; I_flip_flop = V.I_flip_flop; S_flip_flop = V.S_flip_flop; E_flip_flop = V.E_flip_flop; R_flip_flop = V.R_flip_flop; IEN_flip_flop = V.IEN_flip_flop; FGI_flip_flop = V.FGI_flip_flop; FGO_flip_flop = V.FGO_flip_flop; si_mIndirect = V.si_mIndirect; MainMemory = V.MainMemory; } ~BasicMano(){} int LoadMano( InstructionWord mem_NewCell ) { if( DEBUG ) cout << "Basic Mano: LoadMano 0 " << endl; return MainMemory.LoadCell( mem_NewCell ); } void reset() { if( DEBUG ) cout << "Basic Mano: Reset 0 " << endl; D_flip_flop = 0; I_flip_flop = 0; S_flip_flop = 0; E_flip_flop = 0; R_flip_flop = 0; IEN_flip_flop = 0; FGI_flip_flop = 0; FGO_flip_flop = 0; T_sequence_counter.clear(); OUTR = '\0'; INPR = '\0'; MainMemory.erase(); } void run() { if( DEBUG ) cout << "Basic Mano: Run 0 " << endl; do { cout << "Basic Mano: Run 1 " << endl; T_sequence_counter.clear(); Fetch(); // Fetch instruction Decode(); // Decode instruction InstructionWord_AR = InstructionWord_IR.CellToDec(); // load raw address I_flip_flop = InstructionWord_IR.getIcode(); // get indirect flag } while( Execute() ); // Execute Instruction } }; #endif // BasicMano_CC
Internal Links
Parent Article: Mano PDP-8 Simulation Project Source Code