Beiträge anzeigen

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


Nachrichten - erik.vikinger

Seiten: 1 2 3 [4] 5 6 ... 64
61
Hallo,


Wenn du das machst, hast du kein C mehr.
Deswegen vermute ich ja das dann einige Programme nicht mehr compilierbar sind. Die Frage die mich da noch interessiert ist: wie viele Programme trifft das wirklich? Wenn ich an meine eigenen C/C++-Programme denke (privat und beruflich) würde ich sagen das diese auch weiterhin noch compilierbar sind, einfach weil die IMHO solche Pointer-Tricks nicht benutzen (mir fallen auch nur wenige Fälle ein wo man sowas überhaupt benötigt und die liegen alle nicht im Bereich normaler C-Programme sondern eher sowas wie malloc/free oder die Speicherverwaltung in einem OS-Kernel).

C garantiert, dass uintptr_t ein Integertyp ist, also kann man damit rechnen.
Okay, aber welche Arten von Rechenoperationen sind denn damit sinnvoll? Mal ganz davon abgesehen das so ein Typ bei mir 48 oder 80 Bit groß wäre (was sich nur etwas umständlich auf die normalen Integer-Rechenbefehle der CPU abbilden lässt) so ergeben doch bei (u)intptr_t nur die selben sehr beschränkten Varianten einen Sinn wie bei Pointern direkt. Auch glaube ich nicht das es allzu viel real existierenden C-Code gibt in dem mit (u)intptr_t tatsächlich komplexe Rechenoperationen durchgeführt werden so das IMHO hier nur ein geringes Potential besteht ein vorhandenes Programm nicht mehr compilierbar werden zu lassen.

Und es erlaubt, zwei Pointer voneinander abzuziehen, wenn sie ins selbe Objekt zeigen.
Ist denn auch definiert was passieren soll wenn die zwei Pointer nicht ins selbe Objekt zeigen? Grundsätzlich gebe ich Dir ja Recht das es möglich sein sollte die Differenz zwischen 2 Pointern zu ermitteln (ebenso wie auch < , > , <= und >= Vergleiche zwischen 2 Pointern möglich sein sollten) aber bei einem segmentiertem Speichermodell ist das eben nicht immer möglich, nebst dessen dass das Ergebnis ein Integer mit der selben Größe wie der Offset-Teil sein muss und kein Pointer. Da ich mir es als recht schwierig vorstelle zur Laufzeit die entsprechenden Bedingungen zu prüfen und eine Verletzung auch korrekt zu behandeln bin ich daher dafür solche Operationen lieber gleich ganz zu verbieten. Ich denke auch nicht dass das eine nennenswerte Einschränkung darstellt, um z.B. die Offsets von Struktur-Membern zu ermitteln gibt es doch sicher auch andere Wege.


und dieser muss dann mit dem größeren übereinstimmen, oder?
Wimre sichert der C-Standard bei Pointer-Arithmetik gar nichts zu, das läuft alles unter "implementierungsspezifisch".


Du kannst auch eins mehr wieder dazuaddieren, ohne dass es undefiniert wird.
Ist dann auch definiert ob an dieser neuen Adresse auch tatsächlich Speicher vorhanden ist? Wimre nein.

Schwierig wird es erst, wenn du mit einem gecasteten Integer rumrechnest und dann wieder einen Pointer draus machst.
Solange man direkt bei Pointern bleibt hat der Compiler ja zumindest eine theoretische Chance das Gesamtconstruct zu verstehen und etwas sinnvolles daraus zu bauen. Das Problem an FAR-Pointern in simplen Integern ist eben das Selector-Arithmetik eigentlich keinen Sinn ergibt.


Grüße
Erik
62
Hallo,


Die Frage die sich mir nun stellt würden dadurch größere Probleme entstehen wenn die möglichkeit Zeiger in andere Typen zu casten entfallen würde?.
Ja, ich denke schon. Streng genommen ist jedes C-Programm das Pointer in beliebige Nicht-Pointer oder andersherum castet nicht so wirklich konform zum C-Standard. Es wird zwar zugesichert das man einen Pointer nach (u)intptr_t und wieder zurück casten kann und das Ergebnis beim == Vergleich mit dem Original true ergibt aber mehr auch nicht. Selbst die kleinste Rechenoperation darf den in (u)intptr_t gespeicherten Pointer irreparabel zerstören. Gerade das Rechnen mit FAR-Pointern ergibt ja auch keinen Sinn (wenn man mal vom x86-Real-Mode absieht in dem ja jeder FAR-Pointer auf eine eineindeutige lineare 20Bit-Adresse zurückzuführen ist, zuzüglich den Gate-A20-Spielchen natürlich) da unterschiedliche Selectoren ja bedeuten das die jeweiligen Offsets in völlig verschiedenen und unabhängigen Welten eine Bedeutung haben und Selectoren eigentlich keinen mathematischen Bezug zueinander haben.

Bei der Frage welcher Umfang an Rechenmöglichkeiten und Castingmöglichkeiten bei FAR-Pointern überhaupt einen Sinn ergibt bin ich zu dem Ergebnis gekommen das sämtliche Rechnenoperationen mit 2 Pointern grundsätzlich nicht erlaubt sein sollten und nur die einfachen Strichrechenoperationen zwischen einem Pointer und einem Integer (der die selbe Größe wie der Offset-Teil des Pointers haben muss und dann auch nur das Offset im Pointer beeinflusst) überhaupt erlaubt werden dürfen, jegliche Form von Selector-Arithmetik mach IMHO bei richtiger dynamischer Segmentierung keinen Sinn. Casts dürften dann auch nur mit (u)intptr_t erlaubt sein (und das sollte eine vom Compiler angebotene Struktur sein für die keinerlei Rechenoperatoren überladen sind). Das Problem was ich sehe ist das wenn ein Compiler das wirklich strickt durchsetzt das dann vermutlich doch einige C-Programme plötzlich nicht mehr compilierbar sind. Aber ohne es zu versuchen kann ich auch kaum abschätzen wie viele Programme das wirklich trifft, ich habe da die Hoffnung das dies vor allem Treiber und andere systemnahe Programme trifft deren Portierung eh von nur begrenztem Nutzen ist oder eben spezielle Librarys die man dann neu schreiben müsste aber nach Außen das selbe Interface behalten.


Grüße
Erik
63
Lowlevel-Coding / Re: EXTERN und GLOBAL in NASM
« am: 23. January 2012, 14:48 »
Hallo bscreator,


Die Frage nach einem Executable-Format für x86-Real-Mode-Programme wurde da (in einem Deiner Threads) schon man ausführlich beantwortet: http://forum.lowlevel.eu/index.php?topic=2631.msg30018#msg30018.

Das COFF-Objekt-Format kommt meines Wissens nach auch recht gut mit x86-Real-Mode-Segmenten zurecht ist aber nicht "executable" sondern nur "linkable", es wurde früher gerne als Zwischenformat (eben für die OBJ-Dateien) benutzt. Heute ist das natürlich alles längst ausgestorben weil keiner mehr für den x86-RM entwickelt, außer vielleicht die Leute die für GRUB o.ä. den Einsprung in den PM bauen und das ist so wenig das man dafür keine besonderen Dateiformate benötigt.


Grüße
Erik
64
Offtopic / Re: Eigene CPU
« am: 19. January 2012, 20:53 »
Hallo,


Auf der anderen Seite muss ein Schreibzugriff auf den PC natürlich registriert werden.
So wie ich mir das denke ist der PC (der bei mir einfach nur R63 ist und damit von jeden Befehl gelesen und beschrieben werden kann) zwar logisch ein normales Register aber nicht physisch. Bei Lesezugriffen auf dieses Register wird auch einfach immer das Offset des entsprechenden Befehls geliefert (es ist gerade bei positionsunabhängigen Code wichtig das der sich auf ein bestimmtes Verhalten beim Lesen des PC verlassen kann) und Schreibzugriffe auf R63 werden nicht vom normalen Register-File entgegengenommen sondern speziell abgefangen (aber außerhalb der ALUs) und dem Dispatcher zugeleitet damit der weiß von wo er als nächstes Befehle holen soll. Für die eigentlichen Ausführungseinheiten ist R63 ein ganz normales Register wie alle anderen auch. Es wird aber trotzdem einige Operationen geben die nicht mit R63 arbeiten können aber die lassen sich alle im Decoder abfangen und machen in der Pipeline keinen Stress.

