Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - Sannaj

Seiten: 1 [2] 3 4 ... 6
21
Kann es sein, dass dein Programm mit den Adressen durcheinander kommt. Das passiert, wenn du absolute Adressen benutzt, dein Kernel aber nicht an die selbe Stelle geladen wird.
22
OS-Design / Re: C oder C++
« am: 17. February 2012, 20:30 »
Ein weiterer Schwachpunkt von C ist das Fehlen von überladbaren Methoden, das bei der Lowlevelprogrammierung aber auch nicht so zu Geltung kommt. (Der Kernel ist ja keine Mathesoftware, die generische sin(), cos() etc. Funktionen braucht.).
Mit _Generic geht das wohl in C11 so einigermaßen. Obwohl ich jetzt einfach mal sage, einen Schönheitswettbewerb gewinnt das nicht.

Naja, _Generic ist schon in Ordnung. Man kann ja #define generic _Generic oder so nutzten.
Zitat
Womit auch das Stichwort für das eine wirklich fehlende Feature in C gegeben ist: Richtige Generics. Also der Teil von Templates, den man wirklich braucht. Auf das Berechnung von Primzahlen zur Compilezeit verzichte ich gern. ;)
Generische Funktionen ließen sich sehr gut umsetzten, wenn man eine komfortable Makrofunktion einbaut. Allerdings nützten dir generische Funktion in C nicht so viel, weil du keine Operatoren überladen kannst.
23
Softwareentwicklung / Re: .intel_syntax
« am: 17. February 2012, 17:51 »
Das mit dem offset hat folgendes auf sich:

Einige Assembler wie masm/tasm/gas halten sich leider für besonders schlau, indem sie neben Labels auch Variablen einführen. Das führt zu dem Problem, dass gas

mov esp, kernel_stack
genauso wie:
mov esp, [kernel_stack]
behandelt, wenn es kernel_stack als Variable auffasst, leider ist diese Funktion ziemlich unberechenbar.
Deshalb schrieb immer offset davor, wenn du die Addresse haben willst und kein + x oder so dar steht.

NASM hat das Problem erkannt und löst es, indem es grundsätzlich nur mit Labels arbeitet. Ohne Klammern ist in NASM also immer nur die Addresse.
24
OS-Design / Re: C oder C++
« am: 17. February 2012, 16:25 »
Man sollte sich schon zwischen C und C++ entscheiden. C nehmen und dann die Objektorientierung per CPP versuchen nachzuäffen halte ich für wenig ratsam.

Für den Kernel würde ich persönlich C nehmen.
C++ bietet zwar die OOP, der wichtigste Hebel für die Verwendung der OOP, nämlich die GUI-Elemente, sowie die meisten anderen Vorteile der OOP (Dateizugriff, Agenten, etc.) fallen im Lowlevel Bereich weg. (OOP ist immer dann stark, wenn man viele Dingen hat, die sich nur in Details oder nur in Parametern unterscheiden, und auf die verschiedene Aktionen angewand werden können. Mir fallen da in Bezug auf Betriebssysteme eigentlich nur Tasks ein.) Im Lowlevelsektor fallen mir da spontan nur Darüber hinaus, passieren bei der OOP sehr viele Dinge auch implizit und nicht unbedingt vorhersehbar, was bei der Lowlevel Programmierung nicht unbedingt von Vorteil ist.

Ein weiterer Schwachpunkt von C ist das Fehlen von überladbaren Methoden, das bei der Lowlevelprogrammierung aber auch nicht so zu Geltung kommt. (Der Kernel ist ja keine Mathesoftware, die generische sin(), cos() etc. Funktionen braucht.). Auch dynamische Strukturen sind im Kernel recht unbrauchbar. Präprozessormagie zum lösen des Überladeproblems ist übrigens nicht implementierungsunabhängig, oder extrem aufwendig: http://carolina.mff.cuni.cz/~trmac/blog/2005/the-ugliest-c-feature-tgmathh/
25
Offtopic / Re: Eigene CPU
« am: 17. February 2012, 15:08 »
Logische Operationen mit sich selbst währen,

Zu der Sache mit dem BIOS,
würde ich die Mikrocodefunktionalität einbauen, müsste der Mikrocode ja nicht intern generiert werden. Der Mikrocodespeicher könnte auch extern liegen und über eine Schnittstelle eingelesen werden. Hiermit würde der Mikrocode eine Art Prozedursammlung (BIOS) bieten, aber ich glaube mittlerweile nicht mehr, das das so ne gute Idee war. Wenn, dann den Code direkt in den RAM einbinden.
26
Softwareentwicklung / Re: Welche Compiler
« am: 11. February 2012, 13:42 »
Zum anderen gab (und gibt) es keine gute IDE für FreeBASIC unter Linux. Wobei bei mir jetzt Geany als Notlösung herhält.
Was muss den eine Gute IDE können, so was wie FBEdit? Ich hab mit der Kombination FreeBasic und Geany unter Linux eigentlich keinen Probleme. Eventuell musst du Autovervollständigungsbeschreibungen FreeBasic-Configurationsdatei ändern, aber sonst.
27
Offtopic / Re: Eigene CPU
« am: 29. January 2012, 20:57 »
Zählst der Dritte Abschnitt auch noch zu den Sachen, die man auslassen soll?

