Laden...

Proof of Concept: CPU-Simulator

Erstellt von tscherno vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.031 Views
tscherno Themenstarter:in
630 Beiträge seit 2007
vor 16 Jahren
Proof of Concept: CPU-Simulator

Hallo,

habe gerade wieder dieses "Projekt" in meinem Projektordner gefunden. Es ist schon über ein Jahr alt, und da dachte ich mir das es hier vieleicht jemanden interessieren könnte.

Damals habe ich mir Gedanken darüber gemacht, wie ich eine CPU-Simulator implementieren würde.

Erwartet nichts grosses, die CPU die im Moment simuliert wird hat einen Speicher von 255 Byte welcher intern als byte[] dargestellt wird. Es sind zwei 8-Bit Register (a und b) verfügbar. Ansonsten kann man nur Werte aus dem Speicher in die Register laden, einen Sprung ausführen (0x01), sowie die CPU stoppen (0xFF).

Desweiteren ist die Simulation der dauer von Maschienenzyklen vorgesehen (Cycling(int))
aber noch nicht implementiert.

Dieser Quelltext ist wirklich nur ein Dump aus meinem Gehirn d.h ich habe nicht besonders auf gutes Design geachtet.

Das Programm das ausgeführt werden soll ist in der Methode ProgramInit() in Form einer Array-Zuweisung "hart kodiert."

Benutzen könnt ihr die Klasse wie folgt:


Console.WriteLine("PC\tOPCODE\t \tDESC");
Console.WriteLine("**\t******\t*\t****");
cpu Test = new cpu();
Test.ProgInit();  //Programm in Speicher laden
Test.Run();       //CPU starten

Hier der eigentliche Simulator:



/* Proof of Concept: Very Basic CPU simulation in C# 
 */
using System;
namespace TestEmu
{
    /* Machine Data:
     * 
     * 
     * Memory: 255 Bytes flat adressed
     * Registers: 2 8-Bit registers
     * 
     * Implemented Opcodes: 
     * 
     * 0x01 Unconditional jump (Size 2 Bytes (OpCode,Target Adress)
     * 0x02 Move value to register a (Size 2 Bytes Byte1=OpCode, Byte2=Value)
     * 0x03 Move value to register b (Size 2 Bytes Byte1=OpCode, Byte2=Value)
     * 0xFF Shutdown CPU
     * 
     */

    class cpu
    {

        //Basics (Emulation) 
        byte[] Memory = new byte[255];  //Memory
        byte PC = 0x0;                  //Program Counter 
        byte OpCode = 0x0;              //Current Opcode
        //Controles
        bool CPURun = true;               //Cpu runs while this is true

        #region Testprogram
        /// <summary>
        /// Program for the simulator is hardcoded here.
        /// Call this to load the program in to the memory-array
        /// </summary>
        public void ProgInit()
        {
            //Copy 24 to register A, jump to Adress 0x45 
            //Copy 58 to register B then halt CPU
            Memory[0x00] = 0x00;
            Memory[0x01] = 0x02;   //Copy to A
            Memory[0x02] = 0x18;   //DEZ:24
            Memory[0x03] = 0x01;  //Jump command
            Memory[0x04] = 0x45;  //Jump adress
            //****
            Memory[0x45] = 0x00;  
            Memory[0x46] = 0x03; //Copy to b
            Memory[0x47] = 0x3A; //DATA (Value);
            Memory[0x48] = 0xFF; //HALT
            
        }
        #endregion

        #region Registers


        byte a = 0;    //Register A
        byte b = 0;    //Register B
        byte aku = 0; //Akkumulator

        #endregion



        public void Run()
        {
            while (CPURun)
            {
                Fetch();    //Fetch Next Instruction
                Execute();  //Execute it
                PC++;        //Inkrement Programcounter to next Memory Adress
            }
        }


        /// <summary>
        /// Execute Cycle
        /// </summary>
        /// <param name="cycles">Number of Cycles</param>
         void Cycling(int cycles)
        {
            //Implements one machine cycle here ;)

            //Do Cyclic Tasks here, (Interrupt Handling, Screenrefresh...)

        }
        /// <summary>
        /// Execute OpCode
        /// </summary>
        void Execute()
        {
            switch (OpCode)
            {
                case 0x0:
                    {
                        //Do Nothing (NOP)
                        DebugWrite(0x0,"NOP");
                        Cycling(1);  //Cycling Action (Screen Refresh, Int Handling etc.)
                        break;

                    }
                case 0x1:
                    {
                        //Jump to 
                        PC = Memory[PC+1]; //Get Adress from Second Byte
                        
                        
                        DebugWrite(0x1,"JMP");
                        Cycling(1);  //Cycling Action (Screen Refresh, Int Handling etc.)
                        break;
                    }
                  
                case 0x2:
                    {   
                        //Move Value to A
                        PC++;
                        a = Memory[PC];
                        Cycling(1);  //Cycling Action (Screen Refresh, Int Handling etc.)
                        DebugWrite(0x2, "Move "+PC+1+" to Register A");
                        break;
                    }
                case 0x3:
                    {
                        //Move Value to B
                        PC++;
                        b = Memory[PC];
                        Cycling(1);  //Cycling Action (Screen Refresh, Int Handling etc.)
                        DebugWrite(0x2, "Move " + PC + 1 + " to Register B");
                        break;

                    }
                case 0xFF:
                    {
                        //Shutdown Processor
                        CPURun = false;
                        Cycling(1);  //Cycling Action (Screen Refresh, Int Handling etc.)
                        DebugWrite(0xFF, "HALT");
                        break;
                    }
            }

        }
        /// <summary>
        /// Fetch next OpCode
        /// </summary>
        void Fetch()
        {
            OpCode = Memory[PC];  //Get OpCode from PC Adress
        }

        /// <summary>
        /// Write Debug Message to Console
        /// </summary>
        /// <param name="Adress">Adress</param>
        /// <param name="Message">Message</param>
        void DebugWrite(byte Adress,string Message)
        {
            const string DEBUG_OUT = "0x{0:X2}\t:\t{1}";
            Console.WriteLine("@"+PC+"\t"+DEBUG_OUT,Adress,Message);

        }

        }
    }


Viel Spass 😉

To understand recursion you must first understand recursion

http://www.ilja-neumann.com
C# Gruppe bei last.fm