2009-02-23 6 views
16

Obwohl ich diese Hausaufgaben getaggt habe, ist es eigentlich für einen Kurs, den ich alleine mache. Wie auch immer, der Kurs heißt "From Nand to Tetris" und ich hoffe, dass jemand hier den Kurs gesehen oder gemacht hat, damit ich Hilfe bekommen kann. Ich bin auf der Bühne, wo ich die ALU mit der mitgelieferten HDL-Sprache baue. Mein Problem ist, dass ich meinen Chip nicht richtig kompilieren kann. Ich bekomme Fehler, wenn ich versuche, die Ausgabeflags für die ALU zu setzen. Ich glaube, das Problem ist, dass ich keine intermediäre Variable subscriptieren kann, da, wenn ich gerade versuche, die Flags basierend auf einer Zufallsvariablen auf wahr oder falsch zu setzen (sagen wir ein Eingabeflag), bekomme ich die Fehler nicht. Ich kenne das Problem nicht mit den Chips, die ich versuche zu verwenden, da ich alle eingebauten Chips benutze.Wie setze ich Ausgabeflags für ALU in "Nand ​​to Tetris" natürlich?

Hier ist meine ALU-Chip so weit:

/** 
* The ALU. Computes a pre-defined set of functions out = f(x,y) 
* where x and y are two 16-bit inputs. The function f is selected 
* by a set of 6 control bits denoted zx, nx, zy, ny, f, no. 
* The ALU operation can be described using the following pseudocode: 
*  if zx=1 set x = 0  // 16-bit zero constant 
*  if nx=1 set x = !x  // Bit-wise negation 
*  if zy=1 set y = 0  // 16-bit zero constant 
*  if ny=1 set y = !y  // Bit-wise negation 
*  if f=1 set out = x + y // Integer 2's complement addition 
*  else set out = x & y // Bit-wise And 
*  if no=1 set out = !out // Bit-wise negation 
* 
* In addition to computing out, the ALU computes two 1-bit outputs: 
*  if out=0 set zr = 1 else zr = 0 // 16-bit equality comparison 
*  if out<0 set ng = 1 else ng = 0 // 2's complement comparison 
*/ 

CHIP ALU { 

IN // 16-bit inputs: 
    x[16], y[16], 
    // Control bits: 
    zx, // Zero the x input 
    nx, // Negate the x input 
    zy, // Zero the y input 
    ny, // Negate the y input 
    f, // Function code: 1 for add, 0 for and 
    no; // Negate the out output 

OUT // 16-bit output 
    out[16], 

    // ALU output flags 
    zr, // 1 if out=0, 0 otherwise 
    ng; // 1 if out<0, 0 otherwise 

PARTS: 
// Zero the x input 
Mux16(a=x, b=false, sel=zx, out=x2); 

// Zero the y input 
Mux16(a=y, b=false, sel=zy, out=y2); 

// Negate the x input 
Not16(in=x, out=notx); 
Mux16(a=x, b=notx, sel=nx, out=x3); 

// Negate the y input 
Not16(in=y, out=noty); 
Mux16(a=y, b=noty, sel=ny, out=y3); 

// Perform f 
Add16(a=x3, b=y3, out=addout); 
And16(a=x3, b=y3, out=andout); 
Mux16(a=andout, b=addout, sel=f, out=preout); 

// Negate the output 
Not16(in=preout, out=notpreout); 
Mux16(a=preout, b=notpreout, sel=no, out=out); 

// zr flag 
Or8way(in=out[0..7], out=zr1); // PROBLEM SHOWS UP HERE 
Or8way(in=out[8..15], out=zr2); 
Or(a=zr1, b=zr2, out=zr); 

// ng flag 
Not(in=out[15], out=ng); 

} 

