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 - Tufelix

Seiten: [1] 2 3 ... 6
1
Man könnte den Sequentiellen Decoder stark parallelisieren.
Automaten (und der Dekoder ist nichts anderes) sind äußerst schlecht parallelisierbar. Theoretisch könntest du den auch vollständig ausrollen, weil ein Befehl nach maximal 15 Bytes dekodiert ist, aber dann kannst du kein Blockram mehr benutzen. Im Ergebnis wird das nur ein extremer Gatterverhau, für den viel dupliziert werden muss und der durch seine Tiefe gleichzeitig relativ langsam ist.
Der Gatteraufwand hält sich meiner Meinung nach in Grenzen. Für nen Sequentiellen Dekoder benötigt man ja schon die Opcode-Maps für die Opcode-Bytes, ein paar Multiplexer für die Immediate und Displacement und ne Emulationsrom für alle Befehle die emuliert werden müssen. Für den Parallel-Decoder kommen da nur einige Shifter und Multiplexer hinzu, um die Befehls-Bytes in ihre Einzelteile zu zerlegen und ein paar zusätzliche Prefix-Dekoder. Der zusätzliche Gatterdelay lässt sich mit ein paar Pipelinestufen mehr gut handhaben. Bis auf die Prefix-Dekoder(wobei jeder davon sechs 4bit Lut-Tabellen benötigt) wird da eigentlich nicht viel Dupliziert.

Also zunächst alle möglichen Prefix-Bytes decodieren und mit einem Shifter das erste Opcodebyte an erster Stelle schieben.
Der Hauptvorteil eines byteweise durch den Datenstrom laufenden Dekoders ist, dass ihm das Alignment egal ist. Wenn du damit jetzt nur die Präfixe verarbeiten lässt, verlierst du pro Byte einen Takt und musst den Befehl danach trotzdem neu ausrichten.
Die Idee war eigentlich mit 16 Prefix-Dekoder alle Prefixe gleichzeitig zu dekodieren. Ein zweiter Sequentieller Dekoder nur für die Prefixe würde eher wenig sinnvoll sein  :-D .

Naja, das Problem ist der erste Schritt in dem die Befehlslängen dekodiert werden müssen.
Du kannst auch einfach 16 dieser freilaufenden Decoder einfach parallel schalten (mit jeweils einem Byte Versatz) und immer den passenden auswählen. :-D
So was wird auch in einer der Patente die ich oben verlinkt habe beschrieben. Solche 16 Decoder benötigen, verglichen mit 16 vollwertigen Instruction-Length Decoder, einen wesentlich geringeren Gatteraufwand. Das ganze wird aber je ineffizienter je länger die Befehle werden, maximal wird dann 15 Takte für die 16Bytes benötigt.

Ich glaube, du unterschätzt den Nutzen von Blockram. Der von mir ursprünglich skizzierte Decoder braucht schonmal mindestens einen Block (bei Xilinx ein RAM36 == 36 KBit, weil dualported). Auch die eine oder andere Pipelinestufe kannst du mit Blockram sparsam und schnell implementieren, statt das in diskrete Logik zu gießen. Gleiches gilt für die Tabellen, die du für trigonometrische Funktionen brauchst, um float/double in hinreichender Genauigkeit zu implementieren. Im Prinzip kannst du auch alles in Logik (Distributed RAM) lösen, aber damit überrennst du das Routingnetz im FPGA und riskierst, dass dein Design nicht mehr synthetisiert (oder nur nach mehreren Tagen).

Wenn ich mir die Liste der Befehle und deine Wunschliste so anschaue, dann wirst du mindestens 2000 Befehle implementieren müssen, vielleicht auch 4000, je nach Zählweise. Ein Großteil davon ist eher unwichtig, muss aber funktionieren (z.B. BCD-Arithmetik, die x87-FPU, der Real Mode), obwohl es kaum benutzt würde. Wenn du solche Befehle in Software (als Mikrocode) implementieren kannst, sparst du dir einerseits extrem viel Fleißarbeit und hast später bessere Stellschrauben, was Größe und Geschwindigkeit angeht. Das ginge dann in die Richtung, was Transmeta vor gut 15 Jahren gemacht hat (allerdings lief das dort mit Unterstützung durch das BIOS).

So ein Mikrocode kostet aber wieder viel Blockram, der nicht für Caches zur Verfügung steht.
Ich hatte nie vor 486kb Bram nur für Cache zu verwenden  :roll: . Für die Instruction-Cache hab ich 32KB vorgesehen und für die Datencache 24KB. Recht hast du auf jeden Fall, mit Bram lässt sich vieles einfach implementieren. Bei der Verwendung von Bram hab mich bei meinem jetztigen Projekt aber eher zurückgehalten, ich hab die Befürchtung das zu viel Bram nacher bei der Synthese, den Takt unter die 100Mhz Grenze drücken könnte.
Mit meiner optimistischen Zählweiße komm ich auf ganze 813 Befehle die ich implementieren muss. Hab aber einige Befehlsgruppen zusammengefasst. Eine Mikrocode-Rom für die Emulation von Befehlen brauch ich auf jedem Fall. Befehle wie CPUID lassen sich nur damit implementieren. Wie viel Bram ich dafür benötige ist noch nicht klar. Derzeit rechne ich mit maximal 64kB.