Meine Pipe sieht wie folgt aus:
Also quasi der Klassiker. Aber die erlaubt Dir natürlich keine Parallelität zwischen den einzelnen Befehlen und auch keine Out-of-Order-Exection.
Wenn ich Dich richtig verstanden habe möchtest Du z.B. die Division "micro-codiert" erledigen (indem Du anstatt einem Befehl viele Befehle in die Pipeline lässt die diesen Job dann mit vielen Schritten erledigen)? Das macht zwar die Pipeline etwas einfacher aber dafür muss man eben diesen Micro-Code bauen. Hm, ist wohl Geschmackssache.

Dann hast Du aber bei vielen Befehlen ein extra Bit im OpCode das angibt ob die Flags geschrieben werden sollen oder?
Ja so umgefähr.
Ich hab da lieber gleich noch ein Bit mehr spendiert und habe dafür 4 unabhängige Flag-Sets, das dürfte gerade bei komplexen if-Abfragen oder auch verschachtelten if-Abfragen und Schleifen usw. einiges bringen.

Allerdings wollte ich doch eigentlich eine Programmiersprache und keine CPU bauen.
Ist doch hoffentlich kein Problem, oder? ;)


Dein OpCode-Format kannst Du ja, wenn es etwas näher an fertig ist, mal detaillierter vorstellen.


Grüße
Erik
65
Offtopic / Re: HW/CPU/VHDL-Fragen
« am: 19. January 2012, 20:27 »
Hallo,


Woher kommt jedoch die hohe Laufzeit von langen Signalwegen bei FPGAs? Bestehen dort die Leitungen aus Transistoren? Dachte die Latenz hätte was mit der Schaltgeschwindigkeit zu tun, im Kupferleiter sollte die Ausbreitung des Signals mit etwa 60% der Lichtgeschwindigkeit gehen.
Zum einen sind die Leitungen ja nicht schnurgerade und zum anderen gibt es bei FPGAs eben auch immer die Routing-Logik (also die Transistoren die die vielen kurzen Leitungssegmente mit einander verbinden um damit ein Signal quer durch den FPGA zu leiten). Und 60% Lichtgeschwindigkeit sind bei Periodenlängen im Bereich weniger Nanosekunden bis unter einer Nanosekunde auch nur noch eine Strecke die gegenüber der Größe des Silizium-Dies bereits ziemlich klein ist.

Gegen die parasitären Kapazitäten würde ich spontan mit GND abschirmen.
Aha, dann hast Du die selbe Kapazität nicht mehr zwischen 2 Signalen sondern zwischen einem Signal und GND. Parasitäre Kapazitäten kann man nur mit größeren Abständen (was bei der heutigen Miniaturisierung eher nicht so toll funktioniert), kleineren Flächen (was schon eher realistisch ist) oder einer geringeren Permittivität des dazwischen liegenden Materials (woran zur Zeit intensiv geforscht und auch teilweise in der Chipherstellung bereits umgesetzt wird) bekämpfen. Wenn Du Dir anschaust aus welchen Parametern sich die Kapazität eines Kondensators ergibt dann gibt es auch keine anderen Stellschrauben.


Mit dem Wishbone-BUS hab ich schon gearbeitet, der ist relativ einfach zu nutzen (wenn man nicht unbedingt maximale Performance will) und es gibt dazu gute Tools (für die nötigen Routing-Elemente). Für den Einstieg ist das auf jeden Fall eine gute Wahl. Wenn Du später mal was deutlich besseres aber auch deutlich anspruchsvolleres haben möchtest solltest Du einen Blick auf den AIX (aus der AMBA-Familie) von ARM werfen (Xilinx setzt den in seinen besseren IP-Cores gerne ein und die Zinq-Plattform wird auch darauf aufbauen).


Grüße
Erik
66
Offtopic / Re: [erledigt] Komisches Problem ...
« am: 19. January 2012, 20:08 »
Hallo,


bei Modellbauservos ist die Ansteuerung immer schon drin. Die erwarten am Signal-Pin ein PWM Signal mit 50Hz. Mit einer Impulslänge zwischen 1 und 2ms kann man dann die Position regeln. 1,5ms ist die Mittelstellung.
Da ich noch nie Modellbauautos gebaut habe weiß ich sowas natürlich nicht.

Der Servo ist übrigens nicht kaputt
Also wenn schon mal so viel Strom da durch geflossen ist das damit sogar eine Deiner breiten Leiterbahnen zerbrutzelt wurde (2A haben da bestimmt nicht gereicht) dann habe ich da so meine Zweifel, aber das ist natürlich nur meine rein private Meinung die auch keinerlei Anspruch auf ultimative Gültigkeit erhebt. Etwas kritisches tät ich diesem Servo mit Sicherheit nicht mehr anvertrauen.

Ein Datenblatt gibt es aber wirklich nicht, wenn du es mir nicht glaubst, kannst du ja auch versuchen eins zu finden
Ich glaube Dir ja das es zu diesem Servo keine Dokumentation gibt, ich frage mich nur warum Du den trotzdem gekauft hast? Das ist doch bestimmt nicht der einzigste Lenkservo auf dieser Welt, oder?


Grüße
Erik
67
Offtopic / Re: Panikmache wegen DNS-Changer
« am: 19. January 2012, 20:00 »
Hallo,


also ich persönlich wünsche mir ja nichts sehnlicher als das dieses ganze Trusted-Computing-Zeugs und UEFI SecureBoot und das alles wirklich kommt und das jeder normale PC nur noch ein signiertes Windows startet. Ich hab da mal gelesen das dieses TPM auch eine Black-List mit erkannter Schadsoftware enthält, deren Ausführung zuverlässig verhindert wird, und das diese Liste per iNetz geupdated werden können soll. Wenn es dann jemand schafft den aktuellen Windows-Kernel auf diese Liste zu setzen würden überall auf der Welt diese tollen Computer plötzlich ausfallen. Egal wer das schafft oder ob der dann wegen unerlaubter Computer-Manipulation in den Knast muss, diesem Jemand dürfte grenzenloser Ruhm sicher sein (genauso wie der Trusted-Computing-Allianz dann grenzenlose Schmach erfährt). Es wäre schön wenn ich das zu meinen Lebzeiten erleben darf!  (das meine ich wirklich ernst, schon weil mein Linux-PC sicher trotzdem noch funktionieren wird, von meiner eigenen Plattform erst gar nicht zu reden)


sollen sie ihre geheimen Algorithmen halt in die Cloud packen
Und ich soll dann meine privaten/vertraulichen Daten irgendeiner fremden Wolke anvertrauen? Nein, Danke! Ich beobachte ab und an mal zusammen mit meinem Sohn die Wolken am Himmel, das macht auch wirklich Spaß, aber an den Wolken die mir zur Zeit die iNetz-Industrie anbieten möchte habe ich keinerlei Interesse (und da bin ich auch sicher nicht der einzigste mit dieser Meinung).


Grüße
Erik
68
Offtopic / Re: [erledigt] Komisches Problem ...
« am: 19. January 2012, 19:47 »
Hallo,


das große Problem ist, dass es kein Datenblatt für den Servo gibt
Dann wird der eben nicht gekauft, ein Hersteller der mein Geld nicht möchte bekommt es auch nicht und fertig. Und ich glaube nicht das es keine Servomotoren gibt zu denen man auch ne anständige Doku bekommt.