So das Problem zeigt sich, wenn ich versuche, eine indizierte Version von 'out' zu senden, um den Or8Way Chip. Ich habe versucht, eine andere Variable als "out" zu verwenden, aber mit dem gleichen Problem. Dann habe ich gelesen, dass Sie Zwischenvariablen nicht tiefstellen können. Ich dachte, wenn ich die Zwischenvariable an irgendeinen anderen Chip senden würde und dieser Chip es einbetten würde, würde es das Problem lösen, aber es hat denselben Fehler. Leider kann ich mir einfach keine Möglichkeit vorstellen, die zr- und ng-Flags zu setzen, ohne eine Zwischenvariable zu subskribieren, also bin ich wirklich festgefahren!

Nur damit Sie wissen, wenn ich die problematischen Zeilen mit folgenden ersetzen, wird es kompilieren (aber nicht die richtigen Ergebnisse liefern, da ich einige zufällige Eingabe nur bin mit):

// zr flag 
Not(in=zx, out=zr); 

// ng flag 
Not(in=zx, out=ng); 

Wer noch keine Ideen?

Bearbeiten: Hier ist die appendix of the book for the course, die angibt, wie das hdl funktioniert. Sehen Sie sich speziell Abschnitt 5 an, der über Busse spricht und sagt: "Ein interner Pin (wie v oben) darf nicht indiziert sein".

Edit: Hier ist der genaue Fehler, den ich bekomme: "Line 68, kann den Ausgang Pin des Tors nicht mit dem Teil verbinden". Die Fehlermeldung ist jedoch etwas verwirrend, da dies nicht das eigentliche Problem zu sein scheint. Wenn ich einfach "Or8way (in = out [0..7], out = zr1)"; mit "Or8way (in = falsch, out = zr1)"; Es wird diesen Fehler nicht erzeugen, was dazu führte, dass ich im Anhang nachschaue und herausfand, dass die out-Variable, da sie als intermediate abgeleitet wurde, nicht subskribiert werden konnte.

+1

Warum wurde diese Frage geschlossen? Es hat definitiv vielen Besuchern geholfen, wie die Upvotes und Antworten belegen. –

+0

Wählen Sie erneut zu öffnen, weil die Frage über ein gemeinsames Problem bei der Lösung eines Problems in einem bekannten Online-Kurs ist. –

Antwort

5

Die Lösung als Pax vorgeschlagen war eine Zwischengröße als Eingabe verwendet werden, um ein anderer Chip, wie Or16Way. Hier ist der Code, nachdem ich das Problem behoben und debuggt:

CHIP ALU { 

IN // 16-bit inputs: 
    x[16], y[16], 
    // Control bits: 
    zx, // Zero the x input 
    nx, // Negate the x input 
    zy, // Zero the y input 
    ny, // Negate the y input 
    f, // Function code: 1 for add, 0 for and 
    no; // Negate the out output 

OUT // 16-bit output 
    out[16], 

    // ALU output flags 
    zr, // 1 if out=0, 0 otherwise 
    ng; // 1 if out<0, 0 otherwise 

PARTS: 
// Zero the x input 
Mux16(a=x, b=false, sel=zx, out=x2); 

// Zero the y input 
Mux16(a=y, b=false, sel=zy, out=y2); 

// Negate the x input 
Not16(in=x2, out=notx); 
Mux16(a=x2, b=notx, sel=nx, out=x3); 

// Negate the y input 
Not16(in=y2, out=noty); 
Mux16(a=y2, b=noty, sel=ny, out=y3); 

// Perform f 
Add16(a=x3, b=y3, out=addout); 
And16(a=x3, b=y3, out=andout); 
Mux16(a=andout, b=addout, sel=f, out=preout); 

// Negate the output 
Not16(in=preout, out=notpreout); 
Mux16(a=preout, b=notpreout, sel=no, out=preout2); 

// zr flag 
Or16Way(in=preout2, out=notzr); 
Not(in=notzr, out=zr); 

// ng flag 
And16(a=preout2, b=true, out[15]=ng); 

// Get final output 
And16(a=preout2, b=preout2, out=out); 
} 
+0

