500 lines
20 KiB
HTML
500 lines
20 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<!-- Basic Page Needs
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<meta charset="utf-8" />
|
||
<title>Johnny Simulator</title>
|
||
<meta name="description" content="Web based Johhny-Simulator" />
|
||
<meta name="author" content="Christian" />
|
||
|
||
<!-- Mobile Specific Metas
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||
|
||
<!-- CSS
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<link rel="stylesheet" href="css/normalize.css" />
|
||
<link rel="stylesheet" href="css/skeleton.css" />
|
||
<link rel="stylesheet" href="css/cookie.css" />
|
||
<link rel="stylesheet" href="css/colors-light.css">
|
||
<link rel="stylesheet" href="css/colors-dark.css">
|
||
<link rel="stylesheet" href="css/loader.css" />
|
||
<link rel="stylesheet" href="css/pc.css" />
|
||
<link rel="stylesheet" href="css/style.css" />
|
||
|
||
<!-- Favicon
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<!-- <link rel="icon" type="image/png" href="images/favicon.png" /> -->
|
||
</head>
|
||
|
||
<body>
|
||
<!-- Primary Page Layout
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<div id="elm">
|
||
<div class="noscript">Sorry, but this app needs Javascript to run :/</div>
|
||
</div>
|
||
|
||
<div class="spacer"></div>
|
||
|
||
<section class="container fullheight">
|
||
<div id="langPicker">
|
||
<button id="langPickerDE">German</button>
|
||
<button id="langPickerEN">English</button>
|
||
</div>
|
||
<div id="langDE" class="hidden">
|
||
<h1>Wie diese App funktioniert</h1>
|
||
<p>
|
||
Hallo, schön dass du dir diese Seite anschaust.<br>
|
||
Damit du besser verstehst, wie diese Anwendung funktioniert, hier einmal die Basics:
|
||
</p>
|
||
|
||
<h2>Kontrollknöpfe</h2>
|
||
<p>
|
||
Ganz oben findest du eine Reihe mit Kontrollknöpfen. Jeder Knopf hat seine eigene Funktion.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<b>µCycle</b>
|
||
Mit diesem Knopf kannst du einen einzelnen Schritt im µCode ausführen.
|
||
</li>
|
||
<li>
|
||
<b>Instruction</b>
|
||
Hiermit kannst du eine ganze Instruktion ausführen lassen und musst nicht durch jeden µCode Schritt einzeln durchdrücken.
|
||
</li>
|
||
<li>
|
||
<b>Reset PC</b>
|
||
Damit kannst du den PC zurücksetzten. Dabei bleibt der RAM und der µCode erhalten.
|
||
</li>
|
||
<li>
|
||
<b>Autoscroll</b>
|
||
Nachdem im RAM oder im µCode ein anderer Eintrag ausgewählt wurde, kann automatisch zum Eintrag gescrollt werden
|
||
</li>
|
||
<li>
|
||
<b>Configs</b>
|
||
Hier können sie die momentane Konfiguration herunterladen, selber eine Hochladen oder aus einer Liste von Beispielen laden.
|
||
</li>
|
||
</ul>
|
||
|
||
<h2>Bausteine</h2>
|
||
<p>
|
||
Der Computer ist in mehrere Bausteine aufgeteilt. Jeder Baustein hat eine eigene spezielle Funktion. Ein echter Computer ist natürlich deutlich komplizierter, aber so ist der PC deutlich verständlicher.
|
||
</p>
|
||
|
||
<h3>RAM</h3>
|
||
<p>
|
||
Im Arbeitsspeicher wird das Programm gespeichert. Jeder Eintrag ist dabei in ein Low-Byte und ein High-Byte unterteilt. Dadurch kann man in einem Eintrag die Instruktion und Adresse einfacher unterscheiden.<br>
|
||
<a href="#befehl">Siehe Befehle</a>
|
||
</p>
|
||
|
||
<h3>Control Unit</h3>
|
||
<p>
|
||
Wie der Name es schon sagt, steuert und verwaltet die Control Unit alle Vorgänge im Computer. Das passiert dadurch, dass eine Instruktion in viele kleine µCodes aufgeteilt wird.
|
||
</p><p>
|
||
Diese µCodes sind in der Tabelle aufgeführt. Jede Instruktion besteht hier aus bis zu 10 µCodes. <br>
|
||
Bei einem Befehl z.B. <code>001 00000</code> ist die Instruktion in den ersten drei Stellen zu finden. Dieser Wert wird dann mit 10 multipliziert und in den µCode Counter geladen. <br>
|
||
In diesem Fall stände dann <code>0010</code> im Counter.<br>
|
||
In der Tabelle sind dann alle Befehle für die Instruktion <code>001</code> zu finden.
|
||
</p>
|
||
<h3>ALU</h3>
|
||
<p>
|
||
Die Arithmetik Logic Unit ist hier sehr einfach aufgebaut.
|
||
</p>
|
||
<p>
|
||
Sie kann den Akkumulator nur erhöhen oder erniedrigen. Dafür können Werte aber direkt vom Datenbus geladen werden.
|
||
</p>
|
||
<h3>Datenbus</h3>
|
||
<p>
|
||
Über den Datenbus können Daten und Befehle zwischen RAM, Control Unit und ALU übertragen werden.
|
||
</p>
|
||
<h3>Adressbus</h3>
|
||
<p>
|
||
Über diesen Bus kann die Control Unit steuern, welcher Wert im RAM ausgewählt wird.<br>
|
||
Bei normalen Rechnern sind hier natürlich noch deutlich mehr Werte angeschlossen.
|
||
</p>
|
||
|
||
<a id="befehl"></a>
|
||
<h2>Befehle</h2>
|
||
<p>
|
||
Ein Befehl besteht aus einer Instruktion und einem Argument. Deshalb sind im RAM und im Instruction Register alle Werte separiert.
|
||
</p>
|
||
<pre><code>0 0 2 0 0 5 0 4
|
||
Instr Argument
|
||
</code></pre>
|
||
<p>
|
||
In den ersten 3 Stellen wird hier der OpCode der Instruction codiert. Wenn dieser Teil in der Control Unit in den µCode Counter geladen wird, dann wird der OpCode mit 10 multipliziert.
|
||
</p>
|
||
<p>
|
||
In den letzten 5 Stellen wird ein beliebiger Zahlenwert gespeichert. Dieser kann als Argument für einen Befehl genutzt werden.
|
||
</p>
|
||
<p>
|
||
In diesem Beispiel hier würden die µCodes ab Adresse 20 im µCode Speicher ausgeführt werden.
|
||
</p>
|
||
|
||
<h2>µCodes</h2>
|
||
<p>
|
||
Eine Instruktion kann nicht direkt ausgeführt werden. Deshalb wird sie durch mehrere kleine Befehle, sog. µCodes zusammengesetzt.
|
||
</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>µCode</th>
|
||
<th>Beschreibung</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>ProgCounter -> AddrBus</td>
|
||
<td>Lade den Wert des Programm Counters in den Adressbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstrReg -> ProgCounter</code></td>
|
||
<td>Lade das Argument des Instruktionsregisters in den Programm Counter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ProgCounter ++</td>
|
||
<td>Erhöhe den Wert des Programm Counter um 1</td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc == 0 => InstReg -> ProgCounter</code></td>
|
||
<td>Wenn der Wert des Akkumulators 0 ist, dann lade das Argument des Instruktionsregisters in den Programm Counter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Ram -> DataBus</code></td>
|
||
<td>Schreibe den aktuellen Wert aus den RAM auf den Datenbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> Ram</code></td>
|
||
<td>Schreibe den Wert des Datenbus in die momentane Stelle des RAM</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> InstReg</code></td>
|
||
<td>Lade den Befehl vom Datenbus in das Instruktionsregister</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> Acc</code></td>
|
||
<td>Lade den Wert vom Datenbus in den Akkumulator der ALU</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc -> DataBus</code></td>
|
||
<td>Schreibe den Wert vom Akkumulator auf den Datenbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc ++</code></td>
|
||
<td>Erhöhe den Wert des Akkumulators um 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc --</code></td>
|
||
<td>Verringere den Wert des Akkumulators um 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc << DataBus</code></td>
|
||
<td>Verschiebt den Wert im Akkumulator nach links um den Wert im DatenBus.</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc >> DataBus</code></td>
|
||
<td>Verschiebt den Wert im Akkumulator nach rechts um den Wert im DatenBus.</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc + DataBus</code></td>
|
||
<td>Addiere den Wert im Datenbus auf den Akkumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc - DataBus</code></td>
|
||
<td>Subtrahiere den Wert im Datenbus auf den Akkumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc * DataBus</code></td>
|
||
<td>Multipliziere den Wert im Datenbus mit dem Akkumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc / DataBus</code></td>
|
||
<td>Dividiere den Akkumulator durch den Datenbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc AND DataBus</code></td>
|
||
<td>Führe bitweise UND auf Akkumulator mit Datenbus aus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc OR DataBus</code></td>
|
||
<td>Führe bitweise ODER auf Akkumulator mit Datenbus aus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc XOR DataBus</code></td>
|
||
<td>Führe bitweise XOR auf Akkumulator mit Datenbus aus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc NOT DataBus</code></td>
|
||
<td>Führe bitweise NOT auf Akkumulator mit Datenbus aus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> µCounter</code></td>
|
||
<td>Nehme das Argument des Befehls im Instruktionsregister, füge am Ende eine 0 an und Lade ihn in den µCounter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> AddrBus</code></td>
|
||
<td>Lade das Argument im Instruktionsregister in den Adressbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> DataBus</code></td>
|
||
<td>Lade das Argument im Instruktionsregister in den Adressbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>µCounter = 0</code></td>
|
||
<td>Setzte den µCounter zurück</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Signal End of Program</code></td>
|
||
<td>Zeigt ein Popup, dass das Ende des Programms signalisiert.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h1>Source</h1>
|
||
<p>
|
||
Das hier ist ein kleines Hobbyprojekt. Meine Implementation ist also nur mit Vorsicht als "best-practice" Vorlage zu verwenden.
|
||
</p>
|
||
<a href="https://git.yokta.de/Christian/Johnny" class="button">Zum Source Code</a>
|
||
<p>
|
||
Dieses Projekt ist angelehnt an den <a href="https://sourceforge.net/projects/johnnysimulator/" target="_blank">Johnny-Simulator</a>.
|
||
</p>
|
||
</div>
|
||
<div id="langEN">
|
||
<h1>How this App works</h1>
|
||
<p>
|
||
Hello. In order for you to understand what this App does, I want to show you some basics of this app.
|
||
</p>
|
||
|
||
<h2>Control Buttons</h2>
|
||
<p>
|
||
At the top of the application you can see a row of control buttons:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<b>µCycle</b>
|
||
With this button you can execute a single µCode Step.
|
||
</li>
|
||
<li>
|
||
<b>Instruction</b>
|
||
This button executes a whole instruction at a time. This way you don't have to press µCycle all the time.
|
||
</li>
|
||
<li>
|
||
<b>Reset PC</b>
|
||
With this, you can reset the pc. Please note that ram und µCodes are not reset.
|
||
</li>
|
||
<li>
|
||
<b>Autoscroll</b>
|
||
After a value in RAM or in the µCodes is selected you can automatically scroll to them
|
||
</li>
|
||
<li>
|
||
<b>Configs</b>
|
||
Download the current config, import a config from your machine or choose an example.
|
||
</li>
|
||
</ul>
|
||
|
||
<h2>Blocks</h2>
|
||
<p>
|
||
This computer is made up by multiple blocks like any other neumann-maschiene. Every block has it's own unique set of functions. A normal computer is much more complex than this, but the principle is the same.
|
||
</p>
|
||
|
||
<h3>RAM</h3>
|
||
<p>
|
||
The current program is stored in the RAM. Every entry is separated as mentioned in <a href="#entry">entry</a>.
|
||
</p>
|
||
|
||
<h3>Control Unit</h3>
|
||
<p>
|
||
As the name suggests, the control unit manages everything that is done. To know what needs to be done it has a list of µCodes that gets executed when a instruction is requested.
|
||
</p><p>
|
||
These µCodes can be found in the table. Every instruction consists of up to 10 µCodes. <br>
|
||
When a entry is executed, the first three digits (the instruction) gets multiplied by 10. This now is written into the µCounter and the µCodes for it get's executed.
|
||
</p><p>
|
||
Example:<br>
|
||
When the entry <code>001 00000</code> gets executed, the µCounter would be set to <code>0010</code>. Now every µCode starting at location <code>0010</code> in the µCodes gets executed.
|
||
</p>
|
||
<h3>ALU</h3>
|
||
<p>
|
||
The Arithmetic Logic Unit is pretty simple in this case.
|
||
</p>
|
||
<p>
|
||
The ALU can only increment or decrement the accumulator. But it can read numbers from databus.
|
||
</p>
|
||
<h3>Databus</h3>
|
||
<p>
|
||
Via the databus values and entries can be transported between RAM, Control Unit and ALU.
|
||
</p>
|
||
<h3>Addressbus</h3>
|
||
<p>
|
||
With the addressbus the Control Unit can control which value is selected in RAM. On a normal computer there are a lot more things attached to this bus.
|
||
</p>
|
||
|
||
<a id="entry"></a>
|
||
<h2>Entry</h2>
|
||
<p>
|
||
Each entry consists of a instruction and an argument. That's why the entrys in RAM and in µCodes are displayed separately.
|
||
<pre><code>0 0 2 0 0 5 0 4
|
||
Instr Argument
|
||
</code></pre>
|
||
|
||
<p>
|
||
Here, the first 3 digits are the opCode of the instruction. When you try to load this part into the µCode Counter of the Control Unit, it will be automatically multiplied by 10.
|
||
<br>
|
||
In this example µCodes starting at the Address 20 will be executed.
|
||
</p>
|
||
<p>
|
||
The last 5 digits are a numerical value that can be used as an argument for the command.
|
||
</p>
|
||
|
||
<h2>µCodes</h2>
|
||
<p>
|
||
Every instruction consists of a list of µCodes. Here is an explanation for all of them:
|
||
</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>µCode</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>ProgCounter -> AddrBus</code></td>
|
||
<td>Load the value from program counter to addressbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstrReg -> ProgCounter</code></td>
|
||
<td>Load the argument from instruction register to program counter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>ProgCounter ++</code></td>
|
||
<td>Increment program counter by 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc == 0 => InstReg -> ProgCounter</code></td>
|
||
<td>If the accumulator is 0 then write the argument from instruction register to program counter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Ram -> DataBus</code></td>
|
||
<td>Load selected value from RAM to databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> Ram</code></td>
|
||
<td>Write value from databus to selected value in RAM</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> InstReg</code></td>
|
||
<td>Write entry from databus to instruction register</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>DataBus -> Acc</code></td>
|
||
<td>Write value from databus to accumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc -> DataBus</code></td>
|
||
<td>Load value from accumulator to databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc ++</code></td>
|
||
<td>Increment accumulator by 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc --</code></td>
|
||
<td>Decrement accumulator by 1</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc << DataBus</code></td>
|
||
<td>Shift the Accumulator left by the value in databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc >> DataBus</code></td>
|
||
<td>Shift the Accumulator right by the value in databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc + DataBus</code></td>
|
||
<td>Add the value of the databus to the accumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc - DataBus</code></td>
|
||
<td>Subtract the value of the databus from the accumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc * DataBus</code></td>
|
||
<td>Multiply the value of the databus with the accumulator</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc / DataBus</code></td>
|
||
<td>Divide the accumulator by the value of the databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc AND DataBus</code></td>
|
||
<td>Do a bitwise AND to accumulator with the value of the databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc OR DataBus</code></td>
|
||
<td>Do a bitwise OR to accumulator with the value of the databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc XOR DataBus</code></td>
|
||
<td>Do a bitwise XOR to accumulator with the value of the databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Acc NOT DataBus</code></td>
|
||
<td>Do a bitwise NOT to accumulator with the value of the databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> µCounter</code></td>
|
||
<td>Take the instruction from instruction register, add a 0 at the tail and write it to µCounter</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> AddrBus</code></td>
|
||
<td>Write the argument from instruction register to addressbus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>InstReg -> DataBus</code></td>
|
||
<td>Write the argument from instruction register to databus</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>µCounter = 0</code></td>
|
||
<td>Set µCounter to 0</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>Signal End of Program</code></td>
|
||
<td>Show an alert that the end of program is reached.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h1>Source</h1>
|
||
<p>
|
||
This is a hobby project so please don't take my code as a "best-practice" implementation.<br>
|
||
</p>
|
||
<a href="https://git.yokta.de/Christian/Johnny" class="button">See Source Code</a>
|
||
<p>
|
||
This project is my take on <a href="https://sourceforge.net/projects/johnnysimulator/" target="_blank">Johnny-Simulator</a>.
|
||
</p>
|
||
</div>
|
||
|
||
|
||
</section>
|
||
|
||
<footer>
|
||
<div class="container">
|
||
<p>
|
||
Made with ☕ <br>
|
||
© <a href="https://github.com/ChrisgammaDE" target="_blank">Christian</a>, 2022
|
||
</p>
|
||
<p>
|
||
<a href="https://yokta.de/i/impressum.html" target="_blank">Impressum</a>
|
||
</p>
|
||
</div>
|
||
</footer>
|
||
|
||
<!-- End Document
|
||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||
<script src="js/elm.js"></script>
|
||
<script src="js/cookie.js"></script>
|
||
<script src="js/pc.js"></script>
|
||
<script src="js/script.js"></script>
|
||
</body>
|
||
</html>
|