Mfg Tufel



2
Wenn man deine ursprüngliche Idee mit dem einem Sequentiellen Decoder weiterdenkt , dann ist sie eigentlich garnicht so schlecht. Man könnte den Sequentiellen Decoder stark parallelisieren. Also zunächst alle möglichen Prefix-Bytes decodieren und mit einem Shifter das erste Opcodebyte an erster Stelle schieben. Anschließend generieren alle Opcodemaps(also z.B die Map für den Primären Opcode und die Map für den Sekundären Opcode) einen Befehl. Ein Escape-Byte Finder wählt dann die passende Map aus und bestimmt wo sich die Operand-Bytes befinden (also Modrm, Sib, Disp, Immed). Der ausgewählte Befehl wählt am Schluss über Multiplexer die benötigten Operand-Bytes aus. Im Grunde hätte man dann sowas ähnliches wie im i486 als Decoder verwendet wurde. Diesen Decoder könnte man mit dem doppelten Kerntaktrate versorgen. So hätte man einen einzelnen Dekoder für einen 2-fach superskalaren Prozessor. Probleme mit unbekannten Befehlslängen hätte man damit clever umschifft.

 
Ich versuch' mal, meinen Ansatz zu retten, obwohl du ihn schon abgelehnt hast.

Wenn du in einem ersten Schritt die Befehlslänge ermittelst, kannst du auch mehrere solcher Dekoder mit jeweils eigenem Offset gleichzeitig laufen lassen und deren Ergebnisse in einer Tabelle, also einem Decoded-Instruction-Cache (DICache) abspeichern. Die Pipeline stallt dann auf dem DICache, nicht auf dem ICache. Am Ende geht es ja nicht darum, die Befehle möglichst schnell zu dekodieren, sondern sie dann dekodiert vorliegen zu haben, wenn du sie brauchst. Es reicht also, wenn du im Mittel schnell genug bist. Intel-Prozessoren führen schon lange keine x86-Befehle mehr direkt aus, also muss dein Core das auch nicht können.

Stellt sich raus, dass dein Dekoder ein Flaschenhals ist, kannst du immernoch an der Anzahl der Decoder drehen. Wirfst du vorne 32 Byte rein (ein einziger beliebig schlecht ausgerichteter Befehl), kannst du vermutlich im Schnitt acht Dekoder voll auslasten und hättest nach Sprüngen nur wenig zusätzliche Latenz. Gegenüber einem Cache Miss fällt das überhaupt nicht ins Gewicht (und mit dem bisschen integriertem RAM - der größte Cyclone IV hat 486 KB - bekommst du keine großen Caches hin). Sehr kurze Schleifen könntest du aber aus dem DICache versorgen.

