Kürzlich gab es die Diskussion, ob man in einem FPGA einen Prozessor implementieren kann. Und natürlich, man kann. Zu diesem Zweck (und um VHDL zu trainieren) habe ich mich hingesetzt. Ein paar Datenpfadelemente wie Multiplexer, Adressdecoder und Register habe ich bereits gebastelt, jetzt geht es aber an die Frage: ** Welche Architektur solls denn werden? ** Es gibt 2 Möglichkeiten: 1. Etwas eigenes. Nachteil: - Man muss sich selbst Assembler und Compiler basteln, wenn man das Ding richtig testen oder gar einsetzen möchte. 2. Eine bestehende Architektur nachbauen. Nachteil: - Man muss die bestehende Architektur komplett und korrekt interpretieren und nachbauen, um eine bestehende Toolchain zu benutzen. Vereinfachungen oder andere Modifikationen liegen nicht drin. Jedenfalls suche ich nun nach ein paar Vorschlägen für Architekturen, es dürfen sowohl interessante bestehende Prozessoren sein oder auch Ideen für neue Ansätze.
AooA schrieb: > 2. Eine bestehende Architektur nachbauen. > Vereinfachungen oder andere Modifikationen liegen nicht drin. Warum nicht? Auch die ganzen 8051-Derivate, die seit 1995 erschienen sind, sind Opcode-kompatibel und trotzdem bis zu 12 mal schneller als der Original-8051. Und das nicht wegen der Erhöhung der Taktfrequenz, sondern weil die Befehle in 1 statt in 12 Taktzyklen ausgeführt werden...
AooA schrieb: > Kürzlich gab es die Diskussion, ob man in einem FPGA einen Prozessor > implementieren kann. Und natürlich, man kann. Zu diesem Zweck (und um > VHDL zu trainieren) habe ich mich hingesetzt. Ein paar Datenpfadelemente > wie Multiplexer, Adressdecoder und Register habe ich bereits gebastelt, > jetzt geht es aber an die Frage: > > ** Welche Architektur solls denn werden? ** > > Es gibt 2 Möglichkeiten: > > 1. Etwas eigenes. > Nachteil: > - Man muss sich selbst Assembler und Compiler basteln, wenn man das Ding > richtig testen oder gar einsetzen möchte. Oder man nimmt einen Assembler mit ähnlichen output und sortiert die bits um. Das ist dann einfacher als einen assembler komplett selbst zu schreiben. Die op-codes sind nicht so unterschiedlich, irgendwelche bits adressieren die register, andere die Operation, und da mal ein paar bits zu verschieben sollte das nicht das problem sein. Und gab es da nicht Assembler-Compiler?, Also Software mit der du deinen Assembler selbst zusammenstricken kannst. Oder waren das Universalassembler?. GNU hat bestimmt auch was im Quellcode, das sollte das assembler.basteln auch nicht so schwierig sein. MfG,
@AooA ich bin gerade ebenfalls mit einem Softcore dran. Allerdings habe ich mich für Lösung 2 entschieden. Es ist zwar kein schneller Prozessor (durch ein langsames aber universelles Speicherinterface, kein RISC, und "klassisches" Design brauche ich viele Takte bis der Befehl abgearbeitet ist) aber mir geht es auch erstmal um einen Einstieg in die Softcores um zu sehen welche Teile eines Prozessors am meisten Logik benötigen, bzw wie man was anders gestalten kann um einen solchen Prozessor klein zu bekommen. Den Reiz am selbstentworfenen Design finde ich darin das ich selbst bestimmen kann was der Prozessor kann. Ich habe bei mir z.b. eine 16-Bit Architektur in der nahezu jeder Befehl bedingt ausführbar ist, weil ich das von der programmierung her elegant finde. Einen Assembler dafür zu bauen ist kein Problem. Ein C-Compiler dürfte um Klassen komplexer sein (wenn ich das überhaupt in Angriff nehme). Aber da ist man wieder bei pro und contra Selbstbau/Nachbau :-)
Rene Böllhoff schrieb: > kein RISC, und > "klassisches" Design brauche ich viele Takte bis der Befehl abgearbeitet > ist Ich für meinen Teil würde schwer zu einem RISC tendieren. Es ist von Architektur und Simulation her einfach deutlich übersichtlicher, wenn die Daten in jedem Prozessortakt einmal durch den ganzen Datenpfad laufen und wieder sauber zurückgeschrieben werden. Bei einem CISC hingegen wird man die ganzen Zwischenzustände in jedem Mikroschritt analysieren müssen.
Wie wäre es mit der Architektur von Chuck Thacker: http://lambda-the-ultimate.org/node/3232 ? "Presents the design of a complete CPU in under two pages of FPGA-ready Verilog. The TC3 is a Harvard architecture 32-bit RISC with 1KB of instruction memory, 1KB of data memory, and 128 general-purpose registers." Alternativ gäbe es noch MMIX von Donald Knuth: https://secure.wikimedia.org/wikipedia/en/wiki/MMIX . Dort bekommt dann z.B. den gcc dafür.
Ein kleiner 4-Bitter im Stil eines Intel 4004 habe ich mal aufgezeichnet. Den dürfte man wohl fast in ein CPLD bringen, was man als ziemlich coole Bastelei präsentieren könnte. Problematisch bei Architekturen mit so geringer Wortbreite ist aber immer das Handling von Programmcounter, Stack und Instruktionsregister. Diese sind viel breiter als die Datenregister und können somit, im Gegensatz zu einer Architektur mit grösserer Wortbreite, nicht direkt über den normalen Datenpfad abgewickelt werden. Beispielsweise eine call-Anweisung bei 4 Bit Wortbreite, 12 Bit Programmcounter und 12 Bit Datenadressen. Alleine das Speichern des Programmcounters auf dem Stack benötigt also 3 Speicherzugriffe, die wiederum jeweils 3 Addieroperationen brauchen, um den Stackpointer nachzuführen.
Hendrik Lipka schrieb: > Wie wäre es mit der Architektur von Chuck Thacker: > http://lambda-the-ultimate.org/node/3232 ? > Alternativ gäbe es noch MMIX von Donald Knuth: > https://secure.wikimedia.org/wikipedia/en/wiki/MMIX . Dort bekommt dann > z.B. den gcc dafür. Der obere ist bereits von der Architectur her an (Xilinx-) FPGA's angepasst, indem er die Prozessorregister statt aus einzelnenen FF- aus einem Embeded DualPort bastelt. Allerdings scheint mir (nach flüchtiger Durchsicht) ein Unterprogrammaufruf zu fehlen, ebenso wie ein Interrupt. Ohne den MMIX genau zu kennen befürchte ich, das dieser nicht für FPGA's angepasst wurde und daher wahrscheinlich langsam ist. MfG,
Sorry fuer den Offtopic, ich habe aber eine Frage bezueglich ein ARM Klon. Ich habe hier ein Spartan 3E 500K Board und ueberlege was ich damit machen sollte. Reicht eigentlich ein Spartan 3E fuer ein ARM Klon oder braeuchte man mindestens ein Virtex2? Ich habe mir die ARM Architecture Reference Manual(fast 1200 Seiten) runtergeladen und will es die Tagen mal angucken. Danke im voraus. Gruss, Valentin
Vor 30 Jahren war der 6502 der Inbegriff von RISC: wenig Register (A,X,Y,SP,PC,Flags), hartverdrahtete Befehle (zumindest in der NMOS-Version), einfache Architektur. Wenn Du dann noch Energie hast, darfst Du Dich gerne bis zum 65816 hocharbeiten. Siehe 6502.org Willst Du eine aktuelle Architektur, wäre MIPS erwähnenswert, weil wirklich ziemlich RISCig. fchk
Ich würde auch zu einer RISC Architektur raten. Einen eigenen Assembler zu machen ist eigentlich kein großes Ding und wie aufwändig die Hardware wird hängt davon ab, wie du deine Befehle kodierst und welche Adressierungsarten du dir gönnen magst. Hinzukommen dann evtl. noch solche Sachen wie Interrupts, Exceptions, Branch-Prediction, Pipelining usw. je nach Zeitaufwand halt. No RISC no fun ;)
Frank K. schrieb: > Vor 30 Jahren war der 6502 der Inbegriff von RISC: wenig Register > (A,X,Y,SP,PC,Flags), ?Ist es nicht gerade ein Merkmal von RISC viele Register in der CPU zur Verfügung zu stellen? MFG,
AooA schrieb: > Kürzlich gab es die Diskussion, ob man in einem FPGA einen Prozessor > implementieren kann. Und natürlich, man kann. Zu diesem Zweck (und um > VHDL zu trainieren) habe ich mich hingesetzt. Ein paar Datenpfadelemente > wie Multiplexer, Adressdecoder und Register habe ich bereits gebastelt, > jetzt geht es aber an die Frage: > > ** Welche Architektur solls denn werden? ** > > Es gibt 2 Möglichkeiten: > > 1. Etwas eigenes. > Nachteil: > - Man muss sich selbst Assembler und Compiler basteln, wenn man das Ding > richtig testen oder gar einsetzen möchte. Es sollte recht einfach sein, sich einen Quick und dirty assembler per Spreadsheet (Excel;OO Calc)zusammenzubasteln. Ein Instruction wort mit seiner seinen fest zugeordneten Bitfeldern ist doch recht einfach auf einige Spalten Excel abgebildet, meinetwegen noch mit Auswahlmenü für die Operations-Mnemonics. zum Schluss wird dann der Inhalt eines Feldes mit einer Zweierpotenz multipliziert, alle Felder addiert und in Hex angezeigt. Weitere Vorschläge schnell einen Assembler zu schreiben. MfG
Fpga Kuechle schrieb: > ?Ist es nicht gerade ein Merkmal von RISC viele Register in der CPU zur > Verfügung zu stellen? Nein (Ja (Jain)) Siehe http://de.wikipedia.org/wiki/RISC
D. I. schrieb: Hinzukommen > dann evtl. noch solche Sachen wie Interrupts, Exceptions, > Branch-Prediction, Pipelining usw. je nach Zeitaufwand halt. Pipelining (und damit verbunden Sprungvorhersage) erfodert schon größere Umbauten an der CPU, das ist kein "hinzukommen" mehr. Man sollte schon im voraus eine sinvolle Anzahl von Pipelinestufen abschätzen. Bei einem FPGA mit 6er oder 4er LUT sollten es 2 oder drei sein. Bei einer so kurzen Pipeline macht sprungvorhersage wenig Sinn. Und mit einer Ein-takt maschine ohne Pipeline kann man in einem FPGA schon (für Embedded) ordentliche taktraten von 60 - 100 MHz erreichen. Der Aufwand einen IRQ nachzurüsten ist eher gering. sollte aber meines erachtens von anfang an in dem Programmcounter mit eingebaut sein. Notwendigkeit von Exceptions ist nicht ersichtlich, welche Ausnahmebehandlung meinst Du? MfG,
Frank K. schrieb: > Vor 30 Jahren war der 6502 der Inbegriff von RISC: wenig Register > (A,X,Y,SP,PC,Flags), hartverdrahtete Befehle (zumindest in der > NMOS-Version), einfache Architektur. Das passiert, wenn man RISC nur als Reduktion des Befehlssatzes sieht. Sieht man es eher als Reduktion des Ablaufes (IBM Power: C=complexity statt computing) durch ein Architekturschema mit einfachen Operationen auf Register und davon getrennten einfachen Lade/Speicheroperationen, also einer Load/Store-Architektur, dann ist der 6502 aufgrund des recht komplexen Befehlsablaufs speicherindirekter Rechenoperationen kein bischen RISC. Unter den frühen 8-Bittern passt ins RISC-Schema eher RCA 1802.
Ich knüpfe mal an die RISC Diskussion an, da ich noch ein wenig Schwierigkeiten habe mir bestimmte Abläufe vorzustellen. Das Prinzip das mit jedem Takt ein Befehl abgearbeitet wird ist klar. Das (je nach Anzahl der Stufen) dadurch eine Sprungvorhersage nötig wird ist auch klar. Und das die Einheiten (Fetch/Decode/Execute) parallel arbeiten und mit jedem Takt ein Ergebnis ausspucken auch. Mein Problem beginnt bei der Umsetzung. Wenn ich z.b. einen einzigen Speicherbereich habe greife ich mit jedem Takt ja auf diesen Speicher lesend zu (um meinen Opcode rauszufischen). Aber wenn ich nun ein Ergebnis in den Speicher zurückschreiben möchte, muß ich ja eine andere Adresse, ein Datenwort und die Toggle-Leitung für RW/OE (klassisches SRAM) bedienen. Da ich aber ja auch noch Setup/Holdzeiten beachten muß, bzw erstmal einen Takt warten muß bevor ich mein Datenwort auf den Datenbus lege (nachdem ich diesen vorher in Tri-State geschaltet habe, damit möglicherweise 2 Ausgänge nicht gegeneinander treiben) habe ich ja schon mindestens zwei Takte um den Speicherzugriff umzuschalten. Und da ist mein Problem. Das eine ALU oder ein Dekoder in einem Takt fertig sein kann, kein Thema. Aber wie läuft das bei Speicherzugriffen die allein durch die Umschaltung schon evtl. mehrere Takte benötigen ? Oder wird da unterschieden zw. Systemtakt und Prozessortakt die in einem festen Verhältnis (2:1, 3:1, 4:1) stehen damit auch Lese/Schreiboperationen möglich sind während die Stufen fröhlich vor sich hintakten. Oder ist da ein Denkfehler meinerseits ?
Grundlegend: das Speicherinterface ist nicht Bestandteil des Prozessors. Dieses Interface muß natürlich so aufgebaut sein, dass der Code und die Daten hinreichend schnell bereitgestellt werden. Sonst muß der Prozessor Wartezyklen einlegen. Auch bei AVR-Controllern brauchen Befehle, die auf den Programmspeicher gehen, mehrere Zyklen. Zugriffe auf den Datenspeicher laufen aber wegen der Harvard-Architektur parallel zu Programmspeicherzugriffen.
>Dieses Interface muß natürlich so aufgebaut sein, dass der Code und die >Daten hinreichend schnell bereitgestellt werden Wäre eine Lösung dieses Problems also das Speicherinterface mit der doppelten oder vierfachen Geschwindigkeit laufen zu lassen damit "parallel" zu einem Lese-befehl ein Schreib-Befehl ausgeführt werden kann ? >Harvard-Architektur Ok, da ist das Problem vllt nicht so gegeben, obwohl ich da ja u.u. auch mehrere Takte benötige. Aber ich dachte eher an von-Neumann, da man dort je nach Speicher einfach mehr "drankleben" kann, ohne direkt einen 2. Adress/Daten/Steuer-Bus haben zu müssen. Wie könnte ein solches Speicherinterface aussehen ? Ich meine ich brauche ja auch u.u. noch 1-2 Takte Latenz damit der Prozessor bescheid weiß das der Speicher mal wieder nen Snickers braucht. Ich arbeite bei mir momentan immer mit einer Trigger und Ready-Leitung. Dadurch kann der Speicher intern oder extern/schnell oder langsam sein. Aber die Zugriffe da, benötigen noch mehr Zeit (zw 4-6. Takte). Irgendwie tu ich mich mit dem Speicherzugriff bzw "parallelen" Zugriff etwas schwer.
Rene Böllhoff schrieb: > Mein Problem beginnt bei der Umsetzung. Wenn ich z.b. einen einzigen > Speicherbereich habe greife ich mit jedem Takt ja auf diesen Speicher > lesend zu (um meinen Opcode rauszufischen). Solange du nur ein Speicherinterface hast, ist das mit einem Takt pro Befehl auf Lade/Speicherbefehle nicht anwendbar. Daher führen Lade/Speicherbefehle entweder zu Befehlen, die mehr als einen Takt benötigen, oder es existieren mehrere Interfaces, getrennt nach Code und Daten. Letzteres ist bei Caches und bei internem Speicher von Controllern recht verbreitet (AVR, Cortex-M3, ...). > Und da ist mein Problem. Das eine ALU oder ein Dekoder in einem Takt > fertig sein kann, kein Thema. Aber wie läuft das bei Speicherzugriffen > die allein durch die Umschaltung schon evtl. mehrere Takte benötigen ? Es stellt sich die Frage, ob das wirklich sein muss. Oder ob durch geeignetes Pipelining Zugriffe teilweise überlappen können.
Lothar Miller schrieb: > Grundlegend: das Speicherinterface ist nicht Bestandteil des Prozessors. Kommt drauf an, wo man mit dem Begriff "Speicher" ansetzt. Wenn man Caches als Speicher sieht, dann sind diese durchaus Bestandteil des Prozessors. Wenn man das Interface erst jenseits der Caches sieht, dann kann man das ggf. getrennt betrachen.
Hardvard Architecture, Contrast with von Neumann architectures Under pure von Neumann architecture the CPU can be either reading an instruction or reading/writing data from/to the memory. Both cannot occur at the same time since the instructions and data use the same bus system. In a computer using the Harvard architecture, the CPU can both read an instruction and perform a data memory access at the same time, even without a cache. A Harvard architecture computer can thus be faster for a given circuit complexity because instruction fetches and data access do not contend for a single memory pathway .
Beispiele für eine Architektur mit nur einem Speicherinterface und mit den daraus resultierenden Nebeneffekten hinsichtlich des kritischen Speichertimings sind die älteren ARM Cores (ARM2..ARM7). ARM2 war noch für externen Speicher ohne Cache konzipiert und unterschied zwischen sequentiellen Zugriffen und nichtsequentiellen. Sprünge waren klarerweise nichtsequentiell, aber auch Lade/Speicherbefehle führten dazu, erstens beim Datenzugriff selbst, zweitens beim darauf folgenden Codezugriff. In vielen Systemen waren nichtsequentielle Zugriffe einen Takt langsamer. Entsprechendes Timing ist m.W. auch beim ARM7 noch dokumentiert.
A. K. schrieb: > ARM2 war noch für externen Speicher ohne Cache konzipiert und > unterschied zwischen sequentiellen Zugriffen und nichtsequentiellen. > Sprünge waren klarerweise nichtsequentiell, aber auch > Lade/Speicherbefehle führten dazu, erstens beim Datenzugriff selbst, > zweitens beim darauf folgenden Codezugriff. In vielen Systemen waren > nichtsequentielle Zugriffe einen Takt langsamer. Entsprechendes Timing > ist m.W. auch beim ARM7 noch dokumentiert. Richtig. Erst mit dem ARM8 Kern wurde die Pipeline auf fünf Stufen verlängert, so daß Address und Datenphase in unterschiedlichen Stufen ablaufen. Seit dem kann man register- und datenunabhängige, nichtsequentielle Speicherzugriffe ohne Wartezyklen ausführen, vorausgesetzt, der Speicher kann mithalten. Bei den moderneren Cores mit dreistufiger Pipeline (Cortex-M) werden wiederum andere Tricks angewandt, um die Speicherzugriffe meist ohne Wartezyklen ablaufen zu lassen. Das ist aber nicht immer möglich. @Rene: Zum Thema Tri-State: Vergiss es. Keine moderne Architektur verwendet mehr echte Busse. Orientiere Dich lieber and den verschiedenen "Bus"-Systemen, die kommerziell eingesetzt werden. Ich könnte an dieser Stelle auf einen Artikel verweisen: http://www.doulos.com/knowhow/arm/Migrating_from_AHB_to_AXI/ Mach' ich aber nicht, da es als Eigenwerbung verstanden werden könnte :-) Gruß Marcus
@Markus Hätte ich das mit dem "Tri-State-Vergessen" so zu verstehen das ähnlich wie bei den FPGA's es keine bidirektionalen Busse mehr gibt, sondern nur noch unidirektionale, und die "schnelle" Umschaltung an der Anbindung zum RAM (egal ob SRAM/SDRAM/DDR-RAM) der Speichercontroller vornimmt ? Also das intern ein Data-In- und Data-Out-Bus existiert der das Timing auf intern einen Takt herunterbricht ? Ich habe die Werbung gekonnt ignoriert und werde sie später gekonnt nicht durchlesen :-) ... Danke für den Hinweis. Für mich ist das bisher immer so gewesen das die SRAMs/SDRAMs ja noch einen Bidirektionalen Bus haben, und die Anbindung an den Speichercontroller muß ja genauso funktionieren. Nur was intern (zw. Prozessor und Speichercontroller) gemacht wird ist ja was anderes. Daher bin ich mir nicht sicher ob ich o.g. richtig dargestellt habe.
Rene Böllhoff schrieb: > SRAMs/SDRAMs ja noch > einen Bidirektionalen Bus habe Das gilt z.B. für QDR-SRAMs nicht mehr. Durch DDR auf den Datenleitungen bleibt die Pinzahl konstant und man trennt hin- und rücklaufende Daten. Duke
@Duke Ok, lassen wir mal die neuesten RAM-Typen weg. Um die 1-Takt-Zyklus-Philosophie umzusetzen müsste ich also entweder den Prozessor-Takt im einem festen Verhältnis zueinander setzen, damit das System dem Prozessor bei jedem Takt ein Datenwort liefert bzw eines wegschreiben kann, oder aber dafür sorgen das der Datenbus für jede Richtung einmal vorhanden ist. Wie das jetzt realisiert ist, ob ich das in einem getrennten Speichercontroller mache oder aber im FPGA "In-the-Box" ist ja erstmal egal. Aber wäre das ein Ansatz dafür ? Ich wüsste sonst nicht wie man allein mit Überlappung der Schreib/Lese-Anweisungen auf einen Takt kommt ohne Wartezeiten zu bekommen, die ich ja beim Schreiben allein schon für das setzen und rücksetzen der WE-Leitung/Address/Datenleitungen brauche. Irgendwie scheinen mir diese Überlegungen schwieriger zu sein, als ein Design in CISC (oder zumindest eben nicht gepipelined). Aber vllt brauch ich einfach mal nur ein einfaches, gut und vor allem vollständig dokumentiertes VHDL-RISC-Beispiel um da klarer zu sehen. Hätte da jemand mal vllt einen Link ? Ich hab schon einiges gefunden, aber eine wirkliche detaillerte Beschreibung aber so noch nicht.
Rene Böllhoff schrieb: > Hätte ich das mit dem "Tri-State-Vergessen" so zu verstehen das ähnlich > wie bei den FPGA's es keine bidirektionalen Busse mehr gibt, sondern nur > noch unidirektionale, und die "schnelle" Umschaltung an der Anbindung > zum RAM (egal ob SRAM/SDRAM/DDR-RAM) der Speichercontroller vornimmt ? > Also das intern ein Data-In- und Data-Out-Bus existiert der das Timing > auf intern einen Takt herunterbricht ? Genau so. Wobei bei Anbindung externer Speicher mit bidirektionalen Datenleitungen natürlich die Read-After-Write Zyklen immer noch auftreten können und dann auch intern sichtbar werden. Was ich meinte bezog sich allerdings auf die internen Buszyklen. Wenn da schon Zwangspausen eingelegt werden, kannst Du auch mit idealem Speicher nichts mehr richten. Bei typischen on-chip Bussen (die eigentlich keine mehr sind), kann z.B. die Adressphase des nächsten Transfers mit der Datenphase des aktuellen Transfers überlappen. -- Marcus
>Bei typischen on-chip Bussen (die eigentlich keine mehr sind), kann z.B. >die Adressphase des nächsten Transfers mit der Datenphase des aktuellen >Transfers überlappen. Genauso hab ich mir die Überlappung auch vorgestellt. Ich kam nur nicht damit zurecht das ich u.u. eben doch mehr als nur einen Takt benötige, das passt irgendwie nicht in das Pipelining "Muster" ohne das Wartezyklen entstehen. Bei einem vielfachen des Systemtaktes gegenüber dem Prozessortakt lässt sich dann ein gepipelintes Design besser handlen denke ich. Ich glaube ich werd (wenn mein aktuelles Design fertig ist) das mal bei einer Überarbeitung mit einfließen lassen. Danke für die Hinweise. Allerdings wäre ich noch dankbar wenn jemand ein gutes Tutorial bzw ein gutes (einfaches) Design mit ausführlicher Doku hat, damit ich mir das nochmal alles verinnerlichen kann. Viele Infos hab ich hier aus dem Forum, aus Wikipedia, und viele Dinge sind auch einfach klar. Aber bei so manchen "Feinheiten" da komm ich schonmal ins Trudeln.
Sehr interessantes Thema, Ich wollte auch eine Cpu zum Vertauschen von Werten in einem Array bauen. > Danke für die Hinweise. Allerdings wäre ich noch dankbar wenn jemand ein > gutes Tutorial bzw ein gutes (einfaches) Design mit ausführlicher Doku > hat, damit ich mir das nochmal alles verinnerlichen kann. > Viele Infos hab ich hier aus dem Forum, aus Wikipedia, und viele Dinge > sind auch einfach klar. Aber bei so manchen "Feinheiten" da komm ich > schonmal ins Trudeln. vielleicht hilft Dir die Fundstelle weiter, Yann Guidon beschäftigt sich schon länger mit CPU's http://f-cpu.seul.org/cedric/unstable/ http://yasep.org/ Gibt es noch interessante Hinweise für Assamblerprogramme für die eigenen Softcores? Es muss doch was Simples geben, was für den eigenen Befehlsatz abwandelbar ist. Am liebsten wäre mir der gas aus den Binutils, doch ich habe noch nie eine eigene CPU-Architektur angepasst. Eine Skriptsprache würde ich auch nicht schlecht finden.
@Rene Danke für den Link. Werd mir das mal anschauen. Ich habe hier in der Codesammlung einen Parser geschrieben. Mit diesem lässt sich leicht ein einfacher Assembler zusammenbauen. Für die Simulation meines eigenen Softcores habe ich mir ein Assembler für diesen Softcore auf Basis des Parsers geschrieben. Falls interesse besteht kann ich das was ich dazu habe mal posten. Es lässt sich einfach erweitern und anpassen (allerdings sollte man nicht versuchen den Code zu verstehen wenn man mit dem Präprozessor auf Kriegsfuß steht :-)) Gruß Rene :-)
Ja wenn du was hast, würde ich es mir schon mal anschauen. Den Ansatz von tdasm http://www.penguin.cz/~niki/tdasm/ finde ich ganz vernünftig, Tabelle anpassen und nicht einen ganzen Parser selberschreiben und lexikalische Ausdrücke zerpflücken. > zu verstehen wenn man mit dem Präprozessor auf Kriegsfuß steht :-)) > So ist es nun auch wi(e)der nicht. ;-) René
Fpga Kuechle schrieb: > Es sollte recht einfach sein, sich einen Quick und dirty assembler per > Spreadsheet (Excel;OO Calc)zusammenzubasteln. Ein Instruction wort mit > seiner seinen fest zugeordneten Bitfeldern ist doch recht einfach auf > einige Spalten Excel abgebildet, meinetwegen noch mit Auswahlmenü für > die Operations-Mnemonics. Für einfachste Befehle dürfte das gehen. Sobald man aber Sprung- und Speicherlabels verwendet und somit einen Relokationsmechanismus braucht, wird es kompliziert. Von weiteren Makro-Instruktionen mal gar nicht zu sprechen. Rene Böllhoff schrieb: >>Harvard-Architektur > > Ok, da ist das Problem vllt nicht so gegeben, obwohl ich da ja u.u. auch > mehrere Takte benötige. Aber ich dachte eher an von-Neumann, da man dort > je nach Speicher einfach mehr "drankleben" kann, ohne direkt einen 2. > Adress/Daten/Steuer-Bus haben zu müssen. Intern arbeiten die meisten Prozessoren mit einer Harvard-Architektur. Es gibt dann also einen Daten- und einen Instruktionsspeicher, ausgeführt als zwei Caches. Über die Anbindung an den externen Hauptspeicher kümmert sich dann die Cache-Logik, während der Prozessorkern frei von solchem Ballast ist. (Siehe beispielsweise MIPS) Rene Böllhoff schrieb: > Bei einem vielfachen des Systemtaktes gegenüber dem Prozessortakt lässt > sich dann ein gepipelintes Design besser handlen denke ich.
> Rene Böllhoff schrieb: > Bei einem vielfachen des Systemtaktes gegenüber dem Prozessortakt lässt > sich dann ein gepipelintes Design besser handlen denke ich. Ups, letztes Zitat nicht beantwortet: Wie erwähnt bietet sich zu diesem Zweck eher an, zwei interne Speicher bzw. Caches zu haben und einen Harvard-Kern zu bauen, während ein zusätzliche Logik die Anbindung an den Hauptspeicher übernimmt. Man braucht sich dann beim Pipelining nicht noch zusätzlich um unterschiedliche Taktraten zu kümmern. Die Cache-Lösung ist mit grösster Wahrscheinlichkeit auch schneller: Speicher haben gegenüber Logik verhältnismässig niedrige Taktraten. Es macht also keinen Sinn, das Speicherinterface mit einem Vielfachen der Logiktaktrate zu fahren, weil man dann die Logik extrem ausbremst. Besser hält man den Prozessor von Zeit zu Zeit komplett an, um neue Daten oder Instruktionen vom Hauptspeicher in den Cache zu laden. So oft ist das nämlich gar nicht notwendig, da - Lokalitätsprinzip - nahe beieinanderliegende Instruktionen und Daten auch zeitlich nahe beieinander und oft wiederholt benötigt werden. Beispiel Schleife: Wenn eine Schleife aus 20 Instruktionen 100 mal ausgeführt wird, so habe ich gerademal 20 Hauptspeicherzugriffe um die Instruktionen in den Cache zu laden. Arbeite ich direkt auf dem Hauptspeicher, so muss ich 2000 Mal darauf zugreifen. Da ich mit der Cache-Variante höhere Taktraten fahren kann, lohnt sich der Zusatzaufwand allemal.
Tag, Ich finde es richtig Interessant eine Prozessorarchitektur bzw. einen kleinen Mikrocontroller auf dem FPGA selbst zu entwerfen. Gibt es speziell zu diesem Thema eigentlich gute Lektüre? Was ich jetzt beim stöbern gefunden habe ist das Buch VHDL Synthese von Jürgen Reichert und Bernd Schwarz. Dieses enthält laut Inhaltsverzeichnis ein komplettes Kapitel über den Entwurf einer RISC Architektur. Dass dieses Buch brauchbar ist glaube ich, so oft wie es hier vorgeschlagen wird ;) Aber wie sieht es speziell mit diesem Kapitel aus auch brauchbar oder eher so mit eingebaut weil es grade In ist? Gruß Tobias
Der Artikel "Building a RISC System in an FPGA" von Jan Gray ist unbedingt lesenswert. Er beschreibt neben dem RISC Prozessor auch wie man einen C Compiler anpasst um den Prozessor in C programmieren zu können. Den Draft Artikel und die Dokumentation gibts auf http://www.fpgacpu.org/xsoc/cc.html Das Buch "FPGA prototyping by VHDL examples" von Pong P. Chu finde ich recht gut. Es beschreibt als ein Beispiel den Xilinx Picoblaze Prozessor. Ich selbst habe in den letzten Jahren schon mehrere SOCs mit eigenem Prozessoren auf Xilinx S3e und Nexys2 boards zum laufen gebracht, inklusive eigenen Java-like Compiler, OS, GUI toolkit und Apps. Sowas braucht natürlich einige Zeit. Das DRAM auf den FPGA boards anzusprechen ist meist der komplexeste Teil wenn man keinen fertigen memory controller hat.
MT schrieb: > Tag, > > Ich finde es richtig Interessant eine Prozessorarchitektur bzw. einen > kleinen Mikrocontroller auf dem FPGA selbst zu entwerfen. > > Gibt es speziell zu diesem Thema eigentlich gute Lektüre? > Was ich jetzt beim stöbern gefunden habe ist das Buch VHDL Synthese von > Jürgen Reichert und Bernd Schwarz. > Dieses enthält laut Inhaltsverzeichnis ein komplettes Kapitel über den > Entwurf einer RISC Architektur. > > Dass dieses Buch brauchbar ist glaube ich, so oft wie es hier > vorgeschlagen wird ;) > > Aber wie sieht es speziell mit diesem Kapitel aus auch brauchbar oder > eher so mit eingebaut weil es grade In ist? Schwarz hat zwei Vorteile: Es behandelt VHDL nicht als Programmierspracxhe aus sicht eines Informatikers und es ist auf deutsch. Also gut für Einsteiger in VHDL, aber weniger geeignet um sich mit dem Design eines Prozessors auseinanderzusetzen. Das Kapitel mit dem risc -beispiel ist mir nicht besonders in Erinnerung geblieben. Da ist besser Christian Siemers" Prozessorbau" ISBN: 3-446-19330-8. Auf der beiliegenden CD findet sich der VHDL-Code. das Buch hat allerdings schon über 10 jahre auf dem Buckel und ist hinsichtliche der PLD-Möglichkeiten nicht mehr state of the art. MfG,
Rene Böllhoff schrieb: > @Duke > > . Um die > 1-Takt-Zyklus-Philosophie umzusetzen müsste ich also entweder den > Prozessor-Takt im einem festen Verhältnis zueinander setzen, damit das > System dem Prozessor bei jedem Takt ein Datenwort liefert bzw eines > wegschreiben kann, oder aber dafür sorgen das der Datenbus für jede > Richtung einmal vorhanden ist. > Wie das jetzt realisiert ist, ob ich das in einem getrennten > Speichercontroller mache oder aber im FPGA "In-the-Box" ist ja erstmal > egal. Aber wäre das ein Ansatz dafür ? Die FPGA internen Speicherblöcke sind in der Regel als Dual-Port ausgeführt, Da kann man locker in einem Takt lesen und schreiben. Daher kann man diese statt FF als Registerbank benutzen.
Hallo, die Diskussion geht ja schon relativ tief in Details bestehender Prozessoren, aber wie wäre es denn mit einem Java-Bytecode-Prozessor? Dokumentation ist vorhanden, reichlich Tools gibt es auch. Allerdings kann ich nicht abschätzen, ob sich alle Bytecode-Befehle sinnvoll in VHDL umsetzen lassen. Vor allem virtuelle Funktionsaufrufe (für Vererbung) könnten aufwendig werden. Auch die eigentliche Anbindung an die Hardware ist mir unklar. Hätte auf jeden Fall auch einen gewissen Seltenheitswert. Gruss Micha
Micha C. schrieb: > Allerdings kann ich nicht abschätzen, ob sich alle Bytecode-Befehle > sinnvoll in VHDL umsetzen lassen. Naja, RISC geht anders. ;-) Läuft bei einem Teil der Befehle auf komplexes Sequencing hinaus, für das man in traditionellen Architekturen Microcode einsetzt. Die Jazelle Engine in ARM9/11 erledigt nur 95% der ausgeführten Bytecodes selber und überlässt den Rest nativem ARM Code.
Micha C. schrieb: > Vor allem virtuelle Funktionsaufrufe > (für Vererbung) könnten aufwendig werden. Das läuft dann au eine CISC-Architektur hinaus. Die Daten laufen also nicht mehr straight-forward durch einen fixen Datenpfad, sondern werden von einem Mikrocodeprogramm sequentiell abgearbeitet. Und sowas ist schwer bis gar nicht zu pipelinen. Somit lässt sich kein wirklich schneller Prozessor bauen. Gibt es eigentlich heute noch echte CISC-Architekturen? x86 ist ja bekanntlich ein CISC-Instruktionssatz, wird aber intern RISC-mässig verarbeitet.
xst schrieb: > Gibt es eigentlich heute noch echte CISC-Architekturen? x86 ist ja > bekanntlich ein CISC-Instruktionssatz, wird aber intern RISC-mässig > verarbeitet. Die Zerlegung komplexer Befehle in einfache Operationen kennzeichnet auch Microcode. Wenn du als x86 mit interner Befehlszerlegung in Einzelschritte als RISC betrachtest, dann trifft dies auch VAX und 68000 zu. Nur erfolgt diese Zerlegung bei x86 meistens in Hardware statt Microcode und die Operationen spazieren nicht mehr im Gänsemarsch. Zwar lassen sich CISC Befehle als Einheit schlecht pipelinen, für den Microcode muss das indes nicht gelten. Problematisch bei Java Bytecode ist jedoch die etwas pipelinewidrige Stack-Architektur. Microcode ist übrigens keine Bedingung für CISC. Es gab auch welche ohne, wie Z8000. Hat Zilog zwar viele Transistörchen erspart, aber im Ausgleich so viel Zeit gekostet, dass es bei realer Verfügbarkeit ein Reinfall war. Auch wenn sich Intels Core/Core i und AMDs K8 strukturell auf dieser Ebene recht ähnlich sehen: Es gibt beispielsweise auch den Atom, der etwas traditioneller gewirkt ist. Ansonsten muss man nur mal von der Spitze weg in andere Gefilde blicken und man findet CISC. Nämlich im Controller-Sektor. Renesas M16C/80 und M32C haben eine blütenreine hochkomplexe CISC ISA, auch von der Implementierung ist nichts Gegenteiliges bekannt. Und ARMs Java Engine Jazelle hatte ich ja bereits genannt.
PS: Der interne Code von AMD ab K7 definiert auch Makroops wie <mem> = <mem> <op> <reg>/<const> was dem klassischen RISC-Bild eindeutig widerspricht. In diesem Sinn zerlegt AMD den x86 Code also nicht in RISC Operationen sondern in einfachere schematischere CISC Operationen. Bei Intel war es anno PentiumPro..PentiumIII sowie Pentium 4 noch einfach, die internen Codes waren ausgesprochen simpel strukturiert und letzlich RISC-artig. Mit dem Pentium-M und den Core/Core i entwickelte sich der interne Code wieder sukzessive vom RISC-Schema weg, etwas in Richtung AMD.
@Micha Dieser Gedanke ist mir auch schon gekommen :-)) Aber wie die beiden vorherigen Posts schon beschrieben haben, dürfte der Java-Bytecode nicht, oder nur mit großem Aufwand auf einem FPGA direkt interpretiert werden können. Da ist es schon einfacher eine einfache Architektur aufzusetzen (egal ob bestehend oder eigens entworfen) und auf dieser Basis dann einen Java-Bytecode-Interpreter aufzuziehen.
AooA schrieb: > Was meint ihr zum MSP430? Der Instruktionssatz jedenfalls scheint recht > einfach und doch mächtig. Halt ich persönlich für eine super Idee. Gibt da sogar was bei OpenCores in der Richtung (leider in Verilog): OpenMSP430: http://opencores.com/project,openmsp430 Ich hätte selber jetzt vom Instruktinossatz an etwas 8051 kompatibles gedacht.
Ich habe schonmal einen 8051 im FPGA nachgebaut, so richtig from scratch. Das ist schon spassig, keine Frage, allerdings braucht man dazu auch einiges an Zeit und Ausdauer. Und man braucht eine Vergleichsmöglichkeit mit dem Original. Die verfügbare Dokumentation hat jedenfalls nicht gereicht. Irgendwann landet man bei so verrückten Fragen wie: Was macht der Prozessor beim Befehl "pop SP"? Viel Erfolg! Harald
Harald Flügel schrieb: > jedenfalls nicht gereicht. Irgendwann landet man bei so verrückten > Fragen wie: Was macht der Prozessor beim Befehl "pop SP"? So verrückt sind diese Fragen garnicht. Bei den ersten x86-Generationen hat anhand genau solcher Fiesematentchen die verschiedenen Varianten unterschieden.
Harald Flügel schrieb: > Und man braucht eine > Vergleichsmöglichkeit mit dem Original. Die verfügbare Dokumentation hat > jedenfalls nicht gereicht. Irgendwann landet man bei so verrückten > Fragen wie: Was macht der Prozessor beim Befehl "pop SP"? Es gibt noch eine andere Alternative: eine extrem saubere Dokumentation! Die "Principles Of Operation" der IBM /360-Architektur umfaßte - vorsichtig geschätzt - allein gut 500 Seiten zur Beschreibung des Instruktionssatzes einschließlich der Sonderfälle und der modellabhängigen bzw. "kritischen" Operationen (z.B. Store an die Stelle der nächsten Instruktion - ein Graus in der x86-Architektur). Bernhard
Das ganze ist auch etwas globaler zu betrachten. Wollt ihr eine theorische Rechenarchitektur bauen oder etwas was auch dann praktisch eingesetzt werden kann? Dann muss ein Assembler oder besser ein C-Compiler nachgezogen werden. Der MSP430 oder ein AVR hat den Vorteil es gibt schon Tools für die Architektur. Das muss alles bedacht werden. Oft wird auch die MIPS Architektur nachgebaut, soll sich für FPGA Umsetzung sehr gut eignen, die hat hier noch keiner erwählt.
Hier mal von meiner Selbstbau-CPU der Befehlssatz. Nahezu jeder Befehl lässt sich bedingt ausführen. Ausnahmen sind die Immediate Ladebefehle und die Befehle des Condition-Processing. Ein Makro-Assembler dafür ist auch im Entstehen. Das ganze ist zwar noch sehr langsam, da ich für ein universelles Speicherinterface viele Takte benötige, aber ich denke durch pipelining dürfte die CPU noch um einiges schneller werden. Mal schauen wie weit ich da komme. Bei Problemen bzw Hirnknoten werd ich mich bestimmt nochmal melden :-) Falls interesse besteht kann ich die CPU hier ja auch mal posten bzw einen Artikel daraus machen. Hier mal eine kurze Feature Liste : - 16Bit Daten&Adressraum (der Adressraum wird evtl auf 32Bit aufgestockt) - 16x16Bit Register (im Moment nur 8x16Bit, um etwas Platz zu sparen) - benötigt ca 47% der Slices eines Spartan 3-200 - nahezu alle Befehle bedingt ausführbar - Bedingungsprozessor mit 4 benutzer bedingungen - einfache Schleifenkonstrukte mit Mark/Loop (fußgesteuerte Schleife) - Alle Instruktionen immer 16Bit breit (tlw. nachteillig, aber übersichtlich) Ist bestimmt kein Vorzeigeprozessor, oder besonders ausgetüftelt, aber für meine erste Selbstbau-CPU unter VHDL denke ich brauchbar.
Wie funktioniert bei dir ein Vergleich zweier Werte mit Vorzeichen? Traditionell gibt es da zwei Ansätze, wenn man sich schon für ein Statusregister entscheidet: Separate Vergleichsbefehle (IBM Tradition) oder separate Flags (z.B. Overflow-Flag). Ist der Akkumulator ("acc") ein spezielles der 16(8) Register?
@A.K. Ich habe in brute-force-Manier zwei Vergleicher-Zweige (einen Signed und einen Snsigned) gemacht und die Auswahl übernimmt ein Flag im Statusregister. Bei den Shift Operationen geht das genauso. Da habe ich Flags für logischen/arithmetischen Shift sowie für Rotate. Edit : Ich habe auch noch nicht alles bis ins kleinste durchgetestet/simuliert, da ich erstmal den Assembler fertig machen wollte damit das Testen und Simulieren einfacher wird. Edit 2 : Es sind noch 16 SW-Interrupts vorhanden. 15 Hardware-Interrupts werden denke ich auch noch folgen. Aber da ist noch nicht viel getestet.
Rene Böllhoff schrieb: > Ich habe in brute-force-Manier zwei Vergleicher-Zweige (einen Signed und > einen Snsigned) gemacht und die Auswahl übernimmt ein Flag im > Statusregister. Aua! Zuviel 6502 programmiert? Will hoffen, dass du nicht auch noch einen Compiler dafür stricken willst... Sowas macht ähnlich viel Freude wie Bankswitching bei den PICs. Sorry, wills dir nicht madig machen, aber solche Stati sind ein Graus.
Der Akku ist ein 32-Bit Register (für die Multiplikation die auch im moment nur unsigned ist). Das ist auch noch eine "unschönheit" an meinem Design. Die ALU bedient sich zweier Register, das Ergebnis landet aber immer im Akku und muß mit einem weiteren Befehl erst wieder in ein Register transferiert werden. Ich hab das gemacht damit das Register nicht automatisch überschrieben wird, sondern man sie freie wahl hat wo das Ergebnis landen soll. Na ja ... mit dem 6502 hab ich angefangen :-) Die signed/unsigned Problematik (bei Vergleichen, Status-Reg und Multiplikation und ALU) liegt mit sowieso noch was schwer im Magen. Muß mir da auch mal anschauen wie das bei anderen Architekturen gelöst ist. So zufrieden bin ich damit ohnehin noch nicht.
Von einem Compiler bin ich noch soweit entfernt wie ein Tretroller von der Saturn V ;-) Aber ich glaub aus solchen "Fehltritten" (selbst wenn es im ersten Moment erstmal ein Erfolg ist) lernt man auch. Was mich halbwegs erfreut ist das ich einen relativ einfachen Prozessor der aber auch schon das was ein Prozessor können muß beherrscht entworfen hab der auch noch einigermaßen wenig Ressourcen benötigt. Lässt sich sicherlich nicht mit einem Picoblaze (von der Größe her) oder mit einem Microblaze (von den Features und der Geschwindikeit) vergleichen, aber das war ja auch nicht die Intention :-) Edit : Was wäre denn der bessere Weg ? Die Vergleiche und Logisch/Arithmetisch/Rotierenden Shift Befehle wirklich auszudekodieren (also ala SLL, SLR, SAL, SAR, ROL, ROR und CMPS, CMPU) ? Evtl wäre da ja noch Platz im Opcode-Raum.
Rene Böllhoff schrieb: > Muß mir da auch mal anschauen wie das bei anderen Architekturen gelöst > ist. So zufrieden bin ich damit ohnehin noch nicht. Traditionell wie 68xx, 68xxxx, ARM: 4 Flags, NZVC wie 6502, aber 2*7 Bedingungen. Wird hier natürlich eng. MIPS, Alpha: Ähnlich wie bei dir, nur Standardregister statt Flags, d.h. Ergebnis eines Vergleichsbefehls landet als 0/1 im Zielregister. Aber da hat man dann getrennte Vergleichsbefehle für signed/unsigned, grösser/kleiner usw. IBM 360/POWER: willst du nicht wirklich wissen ;-). Kannst dir als Anregung die Thumb2-Variante vom ARM mal ansehen. Bedingte Ausführung aller Befehle ist ziemliche Ressourcenverschwendung, ganz besonders bei 16bit-Codierung. Dort gibt es einen Präfix-Befehl, der den nächsten maximal 4 Befehlen die Bedingung vorgibt, d.h. eine Bedingung für alle, und ob jeweils wahr oder falsch. Kostet zwar bei einfachem Ablauf einen Takt, setzt aber anderswo dringender benötigte Bits im Opcode frei.
Danke für die kleine Übersicht. Aber soweit ich weiß gibt es beim 6502 keine speziellen signed/unsigned Vergleichsbefehle. Da gibt es meine ich nur einen CMP-Befehl und das wars. Ist aber auch schon ein paar Jährchen her das ganze. Na ja. An eine IBM360 hatte ich bestimmt nicht vor mich anzulehnen :-) >Bedingte Ausführung aller Befehle ist ziemliche Ressourcenverschwendung, >ganz besonders bei 16bit-Codierung. Kannst du mir das mal genauer erklären ? Mir ist nicht klar wie das zusammenhängt a) mit dem Ressourcenverbrauch und b) warum speziell 16Bit-Codierung (meinst wegen den Bits für die Bedingung die mir dann im Opcode "fehlen") ?!
Rene Böllhoff schrieb: > Design. Die ALU bedient sich zweier Register, das Ergebnis landet aber > immer im Akku Was eigentlich nur sinnvoll ist, wenn z.B. acc=R0 gilt. Die obere Produkthälfte wird (wurde) nicht selten in einem separaten Register verbuddelt. Solange man kein Pipelining im Auge hat ist das vertretbar - IBM hatte das gemacht und anlässlich des Übergangs von Power zu PowerPC in den Hintern gebissen.
Rene Böllhoff schrieb: > Aber soweit ich weiß gibt es beim 6502 keine speziellen signed/unsigned > Vergleichsbefehle. Aus den 4 Flags des 6502 lassen sich alle 14 üblichen Bedingungen ableiten, darunter sowohl "grösser mit Vorzeichen" als auch "grösser ohne Vorzeichen". Die entsprechenden Sprungbefehle mit Vorzeichen fehlten beim 6502, aber der Vorgänger 6800 hatte sie alle. Wobei man natürlich bei einer Architektur mit vollständig symmetrischem Vergleichsbefehl ein paar Bedingungen einsparen kann (z.B. "grösser" vs. "kleiner"). > Mir ist nicht klar wie das zusammenhängt a) mit dem Ressourcenverbrauch Alle Befehle eines konkreten Programmablaufs, die nicht wirklich bedingt ausgeführt werden, verschwenden bei dir 3 Bits von 16 des Opcode-Space. Die sich anderswo ggf. besser einsetzen liessen. > und b) warum speziell 16Bit-Codierung 3 "verlorene" Bits in einem in 16 Bits codierten Befehl tun mehr weh als 4 Bits von 32 (ARM). In Thumb1 gabe es deshalb garkeine bedingte Ausführung, was aber hinsichtlich Laufzeit auch nicht so der Knüller war, also brachte Thumb2 den erwähnten Präfix.
Der Hintergedanke mit dem getrennten Akku (der wirklich getrennt ist, also nicht auf irgendein Register gemappt wird) war der das ich aus dem Akku eine MAC-Einheit mache die dann evtl über ein dann eingespartes Flag im SR bei jedem ALU-Befehl mitläuft. Ok. Das mit den (wir bauen uns aus den Status-Flag-bits die entsprechende Bedigung heraus) hab ich verstanden. Das hatte ich auch so in erinnerung. Mit den "fehlenden" Bits ist dann klar. 3 von 16 sind eben mehr als 4 von 32 :-) Der Ursprungsgedanke war auch so ausgelegt das ich versuche wenige Befehle zu implementieren, habe dann aber gemerkt das das dann nur mit immensem SW Aufwand zu machen ist. Daher z.b. auch die SWAP8 und SWAP4 Befehle. Mit der ALU hätte man sich nen Wolf programmiert (Shift-Wert laden, shiften, zurückschreiben, usw).
Rene Böllhoff schrieb: > Der Hintergedanke mit dem getrennten Akku (der wirklich getrennt ist, > also nicht auf irgendein Register gemappt wird) war der das ich aus dem > Akku eine MAC-Einheit mache die dann evtl über ein dann eingespartes > Flag im SR bei jedem ALU-Befehl mitläuft. Ja, aber ich fürchte du verlierst mehr als du gewinnst. Es sei denn du baust einen DSP. Datenrechnung ist bei normalen Programmen nicht so dominant, als dass sich sowas lohnt. Denk übrigens auch an die Frage der Adresserzeugung. Bei dir bestehen ja recht wenig Möglichkeiten, mit Speicher überhaupt etwas anzufangen. Die Lade/Speicherbefehle hatte ich im zweiten Anlauf gefunden ;-) aber eine Antwort auf die Frage, wie in leidlich ökonomischer Weise eine Adresse der sehr beliebten Form [pointer+offset] im RegX landet, noch nicht.
Du hast mich irgendwie entlarvt :-) Eine DSP Option hatte ich nicht nur im Kopf gehabt sondern war auch irgendwo mit der Ausgangspunkt. Bei meinem Audio-DSP habe ich zwar reine DSP-Befehle, aber alles andere nicht. Da kam mir der Gedanke das ich zwar eine MAC-Einheit brauche, diese aber ja durchaus von einem 16-Bit Core gesteuert und gefüttert werden kann. Das ganze ist aber nachher soch "ausgeartet" das ein "normaler" Prozessor daraus entstanden ist. Das mit der Adresserzeugung ist in der Tat echt blöd gemacht. Da hätte ich mehr Hirnschmalz reinstecken müssen. So sachen wie Indirekt indiziert, Autoincrement und dergleichen wären sinnvoll gewesen. Einen Wert (egal ob Datum oder Adresse) lässt sich nur über 2 Move Befehle machen. Dafür gibt es die Move High-Byte/Low-Byte Befehle. Um also von Adr 0x2345 einen Wert nach Register 1 zu laden muß man folgendes machen : 6234 MOVE H#$23, R4 7234 MOVE L#$45, R4 5041 MOVE A, [R4], R1
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.