Come faccio a impostare le bandiere di uscita per ALU in corso “Nand a Tetris”?

StackOverflow https://stackoverflow.com/questions/576242

  •  05-09-2019
  •  | 
  •  

Domanda

Anche se ho taggato questo compito, è in realtà per un corso che sto facendo da solo gratuitamente. In ogni caso, il corso si chiama "Da Nand a Tetris" e sto sperando che qualcuno qui ha visto o preso il corso in modo da poter avere un aiuto. Io sono nella fase in cui sto costruendo l'ALU con il linguaggio HDL in dotazione. Il mio problema è che non posso ottenere il mio chip per compilare correttamente. Sto ottenendo gli errori quando si tenta di impostare i flag di output per l'ALU. Credo che il problema è che non riesco a pedice alcuna variabile intermedia, da quando ho solo provare a impostare il flag su true o false sulla base di alcuni (per esempio una bandiera di input) variabile casuale, non ottengo gli errori. So che il problema non è con i chip Sto cercando di utilizzare dal momento che sto usando tutti i chip builtin.

Ecco il mio chip ALU finora:

/**
 * 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 );

}

Quindi il problema si presenta quando sto cercando di inviare una versione subscripted di '' al chip Or8Way. Ho provato con una variabile diversa da 'fuori', ma con lo stesso problema. Poi ho letto che non siete in grado di pedice variabili intermedie. Ho pensato che forse se invio la variabile intermedia per qualche altro circuito integrato, e quel chip pedice, sarebbe risolvere il problema, ma ha lo stesso errore. Purtroppo non riesco proprio a pensare ad un modo per impostare il Zr e bandiere ng senza l'indicizzazione di alcune variabile intermedia, quindi sono veramente bloccato!

Solo così si sa, se sostituisco le linee problematiche con la seguente, che verrà compilato (ma non dare i giusti risultati dal momento che sto usando solo alcuni input casuale):

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

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

Qualcuno ha qualche idea?

Modifica Ecco il appendice del libro per il corso , che specifica come le opere di HDL. Specificamente guardare sezione 5 che parla di autobus e dice: "Un perno interno (come v sopra) non possono essere pedice"

Modifica Ecco l'errore esatto ottengo: "Linea 68, Impossibile connettersi pin di uscita della porta per parte". Il messaggio di errore è una sorta di confusione, però, dal momento che non sembra essere il problema vero e proprio. Se ho appena sostituire "Or8way (a = out [0..7], out = ZR1);" con "Or8way (a = false, out = ZR1);" non genererà questo errore, che è quello che mi ha portato a cercare in appendice e scoprire che la variabile fuori, dal momento che è stato derivato come intermedio, non poteva essere indicizzato.

È stato utile?

Soluzione 2

La soluzione come Pax suggerito era di utilizzare una variabile intermedia come input per un altro chip, come Or16Way. Ecco il codice dopo ho risolto il problema e il debug:

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 );
}

Altri suggerimenti

Per chiunque altro interessato, la soluzione supporta l'emulatore è quello di utilizzare più uscite Qualcosa di simile:

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

Ecco come ho fatto l'ALU:

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);
}

Hai provato:

// 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 );

Non so se questo funzionerà, ma sembra avere un senso dal guardare questo documento qui .

Mi piacerebbe anche pensare due volte prima di utilizzare out come un nome di variabile dal momento che è fonte di confusione cercando di capire la differenza tra questo e la parola chiave out (come in "out=...").

Dopo la modifica, se è possibile i valori intermedi non pedice, allora sembra si dovrà attuare un "chip" separato come IsZero16 che avrà un valore a 16 bit come input (il vostro out intermedio) e restituire un bit che indica la sua zero ness che è possibile caricare in zr. Oppure si potrebbe fare un chip IsZero8, ma che ci si deve quindi chiamare la la due fasi, come si sta facendo con Or8Way.

Questa sembra una valida soluzione dal momento che possono pedice i valori di input a un chip.

E, solo guardando l'errore, questo può essere un problema diverso da quello suggerite. La frase "Impossibile connettersi pin di uscita della porta per parte" significherebbe per me che tu sei in grado di collegare i segnali dal parametro di uscita di nuovo nella zona di trasformazione chip. Questo ha senso da un punto di vista elettrico.

Si possono trovare si deve memorizzare l'output in una variabile temporanea e l'uso che sia zr set e out (dal momento che una volta i segnali sono stati "inviati" per i pin di uscita chip, potrebbero non essere più disponibili).

Possiamo provare:

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);
}

e poi, nel vostro chip ALU, utilizzare questo alla fine:

// 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);

Ecco una anche con un nuovo chip, ma ci si sente più pulito

/**
 * 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);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top