Eine Zusätzlichen Befehl, welcher ausschließlich ein Register laden kann halte ich für nicht klug. Der Compiler kann das Register nur mit großen Aufwand für etwas anderes nutzten und die Immideate Instruktionen kosten Speicher (der Controlnibble lässt sich nicht so einfach einsparen.)
28
Lowlevel-Coding / Re: EXTERN und GLOBAL in NASM
« am: 21. January 2012, 13:54 »
Traditionell ist es so, das der MBR den Bootsektor der aktiven Pation einließt. Dieser erscheint dann genauso wie ein Diskettenbootsektor auch.
29
Lowlevel-Coding / Re: EXTERN und GLOBAL in NASM
« am: 20. January 2012, 21:25 »
Nur welches Ausgabeformat brauch ich, um 8086-kompatible Binaries mit zusätzlichem Header anzufertigen ?

Das hängt ganz davon ab, wo du den Code ausführst. Wenn du einen Bootloader baust, musst du Flat Binary verwenden. Für den Kernel musst du das Format nehmen, was dein Bootloader unterstützt (bei GRUB sind das elf32 und a.out). Für andere Programme, das was dein Betriebssystem unterstützt. Wenn du wissen willst, wozu da was taugt, musst du "nasm -hf fragen".
30
Offtopic / Re: Eigene CPU
« am: 20. January 2012, 21:19 »
Naja, ich hab mir mein Instruktionsformat noch mal überarbeitet:
Ein Befehl ist 32 bit lang, kann aber Abhängigkeiten von folgenden Befehlen besitzen. Es werden aber immer zwei 64 bit gleichzeitig eingelesen und abgearbeitet (das entspricht bis zu zwei Befehlen, die sich nicht in die Quere kommen sollten.)

Zu den Abhängligkeiten:
Das most significant Bit bestimmt die Bedeutung des dwords:
eine "0" entspricht Daten und eine "1" Befehle. Datenwörter, die nicht benutzt werden, entsprechen in der Ausführung nop.

Im der zweiten Piplinestufe (Dekodierstufe 1) wird das Packetpaar entsprechend vordecodiert. Hierbei entsteht je ein 28 bit Befehl und ein 64 bit Datenwort. Jeder der beiden Einzelbefehle besitzt hierzu einen Controlnibble (4 bit), der folgenden Effekt hat.
(Die Bitnummer beginnt bei 1)
0xxxxb - Datenwort (wird in nop umgewandelt)
1000b - Keine externen Daten benötigt, setzte das Datenwort auf 0.
1001b - 31 bit Immideate, die aus dem folgenden Datenbefehl geladen wird. Das 32igste bit wird auf 1 gesetzt die Zahl mit Nullen auf 64 bit erweitert.
1010b - 31 bit Immideate, die aus dem folgenden Datenbefehl geladen und mit Nullen auf 64 Bit erweitert wird.
1011b - 31 bit Immideate, die aus dem folgenden Datenbefehl geladen und mit Einsen auf 64 Bit erweitert wird.
11xyb - 2x31 bit Immideate, die aus 2 folgenden Datenbefehlen geladen wird und deren 32igstes bit auf y und deren 64igstes bit auf x gesetzt wird.
Wird versucht einen gültigen Befehl (1...b) als Datenbefehl zu übergeben, gibt es eine Invalid-Opcode Exeption

