Как установить выходные флаги для ALU в курсе «Nand to Tetris»?

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

  •  05-09-2019
  •  | 
  •  

Вопрос

Хотя я отметил это домашнее задание, на самом деле оно относится к курсу, который я выполняю самостоятельно бесплатно.В любом случае, курс называется «От Nand до Tetris», и я надеюсь, что кто-нибудь из присутствующих видел или прошел этот курс, и я смогу получить некоторую помощь.Я нахожусь на этапе создания ALU с поставляемым языком HDL.Моя проблема в том, что я не могу правильно скомпилировать свой чип.Я получаю ошибки при попытке установить выходные флаги для ALU.Я считаю, что проблема в том, что я не могу индексировать какую-либо промежуточную переменную, поскольку, когда я просто пытаюсь установить флаги в значение true или false на основе какой-то случайной величины (скажем, входного флага), я не получаю ошибок.Я знаю, что проблема не в чипах, которые я пытаюсь использовать, поскольку я использую все встроенные чипы.

Вот мой чип ALU:

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

}

Итак, проблема проявляется, когда я пытаюсь отправить подписанную версию «out» на чип Or8Way.Я пробовал использовать переменную, отличную от «out», но с той же проблемой.Потом я прочитал, что вы не можете индексировать промежуточные переменные.Я подумал, может быть, если я отправлю промежуточную переменную в какой-нибудь другой чип, и этот чип подпишет ее, это решит проблему, но у него та же ошибка.К сожалению, я просто не могу придумать, как установить флаги zr и ng без индексации какой-либо промежуточной переменной, поэтому я действительно застрял!

Просто чтобы вы знали: если я заменю проблемные строки следующими, он скомпилируется (но не даст правильных результатов, поскольку я просто использую случайный ввод):

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

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

У кого-нибудь есть идеи?

Редактировать: Здесь приложение к книге к курсу который определяет, как работает HDL.В частности, посмотрите раздел 5, в котором говорится об автобусах и говорится:«Внутренний вывод (например, v выше) не может быть подписан».

Редактировать: Вот точная ошибка, которую я получаю:«Линия 68, невозможно подключить выходной контакт затвора к детали».Однако сообщение об ошибке сбивает с толку, поскольку, похоже, это не настоящая проблема.Если я просто заменю "Or8way(in=out[0..7], out=zr1 );" на "Or8way(in=false, out=zr1 );" это не будет генерировать эту ошибку, которая заставила меня посмотреть в приложении и найти, что переменная out, поскольку она была получена как промежуточная, не может быть подписана.

Это было полезно?

Решение 2

Решение, предложенное Паксом, заключалось в использовании промежуточной переменной в качестве входных данных для другого чипа, например Or16Way.Вот код после того, как я исправил проблему и отладил:

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

Другие советы

Для тех, кто заинтересован, решение, поддерживаемое эмулятором, заключается в использовании нескольких выходов Что-то вроде:

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

Вот как я сделал 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);
}

Попытался ли ты:

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

Я не знаю, сработает ли это, но, глядя на этот документ, кажется, это имеет смысл. здесь.

Я бы также дважды подумал об использовании out в качестве имени переменной, поскольку сложно понять разницу между этим именем и ключевым словом out (как в "out=...").

Если после вашего редактирования вы не можете индексировать промежуточные значения, то, похоже, вам придется реализовать отдельный «чип», например IsZero16 который примет на вход 16-битное значение (ваш промежуточный out) и вернуть один бит, указывающий на его нулевое значение, который вы можете загрузить в zr.Или вы могли бы сделать IsZero8 чип, но тогда вам придется назвать это двумя этапами, как вы сейчас делаете с Or8Way.

Это кажется правильным решением, поскольку вы может подписать входные значения на чип.

И, просто взглянув на ошибку, можно понять, что это может быть другая проблема, чем та, которую вы предлагаете.Фраза «Невозможно подключить выходной контакт затвора к детали» означала бы для меня, что вы не можете подключить сигналы от выходного параметра обратно в область обработки чипа.Это имеет смысл с электрической точки зрения.

Вы можете обнаружить, что вам нужно сохранить вывод во временную переменную и использовать ее как для установки zr и out (поскольку как только сигналы были «отправлены» на выходные контакты микросхемы, они могут стать недоступными).

Можем ли мы попробовать:

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

а затем в вашем чипе ALU используйте это в конце:

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

Вот еще один с новым чипом, но на вид он чище

/**
 * 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);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top