Ein Servo sollte ja, wenn er kein Signal bekommt, bei Stromzufuhr in Mittelstellung fahren, oder?
Aha, die Servos die ich kenne haben genau 2 Anschlusspins und drehen sich in die eine Richtung wenn man eine negative Spannung anlegt und in die andere Richtung wenn man eine positive Spannung anlegt. Um das ganze dann in geordnete Bahnen zu bekommen benötigt man einen Drehwinkel-Sensor oder einen Quadratur-Signal-Geber und dann kann man diesen Motor mit Hilfe einer geeigneten Regelung in jede beliebige Position drehen lassen. Dein Servo scheint bereits eine interne Steuerung zu haben und die ist bestimmt anwendungsspezifisch (und daher für mich noch unbekannter als für Dich) und deswegen gehe ich davon aus das es dazu auch zumindest eine rudimentäre Dokumentation gibt.

Edit: ich werde den Servo morgen wieder zu Conrad bringen - mal sehen was die dazu sagen
Die werden Dir sagen das Du den Servo selber kaputt gespielt hast und es damit keine Garantie gibt, fertig.


Grüße
Erik
69
Offtopic / Re: Eigene CPU
« am: 18. January 2012, 10:07 »
Hallo,


... ich denke der Verlust eines Registers wiegt schwerer als der Verzicht auf ein 256tel des OpCode-Raums.
Naja, so schwer schätz ich den bei 32/64 Registern dann nicht ein. Dafür macht so ein Register viele Sachen einfach einfacher.
Naja, das fehlende Register kostet sicher etwas Performance wogegen die Art und Weise wie die Befehle codiert sind erst mal keine Performance kostet, solange diese Codierung nicht so ineffizient ist das die Befehle deutlich größer werden.

Einen CMP-Befehl habe ich auch nicht (ebenso wie ich keinen TEST-Befehl habe) sondern dafür wird ein ganz normaler SUB-Befehl (oder AND-Befehl) benutzt und das Ergebnis einfach nicht verwendet. Aus Sicht der CMP/TEST-Operation ist es egal ob das Ziel-Register grundsätzlich keine Werte speichern kann oder ob der Wert einfach nur ignoriert wird aber für andere Situationen ist ein Register weniger eben eine Register weniger und das kann manchmal etwas Performance kosten. Auf ein MOV würde ich auch grundsätzlich nicht verzichten, klar kann man das mit "ADD RD,RS,R0" ersetzen aber hier würde entweder eine sinnlose Addition passieren obwohl der Wert der in RD rein soll schon einen Takt eher bekannt ist oder Dein Decoder erkennt das und erzeugt einen simplen MOV-Befehl für die Pipeline die dann natürlich trotzdem einen dedizierten MOV-Befehl unterstützen muss und dann ist es IMHO auch nicht mehr schlimm wenn der MOV auch im normalen OpCode-Format enthalten ist. Ich persönlich halte nicht viel davon wenn die Befehle je nach Parameter sich unterschiedlich verhalten, beim klassischen ARM-Befehlssatz ist es ja so das Befehle die R15 modifizieren und die Flags setzen sich anders verhalten und einen Modus-Wechsel durchführen können. Mag sein dass das minimal kompakteren Code ergibt als wenn man diese Operationen mit eigenen Befehlen ermöglicht aber innerhalb der CPU (u.a. beim der internen Befehlsdarstellung) erspart man sich eher nichts da ja trotzdem alle Funktionalitäten unterstützt werden müssen, das macht IMHO nur den Decoder komplizierter.

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

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

das war eh so ein spontaner Einfall
Dafür ist dieser Thread ja da. Von dem was ich am Anfang dieses Threads (immerhin vor knapp 2 Jahren) geschrieben habe ist heute auch nicht mehr alles gültig, Konzepte entwickeln sich eben auch mal weiter.


Grüße
Erik
70
Offtopic / Re: [erledigt] Komisches Problem ...
« am: 18. January 2012, 09:42 »
Hallo,


- ein Servo arbeitet üblicherweise (im RC-Bereich) nicht mit Akkuspannung sondern 4,8 oder 6V
Das hätte man aber auch vorher ermitteln können, oder? Ich kenne Servomotoren die laufen mit bis zu +/- 500 V DC (okay, wenn der Dir auf den Fuß fällt ist der Fuß irreparabel beschädigt und die Ansteuerung belegt 3 HE im Schaltschrank) da wird es doch bestimmt auch Varianten für Deine Spannungen geben.

- der Servo reagiert nicht wenn er Strom bekommt
Als Fehlerbeschreibung ein wenig dürftig.

nur blöd das es hier jetzt ziemlich stinkt :D
=> lüften ;)
Wenn so viel Strom geflossen ist das es eine Leiterbahn (und die sind auf Deiner Platine ja nicht mal besonders dünn) wegbruzelt dann dürfte der Servo sicher auch nicht mehr so ganz heile sein.

.... wenn ich weiß wie ich es mache.
Ich weiß die Frage ist frech: Warum hast Du überhaupt eine Platine fertigen lassen (für Geld) wenn Du nicht mal sicher weißt wie Du Deinen Servo ansteuern musst?

Woran kann es liegen das der Servo gar nicht reagiert? (Signal liegt noch nicht an -> GND aber auch wenn das Signal auf +5V liegt passiert nix)
Wie soll diese Frage jemand beantworten können der nicht mal weiß um was für einen Servo es sich handelt und wie der zumindest laut Datenblatt angesteuert werden soll?


Grüße
Erik
71
Offtopic / Re: HW/CPU/VHDL-Fragen
« am: 17. January 2012, 11:41 »
Hallo,


Schau dir mal folgendes Spiel an, das zeigt einiges recht anschaulich:
http://www.zachtronicsindustries.com/play-kohctpyktop/
Nett! Wenn ich nicht was besseres mit meiner knappen Lebenszeit anzufangen wüsste könnte ich da glatt süchtig werden. ;)


ob man nebenläufige Logik theoretisch beliebig lang verschachteln kann (abgesehen von Latenz), oder ob irgendwann der Strom knapp wird.
Ja, Du kannst beliebig viele Logik-Ebenen zwischen 2 getakteten D-FFs packen, nur die Taktfrequenz muss niedrig genug sein damit das dann auch funktioniert. In absoluter Performance scheint es auf den ersten Blick sogar Sinn zu ergeben genau so zu verfahren. Jedes Flip-Flop kostet immer auch etwas Latenz für jeden einzelnen Pfad, es gibt eine Latenz vom Flip-Flop selber (die neuen Daten liegen nicht unmittelbar sofort nach der Taktflanke am Datenausgang an sondern erst minimal später) und dann muss noch die Hold-Zeit eingehalten werden (die neuen Daten müssen nicht erst unmittelbar vor der Taktflanke ankommen sondern sie müssen schon ein klein wenig eher am Dateneingang anliegen damit diese auch zuverlässig übernommen werden). Wenn Du also eine Logik hast die Du über 3 Takte verteilst und mit der Frequenz X laufen lässt dann wird die mögliche Frequenz etwas mehr als ein Drittel betragen wenn Du das zu einem Takt umbaust indem Du die zwei mittleren FF-Ebenen entfernst. Dafür geht Dir das Pipeline-Prinzip verloren und weil Du mit der 3-stufigen Pipeline in minimal mehr als der selben Zeit 3 Ergebnisse bekommst bist Du damit effektiv wieder schneller. Jetzt könnte man wieder versuchen die Schaltung in noch mehr Stufen aufzuteilen aber dem sind natürlich Grenzen gesetzt weil es einfach immer schwieriger wird sinnvolle Teilschritte zu finden. Auch wird es nur selten möglich sein mit einer Verdoppelung der Stufen den Takt zu verdoppeln weil es kaum möglich ist in einem asynchronen Logik-Geflecht genau in der Mitte aller Laufzeiten (für alle möglichen Wege) aufzutrennen, desto feiner man das aufteilen will desto eher wird man da suboptimale Kompromisse eingehen müssen. Es läuft letztendlich auf einen Trade-Off hinaus bei dem man das gesamte System berücksichtigen muss weil es auch nicht praktikabel ist jede Teilschaltung mit einer eigenen Taktfrequenz laufen zu lassen (durch das korrekte Überführen der Daten von einer Takt-Domäne zu einer anderen entstehen auch erhebliche Latenzen, nebst dessen dass das keine triviale Angelegenheit ist).