Da der Decoder 1. nicht über ausreichend Informationen verfügt, um die Daten vollständig zu ergänzen (er hat ja nur die zwei Befehle zu Verfügung, ergänzt er einfach die ihm bekannten Daten, sowie einige Steuersignale für die nächste Pipliestufe.
Da der Decoder 1 somit auch nicht wirklich 64 bit Datenwörter produziert, sind einige Bits im Ausgangsbus zusammengefasst und zwar:
(Die Bitnummerirung beginnt bei 0)

1. Befehl des Befehlspaars
Abschnitt - Möglicher Werte               Länge im Ausgangsbus
bit[30:0] - individuelle Daten              31
bit[31]                                           1
bit[62:32] - immer alle gleich              1
bit[64]                                           1
Gesamt                                         34

2. Befehl des Befehlspaars
Abschnitt - Möglicher Werte               Länge im Ausgangsbus
bit[30:0] - immer null oder egal           0
bit[31]                                           1
bit[62:32] - immer alle gleich              1
bit[64]                                           1
Gesamt                                          3

In der 3. Piplinstufe werden die 28 Bit Befehle dekodiert. Paralel werden die Datenwörter mithilfe des jetzt in der 2. Pipliestufen liegenden Befehlspaares verfolständigt.
Diese sogenannte Nachladeeinheit erhält von der Dekodierstufe 1 abgesehen von den beiden "64 bit" Datenwörtern folgende Steuersignale.
1. Befehl des Befehlspaars
pldctrl0 - Läd das erste 31 bit Datenwort aus der Dekodierstufe 1 in das 64 bit Datenwort an Prosition [62:32].

2. Befehl des Befehlspaars
pldctrl1 - Läd das erste 31 bit Datenwort aus der Dekodierstufe 1 in das 64 bit Datenwort an Prosition [30:0].
pldctrl2 - Läd das zweite 31 bit Datenwort aus der Dekodierstufe 1 in das 64 bit Datenwort an Prosition [62:32].

Nach dem die 3. Piplinestufe abgeschossen ist, wird das nun vollständige 64 bit Datenwort in das IR geladen.

Somit gibt es bei mir folgende Spezialregister, die aber ganz normal wie andere Register auch adressiert werden können, die aber für die beiden Befehle des Befehlspaares unterschiedlich sind:
IR
PC (ist für den zweiten Befehl beim lesen 4 höher.)

Sprünge werden für beide Befehle danach ausgeführt, sodass wenn der erste Befehl ein Sprung ist, der zweite trotzdem ausgeführt wird.

Die Sache mit dem Mikrocode muss ich mal schauen, wo ich die am besten unterkriege. Ich vermute aber in Piplinestufe 1. Ich hab mir das überlegt. Außerdem könnt man, wenn man den Baustein extern einrichtet, auf die Weise auch so eine Art BIOS unterbringen.
31
Offtopic / Re: Eigene CPU
« am: 18. January 2012, 20:18 »
Vergiss das mit meinen Opcodelängen.

Jeder Befehlsblock besteht aus zwei Befehlspacketen.
Diese enthalten
4 bit Verwaltungsdaten+ 60bit Infos hierbei gilt:
Verwaltungsdaten:
0000b = 2. Befehlspaket einer Folge.
andere.
Kombination aus 20 bit, 40 bit und 80 bit Befehlen.
32
Offtopic / Re: Eigene CPU
« am: 18. January 2012, 19:54 »
Einen CMP-Befehl habe ich auch nicht (ebenso wie ich keinen TEST-Befehl habe) sondern dafür wird ein ganz normaler SUB-Befehl (oder AND-Befehl) benutzt und das Ergebnis einfach nicht verwendet.
Ich hab mir überlegt, das 0reg doch abzuschaffen. Für die nicht vorhandenen TEST/COMP befehle, kann man ja die Daten in das IR schreiben, wo sie quasi weg sind. (Für den Executer ist das IR ein ganz normales Register. Der einzige Unterschied ist, das es extern durch den Pipe Shift geladen werden kann.)
Auf ein MOV würde ich auch grundsätzlich nicht verzichten, klar kann man das mit "ADD RD,RS,R0"
Da ich mit IR kein echtes 0-Register mehr habe, brauch ich natürlich auch einen echten MOV Befehl.

Generell bin ich auch der Meinung, das es bei Befehlen nicht zu viele Ausnahmen geben sollte. Auf der anderen Seite muss ein Schreibzugriff auf den PC natürlich registriert werden.
Ein Problem ist das Verhältnis von PC Addresse und Instruktion Fetch Addresse. Ich persönlich finde, dass man da einen Unterschied machen muss. Das der PC auf die Fetch-Addresse zeigt, halte ich für dumm, weil man so die Piplinelänge festlegt, es dem Programmierer schwieriger macht und zum anderen trotzdem umrechne muss (z.B. beim Sprung zu einem Unterprogramm, ist aber nicht so häufig wie andere Sprünge). Ich löse das deshalb so, das der PC auf den Befehl zeigt, der gerade ausgeführt werden soll. Der Fetcher besitzt dann eine Schaltung, die die Piplinelänge entsprechend addiert. Wichtig ist das ganze bei einem Pipline-Flush, bei dem dann der PC entsprechend dekrementiert wird. (Sodass er dann vor dem eigentlichen Sprungziel liegt. Für beides gibt es natürlich spezielle Schaltungen, die auf diese Funktion optimiert worden sind).

Meine Pipe sieht wie folgt aus:

Fetcher -(Packet)-> Puffer -> Unpacker -(Langer Befehl 60/124 bit) -┬-> Decoder --> Executer (--> Write Back)
                                                                alternativer Fetcher -┘

Eine weitere wichtige Funktion ist der sogenannte alternative Fetcher. Ebenso wie der normale Fetcher, kann auch diese Baugruppe Befehle in die Pipline einlesen, allerdings stehen diese nicht an irgendeiner RAM Adresse, sondern von einem externen oder auch interenen Bauelement. (In der Regel sind einige Funktionen intern vorprogrammiert. z.B. die Division.) Als Faustregel gilt. Negative Integer werden extern ausgeführt, positive Intern. Exteren Befehle werden über einen Port angesteuert. Wichtig beim alternativen Fetcher ist, das es keine Adressen gibt, und dass der PC auch (meist nicht) nicht hochgezählt wird. Schleifen und Sprünge erreicht man einfach durch rekursive Aufrufe oder durch interne Steuerung des alternativen Fetchers.

Man könnte auch unsere beide Stategien kombinieren. Ein Opcodepaket besteht aus meheren Opcodes, die verschiedene Länge annehmen können. Beide Opcodelängen sind identisch, allerdings sind bei den kurzen Opcodes Teile derselbigen abgeschnitten. So enthalten kurze Opcodes zwar vollwertigen Befehl, aber kein Immediate Sektor (der impizit 0 enthält.) Lange Opcodes enthalten eine Immediate, die sich über ein Psydoregister (IR immidete Register, remake von NIR) ansprechen lässt.) Damit würde man variable Opcodelängen ermöglichen und den Decoder einfach halten.
Ja, das klingt interessant. Machen Sie es so! ;)
Ich denke aber ich werde ehr nicht so viele Befehlslängen anbieten. (Es gibt einen 64 bit Doppelpaket, das entweder einen 60 Bit Befehl, 3 20 Bit Befehle oder nur 1 20 bit Befehl + 40 bit Zusatzinfos enthalten kann. (Die dann die Pipe abkürzen.)

Da hab ich mich falsch ausgedrückt. Natürlich kannst du auch mit allen anderen Registern Flags setzten.
Dann hast Du aber bei vielen Befehlen ein extra Bit im OpCode das angibt ob die Flags geschrieben werden sollen oder?
Ja so umgefähr.

Allerdings wollte ich doch eigentlich eine Programmiersprache und keine CPU bauen.
33
Offtopic / Re: Eigene CPU
« am: 17. January 2012, 21:13 »
Naja wenn ich bedenke, das ich nop ohnehin schon indirekt kodiert mit so befehlen wie add 0reg, 0reg, 0reg.
Okay, aber so ein Null-Register hab ich nicht und möchte ich eigentlich auch nicht, ich denke der Verlust eines Registers wiegt schwerer als der Verzicht auf ein 256tel des OpCode-Raums.
Naja, so schwer schätz ich den bei 32/64 Registern dann nicht ein. Dafür macht so ein Register viele Sachen einfach einfacher. Man braucht z.B. keine extra Compare Befehle und kann sich auch Sachen wie den mov Befehl sparen. Ohne Null Reg würde der Opcode dann halt einfach "mov anyGPReg1, anyGPReg1" heißen. Ich mein, ich hab mir ja nur ein paar Gedanken gemacht. Noch kein greifbares Design.

Wenn ich mal nur vom Lesezugriff ausgehe, baue ich einfach eine Schaltung ein, die die Verarbeitung die die Verarbeitung des Folgebefehls behindert. Führe ich alle Befehle nacheinander aus, weiß ich zwei Takte bevor ich den Befehl ausführe, ob dieser ausgeführt werden soll.
Aber was ist wenn Du die Befehl nicht hintereinander sondern gleichzeitig ausführen möchtest? Wäre ja möglich das die alle voneinander unabhängig sind und daher diese Parallelität durchaus erlaubt ist. Ich bleibe vorerst bei der Meinung das Du Dir mit diesem Konzept die nächst höhere Performance-Stufe verbaust oder zumindest erheblich komplizierter machst. IMHO ist es gerade einer der Vorteile wenn man große Befehle hat die komplette Immediates aufnehmen können das der Decoder alle Befehle unabhängig voneinander dekodieren und die Verarbeitungs-Logik diese auch unabhängig voneinander ausführen kann, natürlich soweit keine Datenabhängigkeiten o.ä. vorliegen aber das zu ermitteln ist schon komplex genug so das ich persönlich mir da nicht auch noch so ein NIR aufbürden würde.

Man könnte auch unsere beide Stategien kombinieren. Ein Opcodepaket besteht aus meheren Opcodes, die verschiedene Länge annehmen können. Beide Opcodelängen sind identisch, allerdings sind bei den kurzen Opcodes Teile derselbigen abgeschnitten. So enthalten kurze Opcodes zwar vollwertigen Befehl, aber kein Immediate Sektor (der impizit 0 enthält.) Lange Opcodes enthalten eine Immediate, die sich über ein Psydoregister (IR immidete Register, remake von NIR) ansprechen lässt.) Damit würde man variable Opcodelängen ermöglichen und den Decoder einfach halten.

