Comment puis-je définir des indicateurs de sortie pour ALU en cours « Nand à Tetris »?

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

  •  05-09-2019
  •  | 
  •  

Question

Bien que je tagged ce devoir, il est en fait un cours que je fais moi-même gratuitement. Quoi qu'il en soit, le cours est appelé « De Nand à Tetris » et j'espère que quelqu'un ici a vu ou pris le cours pour que je puisse obtenir de l'aide. Je suis au stade où je suis la construction de l'ALU avec la langue hdl fourni. Mon problème est que je ne peux pas obtenir ma puce pour compiler correctement. Je reçois des erreurs lorsque je tente de définir les indicateurs de sortie de l'ALU. Je crois que le problème est que je ne peux pas indicer une variable intermédiaire, car lorsque je tente simplement les drapeaux à la mise en vrai ou faux basé sur une variable aléatoire (par exemple un indicateur d'entrée), je ne reçois pas les erreurs. Je sais que le problème est pas avec les frites que je suis en train d'utiliser depuis que je suis en utilisant toutes les puces builtin.

Voici ma puce ALU jusqu'à présent:

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

}

Le problème apparaît quand je suis en train d'envoyer une version de indicés « out » à la puce Or8Way. Je l'ai essayé d'utiliser une autre variable que « out », mais avec le même problème. Ensuite, je lis que vous n'êtes pas en mesure de indicer variables intermédiaires. Je pensais que peut-être si j'ai envoyé la variable intermédiaire à une autre puce, et cette puce indicés, il résoudrait le problème, mais il a la même erreur. Malheureusement, je ne peux pas penser à un moyen de définir l'zr et drapeaux ng sans subscripting une variable intermédiaire, donc je suis vraiment coincé!

Juste pour que vous le savez, si je remplace les lignes problématiques avec ce qui suit, il compilera (mais pas donner les bons résultats depuis que je suis juste en utilisant une entrée aléatoire):

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

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

Quelqu'un a des idées?

Modifier Voici annexe rel="noreferrer"> qui précise le fonctionnement du cholestérol HDL. examiner spécifiquement l'article 5 qui parle de bus et dit: «Une broche interne (comme v ci-dessus) ne peut pas être indicé »

Edit: Voici l'erreur exacte que je reçois: « Ligne 68, ne peut pas se connecter la broche de sortie de la porte à une partie ». Le message d'erreur est un peu déroutant mais, puisque cela ne semble pas être le problème réel. Si je remplace simplement "Or8way (in = out [0..7], out = ZR1);" avec "Or8way (en = false, out = ZR1);" il ne génère pas cette erreur, qui est ce qui me conduit à rechercher dans l'annexe et constater que la variable sur, car il a été dérivé comme intermédiaire, n'a pas pu être indicé.

Était-ce utile?

La solution 2

La solution que Pax suggéré était d'utiliser une variable intermédiaire en tant qu'entrée à une autre puce, comme Or16Way. Voici le code après avoir résolu le problème et débogués:

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

Autres conseils

Pour toute personne intéressée, la solution prend en charge l'émulateur est d'utiliser plusieurs sorties Quelque chose comme:

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

Voici comment je l'ai fait 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);
}

Avez-vous essayé:

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

Je ne sais pas si cela va fonctionner, mais il semble logique de regarder ce document ici .

Je pense aussi à deux fois en utilisant out comme nom de variable car il est source de confusion à essayer de comprendre la différence entre cela et le mot-clé out (comme dans « out=... »).

Après votre édition, si vous ne pouvez pas en indice des valeurs intermédiaires, il semble que vous devrez mettre en œuvre une telle que IsZero16 « puce » séparée qui prendra une valeur de 16 bits en entrée (votre out intermédiaire) et retourner un bit indiquant son zéro-ness que vous pouvez charger dans zr. Ou vous pourriez faire une puce IsZero8 mais vous devez appeler ensuite deux étapes comme it que vous faites actuellement avec Or8Way.

Cela semble être une solution valable puisque vous peut les valeurs d'indice d'entrée à une puce.

Et, en regardant juste à l'erreur, cela peut être un problème différent de celui que vous suggérez. L'expression me voudrait dire « Impossible de se connecter la broche de sortie de la porte à la partie » que vous ne parvenez pas à vous connecter des signaux à partir du paramètre de sortie de retour dans la zone de traitement des puces. Cela a du sens d'un point de vue électrique.

Vous pouvez trouver que vous avez à stocker la sortie dans une variable temporaire et l'utiliser à la fois ensemble zr et out (car une fois que les signaux ont été « envoyés » aux broches de sortie des puces, ils ne peuvent plus être disponibles).

Peut-on essayer:

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

et puis, dans votre puce ALU, utiliser à la fin:

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

Voici un aussi avec une nouvelle puce, mais il se sent plus propre

/**
 * 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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top