N'Abend Forum :)
Das vorhaben ist leicht erklaert:
Ich moechte Logisim-Dateien automatisiert auswerten lassen. Da das in
Logisim selbst praktisch nicht moeglich zu sein scheint, und es auch
keine API fuer sowas gibt, muss etwas anderes her. Gluecklicherweise
werden die Logisim-Dateien (.circ) als XML gespeichert, sodass man das
ganze relativ leicht Parsen und in Programmlogik nachbauen kann.
Das Warum:
Wir hatten an der Uni ein paar Hausaufgaben in Logisim zu machen, aber
die Korrekteure (also der Lehrstuhl) haben dafuer ziemlich lange
gebraucht. Klar, wenn jeder Student die Aufgaben alleine abgeben muss,
es aber nur 2 oder 3 Korrektuere gibt, dann dauert das bei 300 Abgaben
etwas. Und je komplexer die Aufgabe, desto laenger dauert auch die
Korrektur.
Die Aufgaben waren immer der Art:
Geben sie die letzten 4 Ziffern ihrer Matrikelnummer ein, dann soll
durch Umsetzung von <Logik nur aus NOR, nur aus NAND, Volladdierer, etc>
die LED leuchten.
Die Ziffern sind BCD-Codiert (vorgabe), es gibt also bei 4 Ziffern 16
Leitungen auszuwerten. Kurz, es muessten 10.000 Kombinationen probiert
werden, um zu ueberpreufen, ob das gewuenschte Verhalten wirklich nur
bei der eigenen Matrikelnummer funktioniert. Da man das aber in Logisim
selbst nicht wirklich automatisiert machen kann, wollte ich zumindestens
mal fuer mich gucken, ob man da nicht was schaffen kann, was das kann.
Aufbau der Logisim-Datei:
In der Datei im Anhang hab ich mal ein XOR nachgebaut, einfach damit ich
ein paar Teile in der Simulation habe. Der interessante Teil der Datei
ist dieser:
1
<circuit name="main">
2
<a name="circuit" val="main"/>
3
<a name="clabel" val=""/>
4
<a name="clabelup" val="east"/>
5
<a name="clabelfont" val="SansSerif plain 12"/>
6
<wire from="(560,270)" to="(580,270)"/>
7
<wire from="(560,350)" to="(580,350)"/>
8
<wire from="(480,340)" to="(530,340)"/>
9
<wire from="(480,280)" to="(530,280)"/>
10
<wire from="(580,300)" to="(610,300)"/>
11
<wire from="(580,320)" to="(610,320)"/>
12
<wire from="(380,360)" to="(530,360)"/>
13
<wire from="(640,310)" to="(680,310)"/>
14
<wire from="(420,260)" to="(530,260)"/>
15
<wire from="(380,200)" to="(380,280)"/>
16
<wire from="(380,280)" to="(460,280)"/>
17
<wire from="(380,280)" to="(380,360)"/>
18
<wire from="(580,270)" to="(580,300)"/>
19
<wire from="(580,320)" to="(580,350)"/>
20
<wire from="(420,260)" to="(420,340)"/>
21
<wire from="(420,200)" to="(420,260)"/>
22
<wire from="(420,340)" to="(460,340)"/>
23
<comp lib="0" loc="(380,200)" name="Pin">
24
<a name="facing" val="south"/>
25
<a name="tristate" val="false"/>
26
</comp>
27
<comp lib="1" loc="(480,340)" name="NOT Gate">
28
<a name="size" val="20"/>
29
</comp>
30
<comp lib="5" loc="(680,310)" name="LED">
31
<a name="color" val="#44ff00"/>
32
<a name="offcolor" val="#243df5"/>
33
</comp>
34
<comp lib="1" loc="(560,270)" name="AND Gate">
35
<a name="size" val="30"/>
36
<a name="inputs" val="2"/>
37
</comp>
38
<comp lib="0" loc="(420,200)" name="Pin">
39
<a name="facing" val="south"/>
40
<a name="tristate" val="false"/>
41
</comp>
42
<comp lib="1" loc="(560,350)" name="AND Gate">
43
<a name="size" val="30"/>
44
<a name="inputs" val="2"/>
45
</comp>
46
<comp lib="1" loc="(640,310)" name="OR Gate">
47
<a name="size" val="30"/>
48
<a name="inputs" val="2"/>
49
</comp>
50
<comp lib="1" loc="(480,280)" name="NOT Gate">
51
<a name="size" val="20"/>
52
</comp>
53
</circuit>
Man bekommt also relativ leicht raus welche Gatter verwendet werden,
soweit so gut.
Die Gatterkoordinaten scheinen immer die Ecke unten Rechts zu sein. Das
heisst als erstes mal:
Das Ende einer Leitung kann eine (leicht)(Koordinatenaufloesung ist
immer in 10er Schritten) andere Koordinate habe, als das Gatter mit dem
es verbunden ist. Das ist schon mal ein Problem.
Aber wie finde ich nun am "besten", welche Gatter verbunden sind? Wie
"verfolge" ich die Leitungen am besten?
Eine Leitung besteht aus 2 Koordinatenpaar. Meine erste Idee war es
jetzt, Die Koordinaten erstmal als Tupel aus 2 Tupeln ((x_0, y_0),(x_1,
y_1)) zu extrahieren. Wenn man das ganze dann nach (x_1, y_1) sortiert,
kann man einfach gucken wo (x_1, y_1) zu (x_0, y_0) wird und dann weiss
man, wo die Leitung weitergeht, und landet so irgendwann an einem Gatter
(oder zumindestens in der Naehe...).
Das scheint mir aber noch nicht so ganz zielfuehrend, denn ich kann dann
zwar irgendein (x_0, y_0)-Paar raussuchen, und gucken wo es weitergeht,
aber ich weiss gar nicht wo der Anfang der Leitung ist.
Das konkrete Problem ist also:
Wie findet man am "besten" welche Bauteile miteinander verbunden sind?
Habt ihr vielleicht ein paar Tipps?
Gruesse
###################
Edit:
Mir faellt gerade auf, das ich natuerlich auch andersrum suchen kann,
also so auch den Anfang finden kann. Ohne das ich anders Sortieren
muesste. Suche koennte man dann mit Binary-Search machen.
Habt Ihr bessere Ideen?
Bleibt immernoch das Problem mit der Koordinatendifferenz zwischen
Leitungsende und Bauteilkoordinate.
Die Umsetzung des ganzen werde ich dann wohl erstmal mit Python machen.
###################
Edit:
Es waere Sinnvoller nach (x_0, y_0) zu sortieren, und nicht nacht (x_1,
y_1)
Ach ja, was dabei ruaskommen soll:
Ziel waere es, ein Programm zu entwickeln, das man einfach mit einer
Logisim-Datei fuettert, und am Ende dann eine Datei mit Werten zur
Analyse rausfaellt. Eine Art Unittest fuer Logsim, koennte man sagen.
Kaj G. schrieb:> Wie findet man am "besten" welche Bauteile miteinander verbunden sind?
Anfang, Ende etc. sind egal und bei verzweigten Wires sowieso nicht
eindeutig. Wichtig ist am Ende nur, welche Punkte zusammengehören.
Zuerst würde man also aus den Wires elektrisch verbundene Netze zusammen
bauen.
Dann kann man aus den Positionen der Bauelemente und dem jeweiligen
Offset der Ein- und Ausgangspins zum Bauteilursprung (den man mühsam
manuell herausfinden muss) die absoluten Positionen der Pins berechnen
und in der Liste der Netze aus dem ersten Schritt nachsehen, zu welchem
Netz der Pin gehört (d.h. welches set() aus Punkten einen halbwegs
identischen Punkt enthält). Hier müsste eine Art Netzliste herauskommen,
die ich dann in irgendein Kommandozeilen-Logik-Simulationsprogramm
stecken würde.
Mit Logisim kann man die eigene Schaltung quasi in ein neues eigenes
(virtuelles) IC packen und als Bibliothek sichern.
Vlt. wird beim nächsten mal einfach die Order ausgegeben, dass jeder
Student so ein virtuelles IC mit genau vorgegebenen Ein- und Ausgängen
zu erstellen hat. Am Bestern serielle Ein- und Ausgänge, dann sind es
nicht so viele!
Dann kann der Korrektor das IC in seine Schaltung importieren und einen
Binärzähler auf die Eingänge loslassen ... wenn an den Ausgängen eine
eigene Auswerteschaltung mit Speicher, Schieberegister und dem
Terminal-Baustein hängt, sollte eine (halb-) automatische Auswertung
möglich sein.
Ich liebe Logisim und verwende es immer exzessiv im Unterricht. Es gibt
in Youtube Beiträge, in denen "Verrückte" damit ganze CPUs designt haben
...
Kaj G. schrieb:> Aber wie finde ich nun am "besten", welche Gatter> verbunden sind? Wie "verfolge" ich die Leitungen> am besten?
Koordinaten sind Scheisse.
Erstelle eine Knotenliste mit Knotennummern, und
repräsentiere die Verbindungen durch Kanten, die
als Paare aus Knotennummern dargestellt werden.
Streiche alle INNEREN Knoten, die in genau zwei
Kanten vorkommen, und ersetze die Kanten durch
eine einzige. (Achtung: I/O-Knoten vorher sperren.)
Mehr weiss ich erstmal nicht :)
http://www.cburch.com/logisim/docs/2.7/en/html/guide/verify/index.html
Logisim includes basic support for executing circuits from the
command-line. This is intended both to help with scripted verification
of circuit designs and to help instructors perform automated testing of
students' solutions.
Kaj G. schrieb:> Habt ihr vielleicht ein paar Tipps?
Ja. Offensichtlich beschreibt die XML-Datei nicht alles, was nötig ist.
Der Rest steckt in den Bauelementen, die auch irgendwo definiert sein
müssen (nämlich: welche Anschlüsse gibt es und wo befinden sich diese
relativ zum Ursprung des Bauteils).
Nur dann, wenn man beides hat, könnte man daraus eine Netzliste bauen,
die dann wiederum Ausgangspunkt für eine Simulation sein könnte.