CPU -Simulation
Dieses Projekt ist ein einfaches Computersystem, das aus einer CPU und einem Speicher besteht. Die CPU und der Speicher werden durch separate Prozesse simuliert, die kommunizieren. Der Speicher enthält ein Programm, das die CPU ausführt und dann die Simulation endet.
Für CPU:
- Es wird diese Register haben: PC, SP, IR, AC, X, Y.
- Es unterstützt die unten angegebenen Anweisungen.
- Es wird das Benutzerprogramm unter Adresse 0 ausgeführt.
- Anweisungen werden aus dem Gedächtnis in den IR eingereicht. Der Operand kann in eine lokale Variable abgerufen werden.
- Jede Anweisung sollte ausgeführt werden, bevor die nächste Anweisung abgerufen wird.
- Der Benutzerstapel befindet sich am Ende des Benutzerspeichers und wächst zu der Adresse 0.
- Der Systemstapel befindet sich am Ende des Systemspeichers und wächst in Richtung der Adresse 0.
- Es gibt keine Hardware -Durchsetzung der Stapelgröße.
- Das Programm endet, wenn die Endanweisung ausgeführt wird. Die 2 Prozesse sollten zu diesem Zeitpunkt enden.
- Das Benutzerprogramm kann nicht auf den Systemspeicher zugreifen (beendet mit der Fehlermeldung).
Für Gedächtnis:
- Es besteht aus 2000 Ganzzahleinträgen, 0-999 für das Benutzerprogramm, 1000-1999 für den Systemcode.
- Es unterstützt zwei Vorgänge: Read (Adresse) - Gibt den Wert an der Adresse zurück; Schreiben (Adresse, Daten) - schreibt die Daten an die Adresse
- Der Speicher wird sich durch Lesen einer Programmdatei initialisieren.
Für Timer:
- Ein Timer unterbricht den Prozessor nach jeder X-Anleitung, wobei x ein Befehlszeilenparameter ist.
Für die Interrupt -Verarbeitung:
- Es gibt zwei Formen von Interrupts: den Timer und einen Systemaufruf unter Verwendung der INT -Anweisung.
- In beiden Fällen sollte die CPU den Kernel -Modus eingeben.
- Der Stapelzeiger sollte auf den Systemstapel umgestellt werden.
- SP- und PC -Register sollten auf dem Systemstapel gespeichert werden. (Der Handler kann zusätzliche Register retten).
- Ein Timer -Interrupt sollte eine Ausführung unter der Adresse 1000 verursachen.
- Die INT -Anweisung sollte eine Ausführung unter der Adresse 1500 verursachen.
- Interrupts sollten während der Interrupt -Verarbeitung deaktiviert werden, um eine verschachtelte Ausführung zu vermeiden.
- Die IRET -Anweisung kehrt von einem Interrupt zurück.
Anweisungssatz:
-> 1 = Lastwert # Laden Sie den Wert in den AC
-> 2 = laden addr # laden Sie den Wert an der Adresse in den AC
-> 3 = loadind addr # laden Sie den Wert aus der in der angegebenen Adresse gefundene Adresse in den AC. (Wenn Sie beispielsweise 500 und 500 100 enthält, laden Sie von 100).
-> 4 = loadIDXX addr # laden Sie den Wert bei (Adresse+x) in den AC. (Wenn Sie beispielsweise loadIDXX 500 und x 10 enthalten, laden Sie von 510).
-> 5 = loadIdxy addr # laden Sie den Wert bei (Adresse+y) in den AC
-> 6 = loadspx # last von (sp+x) in den AC (wenn sp 990 ist und x 1, last von 991).
-> 7 = Speichern addr # Speichern Sie den Wert in der AC in die Adresse
-> 8 = Get # erhält einen zufälligen int von 1 bis 100 in die AC
-> 9 = port # if port = 1, schreibt AC als int auf den Bildschirm; Wenn Port = 2, schreibt AC als Zeichen auf den Bildschirm
-> 10 = addx # Fügen Sie den Wert in x zum AC hinzu
-> 11 = Addy # den Wert in y zum ac hinzufügen
-> 12 = Subx # Subtrahieren Sie den Wert in x vom AC
-> 13 = suby # subtrahieren Sie den Wert in y vom AC
-> 14 = CopyTox # Kopieren Sie den Wert im Wechselstrom nach x
-> 15 = CopyFromx # Kopieren Sie den Wert in x zum AC
-> 16 = CopyToy # Kopieren Sie den Wert im Wechselstrom zu y
-> 17 = CopyFromy # Kopieren Sie den Wert in y auf den AC
-> 18 = COPYTOSP # Kopieren Sie den Wert in AC zum SP
-> 19 = CopyFromsp # Kopieren Sie den Wert in SP zum AC
-> 20 = Sprung addr # springen zur Adresse springen
-> 21 = Jumpifequal ADDR # Springen Sie nur dann zur Adresse, wenn der Wert im Wechselstrom Null ist
-> 22 = Jumpifnotequal ADDR # Springen Sie nur dann zur Adresse, wenn der Wert im Wechselstrom nicht Null ist
-> 23 = Ruf AddR # Push-Rückgabeadresse auf Stack, springen Sie zur Adresse
-> 24 = Ret # Pop-Rendite-Adresse aus dem Stapel, springen Sie an die Adresse
-> 25 = Incx # Inkrementieren Sie den Wert in x
-> 26 = Decx # Deaktivieren Sie den Wert in x
-> 27 = Push # Push AC auf Stapel drücken
-> 28 = Pop # Pop vom Stack in AC
-> 29 = int # Systemanruf ausführen
-> 30 = IRET # Return From System Call
-> 50 = Ende # Endausführung
===============================================================================
Der Beispielordner enthält 5 Beispieldatei.
Sample1.txt
- Tests die indizierten Lastanweisungen.
- Druckt zwei Tische, einer von AZ, der andere von 1-10.
Sample2.txt
- Testen Sie die Anruf-/Ret -Anweisungen.
- Druckt ein Gesicht, in dem die Linien mit Unterroutine -Aufrufen gedruckt werden.
Sample3.txt
- Tests die Int/Iret -Anweisungen.
- Die Hauptschleife druckt den Buchstaben A, gefolgt von einer Zahl, die vom Timer regelmäßig erhöht wird.
- Die Zahl wird schneller gesteigert, wenn der Timerzeitraum kürzer ist.
Sample4.txt
- Testen Sie den ordnungsgemäßen Betrieb des Benutzerstapels und des Systemstapels sowie testet, dass der Zugriff auf den Systemspeicher im Benutzermodus einen Fehler und die Beendigung ergibt.
Sample5.txt
- Dies ist eine, die Sie erstellen sollten. Stellen Sie sicher, dass Sie Kommentare eingeben, damit der Grader weiß, was das Programm tut.
===============================================================================
Schritt zum Kompilieren und Ausführen des Projekts:
- S1: Kopieren Sie die Quelldateien in Linux -System.
- S2: Ändern Sie die direkten in Quelldateien
- S3: Führen Sie den folgenden Befehl aus: GCC -Speicher.c cpu.c Simulator.c
- S4: Führen Sie das Programm aus: ./a.out
- S5: Geben Sie gemäß den Ausgabeinformationen den Timer -Parameter X ein, den Sie ausführen möchten. Jeder Element endet mit "Enter". ZB: 10 ( n) Sample2.txt
- S6: Wiederholen Sie S4 für die verbleibenden Beispiel -Testdateien, um die verschiedenen Ausgänge zu erhalten