Como faço para definir flags de saída para ALU em “Nand para Tetris” curso?

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

  •  05-09-2019
  •  | 
  •  

Pergunta

Embora I marcado esta lição de casa, é realmente para um curso que estou fazendo no meu próprio gratuitamente. De qualquer forma, o curso é chamado de "De Nand para Tetris" e eu estou esperando que alguém aqui tenha visto ou feito o curso para que eu possa obter alguma ajuda. Estou na fase em que eu estou construindo a ALU com a linguagem HDL fornecido. Meu problema é que eu não posso conseguir o meu chip para compilação corretamente. Estou recebendo erros quando tento definir os sinalizadores de saída para a ALU. Eu acredito que o problema é que eu não posso subscrito qualquer variável intermediária, desde quando eu tente definir as bandeiras para verdadeiro ou falso baseado em alguma variável aleatória (dizer uma bandeira de entrada), eu não receber os erros. Eu sei que o problema não é com os chips que eu estou tentando usar desde que eu estou usando todos os chips embutidas.

Aqui está meu chip ALU até agora:

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

}

Assim, os shows de problemas quando eu estou tentando enviar uma versão subscripted de 'fora' para o chip Or8Way. Eu tentei usar uma variável diferente de 'fora', mas com o mesmo problema. Então eu li que você não é capaz de subscrito variáveis ??intermediárias. Eu pensei que talvez se eu enviar o variável intermediária para algum outro chip e que o chip subscripted-lo, seria resolver o problema, mas tem o mesmo erro. Infelizmente eu não posso pensar em uma maneira de definir o zr e bandeiras ng sem subscripting alguma variável intermediária, por isso estou muito preso!

Só para você saber, se eu substituir as linhas problemáticas com o seguinte, ele irá compilar (mas não dar os resultados certos, já que estou apenas usando alguns entrada aleatória):

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

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

Alguém tem alguma idéia?

Editar: Aqui está a apêndice do livro para o curso que especifica como o HDL funciona. Especificamente olhar para a seção 5, que fala sobre ônibus e diz: "Um pino interno (como v acima) não podem ser subscritos"

Editar: Aqui está o erro exato que eu recebo: "Linha 68, não pode pino de saída da porta de conexão para parte". A mensagem de erro é uma espécie de confundir entanto, uma vez que não parece ser o problema real. Se eu substituir "Or8way (in = fora [0..7], out = zr1);" com "Or8way (em = false, out = zr1);" ele não irá gerar este erro, que é o que me levou a olhar para cima no apêndice e achar que a variável de fora, uma vez que foi derivada como intermediário, não poderia ser subscritas.

Foi útil?

Solução 2

A solução foi sugerido como Pax usar uma variável intermediária como entrada para um outro chip, tal como Or16Way. Aqui está o código depois de corrigido o problema e 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 );
}

Outras dicas

Para qualquer outra pessoa interessada, a solução dos suportes emulador é usar várias saídas Algo como:

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

Isto é como eu fiz a 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);
}

Você tentou:

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

Eu não sei se isso vai funcionar, mas parece fazer sentido de olhar para este documento aqui .

Eu também pensar duas vezes utilizando out como um nome de variável, uma vez que é confuso tentando descobrir a diferença entre isso e a palavra-chave out (como em "out=...").

Após a sua edição, se você não pode valores intermediários subscrito, então parece que você terá que implementar um "chip de" separado, como IsZero16 que terá um valor de 16 bits como entrada (seu out intermediário) e retornar um bit indicando its-ness zero que você pode carregar em zr. Ou você poderia fazer um chip IsZero8 mas você tem que, em seguida, chamá-lo-lo duas etapas como você está fazendo atualmente com Or8Way.

Esta parece ser uma solução válida desde que você pode subscrito os valores de entrada para um chip.

E, só de olhar para o erro, este pode ser um problema diferente do que você sugere. A frase "Não é possível pino de saída da porta de conexão para parte" significaria para mim que você é incapaz de conectar sinais a partir do parâmetro de saída traseira para os chips área de processamento. Isso faz sentido do ponto de vista elétrico.

Você pode achar que você tem que armazenar a saída em uma variável temporária e usar isso para ambos zr set e out (desde uma vez que os sinais de ter sido "enviado" para os pinos de saída fichas, eles podem não estar mais disponível).

Podemos tentar:

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, em seguida, em seu chip ALU, usar isso no 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);

Aqui está um também com um novo chip, mas ele se sente mais limpo

/**
 * 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top