Seltsam, dass es kein Puffergerät gibt und dass du zu and16/or16 mit identischen Eingaben zurückkehren musst, um das zu emulieren. Echte Elektronik hat Puffer, ohne Tore zu verschwenden, vielleicht sollte dieses Emulationsprogramm auch haben. – paxdiablo

+0

Ja, es muss eine andere Lösung geben, die keinen neuen Chip erfordert (ich habe Or16Way gemacht), da die Idee darin besteht, nur die Chips zu verwenden, die Sie in den vorherigen Projekten erstellt haben. – MahlerFive

+4

müssen Sie keinen neuen Chip machen. Verwenden Sie einfach mehrere Ausgaben wie folgt: Mux16 (a = F16, b = NF16, sel = nein, out = out, out [15] = ng, out [0..7] = zout1, out [8 ..15] = zout2); Verwenden Sie dann Or16Way für diese Ausgänge: \t Or8Way (in = zout1, out = zr1); \t Or8Way (in = zout2, out = zr2); \t Oder (a = zr1, b = zr2, out = zr3); \t Nicht (in = zr3, out = zr); – mudge

1

Haben Sie versucht:

// zr flag 
Or8way(
    in[0]=out[ 0], in[1]=out[ 1], in[2]=out[ 2], in[3]=out[ 3], 
    in[4]=out[ 4], in[5]=out[ 5], in[6]=out[ 6], in[7]=out[ 7], 
    out=zr1); 
Or8way(
    in[0]=out[ 8], in[1]=out[ 9], in[2]=out[10], in[3]=out[11], 
    in[4]=out[12], in[5]=out[13], in[6]=out[14], in[7]=out[15], 
    out=zr2); 
Or(a=zr1, b=zr2, out=zr); 

Ich weiß nicht, ob dies funktionieren wird, aber es scheint here Sinn aus der Betrachtung dieses Dokument zu machen.

ich auch zweimal überlegen würde über out als Variablennamen verwenden, da es verwirrend versuchen, den Unterschied zwischen dem, um herauszufinden, und dem Schlüsselwort out (wie in „out=...“).

Ihre bearbeiten Folgen, wenn Sie keine Zwischenwerte SUBSCRIPT kann, dann scheint es eine separate „Chip“ implementieren, wird wie IsZero16, die einen 16-Bit-Wert als Eingabe wird (Ihre Zwischen out) und ein Bit zurückkehren zeigt seine Nullheit an, die Sie in zr laden können. Oder Sie könnten einen IsZero8 Chip machen, aber Sie müssten ihn dann zwei Stufen nennen, wie Sie es gerade mit Or8Way machen.

Dies scheint wie eine gültige Lösung, da Sie die Eingabewerte auf einen Chip einschreiben können.

Und wenn Sie nur den Fehler betrachten, kann dies ein anderes Problem sein als das, das Sie vorschlagen. Der Ausdruck "Kann den Ausgangspin des Gate nicht mit dem Teil verbinden" bedeutet für mich, dass Sie keine Signale vom Ausgangsparameter zurück in den Chipverarbeitungsbereich senden können. Das ist aus elektrischer Sicht sinnvoll.

Möglicherweise müssen Sie die Ausgabe in eine temporäre Variable speichern und diese zum Setzen von zr und out verwenden (da, sobald die Signale an die Ausgangspins der Chips "gesendet" wurden, sind sie möglicherweise nicht mehr verfügbar).

Können wir versuchen:

CHIP SetFlags16 { 
    IN inpval[16]; 
    OUT zflag,nflag; 
    PARTS: 
     Or8way(in=inpval[0.. 7],out=zr0); 
     Or8way(in=inpval[8..15],out=zr1); 
     Or(a=zr0,b=zr1,out=zflag); 
     Not(in=inpval[15],out=nflag); 
} 

und dann in Ihrem ALU-Chip, verwenden Sie diese am Ende:

// Negate the output 
Not16(in=preout, out=notpreout); 
Mux16(a=preout, b=notpreout, sel=no, out=tempout); 

// flags 
SetFlags16(inpval=tempout,zflag=zr,nflag=ng); 