Kann man Busse mit einer höheren (mehrfachen) Frequenz zur Pipeline takten?
Klar kann man das, es gibt dafür auch Beispiele aber in der Praxis ist das trotzdem ziemlich selten weil ein Bus ja eben über weitere Strecken kommunizieren soll und deswegen mit deutlich längeren Signallaufzeiten zu rechnen ist als innerhalb einer kompakten Logik-Wolke.


Auf eine minimales Beispiel reduziert würde die Frage lauten, ob man beim nächsten Takt den Status aus einem Latch mit 2 Leitungen abgreifen und in der folgenden Logik an 2 Stellen verwenden kann.
Ja, das geht, ansonsten könnte man keine digitale Schaltung bauen. Du kannst auch innerhalb der Logik-Wolke das Ergebnis jedes Einzelelementes (AND/OR/XOR/...) mehrfach weiter benutzen. Du musst nur berücksichtigen da ein höherer Fan-Out auch mehr Last für das treibende Element bedeutet und damit die Laufzeit dieses Signals für alle Empfänger etwas länger wird. Die FPGA-Synthese-Tools berücksichtigen das aber wenn sie die maximal mögliche Taktfrequenz Deiner Schaltung errechnen.


Kann man auf einen internen Cache im selben Takt von mehreren parallelen Prozessen (VHDL) aus lesend zugreifen? Wie sieht es beim schreibenden Zugriff aus?
Wenn Du mit Cache klassischen SRAM (was auch die Basis für den RAM innerhalb von FPGAs ist) meinst dann nicht. Die RAM-Blöcke in FPGAs sind typischerweise als Dual-Port-SRAM ausgelegt (es gibt da zwar eine spezielle Ausnahme aber das lassen wir jetzt mal lieber, wenn es Dich interessiert dann schau Dich einfach auf tabula.com um) und arbeiten immer taktsynchron. Das bedeutet das wenn Du auf eine bestimmte Stelle im RAM zugreifen möchtest musst Du eine Adresse und ein Lese-Kommando an einen der Ports anlegen und das wird dann mit der nächsten Taktflanke übernommen. Dann gibt es üblicherweise 2 Betriebsarten: entweder die Daten kommen noch kurz vor der darauf folgenden Taktflanke an den Ausgangspins raus so das Du diese eventuell noch mit einer kurzen Logik-Wolke verarbeiten und schließlich in (mehreren) Flip-Flops abspeichern kannst oder die Daten kommen erst kurz nach der darauf folgenden Taktflanke raus so das Du eine größere Logik-Wolke dahinter hängen kannst bevor Du diese (verarbeiteten) Daten dann in (mehreren) Flip-Fops abspeicherst. Die zweite Variante ist der Pipeline-Betrieb und ermöglicht es den RAM mit höheren Taktfrequenzen laufen zu lassen aber dafür bekommst Du einen Takt zusätzliche Latenz bei theoretisch höherem Durchsatz. Bei beiden Varianten kann man mit jedem Takt eine andere Adresse angeben und bekommt dann die Daten in der selben Reihenfolge (entsprechend verzögert) ausgeliefert. Schreiben funktioniert ähnlich nur das man da zusammen mit der Adresse und dem Schreib-Kommando auch noch die zu schreibenden Daten angeben muss, auch lässt sich Lesen und Schreiben beliebig mischen. Es muss nur beachtet werden das die gerade geschriebenen Daten nicht sofort wieder gelesen werden können. Dadurch das diese RAMs Dual-Ported sind hat man eben 2 solcher Ports zur Verfügung die man sogar mit unterschiedlichen Taktfrequenzen betreiben kann aber natürlich fordert auch hier die Physik ihren Tribut indem es u.a. nicht möglich ist auf die selbe Speicherstelle von beiden Ports aus gleichzeitig zu schreiben (das wird aber nicht im RAM irgendwie verhindert sondern der speichert dann einfach Quatsch ab sondern Du als Programmierer musst Dir überlegen wie Du das verhinderst damit nur sinnvolle Daten im RAM landen) und auch wenn ein Port schreibt kann der andere Port diese Speicherstelle erst nach einer gewissen Zeit zuverlässig lesen (ansonsten kommt nur Quatsch raus, vor allem wenn man mit unterschiedlichen Taktfrequenzen arbeitet ist es recht kompliziert festzulegen ab wann mit dem anderen Port zuverlässig gelesen werden kann). Ich schlage vor Du schaust Dir einfach mal die Datenblätter bei den verschiedenen FPGA-Herstellern an, empfehlen würde ich da Actel, Altera, Lattice und Xilinx (die Reihenfolge ist keine Wertung), glücklicherweise sind die FPGA-Hersteller keine notorischen Geheimniskrämer (zumindest die 4 großen, bei den kleineren FPGA-Herstellern ist das leider anders aber auch da ist es relativ einfach schaffbar alles lesenswerte zu bekommen).

Um zu entspannen denke ich zwischen dem Programmieren in Java ein wenig über massiv parallele HW-Architekturen nach.
Hm, aha.

- Sollen ausführbare Instruktionen eine kompakte Form von Schlüssel-Wert-Paaren enthalten?
Hä, von was schreibst Du da? Meine Befehle werden in der internen Darstellung (die aus dem Decoder hinten raus kommt und so in der gesamten Pipeline verwendet wird) immer einen OpCode, die Ausführungsbedingung, ein paar Attribute, die Register-Nummern aller benutzten Register (bis 5 Stück) und noch ein Immediate (mit voller Größe) enthalten. Was davon alles benutzt wird hängt natürlich von dem konkreten Befehl ab der im OpCode kodiert ist.

- Könnten Adressen ausschließlich über Hashtables aufgelöst werden, um sich die Relokalisierung zu sparen?
Auch hier verstehe ich nicht was Du möchtest, vielleicht solltest Du solche Fragen anhand einer konkreten Beschreibung Deines eigentlichen Vorhabens stellen.

- Könnten Konstanten ausschließlich im RAM liegen?
Ja, das kann man machen, aber für Konstanten die normal innerhalb des VHDL-Codes benutzt werden ist das eher nicht geeignet. Das würde sich eher für Konstanten lohnen die mit den eigentlichen Nutzdaten in irgendeiner Form verrechnet werden. Bis auf die von Actel erlauben es eigentlich alle FPGAs das man die internen RAM-Blöcke mit bestimmten Daten vorbelegt wenn der FPGA erwacht so das Du diese Konstanten nicht erst zur Laufzeit dort mühsam mit irgendeiner Logik hineinpacken musst.

- Kann der Code teilweise oder vollständig im Cache gehalten werden?
Ja. Du kannst sogar den Code erst hinter dem Decoder cachen, das hat mal der Pentium 4 so gemacht, um Dir die Latenz des Decoders bei Sprüngen zu sparen, in meiner CPU möchte ich das machen.

- Können die Einheiten innerhalb der CPU über einen(mehrere) spezielle Busse mit "Adressleitung" Aufgaben untereinander verteilen?
- Inwiefern kann die Kommunikation hierarchisch organisiert werden, sodass mehrere parallele Tasks ihre Instruktionen auf mehrfach vorhandene Einheiten verteilen und diese die Ergebnisse im Speicher ablegen können?
Das ist beides nur von Deiner Fantasie und Deinen Fähigkeiten als VHDL-Programmierer begrenzt. ;) Solange es technisch möglich ist sollte es auch umsetzbar sein.

