¿Cómo se configuran las banderas de salida de la ALU en curso “NAND a Tetris”?

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

  •  05-09-2019
  •  | 
  •  

Pregunta

A pesar de que he etiquetado esta tarea, en realidad es de un curso que estoy haciendo por mi cuenta de forma gratuita. De todos modos, el curso se llama "De NAND a Tetris" y espero que alguien aquí ha visto o tomado el curso para que pueda obtener un poco de ayuda. Estoy en la etapa en que estoy construyendo la ALU con el lenguaje HDL suministrado. Mi problema es que no puedo conseguir mi chip para compilar correctamente. Estoy recibiendo errores cuando intento configurar las banderas de salida de la ALU. Creo que el problema es que no puedo subíndice cualquier variable intermedia, ya que cuando yo sólo trato de establecer las banderas de verdadero o falso sobre la base de alguna variable aleatoria (por ejemplo una bandera de entrada), que no consigue los errores. Sé que el problema no es con los chips que estoy tratando de usar ya que estoy usando todos los chips integrado.

Aquí está mi chip de ALU hasta ahora:

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

}

Así que el problema aparece cuando estoy tratando de enviar una versión con subíndice de 'fuera' al chip Or8Way. He intentado usar una variable diferente de 'fuera', pero con el mismo problema. Después leí que usted no es capaz de subíndice variables intermedias. Pensé que tal vez si he enviado la variable intermedia a algún otro chip y el chip subindicadas, sería resolver el problema, pero tiene el mismo error. Por desgracia yo no puedo pensar en una manera de establecer el Zr y banderas ng sin subíndices alguna variable intermedia, así que estoy realmente atascado!

Para que lo sepas, si reemplazo de las líneas problemáticas con lo siguiente, se compilará (pero no dar los resultados correctos, ya sólo estoy usando alguna entrada al azar):

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

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

Alguien tiene alguna idea?

Editar Este es el apéndice del libro, el para el curso que especifica cómo funciona el HDL. Específicamente mirar en la sección 5, que habla de los autobuses y dice: "Un pasador interno (como anteriormente v) no puede ser subíndice"

Editar Aquí está el error exacto consigo: "Línea 68, No se puede conectar el pin de salida de la puerta a una parte". El mensaje de error es una especie de confuso sin embargo, ya que no parece ser el problema real. Si tan sólo reemplazar "Or8way (= en salir [0..7], salida = ZR1);" con "Or8way (en = false, salida = ZR1);" no generará este error, que es lo que me lleva a mirar hacia arriba en el apéndice y encontrar que la variable a cabo, ya que se derivó como intermedio, no se pudo subíndice.

¿Fue útil?

Solución 2

La solución como Pax sugirió fue usar una variable intermedia como entrada a otro chip, como Or16Way. Aquí está el código después de He arreglado el problema y depurado:

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

Otros consejos

Para cualquier persona interesada, la solución es compatible con el emulador es utilizar varias salidas Algo así como:

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

Esta es la forma en que hice la 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);
}

¿Has probado:

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

No sé si esto va a funcionar, pero parece que tiene sentido de mirar este documento aquí .

También me pienso dos veces antes de usar out como nombre de variable ya que es confuso tratando de averiguar la diferencia entre eso y la palabra clave out (como en "out=...").

Después de su edición, si se puede valores intermedios no subíndice, entonces parece que tendrá que implementar un "chip" separado, tal como IsZero16 que tendrá un valor de 16 bits como entrada (su out intermedia) y devolver un bit que indica el cero-dad que se puede cargar en zr. O usted podría hacer un chip IsZero8 pero usted tendría que llamar entonces él él dos etapas como que estás haciendo con Or8Way.

Esto parece como una solución válida ya que puede subíndice los valores de entrada a un chip.

Y, simplemente mirando el error, esto puede ser un problema diferente a la que usted sugiere. La frase "No se puede conectar el pin de salida de la puerta a una parte" significaría para mí que no es capaz de conectar señales desde el parámetro de salida de nuevo en el área de procesamiento de los chips. Esto tiene sentido desde un punto de vista eléctrico.

Es posible que usted tiene que almacenar el resultado en una variable temporal y el uso que tanto zr set y out (ya que una vez que las señales han sido "enviado" a los pines de salida de virutas, que ya no pueden estar disponibles).

Se puede probar:

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

y, a continuación, en su chip de ALU, utilice este al final:

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

Aquí hay uno también con un nuevo chip, pero se siente más limpio

/**
 * 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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top