Setzten der Flags (Arithmetische Befehle die als Rd das Nullregister verwenden.)
Heißt dass das Rechenbefehle die nicht aufs Null-Register schreiben keine Flags ablegen können? Das würde ich als sehr ungeschickt betrachten da es durchaus viele Fälle gibt wo man das Ergebnis haben will und auch die Flags interessieren.
Da hab ich mich falsch ausgedrückt. Natürlich kannst du auch mit allen anderen Registern Flags setzten.


Sprungbefehle fassen hierbei die Aktionen 2-4 oder 3-4 zusammen. Flagorientierte Konditionspräfixe fassen Aktion 2 und 3 zusammen. In beiden Fällen muss der Wahrheitswert dann nicht in notiert werden.
Im Instruction set, unterscheiden sich  evalFLAGS Befehl und Flagorientierte Konditionspräfixe dadurch, dass bei letzteren der Programm Counter als "Evaluationsziel angegeben wird."
Registerorientierte Conditionspräfixe gleichen den 3-4-Sprungbefehlen, nur das der PC als "Sprungziel" angegeben wird.
Beide Präfixe lassen sich deshalb leicht daran erkennen, das sie das PC adressieren.
Um ehrlich zu sein habe ich das überhaupt nicht verstanden, könntest Du noch mal anders beschreiben wie Du bedingte Befehlsausführung realisieren möchtest?
Naja, das war eh so ein spontaner Einfall, den ich vermutlich nicht umsetzten würde.
34
Offtopic / Re: Eigene CPU
« am: 15. January 2012, 18:35 »
Naja, dein Konzept hört sich schon mal gut an. Das mit dem Fehlen der Division gibt es bei mehren RISC Architekturen. Das hat mit dem entfernen des Microcodes zu tuen der Microcode kann auch wie bei den moderen x86-32 ein interner RISC Code sein. Die Division muss ist ein sehr komplexer Ablauf, der in der Regel durch Microcode gelöst werden muss. Und da EPIC auf RISC basiert und deshalb keinen Mikrocode beherrscht, ist die Implementierung der Division ziemlich aufwändig (und wird auch vergleichsweise selten gebraucht.)

