2009-02-23 8 views
16

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

Вот мой 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); 

} 

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

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

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

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

Кто-нибудь есть идеи?

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

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

+1

Почему этот вопрос закрыт? Это определенно помогло многим посетителям, о чем свидетельствуют ответы и ответы. –

+0

Голосование за повторное открытие, потому что вопрос касается общей проблемы при решении проблемы в известном онлайн-курсе. –

ответ

5

Решение, как Pax предложил, чтобы использовать промежуточную переменную в качестве вклада другой чип, такой как 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); 
} 
+0

Необычно, что нет буферного устройства и что вы должны вернуться к и16/или16 с одинаковыми входами для имитации этого. У реальной электроники есть буферы, не тратя впустую ворота, возможно, эта программа эмуляции тоже должна быть. – paxdiablo

+0

Да, должно быть какое-то другое решение, которое не требует от меня создания нового чипа (я сделал Or16Way), так как идея состоит в том, чтобы использовать только чипы, которые вы создаете в предыдущих проектах. – MahlerFive

+4

вам не нужно создавать новый чип. Просто используйте несколько выходов, например: Mux16 (a = F16, b = NF16, sel = no, out = out, out [15] = ng, out [0..7] = zout1, out [8 ..15] = zout2); Затем используйте Or16Way на этих выходах: \t Or8Way (in = zout1, out = zr1); \t Or8Way (in = zout2, out = zr2); \t Или (a = zr1, b = zr2, out = zr3); \t Not (in = zr3, out = zr); – mudge

1

Вы пробовали:

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

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

Я также думаю, что в два раза об использовании 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); 
+0

Проблема заключается в том, что я не могу индексировать переменную 'out' вообще, поскольку она была получена как промежуточная переменная. Кроме того, независимо от того, назначаете ли вы каждый индекс в отдельности или нет, это не имеет значения. Если «in» имеет размер шины 8, то правая часть уравнения должна иметь размер 8. – MahlerFive

+0

Покажите нам фактическую ошибку, которую вы получаете, @MahlerFive. Это может помочь. – paxdiablo

+0

Хорошо, я опубликовал это как редактирование. – MahlerFive

21

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

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

Вот один и с новый чип, но он чувствует себя чище

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

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