Es wird davon davon ausgegangen, dass die meisten Zuhörer Hardware bisher nicht kennen, ausser Platinen in den PC einstecken und drauf Software installieren. Und dabei feststellen, dass das grüne Plastikflachen sind, mit dunklen Linien und so komischen Teilen drauf verstreut. Aber ansonsten keine Ahnung haben, was in den Teilen drin abgeht.
Es wird angenommen, dass der Zuhörer programmieren kann (zumindest Scripts) und Konzepte wie Variablen und Zuweisungen versteht.
Man hat bereits im 17. Jahrhundert Rechenmaschinen gebaut. Blaise Pascal (1623-62), Sohn eines Steuerbeamten, hat damals einen mechanischen Addierer für seinen Vater gebaut. Ältere Zuhörer werden sich noch an die mechanischen Registrierkassen errinnern, die früher in den Läden benutzt wurden, die "300 70 5 + [ratter ratter]" Dinger. Dort war die selbige Mechanik drin, nur mit Elektromotor statt Kurbel.
Hinweis: Der Abakus ist viel älter, ist aber kein Rechner, sondern nur ein Speicher, gerechnet wird im Kopf, nur externer Speicher der Kopf entlastet, wie schriftlich rechnen, aber ohne Papierverbrauch.
Problem all dieser Rechner war, dass sie kompliziert waren, weil sie dezimal rechneten. Alleine eine 1-stellige Addition von 2 Ziffern hat 10 mögliche Ziffern bei jedem Operand, also 10*10=100 möglichen Kombinationen. Wenn man für Ergebnisse grösser 9 auch noch einen Übertrag will, gibt das eine zweite Einrichtung mit 100 Kombinationen. Will man mehrziffrige Zahlen Addieren hat man wegen dem Übertrag der 0 oder 1 sein kann, ab der zweiten Ziffer sogar 10*10*2=200 Möglichkeiten, mal 2 Einrichtungen. Multiplikation will sogar 10*10*10=1000 Kombinationen, weil man 10 mögliche Überträge hat.
Auch der Versuch von Charles Babbage in den 1880ern einen Computer zu bauen, um Tabellen von Navigationsdaten fehlerfrei zu rechnen, und ohne Person dazwischen zu drucken, ist letztlich daran gescheitert, dass dies zu kompliziert war, trotz Finanzierung durch die britische Marine, die gestrandete und gesunkene Schiffe einsparen wollte.
Der Computer wurde realistisch möglich, als man auf binäre Zahlen umstellte, also Zahlen mit nur 2 Ziffern. Das vereinfachte die Rechner gewaltig (nur noch max 2*2*2=8 Kombinationen, selbst für Multiplikation mit Übertrag). Die einzelnen Ziffern von binären Zahlen werden Bits (Binariy digITS) genannt.
Beispiel binär Rechnen mit 8bit Zahlen (Bereich 0..255) 7654 3210 Nummer n des Bits 1 2631 8426 8421 Wert des Bits, 2^n, für n=0..7 = 1..128 ---- ---- 0100 1100 Operand1 | = 64 +8+4 = 76 + 0110 0111 Operand2 | = 64+32 +4+2+1 = 103 ( . . . Übertrag) | ---- ---- | --- 1011 0011 Ergebnis | = 128 +32+16 +2+1 = 179
Als Tabelle sieht das so aus:
a b & | ^ --- ----- 0 0 0 0 0 0 1 0 1 1 1 0 0 1 1 1 1 1 1 0
Schliesslich gibt es noch die NICHT/NOT/~ Funktion, mit nur einem Operand. Dessen Ergebnis ist nicht (= Gegenteil von) Operand, also: ~0=1, ~1=0. Man nennt diese Operation Inversion. Sie ist vergleichbar mit einer Negation (0-Operand). 2 mal Inversion heben sich auf, wie 2 mal Negation.
Die Kombination (a & b) | (c & d) ist übrigens so häufig das man diese auch ohne Klammern standardmässig wie (a * b) + (c * d) ausrechnet.
Diese Logik übrigens ist ein klassischer Fall von etwas das lange vor seiner Nützlichkeit entdeckt wurde (George Boole war Mathematiker im 19. Jahrhundert). Das war, wie man unschwer sieht, im 19. Jahrhundert nur eine mathematische Kuriosität, komplet nutzlos. Heute kann man damit Elektronik beschrieben, genauso wie man mit Formeln Programme schreiben kann.
Wenn man die eine einziffrige Addition anschaut, so sieht man, das diese ihre hintere Stelle ein EXODER ist. Und die vordere Stelle ist ein UND:
a + b = ergebnis dezimal 0 + 0 = 00 | 0 0 + 1 = 01 | 1 1 + 0 = 01 | 1 1 + 1 = 10 | 2 a UND b_/ \_a EXODER b
Aufwendiger wird es wenn man dann die zweite oder folgende Ziffern will, da muss man noch den Übertrag, der bisher immer 0 war, berücksichtigen:
a + b + übertrag = ergebnis dezimal 0 + 0 + 0 = 00 | 0 0 + 1 + 0 = 01 | 1 1 + 0 + 0 = 01 | 1 1 + 1 + 0 = 10 | 2 0 + 0 + 1 = 01 | 1 0 + 1 + 1 = 10 | 2 1 + 0 + 1 = 10 | 2 1 + 1 + 1 = 11 | 3 (a UND b) ODER (a UND übertrag)_/ \_(a EXODER b) EXODER übertrag ODER (b UND übertrag)
Die hintere Ziffer ist schlicht a und b addieren (was nie mehr als 2 geben kann), und dann noch den Übertrag hinzuzählen (geht nie über 3). Vorne braucht man Tests auf "über 1", also ist wenn irgend eine der 3 Kombinationen 2 gibt, für 3 sind dann schlicht alle 3 Kombinationnen aktiv. Das ODER da ist ein "über 1 Sammler".
Da UND ein "Durchlass" und ODER ein "Sammler" sein kann, kann man diese dazu verwenden. Dazu bekommt jeder Eingang ein UND, und einen "Steuereingang". Die Ausgänge aller UND werden von einem breiten ODER gesammelt.
Dies ist ein häufiger Sonderfall von (a & b) | (c & d), wo a und c die Eingänge e1 und e2 sind, und b und d die Steuereingänge s1 und s2 sind.
Sehr oft will, dass ein Ausgang gleich einen oder den anderen Eingang ist. Um zu wählen welchen, will man nur ein Auswahl-Signal. Wenn dies 0 ist soll der erste Eingang, bei 1 der zweite Eingang herauskommen.
e1 e2 auswahl = ausgang 0 0 0 = 0 = e1 0 1 0 = 0 = e1 1 0 0 = 1 = e1 1 1 0 = 1 = e1 0 0 1 = 0 = e2 0 1 1 = 1 = e2 1 0 1 = 0 = e2 1 1 1 = 1 = e2 \_(ein1 & ~(auswahl)) | (ein2 & auswahl)
Hinten ist das UND ein normales "lass e2 durch wenn auswahl = 1". Vorne will man nun e1 durchlassen wenn auswahl = 0, also kehrt man auswahl um, mit ~, um dem UND ein 1 zu bieten. Man nennt so ein Teil überigens einen Multiplexer, hier genauer ein 2:1 Multiplexer.
Man kann auch 4 Eingänge mit 4 UND und entweder 4 Steuereingänge oder 2 Auswahl mit 4 Inverter Kombinationen und breitere (3 Anschlüsse) UND ausführen. Das ist dann ein 4:1 Multiplexer. Mit 8 Steuereingängen oder 3 Auswahl und 4-Anschluss UNDe, kann man auch einen 8:1 haben, usw. Mit n Auswahl kann man immer (2^n):1 multiplexen, weil man daraus 2^n Steuereingänge durch NICHT und (teil-vom)UND generierbar sind. Die n Auswahl Signale kann man als nBit Zahl auffassen, mit Wert 0..(2^n)-1, die man Adresse nennt.
Die Basis aller Elektronik ist der gesteuerte Umgang mit elektrizischem Strom. Strom kann nur fliessen, wenn elektrische Spannung ihn antreibt und ein elektrischer Leiter vorhanden ist, durch den er getrieben werden kann. Wieviel Strom dabei entsteht hängt ab von der Spannung die antreibt sowie dem Widerstand den der Leiter ihm entgegenstellt:
Strom = Spannung / Widerstand
Aus dem Grund, und weil Leistung (bzw Hitzeentwicklung) = Spannung * Strom ist, nimmt man heute übrigens die immer kleineren Spannungen, 5V, 3.3V, 2.8V, 2.5V, 1.8V, ... . Je weniger umso kühler, aber zuwenig und der Rechner wird unzuverlässig (leicht störbar). Also geht es in kleinen Schritten, und man ärgert sich über Spannungseinsteller einstellen auf den Motherboards.
Diese Vorgänge sind zwar interessant, aber kompliziert und interessieren uns für die Verständnis von Computer Hardware nichts! Wir nehmen hier daher einfach an, das wir ein Netzteil haben, das Spannung liefert, solange wir ihm nicht zuviel Strom abverlangen (dann tut besseres Netzteil abschalten und schlechteres geht in Rauch auf). Im restlichen Vortrag interessiert uns daher nur der Leiter, in diesem Fall die Chips auf den Platinen.
Strom = Spannung / (Widerstand1 + Widerstand2 + Widerstand3)
Strom Spannung ---->-----. | voll 100% .-. | | W1 | | 50% `-' | wenig 50% .-. | | W2 | | 25% `-' | weniger 25% .-. | | W3 | | 25% `-' | nichts 0% ----------'
Dabei stellt man dann fest, dass an jedem Widerstand genau ein Teil der Gesammtspannung "verbleibt" der seinem Teil am Gesammtwiderstand gibt.
Wenn man den Transistor in einen Spannungsteiler einbaut, und auf gross schaltet, bekommt er den grossen Teil der Spannung ab, wenn man ihn auf wenig schaltet, bekommt er wenig ab. Damit hat man eine variable Spannung am im Spannungsteiler:
Strom Spannung ---->-----. | voll voll .-. | | W1 | | `-' --. |------- T2 = klein fast nichts, sonst fast voll | |---' `--|| T2 (n Typ) |->-. | | nichts nichts ----------'
Noch stärker wird es, wenn man 2 Transistoren nimmt, von denen jeweils einer gross und der andere klein hat, und diese dann wechselt. Sowas nennt man Komplementär-Betrieb, mit MOS-FET Transistoren CMOS Technik (C wie complementary).
Strom Spannung ---->-----. | voll voll |-<-' .--|| T1 (p Typ) | |---. --| |------- T1 = gross + T2 = klein fast nichts, sonst fast voll | |---' `--|| T2 (n Typ) |->-. | | nichts nichts ----------'
Vor allem ist dann die Stromstärke bei unterem Transistor = klein erheblich kleiner. Und somit der Chip kühler. Daher ist es üblich 2 Transistoren einzusetzen, von denen jeweils einer grossen und einer kleinen Widerstand hat.
Da MOS-FETs ohne Ansteuerung "zu" sind, also grosser Widerstand, und grosse Spannung kleinen Widerstand macht, und somit der Spannungsteiler kleine Spannung abgibt, und umgekehrt, haben MOS-FET Transistor-Spannungsteiler automatisch eine Signal unkehrende Funktion.
Der einfachster Fall ist, sich selber ansteuern. Folge ist: wenig->viel..vorne, worauf dann viel->wenig..vorne ist, wieder w->v und v->w und so weiter. Damit versucht der Spannungsteiler dauernd sich selber umzuschalten, und ist unstabil. Das nennt man einen Oszillator. Der schwingt sehr schnell, so schnell der Transistor schalten kann. Für langsamer bremst man den mit einem Quarz in der Rückleitung.
Ein Kreis von 2 Spannungsteiler hat genau die gegenteilige Wirkung: wenig->viel->wenig..vorne, bzw viel->wenig->viel..vorne, und ist damit bockstabil, ausser er wird von aussen gestört. Das nennt man daher ein Flipflop (FF).
Wenn wir nun unseren Transistor Spannungsteiler mit 0V und 5V anschliessen, so sehen wir, dass bei 0V..0.8V Eingang der Ausgang 4.5..5V ergibt, bei 2.4..5V Eingang aber so 0..0.5V, wegen der Signalumkehrung. Also ist unser Transistor Spannungsteiler automatisch ein NICHT, bei der Definition von Spannung = Bits!
Nimmt man nun mehrere untere Transistoren so müssen alle mit 2.4..5V gefüttert werden, damit sie alle leiten und der Ausgang auf 0..0.5V geht. Damit ergibt sich automatisch ein NICHT-UND, (NOT-AND, kurz NAND). Daher ist NICHT-UND basierte Elektronik weit verbreitet. Daher besteht auch der erste Chip der 74xx TTL Reihe, der 7400, aus 4 2-Eingang NICHT-UND Elementen.
Strom Spannung ---->-----. voll = 5V | .-. | | W1 | | `-' |------- T2 = klein UND T3 = klein fast nichts, s fast voll |---' UND + nichts = NICHT-UND -----|| T2 |->-. | |---' -----|| T3 |->-. | | ----------' nichts = 0V
Dies kann man auch komplementär machen, mit je 2 Transistoren pro Eingang. Dabei werden die unteren "gefaltetet" verdrahtet (zwischen T2 und T4), und die oberen "neben einender" verdrahtet. Jeder Eingang steuert sein Paar. Man kann dies für beliebige Einganszahlen "verbreitern". Ein CMOS Chip besteht nun aus vielen Zeilen mit Serien solcher n*2 Transistoren grossen NICHT-UND Gatter, und pro Zeile 2 Stromleitungen.
| ---->------------------------)|(------------ voll = 5V | | | | |-<-' |-<-' | |-<-' .--|| T1 .--|| T3| .--|| T1 | |---. | |---. | | |---. | |-----)|(------+----' | |-- | | | | | hier dann nächstes Gatter | | .---)|(------. | | | |---' | | |---' | |---' |--|| |T2 |--|| T4 |--|| T2 | |->---' | |->-. | |- | | | | | | | | -)|(------------)|(------------)|(---------- nichts = 0V | | |
Bisher können wir nur NICHT-UND herstellen. Wie steht es mit dem Resten der logischen Funktionen?
Für ein Bit zu berechnen reicht 1 2-Eingang EXODER und 1 2-Eingang UND. Das Paar nennt man einen Halb-Addierer, weil er nur a+b, aber nicht +Übertrag rechnen kann.
Für einen Voll-Addierer, muss wegen Übertrag, auf 2 2-Eingang EXODER, 3 2-Eingang UND, sowie 1 3-Eingang ODER gegangen werden (wobei die UND + ODER durch NICHT-UND + NICHT-UND ersetzt werden, weil kleiner und schneller). Dies muss man nun für die Anzahl Bits wiederholen.
Dies kostet bereits ordentlich viele Transistoren. EXODER ist ja selber 2 NICHT, 2 NICHT_UND und ein weiterer NICHT-UND = 2*2+2*4+4 = 16 Transistoren. Das mal 2 und die weiteren 3*4+1*6 addieren = 2*16+12+6 = 50 per Bit! Für 8bit Rechner sind bereits 8*50 = 400 Transistoren verbraucht, bei 32bit sind es bereits 32*50 = 1600.
Und das ist immer noch ein ineffizienter Addierer. Es muss jeweils für jedes Bit sein Übertrag-aus zum nächsten Bit sein Übertrag-ein, das nennt man kaskadieren. Und das ist langsam, weil das Bit durch 2 NICHT-UND pro Bit muss. Man kann dies beschleunigen, aber das kostet weitere Transistoren.
Und dann sollte ja noch die Subtraktion rein. Die kann man zum Glück recht einfach rechnen, indem man a-b = a+(-b) nimmt. Also den bestehenden Addierer und einen Negierer beim zweiten Operand. Negative Zahlen sind ausserhalb diesem Vortrag, zum Zeit sparen, also keine Erklärung wie ein Negierer funktioniert, aber der Aufwand ist hauptsächlich ein weiteres EXODER pro Bit. Kostet also massiv weitere bits*16 Transistoren, also 1/3 mehr.
Multiplikation oder gar Division brauchen noch viel mehr Aufwand. Für 32bit*32bit muss man entweder langsam 32 separate Additionen hintereinander in der selbigen Hardware (kostet 32 Taktzyklen) machen, oder für jede Addition eine Wiederholung der obigen Hardware (kostet also 32*1600 = 51200 Transistoren). Wie man sieht wurde dies aus gutem Grund erst so um 1990 (486er) im PC zum Standard, alles aufs mal zu rechnen.
Man sieht auch langsam, wohin all die Millionen Transistoren gehen.
Sobald wir Bits speichern können, können wir unsere Logik über mehrere Schritte laufen lassen. Dabei entsteht eine Abfolge (= Sequenz) von Speicherzuständen. Daher nennt man dies sequenzielle Logik. Logok ohne Speicher nennt man kombinatorische Logik, weil dort nur eine Kombination der aktuellen Eingänge möglich ist.
Wie speichert man nun Bits? Bei unserem Flipflop aus einem doppelten Spannungsteiler haben wir gesehen, dass das ganze stabil wird: In Bits können wir das schreiben als: b = ~(a), c = ~(b), wobei a = c. Damit können wir einen beliebigen Zustand, 0 oder 1, anlegen und er wird festgehalten, bis wir ihn überschreiben.
Zum so ein FF umschalten, muss man ihm von aussen "stören", also ein Bit "verteilt" zuführen, je nach 0 oder 1 muss dafür der eine oder der andere NICHT "angeschubst" werden, daher wird das auch Reset/Set FF (RS-FF) genannt.
Ein RS-FF zu benutzen ist mühsam. Zum dies einfacher machen gibt es verschiedenste "Verteiler" Schaltungen, die ich wegen Kompliziertheit und Irrelevanz der Details hier zum Zeit sparen weglasse. Das Resultat davon ist jedenfalls das heute üblich benutzte Data FF (D-FF), das 2 Eingänge hat: d für Daten, und clk (= Clock, = Takt) zum es "anschubsen", als "speicher jetzt" Signal. Dieses Signal ist ähnlich wie das "auswahl" Signal beim Multiplexer, keine Daten sondern Steuerung. Dieses Takt Signal ist natürlich genau das, was man an MHz oder GHz in den Prozessor einspeisen muss.
Will man mehrere Variablen (braucht ja jedes normale Program) so muss man eine ganze Sammlung Register haben, inklusive einem grossen n:1 Multiplexer zum aus ihnen auswählen. Das ganze ergibt dann zusammen einen Speicher. Neben dem, dass der Speicher in Bitgruppen Daten speichert, braucht er auch eine weitere Bitgruppe von n Bits um den Multiplexer zu ansteuern. Diese Bitgruppe nennt man die Adresse.
Jede Variable entspricht einer Speicherstelle, Array Variablen einer Serie von gleich grossen Speicherstellen. Variablennamen sind nichts anders als Symbole für die Adressnummer der Speicherstelle dieser Variable.
Da Adressen durch Bits representiert sind, kann man Adressen auch im Speicher als Daten abspeichern. Es ist dann möglich eine Adresse aus einer Variablen zu holen, in ein Register zu laden, mit dessen Inhalt den Speicher erneut zu addressieren, und mit den Daten die dann ausgewählt sind zu arbeiten. Sowas nennt man indirekte Addressierung. Die dafür benutzten Variablen sind die allseits bekannten und oft nicht verstandenen Pointer.
Heute gibt es 2 Sorten Speicher Chips:
bit=0 für diese Spalte bit=1 | | -)|(----------------------------)|(---- 5V | | | | | `-| |-' | ein SRAM Speicherbit | ||-. .-|| | | .-| | | |-. | in beiden Richtungen | | | | | | horizontal und vertikal |--. .--+----|-..-|----+--. .--| viele Male wiederholt | | | | | /\ | | | | | | ----- `-| |/ \| |-' ----- | | --- ||-' `-|| --- | | | .-| |-. | | | | | | | | -)|(----------------------------)|(---- Auswahl der Zeilen | | | | -)|(----------------------------)|(---- 0V | | ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ Gesammtstruktur vom SRAM ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ Z = Zellen wie oben ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ A = Auswahl der Zeilen ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ B = Bits auslesen oder ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ einschreiben BBBBBBBBBBBBBBBBSSBBBBBBBBBBBBBBBB S = Steuerung des Chips ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ Beispiel: ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ 6264, 64kBit = 65536 Bit ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ organisiert als 8kx8bit ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ 256 Zeilen a je 32*8Bit ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZAAZZZZZZZZZZZZZZZZWelche der Zeilen "aktiv" ist, wird von einer Hälfte der Adresse bestimmt. Die Spalte die "angeschubst" wird, hängt von der anderen Adresshälfte ab, und ob eine 1 oder 0 gespeichert werden muss. SRAM wird im Prozessor für Register und Caches benutzt, ebenso in externen Cache Chips
bit f Spalte 0V | | | || | ein DRAM Speicherbit |--. .----||--| | | | || | wie SRAM wiederholt | ----- C | ebenso A, B und S | --- | | | | | | | -)|(-----------)|(---- Zeilenauswahl | |Alle C einer Zeile werden zusammen geladen und entladen. Um eins zu ändern muss die ganze Zeile geholt werden, das eine Bit ersetzt, und die Zeile zurückgeschrieben werden (Lesen leert die Kondensatoren, also löscht alle Bits, also müssen alle neu geschrieben werden). Das ist der Grund warum DRAM langsam ist. DRAM wird in den SD-RAM Chips auf den DIMMs benutzt. Der Cache (aus SRAM) soll die Langsamkeit vom SDRAM (und den Leitungen) verstecken, indem er (hoffentlich) die häufig benutzten Daten beinhaltet. Ausserdem tut der Cache gleich einen Block von 4 oder 8 Speicherstellen holen, damit man nur jedes 4te oder 8te Mal warten auf die DRAMs muss
Weil Speicher mit einem x:1 Multiplexer ausgewählt wird, der mit n Bits an Auswahl Signalen angesteuert wird (also ein (2^n):1 Multiplexer), haben Speicher Chips auch immer 2^n Bits Grösse, und das ergibt die bekannte Grössenserie 2^10 = 1024 = 1k, 2^20 = 1048576 = 1M, 2^30 = 1073741824 = 1G.
Wie wir schon wissen rechnet der Addierer als kombinatorische Logik dauernd mit egal was vorne ansteht, egal ob das Ergebnis benutzt wird. Anderseits wissen wir dass man Addition/Subtraktion muss wählen können. Ebenso muss man x verschiedene Multiplexer steuern. Und schliesslich Register und Speicher mit clock Signalen versorgen.
Für jede Operation braucht es dazu eine Sequenz von solchen Steuersignalen. Das Program sollte nun dann eine Sequenz von diesen Sequenzen aufrufen. Dazu besteht es aus einer Liste von Nummern, die Gruppen von Steuersignalen auslösen.
Ein Stück C Code als Beispiel: int b=10, c=5; int proc(int a) { b = a+b*c-30; return (b*4-1); } /* .. */ int d; d=proc(5); Übersetzen (compilieren) wir das zu Assembler: b: * c: * proc: load b, r2 ; r2 = b (r1 hat erster Parameter, a) mult c, r2 ; r2 = b*c add r2, r1 ; r1 = a+b*c sub 30, r1 ; r1 = a+b*c-30 store r1, b ; b = r1 mult 4, r1 ; r1 = b*4 sub 1, r1 ; r1 = b*4-1 return ; r1 ist Rückgabewert : .. d: * const 5, r1 call proc Übersetzen (Assemblieren) wir das weiter zu Binary (16bit): 0000: 000A ; b ist 0x000A = 10 0002: 0005 ; c ist 0x0005 = 5 0004: LDM2 0000 ; LDM2 ist eine Zahl, Prozessorabhängig ; die Systematik dieser Zahlen ergibt den ; Befehlssatz des jeweiligen Prozessors ; 0000 ist die Adresse von b 0008: MUM2 0002 ; 0002 ist die Adresse von c 000C: AD21 ; Addition braucht keine Adresse, nur Register 000E: SUC1 001E ; Subtraktion mit Konstante 0x1E = 30 ; Unterschied Konst 0x1E und Speicher 001E ; (= Zahl für RETN) ist SUC1 vs SUM1 Befehl 0012: ST1M 0000 ; speichern nach b (0000) 0016: MUC1 0004 ; Multiplikation mit Konstante 001A: DEC1 ; Decrement = Subtraktion 1 001C: RETN ; und ab 013A weiter 001E: .... ; .. 0156: 0000 ; d mit 0 vorbesetzt, da kein = etwas 0158: .... 0134: LDC1 0005 ; die 5 für den Call 0138: CALL 0006 ; und ab 0006 weiter 013A: ST1M 0156 ; hier Resultat in r1 nach d speichern
Um dies auszuführen wird nun so vorgegangen: Mit einem speziellen Register (Programzähler (PC)) das momentan 0x0134 drin hat, wird auf den Speicher zugegriffen. Es kommt "LDC1" zurück. Dem PC wird 2 addiert, damit er für das nächste Wort vom Program bereits it. Der Prozessor führt dann die für LDC1 einverdrahtete Funktion aus: mit PC nochmals Zugriff (und danach PC+=2) und die Daten in Register 1 verfrachten. Dann ist der Befehl fertig.
Also nächster holen (und PC+=2), was CALL ergibt. Der wird ausgefüht als: PC+2 nicht in PC laden, sondern wegspeichern für den RETN später. Dann das 0006 in den PC laden -> nächster Befehl ist der LMR2 in 0006.
So geht das weiter, Befehl für Befehl, solange Strom da ist. Immer Befehl holen und auswerten und ausführen. Wer mal ein beliebiges C Program in den Assembler seines PCs sehen will, sollte die -S Option vom gcc anschauen.
Die Rechner wurden kleiner, schneller und billiger, dadurch das man in der zweiten Hälfte der 1960er integrierte Schaltungen einführte. Zuerst mit SSI (small scale intergration, bis 30 Transistoren) TTLs nur ein Modul pro Chip (7400 ist 4 Stück 2-Eingang NICHT-UND). Dann mit MSI (medium scale integration, bis 300 Transistoren) immer mehr (7474 ist 2 volle D-FF, 7483 ist ein 4Bit Voll-Addierer), und dann mit LSI (large scale integration, bis 3000 Transistoren) noch mehr (74181 ist 4bit Addier+Sub+anderes, 74374 ist ein 8bit Register) und schliesslich ganz viel (74481 ist ein 4bit Ausschnitt eines ganzen Rechner Datenpfades).
Solche 74(x)xx Chips sind relativ universell, und wurden daher bis ca 1990 auch in professionellen Schaltungen verbaut. Heute sind die wegen langsam und viel Platzverbrauch und teuer (die Kosten vieler kleine Chips addieren sich) fast nur noch in Hobby und unkritischen professionellen Schaltungen drin.
Je grösser man Chips macht, umso mehr trift nun aber ein Problem auf, dass sie zu spezialisiert werden, nur für eine Funktion brauchbar, also nicht für jedermann nutzbar. Kombiniert man die so resultierenden geringeren Stückzahlen mit den immer grösseren Entwicklungskosten grosser Chips und sie werden zu teuer. Das ist so ab 1000-10'000 Transistoren der Fall.
Grosse Firmen wie IBM oder Telephonzentralen Hersteller können sich diese Kosten erlauben, einen eigenen 1000-1'000'000 Transitor Chip nur für sie entwickeln zu lassen und die Kosten über wenige 1000 Kopien bezahlen zu lassen. Sowas nennt man ein ASIC (= Application Specific Integrated Circuit). Der Rest hat keine Chance da mitzumachen.
Eine Spezialform von ASIC, Gate Arrays (GA) nutzen die CMOS Chip Struktur aus und baut die ganzen Transistor Zeilen und Stromversorgung nur einmal, und dann nur die Verdrahtung Kundenspezifisch. Das verringert die Entwicklungskosten um den Faktor 10, aber unterhalb von 10'000 Stück wirds auch so teuer. Ein einzelnes solches GA im ZX81 ersetzte die gleichwertigen 18 74(x)xx Chips des ZX80 (heute gibt es ein ZX81 Nachbau in FPGA und CPLD. Ebenso haben ein paar ASICs in meinem 386er ersetzen die fast gleichwertigen vielen 74(x)xx Chips in meinem 286er ersetzt.
Der Speicher kann, da universell und für jedes Program geeignet, beliebig gross hergestellt werden. Speicher sind so kleiner und billiger als viele einzelne Chips. Wie wir heute wissen, entstanden aus Mikroprozessoren am Schluss PCs, also ganze richtige Computer.
Der Erste Mikroprozessor, der Intel 4004 bestand aus 2300 Transistoren, rechnete mit 4 Bit, hatte 16 4bit Register, und konnte 4096*4bit ROM und 64*4bit SRAM addressieren. Er wurde ab Nov 1971 verkauft.
Als logische Konsequenz der Mikroprozessoren gab es danach die Mikrocontroller. Diese haben auf einem Chip den Prozessor und etwas Speicher und etwas IO, also ein ganzer simpler Computer auf einem Chip. Das ist was man üblicherweise heute in Gerätschaften findet, z.B. in Audio oder Video Geraten, oder in Haushaltsgeräten, oder in Maschinen oder Autos.
Mikroprozessoren sind erfolgreich als Computer, aber in der ursprünglichen Anwendung, viele Chips zu ersetzen haben die ein grosses Problem: sie sind zwar kleiner und billiger, aber langsam. Verdrahtete Logik arbeitet je nach Ausgabe etwa 30-1000 mal schneller als Programme, weil bei Logik alles gleichzeitig passiert, während ein Program jede einzelne Funktion sequenziell abarbeiten muss. Das sieht man gut bei Emulatoren, wo ein x00MHz PC gerade einen 1MHz C64 emulieren kann. Das ist der Preis den man zahlt dafür, dass der Mikroprozessor ein Program Befehl für Befehl abarbeitet.
Für manche Anwendungen (z.B. einer Lichtsignal Anlage oder Waschmachine) ist das akzeptabel, weil die Geschwindigkeit von verdrahteter Logik eh viel schneller als nötig war. Für andere Anwendungen reicht es gar nicht. Eine dieser Anwendungen ist open source Hardware, die beliebige Funktionen machen kann.
Ein Problem der ersten ROMs war, dass ihr Inhalt bei der Herstellung eingebaut werden muss, bevor das Gehäuse hergestellt wird. Die Struktur ist ähnlich DRAM, aber mit einem Metalltröpfchen (oder eben nicht) statt dem Kondensator. Also musste man sein Program dem ROM Hersteller schicken, damit er die Tröpfchen richtig setzt/weglässt. Das war zeitaufwendig, vor allem bei Bugfixes. Und teuer war der Prozess auch, wenn auch deutlich weniger langwierig und teuer als ein Gate Array oder gar ein ASIC fertigen lassen. Das kann man heute mit dem pressen von CDs vergleichen.
Dieses Problem wurde gelöst durch die Erfindung von PROM Chips (P = programmierbar), die erst beim Chip-Käufer programmiert werden. Die haben statt Metalltröpfchen kleine Nickelbückchen, welches an unerwünschten Orten vom Benutzer "weggebrannt" werden können. Die PROMs stehen zu ROMs im selbigen Verhältnis, wie CD-Rs zu gepressten CDs.
Später entstanden auch noch die mit UV-Licht löschbaren EPROMs (E = erasable) was übrigens eines der ersten Chips der Firma Intel waren. Die heutigen elektrisch löschbaren Flash Chips sind deren Nachfolger (mit Intel als grösster Hersteller), quasi die CD-RWs der Chips.
SRAM und DRAM ist im Vergleich zu all denen die HD der Chips, beliebig jederzeit beschreibbar, die allerdings ohne Strom alles vergessen.
ROMs/PROMs/EPROMs/Flash machen eigentlich nur eines: für jede Adresse (= Eingangs Kombination von a Bits) am Ausgang d Datenbits von sich geben. Damit kann man die auch als kombinatorische Logik Chips missbrauchen. Dazu lädt man in den Speicherchip die gewünschte Logik als Tabelle. So wurde z.B. ein PROM im Disk Controler vom Apple II benutzt.
Als kleines Beispiel würde unser Multiplexer von vorher eine Tabelle von 2^3x1 Bit benötigen:
Adresse Daten Wir verdrahten: ...3210 76543210 A0 = e1 A1 = e2 ...a000: ...d0 A2 = auswahl ...a001: ...d1 A3... = andere Eingäange ...a010: ...d0 a heisst Adressteil invariant, also ...a011: ...d1 wiederholen für alle möglichen ...a100: ...d0 Positionen ...a101: ...d0 D0 = ausgabe ...a110: ...d1 d heisst Daten irrelevant für hier ...a111: ...d1 von anderen Gattern mit A3... benutzt
Als grösseres Beispiel würde ein 4bit Addierer, 9 Eingänge (4 a Bits, 4 b Bits, 1 Übertrag) und 5 Ausgänge (4 Ergebnis Bits, 1 übertrag) haben. Also braucht das ein 2^9x5bit = 512x5bit an PROM Platz. Und hier eine 512 Zeilige Tabelle, wesshalb ich das weglass. Das würde man minimal in einem 512x8 = 4kBit Chip implementieren. Wenn man aber z.B. einen 64kBit = 8192x8bit Chip hat, könnte man noch eine weitere 13-9 = 4 Eingang und 8-5 = 3 Ausgang Funktion mit einbauen. Oder man nimmt einen weiteren Eingang und verwendet diesen um zwischen Addition und Subtraktion Tabellen zu wählen.
PROMs brauchen so viel Platz, weil sie voll dekodiert sind. Das heisst für jede Kombination der Eingänge hat es eine Zeile im Chip drin. Das gibt für n Adressleitungen, 2^n Adressen und somit 2^n Zeilen. Dies wird so verdrahtet:
(P)ROM Ausschnitt, 3 Adressleitungen, 2^3=8 Adressen, 4bit breit I = Inverter, ergeben ~A0, ~A1, ~A2, ... o = verbunden, - = keine Verbindung U = UND um Adresse zu dekodieren, pro Adresse eine Zeile ... A2 A1 A0 |__ |__ |__ | | | | | | | I | I | I Produktterm: | | | | | | | | | | ..-----o-----o-----o--U - 0 ---..--x--x--x--x- alle ~An UND = 0 | | | | | | | | | | ..-----o-----o--o-----U - 1 ---..--x--x--x--x- nur A0 rest ~ UND = 1 | | | | | | | | | | ..-----o--o--------o--U - 2 ---..--x--x--x--x- nur A1 rest ~ UND = 2 | | | | | | | | | | ..-----o--o-----o-----U - 3 ---..--x--x--x--x- A1 UND A0 rest ~ = 3 | | | | | | | | | | ..--o--------o-----o--U - 4 ---..--x--x--x--x- nur A2 rest ~ UND = 4 | | | | | | | | | | ..--o--------o--o-----U - 5 ---..--x--x--x--x- | | | | | | | | | | ..--o-----o--------o--U - 6 ---..--x--x--x--x- | | | | | | | | | | ..--o-----o-----o-----U - 7 ---..--x--x--x--x- x = Datenbits | | | | | | | | | | = o oder - : : : : : : : : : : | | | | O O O O ODER der Bits | | | | .. D3 D2 D1 D0 Daten Ausgang
Die "I" sind Inverter, die "o" sind Verbindungen (- = keine Verbindung) die beim Herstellen eingebaut werden, die zusammen mit den "U" UND Elementen sorgen dafür, dass bei jeder möglichen Adresse ein Produktterm aktiv wird. Die x sind die Daten. Bei ROMs sind das die Metalltröpfchen. Bei PROMs die Metallbrückchen. Bei DRAMs die Transitor+Kondensatoren. Bei SRAMs die 6er Gruppen Transistoren. Beides wirken mit dem "O" ODER Elementen unten zusammen um die Daten zu sammeln. Das (P)ROM ist also eine NICHT+UND+ODER Logik (implementiert als NICHT+NICHT-UND+NICHT-UND).
Das ist so für Speicher sinnvoll, aber für Logik massive Platz Verschwendung. Das exponentiale Wachstum an Zeilen killt diese Lösung oberhalb von etwa 10..12 Eingängen.
Die Antwort darauf war ein Chip mit ebenfalls brennbarer Definiton der Zeilen, also auch "x" links. Das gibt ein PLA. So eins hat nur etwa 4*Ausgänge an Zeilen statt 2^Eingänge. Z.B wurde so ein im C64 ein PLA als Adress-Manager verwendet um die Speicher Chips auszuwählen. Mit 16 Eingängen und 8 Ausgängen wäre dazu ein 64kx8 = 512kbit PROM nötig gewesen. So ist es aber nur ein kleiner 2*16x4*8+8x4*8 = 1280 Bits PLA. Das zu einer Zeit als es bei ROMs noch mit 64kbit Schluss war.
Aber die PAL Entwickler gingen noch weiter und lieferten auch PALs mit Flipflops bereits drin, damit man nicht mit Ausgang-pin + externes FF + Eingangs-pin Pins verschwenden muss. Das waren die "R" Serie Register PALs. Z.B. ist ein PAL16R6 ein 20pin (2 Strom, 18 Daten) Chip, mit 8 Eingangspins, 16 Spalten (8 von Pins, 8 von Ausgängen), 64 Zeilen, 8 8-Eingang ODER, 6 FFs (andere 2 ohne FF), 8 Ausgangspins. Die restlichen 2 Pins sind einer clk für die FFs und einer um die FF Ausgänge abzuschalten. Alle PAL16Rx haben 2*16*8*8 = 2048 Bits.
Aber die "R" PALs waren recht inflexibel. Sie haben genau 2/4/6/8 FFs, fest verdrahtet. Die Firma AMD hat dann den flexiblen 22V10 erfunden, ist ein 24pin (2 Strom, 22 Daten), mit 12 Eingangspins, 22 Spalten, abgestuft 2*8+2*10..+2*16 = 120 Zeilen, 10 ODER, 10 wählbar aktiven FFs, sowie auch wählbar Ein-/Ausgänge, sogar in Betrieb schaltbar. Der 22V10 hat 5280 Bits. Diesen konfigurierbaren Ausgangs Mechanismus nennt man Makrozelle.
Später hat die Firma Lattice die kleineren 16V8 und 20V8 produziert. Ziel war, so klein wie 16R8 bzw 20R8, kann alle L und R Typen emulieren, und doch so viel wie möglich der 22V10 Features. Diese waren ein Riesenerfolg. Seit 15 Jahren werden daher nur noch "V" PALs eingesetzt.
Es gibt heute PALs bis zu 68pin mit 48 Ausgängen (Altera EP1810). Ebenso bis es solche mit bis zu 40pin mit und 24 externen Ausgängen aber 72 internen, weil 48 nur zum weiter intern verwerten (Atmel ATV2500).
Die heutigen PALCE Chipfamilien sind ausserdem noch löschbar, wie EPROMs. Sie sind auch durch Fehlprogrammierung nicht zerstörbar. Und sie sind heute immer noch von mehreren Firmen erhältlich, und daher billig. Also ideal für Elektronik-Einsteiger ihre Programmierversuche.
Leider fehlt ein standard Board Design, dass jeder dann mit PAL Designs füttern kann. Also muss man hier selber etwas löten oder wrappen oder stecken. Und da PALs sehr klein sind, ist es unwahrscheinlich, dass jemand ein universelles Board macht.
Aber für komplexe Schaltungen, mit viel Innenleben in einem Chip, muss man alle die internen (nicht nach aussen verdrahteten) Makrozellen auch als "Ausgänge" (und folglich auch Eingänge) des Arrays zählen. Wenn man eine quadratisch anwachsende Anzahl MZs haben will, wie bei ASICs, dann muss man die Bits auf O(1) reduzieren können.
Als einen Ausweg hat man die CPLDs erfunden. Diese haben b Blöcken mit je einer konstanten Arraygrösse, üblicherweise mit i=16..64, o=8..32 n=4..8, z.B. häufig ein 2*48*5*16 = 7680bit, pro Block. Diese gibt es nun dann je nach Hersteller in b=2/4/6/8/12/16/24/32 Grössenabstufung. Das gibt also für b*16 MZs bei unseren 7680 Bit = (2..32)*7680 = 15360..245760, ist also O(1).
Um die b Blöcke zu verbinden braucht es nun aber eine "Vermittler" Verdrahtung zwischen ihnen. Die hat selber b^2*i*2*o (in unserem Beispiel b^2*48*2*16 = b^2*1536bits = (2..32)^2*1536 = 6144..1572864) mögliche Positionen und ist daher wieder O(2). Aber von denen sind, da nicht jeder Ausgang mit jedem beliebigen Eingang verbindbar sein muss, nur ein Teil besetzt (sparse matrix). Das ergibt bei geschätztem 10% besetzt: (2..32)^2+1536*0.1 = 614..157286 Bits, also noch unter den 15360..245760 von oben.
Bis auf ca 512 MZs hinauf ist dieser Vermittler, der O(2) wächst, also noch kleiner als die O(1) wachsende Summe aller Blöcke. Darüber würden die CPLDs wieder nur linear wachsen. Weshalb über 512 MZs hinaus bei CPLDs Schluss ist. Bereits 384 FFs und 512 MZs sind sehr viel teuerer als 256 MZs, was mir nahe legt, dass die vielleicht mehr als 10% besetzt sind.
Neben den b*2/4/6/8/12/16/24/32 gibt es auch noch ein paar spezielle Grossformen, wie "Blöcken von Blöcken" mit 6*(8*20)=960 MZs (Philips/Xilinx XPLA2, gestorben), oder "Array von Blöcken" mit bis zu (7x5)*16=560 MZs (Altera MAX9000), oder gar ganz neu (2002) "Array von Blöcken" mit bis zu (7x6)*(8*16)=5376 MZs (Cypress Delta39K).
Während PLA/PAL/CPLD aus PROMs mit verringerter Grösse bei vielen Eingängen entstanden sind, gingen die FPGA Erfinder einen ganz anderen Weg. Sie verwenden analog zu einzelnen TTL Gattern pro FF separate kleine PROMs, üblicherweise mit nur 4 Eingängen und 1 Ausgang, also ganze 16bit gross. Damit kann man je ein beliebiges Gatter mit max 4 Eingängen machen, z.B. ein 4-Eingang NICHT-UND, oder aber einen EXODER, oder aber einen ganzen Multiplexer. Ein 1bit Addierer braucht wegen 2 Ausgängen 2 solche mini-PROMs.
Unser kleines Beispiel mit dem Multiplexer von vorhin sieht dann so aus:
Adresse Daten Wir verdrahten: 3210 A0 = e1, A1 = e2, A2 = auswahl, A3 = leer 0000 = 0: 0 0001 = 1: 1 Tabelle = 01010011 01010011 0010 = 2: 0 0011 = 3: 1 0100 = 4: 0 0 3 0101 = 5: 0 \ / 0110 = 6: 1 Graphisch 4x4 Format: 0101 0111 = 7: 1 0011 (wiederholung) 0101 1000 = 8: 0 0011 1001 = 9: 1 / \ 1010 = 10 = A: 0 C F 1011 = 11 = B: 1 1100 = 12 = C: 0 Das "rotierte R" Muster ist 1101 = 13 = D: 0 typisch für Multiplexer 1110 = 14 = E: 1 1111 = 15 = F: 1
Dafür das die PROMs klein sind, hat ein FPGA sehr viele davon (100e bis 10'000e), in einem Array von Zellen angeordnet:
IOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO Struktur eines FPGA: IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO [] = ein Element von 16bit PROM IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO = eine Schaltung zum IO[][][][][][][][][][][][][][][][]IO Daten in und aus dem IO[][][][][][][][][][][][][][][][]IO Chip zu befördern IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IO[][][][][][][][][][][][][][][][]IO IOIOIOIOIOIOIOIOIOIOIOIOIOIOIOIOAuf einem Chip Photo (vermutlich XCV2000E, da 80 Zeilen von Blöcken) seht es so aus: Rand die weissen Teile die IO Schaltungen, die blau bis grünen Teile sind die [] Logik, die dunkelgrünen Teile sind zusätzliche Verdrahtung.
Wenn wir nun für 32bit 32 Stück Multiplexer benötigen, so nehmen wir einfach einen 32 Elemente langen Ausschnitt aus einer Spalte von Elementen. Für das nächste Schaltungsteil gibs weitere 32 Elemente der nächsten Spalte. So passt jede Schaltung in genug Elementen.
Ein Beispiel für FPGA Gebrauch ist mein PDP-10 Clone Projekt. Es hat auf der Projekt Website eine genauere Beschreibung (in Englisch). Man sieht auf dem Bild deutlich die Zellenstruktur, das 64x96 Zellen grosse Array eines XCV300. Man sieht auch die vertikalen Streifen von für alle Bits wiederholten Funktionen. Und man sieht viele Streifen mit dem "rotierten R" Muster, weil Multipleyer so weit verbreitet sind. Überhaupt ist der streifige Block der Teil der die Daten verarbeitet. Die "Anhängsel" oben sind die Steuerung, die so Sachen wie Multiplexer Auswahl oder D-FF Speichern Signale generiert.
Damit die mit vielen kleien Zellen noch grössere Menge an Verdrahtung nicht überhand nimmt, wurde hier eine Art "programmierbare Platine" erfunden. Da kann eine Zelle direkt nur mit seinen Nachbaren verbunden werden. Für weitere Verbindung gibt es "Verlängerungsteile" die bis zum Ziel "zusammengesteckt" werden können. Beispiel ist die Xilinx Virtex Verdrahtung, die ich mal aufskizziert habe. Damit kann man die Bitzahl des ganzen Chips O(1) halten, je nach Chip Familie etwa 128..256 Bit pro FF, hier mit 864 bits pro 4er Block an FFs, bzw 216 bits pro FF.
Damit können FPGAs mit der vollen "alle 3 Jahre mal 4 Grösse" wachsen, ohne irgendeine Limite nach oben. Die Hersteller liefern ganze Grössen-Serien. Z.B. die Xilinx Virtex Familie gibt es von 32x48 = 1536 FFs bis 128x192 = 24576 FFs. Mit der voll kompatiblen Spartan-II Serie wurde das auf 16x24 = 384 FFs hinunter erweitert. Mit den etwas ausgebautem Virtex-E auf 208x316 = 65728 FFs hinauf erweitert. Die Chips haben alle 216 Bit/FF, die sind also von 82944 bis 14197248 Bits gross.
Ich compiliere momentan für einen XCV300, der 64x96 = 6144 FFs hat, also 1327104 Bits gross ist. Ein CPLD von 6144 MZs hätte bei 10% 384*7680+384^2*1536*0.1 = 2937600+22649241 = 25586841 Bits. Ein PAL mit 6144 FFs hätte gar 2*5144*8*5144 = 603979776 Bits.
Eine Kuriosität haben FPGAs noch: Im Gegensatz zu PLA/PAL/CPLDs die PROM oder EPROM oder Flash Technologie verwenden, ist in den FPGAs SRAM Speicher üblich. Das hat einen Vorteil, dass man sie beliebig oft neu laden kann (ideal zum ein Board abwechslungsweise mit mehreren Designs zu fahren), oder sogar in Betrieb abändern kann. Auch für Debugging (schnell mal ein "printf" eines Signals auf einen Pin) oder für regelmässige Testläufe (was für Effekt hat Änderung) ist dies von Vorteil, da es Hacker/experimentale Programmiermethoden statt Ingenieur/durchgeplant erlaubt. Aber dafür müssen die FPGAs bei jedem Gebrauch "gebootet" werden, wie ein Rechner. Dafür muss man einen separaten PROM/EPROM/Flash Chip (Bootmedium) haben, und einen Bootmechanismus. Die Hersteller bieten spezielle autonome Chips mit dem Mechanismus drin, aber die sind schweineteuer. Üblich ist daher auch ein normaler PC BIOS Flash Chip mit einem Mikrocontroller. Bei FPGA basierten PCI Karten wird oft einfach der FPGA vom Treiber her geladen.
Es gibt seltene Hersteller von FPGAs mit einem PROM-artigen System namens "antifuse", bei dem Leiterbahnen im Chip "zusammengeschweisst" werden, etwas wie Thermit-Schweissen bei Eisenbahnschienen. Aber deren Herstellung macht Probleme, und hinkt in der Chipgrösse den SRAMs hinterher, was kleine und langame Chips ergibt. Ausserdem gibt es vom "Verschweissen" her Verschmutzung des Chips (noch mehr als bei Metallbrückchen durchbrennen), was der Technologie weitere Limiten setzt. Und experimentell kann man mit denen auch nicht arbeiten.
Einerseits stammen die Methodologien, auf die diese Tools aufbauen, aus der ASIC Produktion, wo ein "Compiledurchlauf" Edit->Chip mehrere Wochen(!) dauert. Also ist da nichts mit "schnell mal Test" (und desshalb wird das auch nicht unterstützt). Es ergibt sich dadurch ein sehr rigoros geplanter Arbeitsstil mit Modellierung und Simulation, der vorgegeben (und erzwungen) wird, der mit dem typischen Hacker inkompatibel ist.
Anderseits sind alle diese Tools closed source, und zumeist nur für Windows NT und Solaris/Sparc, selten mal noch AIX oder HP-UX. Und die offiziellen Compiler sind Kommerzsoftware vom schlechtesten: bloatig, buggy, und mit einer "Der User muss nichts wissen" (und darf nichts wissen) Einstellung geschrieben. Und ausser den kostenlosen Abgaben für ausgewählte kleine Chips (für Schulungszwecke) sind die Tools schweineteuer, so $3000-30'000.
Kritiken an dieser Politik werden grundsätzlich abgewiesen: "Wir machen Tools, unsere User wollen die Chips verwenden, nicht selber nochmals Tools machen. Und wir erachten es als Behinderung unserer Möglichkeiten der Innovation, wenn User unsere Interna kennen und ihre Designs davon abhängen." Und für nicht-Hersteller Tools erachten sie Information unter NDA an kommerzielle closed source Compiler Hersteller als ausreichend. Die ganze Idee von open source und aus User-Zusammenarbeit entstehenden Tools, und warum die besser sind, ist ihnen völlig fremd, trotz ihnen X mal erklärt worden.
Man stelle sich vor, Intel und alle anderen Prozessor Hersteller hätten nach den 8bit Generation unisono erklärt: "Ihr braucht die Bits nicht mehr zu kennen, das behindert uns nur in neue Prozessoren entwickeln, wir liefern alles was ihr braucht: einen Fortran, Cobol und sogar Algol Compiler". PCs wären nie das was sie heute sind. Die Logik Chip Hersteller haben nach den PALs diese Strategie durchgezogen.
Die PALs sind, bis zum 22V10 hinauf vollständig dokumentiert. Darüber noch vereinzelt (Atmel ATV750 und ATV2500, nicht aber die Altera EP610/EP910/EP1810). Also kann man für die auch open source Compiler machen. Aber weder Freshmeat noch die Debian apt-get Liste zeigt einen PAL Assembler oder Compiler. Aber über Google fand ich zwei, die aber nur die 16V8 und 20V8 Teile können: galprog - GAL Programmer Software for Linux und Galassembler für 16V8 und 20V8 Gals.
Für CPLDs ist das Hauptproblem, dass die Hersteller deren Programmierung nichts dokumentieren. Also ist nix mit open source Compiler für diese schreiben. [Nachtrag: Das zumindest war mein Kenntnisstand bis Dienstag den 20. Mai. Einer meiner Testleser von diesem Vortrag hat darauf hingewiesen, dass die Lattice isp1000 Chips (32-96 IOs, 64-192 MZ) die er benutzt teilweise dokumentiert sind. Das scheint zu reichen um sie zu reverse engineeren, soweit ich mal schnell die Doku überflogen hab.]
Bei den FPGAs wär die Situation auch ebenso verloren, wenn nicht ein Hersteller eine Ausnahme gemacht hätte, die bis heute nachwirkt. 1990 hatte eine kleine Firma namens Algotronix einen primitiven FPGA namens CAL1024 gemacht und den voll dokumentiert. Die Firma wurde ca 1995 von Xilinx aufgekauft und deren fast fertiger CAL2 Chip kam als XC6216 auf dem Markt, ebenfalls mit voller Doku. Dieser wurde schnell der Liebling der ganzen Akademiker, weil sie dafür Compiler designen konnten, und damit mit eigenen Sprachen experimentieren konnten, statt den von den Herstellern vorgegebenen benutzen, z.B. an der ETH Informatik.
Leider war der XC6216 ausserhalb der Akademiker erfolglos, weil langsam. Also hat Xilinx ihn eingestampft. Das gab eine Menge unzufriedener Akademiker, was Firmen nicht mögen (weil schlechte Publicity). Also hat Xilinx ihren damals neuesten Virtex Chip teilweise dokumentiert, woher ich auch weiss, dass es pro 4-er Gruppe von FFs 48x18 = 864bit braucht. Ebenfalls haben die eine (closed source) Java Library namens JBits herausgegeben, mit der man den Chip relativ direct ansprechen kann, also in Java eigenen Compiler schreiben kann. Diese läuft wenigstens auf dem Linux JDK, und ist damit das, was ich momentan benutze. Noch besser aber, diese Doku und JBits sind zusammen gut genug, dass man definitiv damit den Chip Reverse-Engineeren kann! Aus dem Grund hab ich auch mein VirtexTools Projekt gestartet, das eines Tages die Chips offen benutzen lassen soll.
Ein System das momentan in Entwicklung ist funktioniert mit Plastik. Basis ist statt Silizium etwas wie eine Projektorfolie. Darauf wird wie mit einem Tintenstrahl Drucker die Transistoren und Leiter aus einem organischen Material aufgetragen. An den dafür benötigten Chemikalien wird u.a. an der ETH Zürich geforscht. Meine Daten hab ich vom Professor Batlogg dort, der dies erforscht. Probleme hat das System aber: Platz geht recht gut (momentan so 100'000 Transistoren und wird sicher steigen), aber die Chips sind langsam, weil Kohlenstoff seine Elektronen gerne für sich behält (momentan so 1/3MHz, und Steigerung unsicher). Die Langsamkeit kann man aber umgehen (Nervenzellen haben ganze 300Hz, also 100 mal langsamer), was aber Fläche kostet. Aber viel schlimmer ist aber, dass die "Drucker" Hersteller vermutlich die Ansteuerung nicht frei geben werden, wenn man deren Verhalten bei WinPrintern anschaut. Also nur closed source Treiber, oder sogar Compiler.
Ein anderes System wäre ein Gate Array, das man mit Laser belichten kann, um die Verdrahtung zu machen. Würde die Geschwindigkeits Probleme lösen (weil Silizium), aber auch die selbigen Ansteuer und Rohmaterial Probleme haben. Und es gibt meines Wissens nach keine Firma die sowas herstellt oder vor hat.
Besser wär ein System, das einen rohen Chip nimmt, und diesen per Ionenimplantierung "beschreibt". Rohe Chips (oder zumindest Wafer) sind bei mehreren Herstellern zu haben. Und die Hersteller dieser Geräte, die vor allem an wissenschaftliche Laboratorien gehen, dokumentieren wie man den Strahl beliebig steuern kann. Deren Erweiterung auf Hardware herstellen könnte daher offen selber hergestellt werden. Problem hier ist, dass ein gebrauchter Ionenimplantator momentan bei $100'000 anfängt.
Der Wunsch open source Hardware Designs zu haben, die jeder User einfach herunterladen, "ausdrucken", modifizieren kann, mit nur open source Software, benötigt offene Chip Herstellungs Architekturen, und da steht es momentan schlecht drum aus. Momentan sind die Virtex FPGAs das was wir am besten in den Griff bekommen können.
Bereits vor über 10 Jahren brauchte ich dringend einen in "Points" (1/72 Zoll) geeichten Massstab, um eine Graphik auszumessen, um sie in Postscript zu implementieren. Der Geistesblitz traf ein: mit dem Postscript Drucker selber einen Points Massstab ausdrucken. Mit der selbigen Methode könnte man beliebige Masstäbe, Kurvenlineale, etc herstellen. Aber auch Sternsuchkarten sind nur ein paar Folien mit einer Niete zusammengeheftet. Oder gar architektonische Modelle, wie die Bastelbögen früher in der Schule, einfach festes Papier in den Drucker, und raus damit.
Und die Limite ist nicht bei Projektorfolie oder festes Papier bearbeiten. An der ETH Architektur Abteilung wird gross mit Laser Blechschneide Maschinen gearbeitet. Einfach CAD Zeichung exportieren und "Drucken". Unter anderem der dort eingesetzte Kleiderbügel Halter, oder deren CD Racks, oder die Rechner Boxen, aber auch Modelle. Wobei da wieder die Probleme mit unbekannter closed source Ansteuerung auftreten. Und Zugriff auf solche Maschinen mit standard Datenformat hat nicht jeder.
Im Maschinenbau gibt es seit mindestens 20 Jahren Bearbeitungscenter, wo man beliebige Formen Fräsen/Bohren/Drehen lassen kann. Deren Ansteuerung ist sogar offen, wenn auch nicht standardisiert. Problem ist da wieder die massiven Kosten der Maschinen (>$100'000), und daher geringe Verfügbarkeit für open source Hardware User.
Sogar Kunststoffteile oder gar Guss kann man heute per Computer formen. In der ETH Architektur waren 2 Actua Solid Modeller in Betrieb, bis der Hersteller die nicht mehr wartete und Rohmaterial lieferte. Zumindest ein detailliertes Modell der Millenium Falcon mit etwa 30cm Durchmesser wurde einfach so zum Scherz hergestellt. Von sich aus ist das Teil ein 3D Tintenspritzer, dessen "Tinte" ein Kunststoff ist, der sich verfestigt zum Werkteil. Man kann den Kuststoff aber nachher auch als "verlorene Form" für Präzisionsguss Techniken verwenden. Ein anderes Verfahren verfestigt eine Flüssigkeit per Laserbelichtung.
Das Gebiet das man da beobachten sollte nennt sich offiziell "Prototypenbau". Das ist der Begriff fur industrielle Herstellung einzelner Teile während der Entwurfsphase für spätere Massenfabrikation. Unser Interesse wär die Prototypen gleich als Endprodukt zu benutzen.
Das erste was einem zu Hardware, die nach Bits automatisch hergestellt wird, einfällt ist logischerweise Star Trek, genauer deren Replikatoren. Die dürften der Traum jedes Hardwarebastlers sein. Es wundert nicht, dass einer der beiden Actua Solid Modeller and der ETH prompt den Hostnamen replikator.ethz.ch bekam. Das war übrigens auch der, der später die Millenium Falcon "ausdruckte" (ja, das ist Star Wars).
Wenn man die offiziellen ST Handbücher anschaut, die Paramount rausgibt (ja, ein Kollege hat die), wird es aber schnell klar, dass ein Gerät der Bauart nie wird brauchbar sein. Das Gerät soll nämlich mit Atomsynthese (aus roher Energie, vom Atomraktor der Enterprise) arbeiten. Das Resultat wär total radioaktiv! Definitiv unbrauchbar. Dito übrigens die Transporter (die sind Scanner+Drucker), die Replikatoren wurden davon abgeleitet (Atommuster berechnen statt scannen und mehrfach ausdrucken).
Nach dem, was nicht funktioniert, nun die Frage nach funktionierendem. Dieses muss bestehende Atome beliebig anordnen können. Ein Weg: Die oben aufgeführten mechanischen Systeme können alle nur ein Bauteil aus einem Material formen. Spätestens bei mehreren Teilen oder gar gemischtem Material ist da auch Schluss. Das kann heute kein mir bekanntes System. Und ein System dass das kann wird kompliziert (Aufbau und Rohmaterialversorgung). Solange man aber Montage (Zusammensetzen) an den User abdelegieren kann (so a la Ikea) ist es nur noch eine Frage von aus mehreren Materialien separate Teile machen. Das wäre noch mit mehreren Maschinen vereinfachbar, aber das kostet noch mehr Platz und Geld. Das setzt vermutlich eine "Copy-Shop" artige Infrastruktur voraus. Aber das würde viele User brauchen um profitabel zu sein, also ein Henne-Ei Problem. Da wird also noch viel passieren müssen. Eventuell Universitäten die solche Maschinen haben, und andere Leute dran lassen. Solche Maschinen werden aber vermutlich eh immer speziell aufbereitetes Rohmaterial brauchen, mit den selbigen Problemen wie man es heute mit den Tintenpatronen Herstellern hat.
Neben schlicht mehrere Maschinen und Montage gibt es doch ein universelles Fabrikationssystem, das ich als möglich erachte: Biotechnologie. Immerhin schafft es die Biologie aus nichts ausser Nahrung ganze Körper wachsen zu lassen, X Teile, X Materialien, alles fixfertig montiert. Das Verfahren ist bekannt, aber sehr kompliziert: DNA->tRNA->Proteine->Rest. Das könnte man mit *.dna File Download, "Ausdruck" mit DNA Synthesiser, in Nährlösung, Teile wachsen lassen, machen. Aber um das zu können, benötigt für jedes Teil spezifische DNA Sequenzen. Das zu programmieren wird der Horror schlechthin. Viel Forschung wird da nötig sein. Ich erwarte das nicht in den nächsten 30 Jahren, ev sind es auch 100 Jahre. Und DNA Synthesizer Viren werden die heutigen Microsoft Viren harmlos erscheinen lassen, das .dna File eines Influenzia Viruses ist nur der Anfang.
Diese Seite ist von Neil Franklin, letzte Änderung 2003.07.07