Das Problem ist, das man dadurch einen großen Teil des möglichen Befehlssatzes blockiert.
Hä, was meinst Du? Denkst Du das ein NOP mit nur 8 Bits zu kodieren Verschwendung ist?
Naja wenn ich bedenke, das ich nop ohnehin schon indirekt kodiert mit so befehlen wie add 0reg, 0reg, 0reg. Halte ich es für nicht so praktisch wenn ich ein 256tel der möglichen Instructionswörter für nop's hergebe und dann für viele, zusätzliche Befehle, die dann auch noch Platz für die restlichen Bits reservieren müssen, find ich Problematisch. (Natürlich könnt man einen Bareal Shifter verwende und den shift 0 Funktionen, eine Spezialfunktion zuweisen.

Ja, aber wenn Du das erst bei der tatsächlichen Ausführung der Befehle machst verhinderst Du damit effektiv jegliche Form von Instruction-Level-Parallelism weil Du den (über)nächsten Befehl erst dann dekodieren kannst wenn der aktuelle Befehl abgearbeitet wird. Ich kann Dir nur dringlichst empfehlen zu versuchen dafür eine Lösung zu finden die nur im Decoder alleine passiert damit Du Dir später nichts verbaust.
Wenn ich mal nur vom Lesezugriff ausgehe, baue ich einfach eine Schaltung ein, die die Verarbeitung die die Verarbeitung des Folgebefehls behindert. Führe ich alle Befehle nacheinander aus, weiß ich zwei Takte bevor ich den Befehl ausführe, ob dieser ausgeführt werden soll. Jetzt baue ich einfach eine Flag ein, die die Ausführung des Befehls unterbindet. Du darfst nicht vergessen, das ich einen Befehl auch dann dekodieren kann, wenn ich ihn gar nicht ausführe. (Die Ausführschaltung ist einfach für einen Takt gesperrt). Umgekehrt weiß ich auch schon nach dem dekodieren, ob ich auf das NIR zugreifen werden, und deshalb den nächsten Befehl nicht ausführen darf.
Für den Schreibzugriff hast du recht. Da ich aber Schreibzugriff auf das NIR als ehr wenig gebrauchte Anweisung betrachte, braucht diese Funkion auch keine super effektive Ausführmethode. Das heißt, ich der Schreibzugriff würde halt die Pipline leeren, oder zumindest zurück schieben. Eine sehr lange Pipline halte ich sowieso für unpraktisch.
Ja, es wird für die Bedingung nicht nur eine Register-Nummer (die bei Alpha 5 Bit groß ist) benötigt sondern auch die Bedingung als solches (da gibt es auch > 0 oder <= 0 jeweils nach signed und unsigned getrennt, wimre gibt es das bei Alpha auch für Floating-Point) und deswegen gibt es bei Alpha wohl nur bedingte Sprünge und sonst nichts. Wenn man diese Bedingung aber in ein eigenständiges Präfix auslagert, das sich mit jedem Befehl kombinieren lässt, dann hat man ja eigentlich auch genügend Bits zur Verfügung um hier auf möglichst große Flexibilität zu setzen. Wenn das Präfix 32 Bits groß ist könnte man sogar die eigentliche Vergleichsoperation (SUB oder AND) und 2 Register mit hinein kodieren. Aber das bläht die interne Befehlsdarstellung ziemlich auf. Ich benötige 7 Bits für die Bedingung (2 Bits für das benutze Flag-Set und 5 Bits für die eigentliche Bedingung, da sind zum einen die 14 Klassiker und noch einige Floating-Point-Bedingungen) und das auch hinter dem Decoder bei der internen Befehlsdarstellung, was IMHO einen brauchbar guten Kompromiss darstellt.
Naja ich würde ohnehin nur zwei Konditionale Befehle verwenden: Den primitiven Sprung Befehl mit Registerhilfe (oder über NIR auch mit Immidiate.) und halt das Condition Präfix, sowie der evalFLAGS Befehl (setzt ein Register auf 0 oder -1, entsprechend der FLAGS). Da ich mit Nullregister arbeite, sind die bedingungsfindenden Opcodes nicht so speziell.
Im allgemeinen Sind folgende Optionen für eine Condition notwendig, die aber auch zusammengefasst werden.
1. Setzten der Flags (Arithmetische Befehle die als Rd das Nullregister verwenden.)
2. Evaluation der Bedingung in einen Wahrheitswert. evalFLAGS Befehl
3. Aktivierung der Bedingung (Registerorientierte Conditionspräfixe)
4. Aktion die unter der Bedingung ausgeführt wird.