- Kann jede instruktion ihre eigene Pipeline haben? (Die Takte einer jeweiligen Instruktion sind konstant)
Also für jede einzelne Instriktion würde ich das nicht machen wollen, das sind üblicherweise ne ganze Menge. Aber bei den größeren CPUs arbeitet man mit mehreren Ausführungseinheiten parallel. Da kann man z.B. mehrere ALUs haben in die alle einfachen Rechenbefehle (die meisten brauchen ja auch nur einen Takt) rein kommen, dazu dann noch eine/mehrere FPU-Einheit(en) (hier brauchen eigentlich alle Befehle mehrere Takte) und noch Speicherzugriffeinheiten usw.. Nur zu viele solcher Einheiten sollten es nicht werden da natürlich jede Einheit Logik braucht und auch mit Befehlen versorgt werden will (gerade das ist ja eine der Schwächen der aktuellen Bulldozer-CPUs von AMD, der Decoder schafft es nicht für die vielen Ausführungseinheiten immer genügend Befehle nachzuliefern damit die sich nicht langweilen müssen).

- Wie verhalten sich Pipelines bei einem geänderten Ausführungspfad, anders gefragt: Kann der Code statisch (oder dynamisch) nach dem definitiven oder warscheinlichsten Pfad analysiert werden?
Typische Pipelines reagieren auf Verzweigungen im Programmablauf eher schlecht, das liegt an der Länge da ja das Ziel einer Verzweigung oft erst am Ende der Pipeline fest steht kommt es da zu teilweise erheblichen Latenzen bis die neuen Befehle (vom Sprungziel) wieder Ergebnisse liefern können. Gerade bei bedingten Verzweigungen ist das ein ernstes Problem. In der Oberliga nutzt man dazu spekulative Ausführung, die bei bedingten Verzweigungen eben den Pfad der mit höherer Wahrscheinlichkeit ausgeführt werden wird schon mal in die Pipeline lässt. Solange diese Vorhersage stimmt ist alles prima aber wenn diese Vorhersage falsch liegt gibt es noch mehr Straftakte da ja erst mal die Pipeline von diesen falschen Befehlen gesäubert werden muss.


Grüße
Erik
72
Offtopic / Re: Panikmache wegen DNS-Changer
« am: 17. January 2012, 10:09 »
.... die so gut abgesichert ist, dass sie mehr oder weniger jeder benutzen kann.
Stimmt, mein Fehler. Bitte streicht das "und kontrollieren". ;)
73
Offtopic / Re: Eigene CPU
« am: 15. January 2012, 21:42 »
Hallo,


Das mit dem Fehlen der Division gibt es bei mehren RISC Architekturen.
Das hat aber nichts mit RISC oder Microcode zu tun, es geht einfach darum sich die Transistoren für die HW-Divisions-Schaltung einzusparen. Bei den CPUs wo es etwas mehr auf Rechenleistung ankommt (also eben nicht die typischen kleinen Micro-Controller) ist für gewöhnliche ein HW-Divisions-Schaltung drin, auch bei RISC. Die braucht halt einfach nur einige Takte bis das Ergebnis anliegt und solange steht eben die Pipe-Line wenn es keine Out-of-Order-Execution gibt, trotzdem ist diese Zeit immer noch deutlich kürzer als wenn der Compiler eine Division händisch baut (außer natürlich beim Itanium da der spezielle Befehle hat die direkt die einzelnen Iterationsschritte der Division anbieten, was wimre keine andere CPU hat). Auch bei der Verarbeitung von Floating-Point-Zahlen ist bei den meisten CPUs (so sie denn Floating-Point überhaupt können) nicht nur Addition/Subtraktion und Multiplikation in HW verfügbar (üblicherweise benötigen selbst diese 3 Befehle bereits mehrere Takte) sondern oft auch Division und Quadratwurzel (die dann noch mehr Takte benötigen, deswegen sind diese beiden auch beim Itanium nicht vorhanden (ebenso wie die noch komplexeren Operationen wie Logarithmus oder Sinus) sondern nur als Einzelschritte, es gibt beim Itanium also die passenden Rechenwerke aber die State-Machines die das üblicherweise ansteuern fehlen und da muss dann der Compiler nachhelfen).

Naja wenn ich bedenke, das ich nop ohnehin schon indirekt kodiert mit so befehlen wie add 0reg, 0reg, 0reg.
Okay, aber so ein Null-Register hab ich nicht und möchte ich eigentlich auch nicht, ich denke der Verlust eines Registers wiegt schwerer als der Verzicht auf ein 256tel des OpCode-Raums.

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

sowie der evalFLAGS Befehl (setzt ein Register auf 0 oder -1, entsprechend der FLAGS).
Also für so einen Befehl sehe ich keine Verwendungsmöglichkeit. Wenn Du dann dieses Register mit einem folgenden bedingten Befehl prüfen möchtest so könntest Du auch gleich die Flags prüfen und würdest Dir einen Schritt sparen und wenn es Dir um das bedingte Laden von Immediates geht um diese dann einheitlich weiter zu verarbeiten dann benutze doch gleich einen bedingten Load-Immediate-Befehl der die Flags prüft.

Setzten der Flags (Arithmetische Befehle die als Rd das Nullregister verwenden.)
Heißt dass das Rechenbefehle die nicht aufs Null-Register schreiben keine Flags ablegen können? Das würde ich als sehr ungeschickt betrachten da es durchaus viele Fälle gibt wo man das Ergebnis haben will und auch die Flags interessieren.

Sprungbefehle fassen hierbei die Aktionen 2-4 oder 3-4 zusammen. Flagorientierte Konditionspräfixe fassen Aktion 2 und 3 zusammen. In beiden Fällen muss der Wahrheitswert dann nicht in notiert werden.
Im Instruction set, unterscheiden sich  evalFLAGS Befehl und Flagorientierte Konditionspräfixe dadurch, dass bei letzteren der Programm Counter als "Evaluationsziel angegeben wird."
Registerorientierte Conditionspräfixe gleichen den 3-4-Sprungbefehlen, nur das der PC als "Sprungziel" angegeben wird.
Beide Präfixe lassen sich deshalb leicht daran erkennen, das sie das PC adressieren.
Um ehrlich zu sein habe ich das überhaupt nicht verstanden, könntest Du noch mal anders beschreiben wie Du bedingte Befehlsausführung realisieren möchtest?


Grüße
Erik
74
Offtopic / Re: Eigene CPU
« am: 15. January 2012, 12:14 »
Hallo,


