内存芯片实现中的无限循环问题 (Nand2Tetris)

Posted

技术标签:

【中文标题】内存芯片实现中的无限循环问题 (Nand2Tetris)【英文标题】:Problem with an infinite loop in Memory Chip implementation (Nand2Tetris) 【发布时间】:2020-11-29 15:23:36 【问题描述】:

我有两个几乎相同的内存芯片实现,除了一个有效,另一个在我使用 Memory.tst 在硬件模拟器中进行测试时,当程序希望我按 Y 键时给出一个无限循环。

WORKS的实现是:

 CHIP Memory 
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=ignored);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);

    And(a=address[13], b=address[14], out=canBeKbd);
    Or8Way(in=address[0..7], out=anyOne07);
    Or8Way(in=address[5..12], out=anyOne512);
    Or(a=anyOne07, b=anyOne512, out=anyOne012);
    Not(in=anyOne012, out=allZero012);
    And(a=canBeKbd, b=allZero012, out=isKbd);
    Keyboard(out=kdb);
    Mux16(a=false, b=kdb, sel=isKbd, out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);

不工作的实现是:

 CHIP Memory 
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=canBeKbd);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);

    Or8Way(in=address[0..7], out=anyOne07);
    Or8Way(in=address[5..12], out=anyOne512);
    Or(a=anyOne07, b=anyOne512, out=anyOne012);
    Not(in=anyOne012, out=allZero012);
    And(a=canBeKbd, b=allZero012, out=isKbd);
    Keyboard(out=kdb);
    Mux16(a=false, b=kdb, sel=isKbd, out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);

第二个实现的唯一区别是我从第一个 DMux 获得了 canBeKbd。这应该有效,但它没有。如果有人能告诉我原因,我会很高兴。

通过给定测试的其他实现是:

CHIP Memory 
    IN in[16], load, address[15];
    OUT out[16];

    PARTS:
    // RAM
    // [00]0 0000 0000 0000
    // [01]1 1111 1111 1111
    // Screen
    // [10]0 0000 0000 0000
    // [10]0 1111 1111 1111
    // Keyboard
    // [11]0 0000 0000 0000
    DMux4Way(in=load, sel=address[13..14], a=ram1, b=ram2, c=loadScreen, d=loadKbd);
    Or(a=ram1, b=ram2, out=loadRam);
    
    RAM16K(in=in, load=loadRam, address=address[0..13], out=outRam);
    Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen);
    Keyboard(out=outKbd);

    Mux4Way16(a=outRam, b=outRam, c=outScreen, d=outKbd, sel=address[13..14], out=out);

但我不能使用第三种实现,因为我不会测试所有前 12 位是否为 0。因为键盘内存位置仅为 0011 0000 0000 0000 (0x6000)。

【问题讨论】:

【参考方案1】:

看看这两种实现之间的区别,你应该考虑两个问题。

    DMux4Way 的实现是否正确产生输出 d?

    如果 outRam、outScreen outKbd 都为假,Mux4Way16 如何响应?因为乍一看,如果你给它一个 0x6nnn 范围内的地址而不是 0x6000,就会发生这种情况。

祝你好运!

【讨论】:

它起作用了,问题是我没有考虑到第二个例子中的负载值可能是 0。当我解决这个问题时,混合使用第一个和第二个实现,问题就解决了。

以上是关于内存芯片实现中的无限循环问题 (Nand2Tetris)的主要内容,如果未能解决你的问题,请参考以下文章

如何从循环外部杀死处于无限循环中的 pthread?

无限循环滚动视图思路一

如何从循环外部杀死无限循环中的pthread?

重新加载行包含带有 rightView 的 UITextField 会导致无限循环和内存溢出

导致内存错误的无限循环错误

PHP无限循环取MySQL中的数据。