Sprungbefehle fassen hierbei die Aktionen 2-4 oder 3-4 zusammen. Flagorientierte Konditionspräfixe fassen Aktion 2 und 3 zusammen. In beiden Fällen muss der Wahrheitswert dann nicht in notiert werden.
Im Instruction set, unterscheiden sich  evalFLAGS Befehl und Flagorientierte Konditionspräfixe dadurch, dass bei letzteren der Programm Counter als "Evaluationsziel angegeben wird."
Registerorientierte Conditionspräfixe gleichen den 3-4-Sprungbefehlen, nur das der PC als "Sprungziel" angegeben wird.
Beide Präfixe lassen sich deshalb leicht daran erkennen, das sie das PC adressieren.
35
Offtopic / Re: ARM-Systeme
« am: 14. January 2012, 17:34 »
Wenn ARM auch im Desktop/Notebook-System wird sich da sicher irgend etwas festsetstellen. Und da ich nicht glaube das die Intel-Architektur ewig lebt, muss irgendjemand die Nachfolgerschaft antreten. Wobei ARM natürlich trotzdem er Low End bleiben wird. Vielleicht stirbt auch irgendwann der PC in seine heutigen Gestalt einfach aus oder es setzt sich am Ende eine x86-ähnliche Architektur durch.
36
Offtopic / Re: Eigene CPU
« am: 14. January 2012, 17:29 »
Hallo,


Dabei habe ich mich hauptsächlich mit einem Problem beschäftigt, das bei RISC CPU's auftritt, nämlich die Befehlslänge.
Ja, das ist wohl wahr. Aber es gibt auch interessante Lösungen dafür, schau Dir mal den Itanium an. Auch das Problem mit der bedingten Ausführung ist dort auf sehr interessante Art und Weise gelöst.
(eigentlich könnte hier meine Antwort schon zu Ende sein aber ich hoffe man nimmt es mir bei diesem Thema nicht übel wenn ich das doch mit ein paar Buchstaben mehr erkläre)[...]
Naja, ganz grob entspricht das meiner Möglickeit 2. Allerdings halte ich so einen Itanium-Befehlssatz für überflüssig, weil diese Art von Parallelität nur selten vorkommt (entweder will man SIMD oder MISD.) Für SIMD ist der Befehlssatz zu mächig und damit zu teuer (Man nutzt die Möglichkeiten nicht richtig aus). MISD lässt sich, da Abhängigkeiten zwischen den Paralellbefehlen verbotenen sind, nicht schnelle als bei einem konservativen Befehlssatz lösen. (Ein MISD Prozessor wäre auch mal interessant.)
Zitat

(Auch wenn die z.B. bei ARM vorgestellten Möglichkeiten schon gut sind.)
Ja, der Weg von ARM ist interessant aber er hat auch einen eklatanten Nachteil, er erfordert das der Code immer auch lesbar ist (es werden ja ganz normale Speicherzugriffe nur eben mit IP-relativer Adressierung benutzt). Aus Gründen der Sicherheit ist es aber besser wenn Code nicht lesbar sondern nur ausführbar ist.

Ansonsten gibt es für Deine Version mit den 32Bit Befehlen noch eine Möglichkeit 4:
Um ein NOP zu kodieren sollten nicht mehr als 8 Bit nötig sein so das in jedem NOP immer 24 Bit an Daten enthalten sein können. Wenn Du nun einen Load-Immediate-Befehl baust der selber noch 16 Bits Daten enthält (die restlichen 16 Bits sollten doch reichen um den Befehl ansich und das Zielregister zu kodieren) dann könnte der im Decoder um 2 Takte verzögert werden (es käme eben für 2 Takte kein Befehl aus dem Decoder raus) und der Decoder würde intern aus diesem Befehl und den 2 folgenden NOPs insgesamt einen Load-Immediate mit vollen 64Bit Nutzdaten bauen. (wenn einer der beiden folgenden Befehle kein NOP ist gibt es eben eine Illegal-OpCode-Exception) Das hätte auch den Vorteil das nichts schlimmes passiert wenn mal einer der beiden Daten-NOPs angesprungen wird und auch der Disassembler (im Debugger) hätte keine Probleme was sinnvolles anzuzeigen. Ein weiterer Vorteil ist das diese Variante allein im Decoder passiert und Dein eigentlicher CPU-Kern davon nicht betroffen ist, spätestens wenn Du irgendwann doch mal das simple In-Order-Pipeline-Konzept verlassen möchtest wird es Dir sehr entgegen kommen Dich im CPU-Kern auf die eigentliche Arbeit konzentrieren zu können.
Das Problem ist, das man dadurch einen großen Teil des möglichen Befehlssatzes blockiert. Bisher hab ich mich außerdem nie mit Befehlen die mit doppelter Datenabhängigkeit funktionieren beschäftigt. Die von dir beschriebene Möglichkeit hatte ich auch schon mal, da sie z.B. bei ARM schon vorbereitet wurde. Die never Kondition entspricht quasi deinem nop. Ein weiterer Nachteil deines Vorschlags ist, das man spezielle Befehle hierfür benötigt. Möglichkeit 3 zeichnete sich ja gerade dadurch aus, das man die Immideate wie ein Register nutzten konnte, weil die Daten allein über einen Registerzugriff aktiviert werden. Bei Dissassemblen hab ich eigentlich keine Schwierigkeiten. Der Dissassembler dekodiert dann halt so was wie add r1, r2, nir(0xABCDEF01) und setzt den abhängigen Befehl in Klammern, oder so.
Zitat
Das mit dem Skip-Befehl ist keine so schlechte Idee aber auch hier solltest Du das gleich im Decoder lösen und dem CPU-Kern nur Befehle übergeben bei denen die Ausführungsbedingung integraler Bestandteil ist. Es sollte auch möglich sein das sich dieses Condition-Präfix mit jedem Befehl kombinieren lässt, damit lassen sich wieder viele Sprünge vermeiden und das bringt einiges an Performance und spart oft auch Code. [...]
Das mit der universellen Zuordnung hatte ich eh so vorgesehen (es hieß ja nicht skip next branch). Überhaupt hab ich mir überlegt, ob ich nicht zwei Dekodierstufen einfügen soll. Das macht die Sache einfacher.
Zitat
... solltest Du Dir mal anschauen wie das bei Alpha gelöst ist.[...]
Die Alpha Methode wäre natürlich auch ne Möglichkeit, allerdings ist die Nutzung eines beliebigen Register natürlich mit viel notwendiger Information verbunden. Dafür ist diese Möglichkeit ziemlich nah an dem System, das auch viele Programmiersprachen anwenden. (von FreeBasic weiß ich, das ein if ausgeführt wir, wenn der Ausdruck ungleich null ist. In C ist es glaub ich genauso.)