eines vorweg: in meiner CPU gibt es kein EPIC. Das empfinde ich persönlich als fürchterliche Fehlentscheidung von Intel, auch wenn es objektiv dafür wohl keinen Grund gibt da die Itaniums ja durchaus recht schnell sind. In kleinen DSPs mit internem RAM macht EPIC eventuell noch Sinn da hier alle Befehle, auch die Speicherzugriffe, mit kurzer und bekannter Latenz auskommen aber für eine General-Purpose-CPU, wo einzelne Befehle auch mal unvorhersehbar lange dauern können, ist EPIC meiner persönlichen Meinung nach absolut fehl am Platz. Hier ist Out-of-Order-Execution deutlich sinnvoller. Weil im Itanium angestrebt wird das jedes Befehls-Paket für seine Ausführung in der Pipeline immer nur einen Takt benötigt sind da einige ziemlich krasse Design-Entscheidungen getroffen wurden. Es gibt da z.B. keine klassischen Multi-Takt-Befehle wie die Division (bei Integer und Floating-Point) oder überhaupt komplexe mathematische Befehle (die müssen alle händisch vom Compiler gebaut werden), dafür gibt es jeweils spezielle Befehle die die einzelnen Iterationsschritte der benötigten Algorithmen (die normalerweise eine HW-State-Maschine selbstständig erledigt) anbieten und der Compiler muss dann damit zurecht kommen. Der Itanium arbeitet rein In-Order mit einer ziemlich kurzen Pipeline, von daher würde er auch alles blockieren wenn er Befehle hätte die mehrere Takte brauchen. Bei der Division verkauft Intel das sogar als Vorteil weil der Compiler bei der Zusammenstellung der händischen Division zwischen möglichst kurzer Latenz für eine Division und möglichst hohem Durchsatz für viele Divisionen wählen kann. Ja, das ist durchaus ein nettes Feature aber es macht den Compiler ziemlich komplex und langsam und es gibt auch etliche Situationen wo der Compiler diese Entscheidung gar nicht wirklich treffen kann weil er einfach nicht weiß wie sich das Gesamtsystem zur Laufzeit verhält. Bei den Speicherzugriffen arbeitet der Itanium exzessiv mit Prefetch-Befehlen die der Compiler passend einflechten muss, damit wird dem Cache-Controller schon mal mitgeteilt was als nächstes benötigt wird so das schon mal vorgesorgt werden kann damit dann wenn der eigentliche Speicherzugriff passiert dieser auch in möglichst einem Takt direkt vom Cache bedient werden kann. Das Problem ist dass das nicht immer gut funktioniert (es gibt ja z.B. auch Speicherbereiche die gar nicht cachebar sind wie HW-MMIO oder Algorithmen deren als nächstes benötigten Daten nicht so einfach vorhersehbar sind) und der Cache-Controller dadurch auch ziemlich komplex wird da er mit vielen parallelen Prefetch-Jobs umgehen können muss.
Alles in allem muss man sagen das Intel mit dem Itanium eine absolut einzigartige CPU geschaffen hat, etwas wirklich vergleichbares gibt es meines Wissens nach nicht auf diesem Planeten. Das trotz all der potentiellen Schwierigkeiten, die bei allen anderen EPIC-Designs auch voll zuschlagen oder auf Grund bestimmter Randbedingen nicht auftreten die dann aber keine General-Purpose-CPU mehr sind, eine so leistungsfähige CPU bei raus gekommen ist bleibt allein eine Leistung der guten Ingeniöre bei Intel die eben für jedes dieser Probleme eine gute Lösung gefunden haben. Unterm Strich ist damit der Itanium zwar extrem leistungsfähig aber die vielen Extras die Intel braucht um das auch tatsächlich mit EPIC zu schaffen machen den Itanium einfach unwirtschaftlich. Ich hab selber einige Zeit überlegt ob man mit diesem Konzept was ansprechendes erreichen kann bin aber zu dem Schluss gelangt das ich lieber auf eine klassische Out-of-Order-Execution einer seriellen Befehlsfolge setzen möchte. Deswegen benutze ich zwar eine Art VLIW-Kodierung, um eine möglichst hohe Code-Dichte bei trotzdem sehr leistungsfähigen Befehlen zu erreichen, aber jeder Befehl ist für sich eigenständig und wird, aus Sicht des Programmierers/Compilers, seriell abgearbeitet. Trotzdem sollen die Abhängigkeiten zwischen den Befehlen natürlich möglichst klein sein (was bei 60 frei nutzbaren Registern und 4 unabhängigen Flag-Sets auch kein so großes Problem sein sollte) damit der CPU-Kern bei der Befehlsausführung ein möglichst hohes Maß an Instruction-Level-Parallelism schafft und eben auch ein Out-of-Order-Commit der Befehle kein Problem darstellt. Mein Decoder wird mit Sicherheit sehr viel Logik im FPGA belegen, vermutlich mehr als alle ALUs der Verarbeitungspipeline zusammen, aber er wird einen seriellen Strom an (einheitlichen) Befehlen liefern und man wird es den einzelnen Befehlen dann nicht mehr ansehen ob sie mit 20 Bit, 39 Bit oder 60 Bit codiert waren. Ich möchte es erreichen das der Decoder pro Takt 2 bis 6 dekodierte Befehle liefern kann (eben ein komplettes Paket) um für die eigentliche Verarbeitung immer genügend Nachschub zu liefern.


Das Problem ist, das man dadurch einen großen Teil des möglichen Befehlssatzes blockiert.
Hä, was meinst Du? Denkst Du das ein NOP mit nur 8 Bits zu kodieren Verschwendung ist?

Möglichkeit 3 zeichnete sich ja gerade dadurch aus, das man die Immideate wie ein Register nutzten konnte, weil die Daten allein über einen Registerzugriff aktiviert werden.
Ja, aber wenn Du das erst bei der tatsächlichen Ausführung der Befehle machst verhinderst Du damit effektiv jegliche Form von Instruction-Level-Parallelism weil Du den (über)nächsten Befehl erst dann dekodieren kannst wenn der aktuelle Befehl abgearbeitet wird. Ich kann Dir nur dringlichst empfehlen zu versuchen dafür eine Lösung zu finden die nur im Decoder alleine passiert damit Du Dir später nichts verbaust.

Die Alpha Methode wäre natürlich auch ne Möglichkeit, allerdings ist die Nutzung eines beliebigen Register natürlich mit viel notwendiger Information verbunden.
Ja, es wird für die Bedingung nicht nur eine Register-Nummer (die bei Alpha 5 Bit groß ist) benötigt sondern auch die Bedingung als solches (da gibt es auch > 0 oder <= 0 jeweils nach signed und unsigned getrennt, wimre gibt es das bei Alpha auch für Floating-Point) und deswegen gibt es bei Alpha wohl nur bedingte Sprünge und sonst nichts. Wenn man diese Bedingung aber in ein eigenständiges Präfix auslagert, das sich mit jedem Befehl kombinieren lässt, dann hat man ja eigentlich auch genügend Bits zur Verfügung um hier auf möglichst große Flexibilität zu setzen. Wenn das Präfix 32 Bits groß ist könnte man sogar die eigentliche Vergleichsoperation (SUB oder AND) und 2 Register mit hinein kodieren. Aber das bläht die interne Befehlsdarstellung ziemlich auf. Ich benötige 7 Bits für die Bedingung (2 Bits für das benutze Flag-Set und 5 Bits für die eigentliche Bedingung, da sind zum einen die 14 Klassiker und noch einige Floating-Point-Bedingungen) und das auch hinter dem Decoder bei der internen Befehlsdarstellung, was IMHO einen brauchbar guten Kompromiss darstellt.