// Transfer tempout to out (may be a better way). 
Or16(a=tempout,b=tempout,out=out); 
+0

Das Problem ist, dass ich die Variable 'out' überhaupt nicht subscriptieren kann, da sie als eine Zwischenvariable abgeleitet wurde. Außerdem spielt es keine Rolle, ob Sie jeden Index einzeln oder nicht zuweisen. Wenn "in" eine Busgröße von 8 hat, muss die rechte Seite der Gleichung die Größe 8 haben. – MahlerFive

+0

Zeigen Sie uns den tatsächlichen Fehler, den Sie bekommen, @MahlerFive. Es kann helfen. – paxdiablo

+0

Okay, ich postete das als eine Bearbeitung – MahlerFive

21

Für alle Interessierten, die Lösung der Emulator unterstützt ist wie mehrere Ausgänge Etwas zu verwenden:

Mux16(a=preout, b=notpreout, sel=no, out=out,out=preout2,out[15]=ng); 
1

Hier ist man auch mit einem neuer Chip aber es fühlt sich sauberer

/** 
* Negator16 - negates the input 16-bit value if the selection flag is lit 
*/ 
CHIP Negator16 { 
    IN sel,in[16]; 
    OUT out[16]; 

    PARTS: 
    Not16(in=in, out=negateIn); 
    Mux16(a=in, b=negateIn, sel=sel, out=out); 
} 

CHIP ALU { 
    // IN and OUT go here... 
    PARTS: 
    //Zero x and y if needed 
    Mux16(a=x, b[0..15]=false, sel=zx, out=x1); 
    Mux16(a=y, b[0..15]=false, sel=zy, out=y1); 

    //Create x1 and y1 negations if needed 
    Negator16(in=x1, sel=nx, out=x2); 
    Negator16(in=y1, sel=ny, out=y2); 

    //Create x&y and x+y 
    And16(a=x2, b=y2, out=andXY); 
    Add16(a=x2, b=y2, out=addXY); 

    //Choose between And/Add according to selection 
    Mux16(a=andXY, b=addXY, sel=f, out=res); 

    // negate if needed and also set negative flag 
    Negator16(in=res, sel=no, out=res1, out=out, out[15]=ng); 

    // set zero flag (or all bits and negate) 
    Or16Way(in=res1, out=nzr); 
    Not(in=nzr, out=zr); 
} 
5

Dies ist, wie ich die ALU tat:

CHIP ALU { 
IN // 16-bit inputs: 
    x[16], y[16], 
    // Control bits: 
    zx, // Zero the x input 
    nx, // Negate the x input 
    zy, // Zero the y input 
    ny, // Negate the y input 
    f, // Function code: 1 for add, 0 for and 
    no; // Negate the out output 
OUT // 16-bit output 
    out[16], 
    // ALU output flags 
    zr, // 1 if out=0, 0 otherwise 
    ng; // 1 if out<0, 0 otherwise 
PARTS:  
    Mux16(a=x, b=false, sel=zx, out=M16x); 
    Not16(in=M16x, out=Nx); 
    Mux16(a=M16x, b=Nx, sel=nx, out=M16M16x); 

    Mux16(a=y, b=false, sel=zy, out=M16y); 
    Not16(in=M16y, out=Ny); 
    Mux16(a=M16y, b=Ny, sel=ny, out=M16M16y); 

    And16(a=M16M16x, b=M16M16y, out=And16); 
    Add16(a=M16M16x, b=M16M16y, out=Add16); 
    Mux16(a=And16, b=Add16, sel=f, out=F16); 

    Not16(in=F16, out=NF16); 
    Mux16(a=F16, b=NF16, sel=no, out=out, out[15]=ng, out[0..7]=zout1, out[8..15]=zout2); 

    Or8Way(in=zout1, out=zr1); 
    Or8Way(in=zout2, out=zr2); 
    Or(a=zr1, b=zr2, out=zr3); 
    Not(in=zr3, out=zr); 
}