Grundsätzlich gibt es drei Konditionsmöglichkeiten.
A) Keine Konditionellen Befehle außer bei Sprüngen. Pro. Keinen Speicherbedarf im Opcode  Kontra: Piplineunfreundlich
B) ARM-artige Konditionen: Pro: mächtig Kontra: Wenig Erweiterungsmöglichkeiten, Koste viel Speicher im Opcode
C) Alpha-artige Konditionen: Pro: Flexible Konditionsverwaltung Kontra: Externen Vergleichsoperatoren nötig. Koste viel Speicher im Opcode und Register
D) if TRUE Flag set Kondition: Pro: Wenig Speicher im Opcode Kontra: Externe Unterstützung nötig.

Ich persönlich könnte mir also eine Möglichkeit vorstellen, bei der der einzelne Befehl keine Kondition trägt. Sprünge hätten dann sowas wie eine erweiterte Alpha-artige Kondition und Skip-Präfixe ein leistungsfähiges Konditionssystem.

Darüber hinaus gibt es natürlich noch Möglichkeiten, den Aufbau zu erweitern, indem man konditionelle Sprungbefehle oder Befehlspräfixe einführt.
Zitat
Auch ich habe mir über die beiden Punkte (Befehlsgröße und bedingte Ausführung) einige Gedanken gemacht und (wie ich meine) auch ein paar interessante Lösungsmöglichkeiten gefunden, das ist ganz am Anfang dieses Threads recht gut beschrieben.
Du weißt aber schon, das du den Decoder damit ziemlich auf blähst, da du eigentlich 3 Instructionsets verwendest. Ich würde den Dekoder in verschiedene Teile aufteilen. Du brauchtest also 1 Meta-Decoder (Trennt das Pakete auf) + 2 60bit-Decoder + 3 42bit-Decoder (39bit+3bit Condition) + 6 20bit Decoder = 12 Teildecoder. Da eigentlich alle Teildecoder das gleiche machen, hättest du ziemlich viele Einzellschaltungen. (zum Vergleich ARM brauch für seine Schaltung nur ein ARM und einen Thumb decoder.) Ich würde mir deshalb überlegen, ob du nicht die kurze Befehle auf den langen Abbilden kannst, z.B. indem du konstante Bits einfügst. Außdem würde ich mich fragen, ob du wirklich 6 20bit Anweisungen simultan ausführen musst, oder ob es reicht, immer nur 3 Befehle gleichzeitig zu bearbeiten und die Pipline entsprechend zu modifizieren, oder die Piplinegeschwindigkeit zu halbieren.

Darüber hinaus sollte dir klar sein, das es schwierig ist für einen VLIW Befehlssatz Code zu schreiben, weil das Design nicht der traditionellen Logik entspricht, weshalb das Compiler Backend ziemlich kompliziert wird. Assemblerprogrammierung für eine solche Plattform ist sogar noch schwieriger. Auch die interne Logik wird aufgebläht, weil viele Baugruppen mehrfach auftreten. Von der Theorie her, mag solch ein Befehlssatz ja interessant sein, in der Praxis implementiert man aber lieber SIMD Instruktionen.
37
Offtopic / Re: Panikmache wegen DNS-Changer
« am: 11. January 2012, 20:36 »
Wikipedia bietet dazu eine Hübsche Statistik: http://de.wikipedia.org/wiki/DNS-Server#Nameserver