Grüße
Erik
75
Offtopic / Re: ARM-Systeme
« am: 15. January 2012, 00:58 »
Das Thema (ordentliches) PCIe + SATA + USB 2.0 + GBit in einem ARM hatten wir schon: Gibt es nicht. :-(
Doch gibt es, müsste eigentlich irgendwo in meinem viel zu langen Beitrag drin sein, wimre.
76
Offtopic / Re: Panikmache wegen DNS-Changer
« am: 14. January 2012, 12:18 »
Hallo,


Und wenn man mal davon ausgeht, dass der Bundestrojaner nur von deutschen Behörden kontrolliert wird, hätte ich mehr Angst vor einem DNS-Changer der von Kriminellen kontrolliert wird.
Nur das Du bei den Kriminellen recht genau weißt was die wollen: Dein Geld und das möglichst ohne das sie bemerkt werden. Wogegen bei den Strafverfolgungsbehörden (die den Bundestrojaner letztlich einsetzen und kontrollieren) die wahren Absichten eher als schleierhaft zu betrachten sind und das die wenn dann deutlich tiefer in Deiner Privatsphäre rum bohren als ein paar Kriminelle!


So und jetzt Schluss mit der Panikmache, hier wird ja schlimmer gegackert (und vor allem größerer Unfug) als im Hühnerstall!


Grüße
Erik
77
Offtopic / Re: Eigene CPU
« am: 13. January 2012, 21:59 »
Hallo,


Dabei habe ich mich hauptsächlich mit einem Problem beschäftigt, das bei RISC CPU's auftritt, nämlich die Befehlslänge.
Ja, das ist wohl wahr. Aber es gibt auch interessante Lösungen dafür, schau Dir mal den Itanium an. Auch das Problem mit der bedingten Ausführung ist dort auf sehr interessante Art und Weise gelöst.
(eigentlich könnte hier meine Antwort schon zu Ende sein aber ich hoffe man nimmt es mir bei diesem Thema nicht übel wenn ich das doch mit ein paar Buchstaben mehr erkläre)
Der Itanium benutzt 128 Bit große Befehls-Pakete und in jedem Paket sind 3 Befehle a 41 Bit (die restlichen 5 Bit dienen wimre der Verwaltung der Abhängigkeiten des aktuellen Pakets zu den vorhergehenden Paketen, das muss der Compiler einfügen damit Intel den Decoder etwas einfacher bauen kann) und jeder dieser Befehle kann bedingt ausgeführt werden. Einer dieser 3 Befehle (wimre nur der erste) kann ein Load-Immediate sein der volle 64 Bit in ein beliebiges Register lädt und der benutzt dann einfach den folgenden Befehl mit für die Daten und dieser folgende Befehl ist dann zwangsläufig ein NOP (ob das der Decoder so richtet oder ob das schon so drin sein muss weiß ich jetzt gar nicht mehr genau). Durch diese Pakete kann der Itanium immer 3 Befehle pro Takt decodieren und auch ausführen (eigentlich immer 6 weil alle real existierenden Itaniums immer gleich 2 Pakete pro Takt laden) und die 41 Bit bieten auch für alles wichtige ausreichend Platz (obwohl pro Operand 7 Bit benötigt werden da der Itanium 128 Register hat). Der Nachteil ist natürlich das der Code sehr groß ist (weswegen die Itaniums auch sehr riesige und teure Caches haben) und da die 3 Befehle in einem Paket immer gleichzeitig ausgeführt werden dürfen diese auch nicht von einander abhängig sein was den Compiler schon mal vor ziemliche Schwierigkeiten stellen kann (oft müssen dann nicht belegbare Plätze in den Paketen mit NOPs aufgefüllt werden so das die eh schon schlechte Befehlsdichte noch mehr leidet). Das Ergebnis spricht aber für sich, die Itaniums waren die schnellsten CPUs ihrer Zeit, vor allem in Relation zu ihrer gemächlichen Taktfrequenz. Zumindest für wissenschaftliche/mathematische Programme sind die Itaniums eigentlich eine perfekte Wahl, nur leider waren sie immer viel zu teuer und auch viel zu durstig.

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

Ansonsten gibt es für Deine Version mit den 32Bit Befehlen noch eine Möglichkeit 4:
Um ein NOP zu kodieren sollten nicht mehr als 8 Bit nötig sein so das in jedem NOP immer 24 Bit an Daten enthalten sein können. Wenn Du nun einen Load-Immediate-Befehl baust der selber noch 16 Bits Daten enthält (die restlichen 16 Bits sollten doch reichen um den Befehl ansich und das Zielregister zu kodieren) dann könnte der im Decoder um 2 Takte verzögert werden (es käme eben für 2 Takte kein Befehl aus dem Decoder raus) und der Decoder würde intern aus diesem Befehl und den 2 folgenden NOPs insgesamt einen Load-Immediate mit vollen 64Bit Nutzdaten bauen. (wenn einer der beiden folgenden Befehle kein NOP ist gibt es eben eine Illegal-OpCode-Exception) Das hätte auch den Vorteil das nichts schlimmes passiert wenn mal einer der beiden Daten-NOPs angesprungen wird und auch der Disassembler (im Debugger) hätte keine Probleme was sinnvolles anzuzeigen. Ein weiterer Vorteil ist das diese Variante allein im Decoder passiert und Dein eigentlicher CPU-Kern davon nicht betroffen ist, spätestens wenn Du irgendwann doch mal das simple In-Order-Pipeline-Konzept verlassen möchtest wird es Dir sehr entgegen kommen Dich im CPU-Kern auf die eigentliche Arbeit konzentrieren zu können.


Das mit dem Skip-Befehl ist keine so schlechte Idee aber auch hier solltest Du das gleich im Decoder lösen und dem CPU-Kern nur Befehle übergeben bei denen die Ausführungsbedingung integraler Bestandteil ist. Es sollte auch möglich sein das sich dieses Condition-Präfix mit jedem Befehl kombinieren lässt, damit lassen sich wieder viele Sprünge vermeiden und das bringt einiges an Performance und spart oft auch Code. Im klassischen ARM-Befehlssatz ist auch jeder Befehl bedingt ausführbar aber das kostet bei ARM in jedem Befehl 4 Bit so das die ARM-Befehle nur 28 Bit wirklich zur Verfügung haben und das ist, trotz dessen das die Operanden nur 4 Bit benötigen, schon ziemlich knapp. Falls Du fürchtest mit nur einem Flag-Set irgendwann an Performance-Probleme zu stoßen, und das ist bei so einem Single-Point-of-Dependency sehr wahrscheinlich, solltest Du Dir mal anschauen wie das bei Alpha gelöst ist. Die haben zwar nur bedingte Sprünge (alle anderen Befehle werden immer unbedingt ausgeführt) aber dafür kann Alpha direkt ein beliebiges Register auf bestimmte Eigenschaften prüfen, z.B. == 0 oder != 0, und da es mehrere Register gibt kann zwischen dem Befehl der eine Bedingung ermittelt und dem zugehörigen bedingten Sprung-Befehl noch beliebiger anderer Code stehen solange der das eine bestimmte Register nicht verändert. Das sorgt dafür das der bedingte Sprung nicht erst warten muss bis der unmittelbar vorangegangene Test-Befehl durch die Pipeline gekommen ist sondern weil das eben oft schon einige Befehle her ist gibt es weniger Pipeline-Stalls.


Auch ich habe mir über die beiden Punkte (Befehlsgröße und bedingte Ausführung) einige Gedanken gemacht und (wie ich meine) auch ein paar interessante Lösungsmöglichkeiten gefunden, das ist ganz am Anfang dieses Threads recht gut beschrieben.


Grüße
Erik
78
Offtopic / Re: ARM-Systeme
« am: 10. January 2012, 17:03 »
Hallo,


Ansonsten wollte ich mit dem Thread mal ausloten, was es so an developerfreundlichen ARM-Geräten jenseits der Evaluationsboards gibt.
Also da wird wohl nicht viel bei raus kommen.


So wie ich das sehe gibt es da 2 Kategorien an interessanten ARM-Chips: einmal die typischen Microkontroller (Cortex-M[0..4], von etlichen Firmen wie NXP,STM,Freescale u.v.m.) und zum anderen die richtigen SoCs (wie den Tegra von NVidia, den Exynos von Samsung, den Snapdragon von Qualcomm, den OMAP von TI und etwas weniger bekannt die ARMADA von Marvell (wurde aus dem PXA entwickelt der von Intel übernommen wurde welche von den StrongARM abstammen, mit den PXA hab ich selber schon gearbeitet)).

Die Vertreter der Microkontroller-Klasse haben alle gewisse Gemeinsamkeiten wie das nur sehr kleine Mengen an RAM/Flash verfügbar sind und oft auch eine MMU fehlt (was beides den Einsatz von Linux wirksam verhindert) dafür gibt es da eine sehr große Fülle an Varianten und man bekommt eigentlich bei allen Hersteller anständige Datenblätter usw. An Pehripherie wird oft Ethernet (meist nur 100MBit ganz selten auch mal 1GBit), USB (meistens maximal Full-Speed (1.1) als Device und/oder Host aber manchmal auch High-Speed (2.0) als Device und ganz selten sogar als Host mit einem EHCI-kompatiblen Interface) und all den anderen Kram den man so gewöhnt ist wie UART/SPI/I²C/CAN/LIN/.... Auch gute Development-Board bekommt man in allen möglichen Varianten für fast jede Familie der ARM-Microkontroller von etlichen Herstellern (nicht nur vom Chip-Hersteller selber), meistens liegt auch ein vollständer Schaltplan/Stückliste/... bei um auf Basis dessen ein eigenes Produkt zu entwickeln.

In der SoC-Klasse bekommt man oft keine vollständigen Datenblätter und auch nur selten frei käufliche Development-Boards. An Peripherie steckt meistens ein richtiger DRAM-Controller, Flash-Controller (meistens mit irgendeiner Boot-Fähigkeit), USB (meistens Host und Device mit High-Speed), ein paar UARTs, Bluetooth, Touch-Controller und ne GPU drin. Oft sind auch noch irgendwelche Funk-Module für WLAN, GPS oder auch GSM/EDGE/UMTS drin da ja Handys/Tablet-PCs das primäre Marktsegment sind das die Hersteller bedienen wollen. Leider fehlen oft ein paar Schnittstellen die benötigt werden um daraus einen normalen PC zu bauen, wie z.B. LAN und SATA. In dem Trim-Slice ist SATA z.B. über einen zusätzlichen USB-SATA-Chip angebunden was natürlich keine berauschenden Performance-Werte beim Umgang mit HDDs ermöglicht, LAN ist dort mit einem Realtek-Chip per PCI-Express angebunden. Immerhin hat der Tegra 2 von NVidia eine einzelne PCI-Express-Lane als Root-Port, die meisten anderen ARM-SoCs haben sowas überhaupt nicht so das es kaum möglich ist irgendein vermisstes Interface nach zurüsten, diese SoCs sind also so wie sie sind und fertig. Als ich im Februar 2011 auf der Embedded-World war habe ich an vielen Ständen sehr interessante Embedded-Boards mit dem Tegra 2 gesehen und man hat mir auch oft gesagt das NVidia den Embedded-Markt bedienen will und demzufolge auch Datenblätter usw. veröffentlichen wird, nur leider ist das bis heute nicht passiert und die Auswahl an tatsächlich käuflichen Tegra 2 Boards ist auch eher kleiner als größer geworden. Die Hoffnung das tatsächlich mal einer der ARM-SoC-Hersteller sich diesen, sicher lukrativen, Markt erschließen will war also vergebens.

Es gibt zwar mit älteren ARM-SoCs durchaus interessante frei käufliche Boards aber einen echten PC kann man aus diesen auch nur selten bauen da keine echte Erweiterungsschnittstelle (wie eben PCI-Express) verfügbar ist und selbst einige Basics wie SATA konsequent fehlen. Dazu kommt das der RAM-Ausbau oft sehr bescheiden ist. Der Exynox unterstützt zwar 2 GB aber es gibt keine freien Boards damit. Der Tegra 2 untersützt auch nur maximal 1 GB RAM, so wie alle übrigen ARM-SoCs auch, aber der Tegra 3 soll immerhin schon 2 GB unterstützen.

Wer sich überlegt aus einem ARM-SoC einen halbwegs brauchbaren General-Purpose-PC zu bauen wird leider auf ganzer Linie enttäuscht. Das einzigste was zumindest auf dem Papier einen guten Eindruck macht ist der ECX-1000 von Calxeda, der kann echte 4GB RAM und die nicht nur mit lahmen 32Bit Datenbus-Breite und maximal 800MT/s sondern mit vollen 64Bit Datenbus-Breite (eigentlich 72 Bit für ECC) und bis zu 1333 MT/s DDR3. SATA (mit AHCI-kompatiblen Host-Controller) und LAN sind auch schon drin, neben einem SD-Card-Controller und jeweils mehreren UART/SPI/I²C-Schnittstellen. Es fehlen ihm zwar 2 sehr wichtige Dinge, eine GPU und USB-Anschlüsse, aber da er mehrere PCI-Express-Root-Ports hat kann man beides extern nachrüsten. Von TI gibt es einen USB 3.0 Host-Controller mit xHCI-Interface für PCI-Express, sogar mit Datenblättern, und ne taugliche PCI-Express-GPU bekommt man gleich mit Platine in jedem Computer-Laden (sogar Versionen wo man auch freie Treiber für bekommt) so das dem eigentlich nichts im Wege steht um aus einem ECX-1000 einen echten vollwertigen PC zu bauen. Ob der Chip auch wirklich was taugt versuche ich gerade raus zu finden, ich hab bei Calxeda einfach mal Datenblätter angefordert.


Wenn irgendjemand noch andere interessante ARM-SoCs kennt so wäre es toll hier etwas darüber zu lesen.

An dem Performance-Vergleich, den Svenska verlinkt hat, finde ich besonders interessant das die beiden ARM-SoCs den beiden Atom-CPUs durchaus dicht auf den Fersen sind bzw. sogar oft überholen, auch der Pentium-M ist in einigen Disziplinen gar nicht mehr weit entfernt. Trotzdem benötigen die ARM-SoCs nur einen Bruchteil an elektrischer Energie, selbst gegenüber den Atom-Systemen. Ich denke (und hoffe) spätestens wenn erste ARMv8-Systeme verfügbar sind dürfte sowas gegenüber einem klassischen x86-PC eine ernstzunehmende Alternative darstellen und dann wird hoffentlich auch der Markt nach anständigen Datenblättern verlangen.


Grüße
Erik
79
OS-Design / Re: GUI LowLevel
« am: 08. January 2012, 16:30 »
Hallo,


ich hab zu dem Thema Busmaster-fähige HW und IOMMU noch ein wenig nachgedacht.
Moderne HW unter stützt ja für gewöhnlich das Scatter/Gather um die Daten, die sich im physischen RAM ja total zerstreut befinden (Paging sei dank), wieder anständig zusammen zu suchen. Wenn sich im Chipsatz immer eine IOMMU befindet dann gibt es doch damit die Möglichkeit das sich die von der HW benötigten Daten wieder linear am Stück in einem zusätzlichen virtuellen Adressraum befinden und somit die Notwendigkeit für Scatter/Gather-Unterstützung in der HW entfällt. Das würde sicher die Entwicklung von Treibern erleichtern, wer das nicht glaubt sollte sich mal die zugehörigen Strukturen in EHCI, xHCI oder AHCI ansehen, und auch die HW etwas weniger komplex machen. Auch die GPUs bräuchten keine eigene MMU mehr da das ja schon alles die IOMMU macht.
Ich hoffe das sich das Konzept von IOMMUs möglichst bald durchsetzt, da ich davon ausgehe das damit einiges für die Computer-Sicherheit getan werden kann.

Hat denn einer von Euch vor die IOMMU in sein OS mit einzubinden?


Grüße
Erik
80
OS-Design / Re: IPC - Popup-Threads
« am: 08. January 2012, 16:00 »
Hallo,


ich wuste gar nicht das Linux größere Mengen Speicher 1:1 mappt. Wirklich mit virtuell == physisch? Das kann ich mir ehrlich gesagt nicht so gut Vorstellen, Linux benutzt doch auch einen Higher-Half-Kernel oder?
Sorry, das ich mich da unklar ausgedrückt habe, mit 1:1 meinte ich nicht virtuell == physisch sondern nur das der tatsächlich benutzte physische Adressraum (der ja kleiner sein muss als die Plattform eigentlich kann) irgendwo als ganzes lineares Stück im virtuellen Adressraum (in dem Teil der zum Kernel-Space gehört) zu finden ist.

Da kommt mir die Idee das wenn man einen Lower-Half-Kernel machen würde dann würde das sogar echt gehen, tät immerhin die Additionen ersparen und bei einem Monolithen würden sicher auch die enthaltenen Treiber profitieren wenn Sie ihre HW direkt mit der physischen Adresse ansprechen können ganz ohne Umrechnung o.ä., man müsste den virtuellen Adressraum einfach so aufteilen dass das unterste Viertel dem 1:1 Bereich gehört, das nächste Viertel wäre dann der normale Kernel-Space und die obere Hälfte wäre dann Prozess-spezifischer User-Mode. Ich denke das könnte richtig gut funktionieren aber ich mach ja gar kein Flat-Memory-OS.


Grüße
Erik
Seiten: 1 2 3 [4] 5 6 ... 64

Einloggen