Hallo,
hier mal ein Zwischenbericht aus dem Projekt, dem ich jetzt spontan mal den Arbeitstitel "open1541" gebe.
Wer nicht weiß, worum's geht: Siehe die letzten Posts in RTC sinnvoll? .
Den LPC habe ich zum Laufen bekommen, erstmal PLL, UART, Timer und so dieses grundlegende Geraffel. Dann habe ich in den letzten Tagen mit einer zyklengenauen 6502-Emulation im Timer-FIQ (Fast Interrupt) begonnen. Im Moment sind erst eine Handvoll Opcodes implementiert, die aber vollständig, also mit Flags, Zusatzzyklus bei Bxx Seitenüberschreitungen etc. Es ist auch schon vorgesehen, für die verschiedenen Speicherbereiche spezialisierte Lese/Schreibfunktionen zu benutzen (Sprungtabelle), von denen momentan nur RAM-Read implementiert ist. Einerseits sind noch Optimierungen möglich, andererseits kommen sicher noch Sachen dazu. Die ersten Ergebnisse sind nicht prickelnd, aber akzeptabel. Natürlich kann man auch noch das Konzept überdenken, dass immer nur exact eine Instruktion pro IRQ ausgeführt wird, aber dass macht die Sache ziemlich leicht handhabbar.
Zum Messen habe ich im Hauptprogramm eine Schleife, die eine Sekunde lang zählt und dann die Anzahl der Loops ausgibt.
Volle Geschwindigkeit: 2282748
Code im Flash ohne MAM: 571100
Code im Flash 2ws: 629143 (standard)
Code im Flash 1ws: 865076 (flash overclocked)
Code im RAM: 951207 (IRQ-Vektor noch im Flash)
Man sieht also, das beim Ausführen aus dem RAM bei 60 MHz noch etwa die Hälfte für die Emulation von allem, was nicht CPU ist, übrigbleibt. Man merkt auch, dass der Flash doch ein Flaschenhals ist. Beim LPC ist der 128 bit breit angebunden (= 4 32-Bit-Instruktionen), bei 60 MHz ist 1 Flash-Zyklus auf 3 CPU-Zyklen empfohlen. Rechnerisch passt's also. Es gibt auch einen MAM (Memory Acceleration Module), der drei dieser Lines vorspeichert (Prefetch, Branch Trail, Data). Mit meinen Sprungtabellen für Opcodes und Speicherzugriffe scheine ich den Mechanismus aber recht effektiv auszuhebeln Na mal sehen. Wen's genauer interessiert: um10120-1.pdf, Kapitel 4.
Unseen: Danke nochmal für den Hinweis mit dem einen Zyklus bei den VIA-Registern. Beim Schreiben ist mir eine Möglichkeit eingefallen, die ohne Busy Wait oder Extra-IRQ auskommt: Der LPC hat für den Timer, den ich für die CPU benutze, 4 Match Register. Das erste nehme ich für die CPU-Emulation. Mit den anderen kann man das Kunststück anstellen: Man kann einen Pegel festlegen, der beim Erreichen des Zeitpunkts auf bestimmte Datenleitungen gelegt wird. Man kann also t + 1 programmieren, den Pegel zwischenspeichern und den Rest macht die Hardware. Beim Lesen würde ich momentan zu Busy Wait neigen, was besseres ist mir da noch nicht eingefallen. Beide Möglichkeiten lassen jedenfalls den IRQ-Latenz-Jitter verschwinden.
Im Moment denke ich darüber nach, ATN-ACK wie in der 1541 extern umzusetzen. Wenn sowieso schon FETs für die Leitungen benutzt werden, kann man vielleicht auch einen mehr benutzen, um den Mechanismus so umzusetzen. (Mir schwebt was vor, wie man die zusammenknüppern müsste. Bin mir aber nicht so sicher. Shadowwolf: Kannst Du sowas ausklügeln?) Vielleicht kann man auch einen preiswerten 74LSirgendwas für alle Leitungen und diese Logik benutzen.
(Teil 2 kommt gleich, will erstmal abschicken)