So wie ich das sehe, für gibt es für deinen Computer eine lokalen Cache, mit dem du recht viele Domains einfach selbst auflösen kannst, oder am Root Server vorbeigehen kannst. Außerdem gib es für jede Abwicklungsstufe mehre Anbieter.
38
Offtopic / Re: Eigene CPU
« am: 11. January 2012, 18:36 »
Naja ich hab mir auch mal Gedanken bezüglich einer CPU (eigentlich mehrerer CPU's) gemacht. Zwar hab ich kein vollständiges Konzept entwickelt, aber folgende Ideen will ich dann dennoch der Allgemeinheit mitteilen.
Dabei habe ich mich hauptsächlich mit einem Problem beschäftigt, das bei RISC CPU's auftritt, nämlich die Befehlslänge.
Bei einer RISC Architektur stößt man immer auf folgende Probleme:
Wählt man die auf 32bit RISC Maschinen übliche Befehlslänge gleich der Wortlänge ist sie zu kurz um Konstanten und Adressen aller Art ohne großen Aufwand vernünftig laden zu können. (Auch wenn die z.B. bei ARM vorgestellten Möglichkeiten schon gut sind.) Würde man eine länger Befehlslänge nehmen (z.B. 64 bit) verschwendet man Speicher und braucht einen breiteren Bus oder doppelte Ladezyklen. Bei einer kürzeren Wortlänge (z.B. 16 bit) passt der Befehl selber, kaum in den Opcode.
Auf 64 Bit Architekturen verschärft sich das Problem. Verwendet man weiterhin 32 bit Befehlslänge kann der Befehl relativ gesehen nur halb so viele unmittelbare Informationen auf nehmen wie auf einem 32 bit Prozessor. Wält man eine Befehlslänge von 64 bit verbraucht das Programm unverhältnismäßig viel Arbeitsspeicher.
Analysiert man den Befehlssatz, erkennt man das es Befehle gibt, die mit wenig Speicher auskommen (Arithmetik, Flags setzten, Stack) und solche, die viel mehr Speicher brauchen.
Natürlich könnte man hingehen und grundsätzlich mit Variablen Befehlslängen arbeiten, aber das wäre nicht so Praktisch. Also habe ich versucht, nur mit Befehlen einfacher und doppelter Länge (32bit/64bit) zu arbeiten, ohne das Design zu sehr zu beeinträchtigen:

Möglichkeit 1:
In bestimmte Abständen, wird anstelle eines Befehls ein Datenwort geladen, das in einem speziellen Konstantenregister gespeichert wird, das man dann ganz normal auslesen und für seine Berechnungen verwenden kann. Der Prozessorbus wurde so erweitert, das er die Konstante mitläd. Die Informationen werden dann intern gepuffert. (z.B. sind die Befehle jeweils 32 bit lang und nach zwei Befehlen folgt ein 64 bit langes Datenwort. Der Prozessor besitzt einen 64 bit Bus, sodass er für jeden bearbeiteten Befehl 64 Bit einlesen kann.
Bei Befehlszyklus 1 ließt der Fetcher beide Befehle ein und gibt den 1. an den Dekoder und schreibt den 2. in den Puffer. Beim Befehlszyklus 2 liest der Fetcher das Datenwort in das Konstantenregister ein und übergibt den gepufferten Befehl an den Dekoder.

Möglichkeit 2:
Alle Befehlswörter haben doppelte Länge. Alle zwei Befehlszyklen ließt der Prozessor ein Befehlswort ein. An einem Steuerbit kann der Predekoder nun erkennen, ob es sich um einen langen Befehl, oder um zwei kurze Befehl handelt. Die interne Pipe hat immer eine größere Länge (z.B. 65 bit). Bei zwei kurzen Befehle werden diese auf Pipelange vergrößert und nacheinander in die Pipe geschoben. Bei einem langen Befehl, wird dieser gefolgt von einem "nop" Wort auf die Pipe geschoben.

Möglichkeit 3 (Die ich am besten finde):
Alle Befehlswörter haben einfache Länge. Es gibt aber ein Psydoregister, "Next Instruction Register" (nir), mit dem man den nächsten Befehl auf der Pipe ansprechen kann (oder den übernächsten Befehl). Der Lesezugriff erfolgt destruktiv, d.h. der Befehl wird beim lesen durch "nop" ersetzt, oder entsprechend markiert (das geht beim übernächsten Befehl einfacher, weil dieser noch nicht dekodiert wurde.) Der Schreibzugriff ist auch möglich wenn man dadurch den übernächsten Befehl anspricht, wodurch man eine Art selbst modifizierenden Code bauen kann.

Darüber hinaus bin ich dafür, Operatorlastige Befehle zu trennen, z.B favorisiere ich anstatt von konditionalen SprungBefehlen oder Bedingungspräfixe, lieber eine Kombination aus unbedingten Sprungbefehlen und einer "skipp next instruktion if <condition>" - Anweisung.

Eine Weiter Idee, die ich hatte, ist mal eine Stack basierende Architektur zu bauen oder eine Möglichkeit zu finden Registersicherung zu sparen. (Z. B. für einen eigenen Registersatz für den Taskshedule.)
39
Das Wiki / Re: Registrierung fürs Wiki fehlerhaft?
« am: 03. January 2012, 14:43 »
Das Problem ist, das Ip Addressen umgeordnet werden und du, wenn du Pech hast, eine vorbelastete Ip bekommst. Dagegen hilft nur ein Abluafdatum bei IPs
40
Lyrisches Eck / Re: Frohes Fest
« am: 24. December 2011, 21:24 »
Danke gleichfalls
Seiten: 1 [2] 3 4 ... 6

Einloggen