Naja, das Problem ist der erste Schritt in dem die Befehlslängen dekodiert werden müssen. Dazu benötigt man wieder nen Instruktion-Length Decoder. Die DICache die du beschreibst, ist ja sowas ähnliches wie ne Trace- oder Micro-op Cache. So ne Cache find ich speziell in nem x86 Prozessor ziemlich sinnvoll, man spart sich einige Pipeline-Stufen und kann den Nachteil des Energie-verbrauch eines Frontend für nen x86 Prozessor gegenüber das eines Risc-Prozessors stark minimieren (Hab mal eine schöne Arbeit gefunden in der es um Verschiedene Implementierungs-Ansätze für Loop-Buffer geht, da wurde auch die µ-Op Cache untersucht: http://pharm.ece.wisc.edu/papers/hpca14_revolver.pdf).
486kb für Cache sollte man nicht unterschätzen. Mit einem ausgereiften Prefetcher kann man da einiges an Performance heraus holen.

Mfg Tufel
3
Huhu Svenska,

danke für deine Antwort. Joar mein Ziel ist ziemlich ambitioniert  :mrgreen: . Der größte Widersprung in diesem Projekt ist wohl die maximal benötigte Logik für die CPU. In einem ähnlichen Projekt in dem "nur" ein Superskalarer Pentium-Prozessor auf ner FPGA realisiert wurde (http://www.eecg.toronto.edu/~yiannac/docs/fpga07.pdf) benötigte man mehr als das doppelte an LUT-Tabellen wie ich für mein Projekt vorgesehen habe. Der RTL-Code war aber nicht für eine FPGA optimiert, auserdem habe ich es geschafft für mein Projekt ein ziemlich kleines Backend zu entwerfen.  Das Backend ist dadurch ziemlich fragil und ich bin mir noch nicht ganz sicher ob es eine gute Performance liefert oder einfach nur ein riesiger Bottleneck in meinem System ist  :-D . Aber damit sollte es zumindest möglich sein die relativ geringe Logikgröße zu erreichen.

Mit den Patenten und den Ansätzen befasse ich mich jetzt nicht, sondern gebe eine weitere Idee. Die Alignment-Unit kannst du mit einem Dual-Ported BRAM mit einem byteweisen Ausgabeport nachbilden. Bei Sprüngen musst du dann nur den Offset beim Zugriff draufaddieren und bekommst einen Bytestrom. Den kannst du klassisch durch eine FSM dekodieren, was natürlich mehrere Takte (einen Takt pro Byte) dauert. Da du aber einen FPGA hast, kannst du den Dekoder in eine eigene, schnell laufende Taktdomäne legen (vermutlich musst du den Teil dann ziemlich massiv constrainen, damit das performt, aber es spart gut Logik).

Der Dekoder würde pro Takt ein Byte dekodieren, muss also für zweifache Superskalarität und einer durchschnittlichen Instruktionslänge von 3 (vgl. Quelle) sechsmal so schnell laufen wie der Core selbst. Bei geschätzten 200 MHz Dekodertaktrate und 40 MHz Kerntaktrate passt das einigermaßen zusammen.
Die idee find ich ziemlich Smart, man spart sich damit viel Logik und Entwicklungsaufwand beim Dekoder. Der Entwurf ist aber für mein Projekt weniger gut geeignet. Der gesamte zweite Entwurf aus meinem letzten Beitrag benötigt rund 2000 4bit Lut-Tabellen. Zusammen mit dem Decoder -wessen Logik-Verbrauch ich bis jetzt aber nur abschätzen kann- werden für die gesamte Instruktion-Dekodier Einheit der CPU etwa 12% bis 15% des gesamten Logik-Budget verbraucht (Im oben gennanten Pentium wurde prozentual für die Decodereinheit noch weniger Logik benötigt, daher denke ich das meine Schätzung relativ realistisch ist). Die Vorteile des Resourcen-Verbrauchs deiner Idee ist in meinen Augen zu gering um den möglichen zusätzlichen Bottleneck rechtfertigen können. Für nen einfachen i486 Klon wär die idee aber perfekt geeignet (Aber mit sowas kleinem geb ich mich nicht zufrieden  :-D).

Mfg Tufel

4
Huhu, ich arbeite seit einiger Zeit an einem Entwurf einer neuen eigenen CPU( sozusagen Logisim-CPU 2.0  :roll: ). Um Fehler zu vermeiden die ich in früheren ähnlicheren Projekten gemacht habe, habe ich mir von Anfang an ein grobes Ziel und Spezifikation gesetzt:
  • 2fach Superskalar mit Out-of-order Ausführung.
  • Soll nacher einen durchschnittlichen IPC von 1.2 haben.
  • Als Zielplattform soll eine Cyclone 4 FPGA mit einem Speedgrade C7 dienen.
  • Die CPU soll nacher etwa 30k 4bit LUT-Tabellen und 70kByte Bram auf der FPGA benötigen.
  • Als Takt-Fequenz peile ich etwa 100 Mhz an (also pro Pipeline-Stufe etwa ein Delay von 9 LUT-Tabellen).
  • Der Ziel-Befehlssatz ist AMD64( zusätzlich soll SEE 1 bis 4.2 und VT-X implementiert werden).

Die Entwicklung ist bis jetzt recht weit Fortgeschritten, das Back-end (Also Integer-ALUs, Memory-Execution-Unit,  Out of order resource allocation und die FPU) hab ich schon grob fertig entworfen.
Die meisten noch ungelöste Fragen und Probleme meines Projektes befinden sich größtenteils im Frontend welches durch den CISC-Befehlssatzt wesentlich mehr Zeitauswand bei der Entwicklung erfordert wie die restlichen Teile des Entwurfs. Die größten Schwierigkeit davon ist der Instruction-Length Decoder (oder einfach ILD) zusammen mit der Alignment-Unit welche die Befehls-Bytes ausrichtet und an die beiden Decoder weiter gibt.

Ich hatte mir für den ILD und der Alignment-Unit ursprünglich als Ziel gesetzt maximal mit einer Pipeline-Sufe zusammen mit einem Predecode-Bit pro Befehlsbyte auszukommen.
Ich arbeite schon mehr als ein halbes Jahr an diesen beiden Komponenten meiner CPU und hab schon mehrere Entwürfe ausgearbeitet, welche aber allesamt mein selbst gesetztes Ziel verfehlt haben.
Die große Schwierigkeit ist die große Komplexität des x86-Befehlssatz. Zum einem kann ein Befehl 1 bis 15Byte lang sein zum anderen befindet sich das erste Opcodebyte nicht immer am ersten Befehlsbyte sondern bedingt durch die Prefix-Bytes an verschieden Stellen im Befehl.
Meine drei besten Entwürfe für den ILD und der Alignment-Unit sind folgende:

  • Den Kompletten ILD und die Alignment-Unit direkt in der CPU-Pipeline implementieren. Der Entwurf basiert auf diesen beiden Patenten : https://www.google.com.au/patents/US6260134 https://www.google.com/patents/US7818542
    Es werden zunächst 16Bytes aus einem kleinem Buffer -welcher die I-Cache von dem Rest der CPU trennt- herraus geladen. Anschließend schiebt ein Shifter 8Byte der 16 Bytes entweder an die Startposition eines Befehls(z.b nach einem Sprungbefehl) oder an das Ende der letzten 8 Bytes. In diesen 8 Bytes gibt es 8 mögliche Startpositionen von maximal 8 möglichen Befehlen. Daher wird nach dem Shiften mit Hilfe 8 ILD für jedes Bytes die Längen 8 möglicher Befehle parallel Dekodiert. Im Anschluss werden diese 8 Befehlsbytes zusammen mit den ILD-Informationen in einem kleinen 24Byte Buffer zwischen gespeichert. Die 8 ILDs verwenden die letzten 8 Bytes aus diesem Buffer als zusätzliche Informationsquelle (falls ein Befehl die 8 Byte-Grenze überschritten hat). Die Alignment-Unit verwendet den 24Byte Buffer um die entsprechenden Instruction-Bytes zu laden  und anhand den ILD-Informationen in die richtige Position zu schieben.
    Dieser Entwurf hab ich nur grob ausgearbeitet. Insgesamt benötigt die Schaltung 3 Pipeline-Stufen um die geforderte Takt-Fequenz zu erreichen. Zusätzliche Predecode-Bits werden aber nicht benötigt.
  • Predecoder vor der I-Cache. Dieses Konzept basiert auf drei Intel-Patente und sieht dem ILD und Alignment-Unit der Silvermont Architektur nicht unähnlich :-D : https://www.google.com/patents/US6539469 https://www.google.ch/patents/US20130290678 https://www.google.com/patents/US5586276 . Als Predecoder war das oben genannte Patent angedacht: https://www.google.com.au/patents/US6260134
    Ein Predecoder dekodiert Befehle, die in die Instruction-Cache geladen werden, vor und markiert mit einem zusätzlichen Bit pro Befehls-Byte das Ende jedes Befehls. ByteBlöcke (16Byte) die aus der I-Cache geladen werden, werden in einen 12x8Byte umfassenden Prefetch-Buffer geladen oder über einen Bypass an die Alignment-Unit weitergereicht.
    Der Prefetchbuffer ist mit 3 Speicherblöcken a 4x8 Byte organisiert. In jedem Takt werden 3x8Byte (also pro Speicherblock 8Byte) aus dem Prefetchbuffer geladen und anschließend über drei 5:1 Multiplexer in die richtige Reihenfolge gebracht (es wird halt anhand des PC welcher die Alignment-Unit verarbeiten möchte ausgewählt welcher der drei 8Byte-Blöcke der erste, der zweite und der Dritte Block ist). Zusätzlich werden diese drei Multiplexer verwendet um den Bypass von der Cache an die Alignment-Unit zu organisieren.
    Die Alignment-Unit besteht in diesem Konzept aus zwei unabhängige Teile. Der erste Teil schiebt zunächt anhand der vorgegebenen Startposition( dem zu verarbeitenem PC) mit Hilfe eines 128Bit breiten 8:1 Multiplexers ein 16Byte Block an die Startposition des ersten Befehls. Daneben wird über einen zweiten 16Bit Breiten 8:1 Multiplexer die EndBits in die selbe Position gebracht und diese anschließend mit Hilfe eines Prioritizer das Ende des ersten Befehls gescannt. Falls der erste Befehl kürzer wie 9 Byte ist (Ansonsten bräuchte man für den zweiten Befehl einen 16:1 Mux) werden 8 Befehlsbytes des zweite Befehl mithilfe eines zweiten 64Bit 8:1 Multiplexer, welcher die gerichteten 128Bit des ersten Befehls verwendet, in ihre richtige Position gebracht.
    In Anschluss werden sowohl die 16 Befehls-Byte des ersten Befehls und die 8 Befehls-Byte des zweiten Befehls auf Prefix-Byte gescannt und ein weiteres mal geschoben, bevor sie an die Decode-Unit weitergereicht werden.
    Der Zweite Teil der Alignment-Unit scannt alle 24 EndBits parallel und bestimmt den PC, der im nächsten Takt-Zyklus verarbeitet wird.
    Dieses Konzept ist am besten ausgearbeitet. Es existiert schon ein Verilog-Code und ist schon im großen und ganzen fertig validiert. Bin aber irgendwie nicht richtig Zufrieden mit dem Konzept, es benötigt zwar nur ein Predecode-Bit pro Befehlsbyte, verbraucht aber zwei Pipeline-Stufen in der CPU. Auserdem werden die Befehlsbytes Unnötig oft geschoben.
  • Der Dritte Entwurf ist ein kompletter Eigenentwurf.
    Wie beim zweiten Entwurf werden werden die Befehlsbyte bevor sie in die I-Cache geladen werden vordekodiert. Diesmal wird aber der Start jedes Befehls markiert. Auserdem werden die Befehlbytes umsortiert. Prefix-Bytes welche immer am Anfang jedes Befehls stehen, werden nach hinten geschoben und als Suffixe an die vorherigen Befehlsbytes -welche vorgeschoben wurden- drangehängt. Die Suffixe werden mit einem zweiten Predecode-Bit markiert.
    Die I-Cache ist mit einem Way-Prediction Mechanismus ausgestattet und ladet die 16 Befehls-Byte direkt in einem 8x16Byte umfassenden PrefetchBuffer.
    Der Prefetchbuffer besteht aus 4 Teilblöcken mit je 8x4BefehlsByte. In jedem Taktzyklus ladet jeder Teilblock 4Byte und gibt sie an die nachfolgende Alignment-Unit weiter. Der Prefetchbuffer ist also in etwa so aufgebaut wie im Zweiten Konzept. In einer der 4Byte der vier Teilblöcke befindet sich der Startbyte des ersten Befehls. Die vier 4Byte werden jetzt aber nicht mit Multiplexer in die Richtige Position gebracht sondern direkt an einen Scanner weitergereicht welcher die Startbyte des ersten und zweiten Befehls erkennt. Mit zwei 16:1 Rotierer werden die beiden Befehle ausgewählt und zwei 8Byte Blöcke( jeder Befehl kann maximal 8Byte lang sein. Falls ein Befehl länger ist, wird nur ein Befehl pro Zyklus verarbeitet) und die nachfolgende Decoder weitergeschickt.
    Der Scanner sucht auch nach einem dritten Startbit welches den Start des nächsten Befehls markiert. Falls der Scanner kein drittes Startbit findet wird in diesem Zyklus nur ein Befehl verarbeitet.
    Für denn Fall das nur ein Startbit gefunden wurde, ist eine Speziallogik nötig. Die hab ich aber nocht nicht ganz zuende entworfen.
    Das Konzept benötigt nur eine einzige Pipeline-Stufe. Daher besitzt die CPU mit diesem Konzept eine extrem Kurze Pipeline, die Branch mispredict loop beträgt 7 Zyklen. Es werden aber 2 Predecode Bits pro Byte benötigt. Die I-Cache wird dadurch um 25% größer. Auserdem stellen sich Probleme mit der Branch-Prediction Unit ein, da diese jetzt nurnoch 1 Taktzyklus zeit hat um eine Vorhersage zumachen (Bzw. eine Branch-Byte-Mask zu generieren, welche die Scan-Unit benötigt). 

Ich bin derzeit ziemlich Unschlüssig welcher meiner Drei Konzepte (welche alle meine Spezifikation nicht ganz erfüllen) die geeigneteste für mein Projekt ist. Hat jemand Erfahrung mit diesem Komplexen Thema? Was haltet ihr von diesen drei Konzepten? Und habt ihr eventuell Anregungen und Verbesserungs-Vorschläge?

Mfg Tufel

PS: Ich hatte mir Vorgenommen in diesem Beitrag alles Unterzubringen was wichtig ist, Irgendwie ist Beitrag aber dadurch etwas länger geworden.  :-D
5
Offtopic / Re: Logisim CPU
« am: 03. November 2013, 13:15 »
So hab jetzt mal das datenblatt und die CPU nochmal ein wenig überarbeitet.

Edit: anscheindend ist das Datenblatt etwas zu groß, hab jetzt mal 1 satz rausgestrichen:

LoadRs und Store Rs sind nur im Systemodus aktiv, im Usermodus stellen sie ein nop dar.
6
Offtopic / Re: Logisim CPU
« am: 02. November 2013, 23:11 »
Nun hab ein Weiteres Datenblatt geschrieben, für eine 32bit risc- CPU mit 16 bit Befehlen.
7
Offtopic / Re: Logisim CPU
« am: 16. October 2013, 22:25 »
Zitat
Grundsätzlich: Du möchtest mindestens einen 24-Bit Adressraum und mindestens 32 (besser: 64, wegen Erweiterungen) Befehle. Alles darunter macht keinen Spaß beim Programmieren. (Ja, ich weiß, ein Z80 hat auch nur einen 16-Bit Adressraum, aber als über 35 Jahre alter 8-Bitter darf der das.)

Nun gut dann bau ich intern meine CPU zu einer 32 bit cpu um (mit 32bit registern und einer 32bit alu) , extern hat er dann aber nur noch einen 24bit adressbus und noch den 16bit datenbus.
Die Befehlslänge Bleibt bei 16bit.

Es gibt immernoch 16 Befehle und 16 register.
Das Registerset ist folgenermaßen aufgebaut:
Reg0 = Nullregister,
Reg1-Reg12 = Normale Register
R13 = Flagregister
R14 = Linkregister
R15 = Programmcounter


So das hier sind die 16 Befehle:
  • add
  • sub
  • and
  • or
  • not
  • shift
  • jump
  • store
  • load
  • softint/Ret
  • mul
  • addi
  • subi
  • loadByte
  • addc
  • sbb

die Befehle addi/subi sind nur 2 operanten Befehle(also z.b addi Reg1, 0xFF, also Reg1 = Reg1 + 0xFF )
In den Befehlen Store und Load gibts noch zusätzlich einen 4bit offset.Bei Store wird der 4bit offset von dem adressregister abgezogen und bei load draufaddiert(so kann man Load/store als normale Load/store benutzen indem man den offset auf 0 lässt, oder man verwendet die 2 Befehle als Pop/push indem man den offset auf z.b 1 setzt.)Auserdem werden Bei Load/store nur die unteren 16 bits des Quell bzw Zielregister benutzt.

der befehl shift so aufgebaut: 0-3 Opcode | 4-6 Shiftart | 8-12 shiftweite | 13-16 Register.
shiftart : srl, sll, ror, sra
die shiftweite sagt aus wie weit geshift werden soll

Beim Befehl jump werden keine Flags gesetzt sondern nur geschaut welche Flags gesetzt sind, auserdem kann man über ein Bit entscheiden -falls die richtigen flags gesetzt sind- ob ein Wert aus einem Register oder einen Kostanten wert ( der an der adresse liegt auf dem der PC zeigt) in den PC geladen wird.

Der Befehl LoadByte ladet einen 8 bitwert in das gesamt Register.
8
Offtopic / Re: Logisim CPU
« am: 13. October 2013, 15:02 »
So , ich hab mich jetzt dazu entschlossen erstmal eine kleinere 16bit CPU zu bauen(hab das Datenblatt als pdf angehängt). Nun was hält ihr von meiner CPU und von meinem Datenblatt ? :D
9
Offtopic / Re: Logisim CPU
« am: 01. August 2013, 15:30 »
Zitat
Du hast also extra ports an deiner cpu für diese spezielle peripherie? ich würde tatsächlich einen MMIO Design verwenden, sodass du einfach den IO in den speicher einblendest über einen AdressController, der im bestenfall einfach ein multiplexer ist. Je nach andresse kannst du dann ja die peripherie endweder nach deinem design an den bis anschliessen, sodass es einen port als controllpfad gibt und einen als datenpfad, oder aber gleich einen port je peripherie, oder mehr.
Naja Der I/O bus und der Ram-Bus wollte ich eigentlich über einen sogenannten Bus-Controller in der CPU miteinander Verbinden. So das es zu ein MMIO design wird.

Nun,  ich glaub ich lass das wieder mit dem eigenem Demoboard sein und kauf mir ein Fertiges FPGA board. Ein eigenes Demoboard zu entwickeln wird einfach zu schwierig für mich ...
Naja kann mir einer ein FPGA board empfehlen ?
10
Offtopic / Re: Logisim CPU
« am: 30. July 2013, 23:20 »
Naja ich glaub ich überschätz mich wieder total :-D , aber ich hab jetzt ein Demoboard entwickelt. Hier mal das grobe Design.



3bit - Sysbus beinhaltet : RAS0,CAS0, WE
2bit Sysbus beinhaltet : takt, WE.

Nun es gibt nur 1 SIMM-Modul das 16MB groß ist und nur bei Defekt gewechselt wird.
Bei einem Reset wird zunächst das Bios von der ROM in den Ram geladen und ausgeführt.
Und der SS-Bus ist dafür da einer der drei Slaves(Atmega16, Atmega32 & SID 6581) auszuwählen.
Auserdem kann der ATmega 32 nur einen schwarz-weiß textmode ausführen.

So was hält ihr davon, und hat jemand noch dazu ne frage ?
11
Offtopic / Re: Logisim CPU
« am: 27. July 2013, 17:31 »
Mhh nun der Interrupt-Controller ist dann auch schon fertig geplant.  Naja und der VHDL-Code vom meiner CPU ist auch schon fast fertig. Ich glaub jetzt kann ich mir gedanken zu hardware-umsetzung machen :D. Hat dazu jemand ne idee wie ich das am besten mache ?
12
Offtopic / Re: Logisim CPU
« am: 25. July 2013, 23:25 »
Zitat
Unterbrechen würde ich nur nach ganzen Befehlen, also jeweils am Ende deiner 2 Taktzyklen. Das erspart dir jede Menge Arbeit, da du nicht speichern musst wo dein erster Zyklus unterbrochen wurde (zu Beginn, nach dem Befehl hohlen, nach dem IP inkrementieren)
Mhh bei mir dauert ein takt-zyklus ,1 takt( also 2 takte für einen befehl) Nun wird der erste Takt-zyklus unterbrochen und stattdessen der Interrupt-Befehl ausgeführt, ist das doch am ende der beiden letzten taktzyklen ?   

Zitat
Und denke dran für deine Notfall-Interrupts ein änliches Register wie das EPC vorzusehen, sonst kann es sein dass es Probleme mit dem Wiedereintritt in deinen eigendlichen Interrupt-Handler gibt.
Ah danke, das hab ich ganz übersehen :D

Zitat
Du solltest außerdem Interrupts zuerst latchen, bevor du sie ausführst, damit kein Int verloren geht, der während einem anderen gleichrangigen Int auftritt.
Joar stimmt, dann bau ich das auch ein.
13
Offtopic / Re: Logisim CPU
« am: 25. July 2013, 18:33 »
Zitat
Es ist einfacher einen Befehl nicht zu unterbrechen, sondern ihn immer zu Ende laufen zu lassen. Wenn man dann den IP speichert, der ja schon auf den nächsten Befehl zeigt, kann man nach einem 'iret' einfach da weitermachen wo man unterbrochen wurde.
Ah ok, ich hab jetzt mal dann ein Interrupt-Controller entwickelt. Zunächst mal führt meine CPU jetzt ein Befehl immer in 2 takt-zykluse aus ( 1 Takt:Befehl laden,IP erhöhen ; 2 Takt: Befehl ausführen). Nun nur der erste Takt-zyklus( 1 Takt:Befehl laden,IP erhöhen) kann durch ein Interrupt  unterbrochen werden. Tritt ein Interrupt auf während sich die CPU im 2 Zyklus befindet, muss gewartet werden bis sich die CPU wieder im ersten Zyklus befindet.

So jetzt zum eigentlichem Interrupt-Controller: Es gibt 2 arten von Interrupts -die "normale Interrupts" und die "Notfall Interrupts"-  Ein Normales Interrupt kann nur durch ein Notfall-Interrupt unterbrochen werden. Und ein Notfall-interrupt kann nie unterbrochen werden. Nun der Controller ist ähnlich aufgebaut wie der Interrupt-Controller von Mips. Bei einem Interrupt wird der IP in ein sogenanntes EPC-Register geladen, danach wird die Adresse von Interrupt-Handler in den IP und die Ausnahmen-Ursache in das Register R30 geladen.Das EPC-Register und Das register für die Adresse des interrupt-Handler sind jeweils an den Bus angeschlossen.Treten 2 Interrupts vom selben Typ auf, wird nach dem round-robin-verfahren entschieden wer als erstes dran kommt. Tritt ein Notfall interrupt und ein Normales Interrupt gleichzeitig auf hat das Notfall-Interrupt natürlich vorrang.
14
Offtopic / Re: Logisim CPU
« am: 25. July 2013, 10:52 »
Mhh, ok. Hätte da noch eine weitere frage:
Sollte bei einem interrupt eher die adresse vom befehl der gerade unterbrochen wird, abgespeichert werden oder die Adresse die im Programmcounter steht und auf den nächsten Befehl zeigt?

15
Offtopic / Re: Logisim CPU
« am: 22. July 2013, 17:21 »
Zitat
Es ist deine CPU.
Mhh nun wenn keiner ne andere idee hat, bau ich mein system ein.

Auserdem hab ich jetzt mir mal gedanken zum Interruptcontroller gemacht, kann man den ein interrupt in einer interrupt-service-routine auslösen ?
16
Offtopic / Re: Logisim CPU
« am: 19. July 2013, 23:20 »
Zitat
Das ist dasselbe in grün. Statt einer Steuerleitung, die zwischen Speicher und Hardware umschaltet, schaltet dann die oberste Adressleitung zwischen Segment 0 (Speicher) und Segment 1 (Hardware) um. Vorteil: Du kannst mit den normalen Befehlen deine Hardware erreichen. Nachteil: Jetzt muss jeder Befehl, der Speicher adressieren kann, den aktuellen CPU-Modus kennen...
Naja die speziellen Befehle die auf die hardware zugreifen können, müssen doch auch den CPU modus kennen oder ?  :-)

Zitat
Ja. Dann muss die MMU pro Task statt 4 MB nur noch 1 MB speichern - immernoch zu viel.
Mhh wie wärs wenn ich mein altes konzept wieder aufgreife(das mit den beschränkte bereiche und dem CO-prozessor) und anstatt es über ein co-prozessor zu integrieren ,einfach an den bus anschließe.
17
Offtopic / Re: Logisim CPU
« am: 13. July 2013, 13:04 »
Zitat
Doch ist es, vor allem da es nicht 1MB sondern ganze 4MB sind (jede Adresse enthält 4 Byte um 32Bit Adressen aufnehmen zu können). Das Gute daran ist, das es wenn der SRAM einmal beschrieben ist es nie zu PageFaults kommen kann. Der riesengroße Nachteil ist dass es ewig dauert bis bei einem Taskwechsel der RAM neu beschrieben ist. Den SRAM verkleinern kann man leider auch nicht so ohne weiteres, da mann ja für jede virtuelle Adresse die von der CPU kommt einen Eintrag haben muss. Jetzt könnte man ja versuchen die Adressen auf weniger Einträge zu verteilen, womit wir dann wieder am Anfang wären.
Man könnte ja die pagegröße erhöhen(z.b von 4kb auf 16 kb) dann benötigt man ja weniger Sram da es weniger Pages gibt oder ?

Zitat
Das klingt wieder so kompliziert und gibt bei einem sehr kleinen Kernel sehr viel verschwendeten Platz. Ich würde eher dafür sorgen dass der Kernel bestimmen kann wann er in den Usermode wechselt, und das unabhängig davon wo er sich gerade befindet. Wichtig ist nur das der Usermode nicht einfach in den Kernelmode springen kann, das sollte dann nur über Interrupts geschehen, da der dann ausgeführte Code vom Kernel ist und nicht vom User.
Naja wie wärs dann mit ein paar steuerbit in jedem SRAM eintrag ? Die dann bestimmen ob man auf das Page nur im kernel modus zugreifen kann oder im usermodus nur gelesen werden kann oder ob man es im usermodus lesen und beschreiben kann. Und joar, bei mir wirds auch so sein das man nur über interrupts in den kernelmode kommt.
18
Offtopic / Re: Logisim CPU
« am: 12. July 2013, 23:58 »
Zitat
irgendwie gefällt mir dein Ansatz mit den erlaubten Bereichen und dem Co-Prozessor nicht. Das klingt alles so kompliziert.

Nun ok ich wollte eigentlich auch für die interruptbehandlung nen CO-prozessor einbauen(so ähnlich wie bei mips), soll ich den auch steichen?

Zitat
Eine MMU ist im einfachsten Fall ein SRAM. Bei jedem Speicherzugriff gehen die unteren 12 Bit der (physischen) Adresse an den Adressbus (ergibt 4 KB/Page) und die restlichen, oberen Bits an das SRAM der MMU. Das Datenwort, welches aus diesem SRAM kommt, nimmst du dann als die neuen (virtuellen) oberen Adressbits. Der Inhalt dieses SRAMs enthält dann dein Mapping und muss natürlich irgendwie vom Betriebssystem aus änderbar sein - und unterliegt damit wie jede andere Hardware auch dem Zugriffsschutz(*).
Mhh der SRAM muss ja dann 1 MB groß sein oder? Ist das nicht etwas zu viel ?



Zitat
(*) Wenn du für Hardware einen getrennten Adressraum vorsiehst, ist das recht einfach. IN/OUT dürfen nur im Kernelmodus verwendet werden, denn MMU und Hardware sind Aufgaben des Betriebssystems. READ/WRITE dürfen immer verwendet werden und wenn auf eine ungültige Adresse zugegriffen wird, löst die MMU nachträglich einen Page Fault aus.
Naja hab eher an einen gemeinsamen Adressraum gedacht, wie wärs wenn ich den adressraum in 2 segmente unterteile(die größen der segmente sind immer gleich). Auf das erste Segment kann man nur im kernelmode zugreifen und auf das zweite kernelmode und usermode.



19
Offtopic / Re: Logisim CPU
« am: 07. July 2013, 22:45 »
Nun ich glaub der Svenska hat recht... ich hab versucht die MMU und die CPU in VHDL zu realisieren.
Und ihrgentwie ist mir Die CPU mit der MMU zu kompliziert, daher werd ich die MMU weglassen, die CPU greift direkt mit der physischen adresse auf den bus zu und ein Co-Prozesser prüft ob die CPU gerade berechtigt ist auf die adresse zuzugreifen..

Dazu besitzt der Co-Prozessor 4 registerpaare mit je 2 registern. Jeweils eines der register in einem Registerpaar, markiert der anfang eines Bereichs auf der die CPU zugreifen darf und das andere Register markiert das Ende dieses Bereiches.(also insgesamt kann man im Co-Prozessor 4 Bereiche makieren).

Auserdem kennt sich jemand mit vivado 2013.2 aus?Ich hab da ein Problem mit dem simulator, der öffnet sich zwar aber wenn ich versuche die simulation zu starten Kommt diese Fehlermeldung:
ERROR: [Simulator 45-1] A fatal run-time error was detected. Simulation cannot continue.
Hab schon alles versucht, nicht einmal bei den Projekt-Beispiele funktioniert der simulator.
20
Offtopic / Re: Logisim CPU
« am: 24. June 2013, 20:35 »
Zitat
Lies Dir dazu mal die Tutorials hier auf der Seite durch (OS-Dev für Einsteiger), da wird die MMU zu Beginn auch nicht benutzt und da steht auch drin was man machen muss um Multitasking ohne MMU zu implementieren.
Wow sieht interessant aus.

Nun ich werd jetzt wohl das Konzept der Mips-MMU übernehmen, mit nem TLB mit 32 einträge. Die größten Probleme habe ich noch mit der Verdrängungs-taktik welche eignet sich den am besten für eine einfache TLB-Cache ?
Seiten: [1] 2 3 ... 6

Einloggen