OccupyMars2025 / Nand2Tetris

https://csdiy.wiki/en/%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/N2T/
1 stars 0 forks source link

[solved] Error occurred when I run `bash CPUEmulator.sh` to test `nand2tetris/projects/8/FunctionCalls/FibonacciElement/FibonacciElement.asm` #4

Open OccupyMars2025 opened 1 month ago

OccupyMars2025 commented 1 month ago

commit: https://github.com/OccupyMars2025/Nand2Tetris/commit/dd9ce202eae687dfda1eac92c36f2f36a0be29c5

occupymars2025@occupymars2025:~/Downloads/Nand2Tetris/nand2tetris/tools$ Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:245)
    at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
    at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
    at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
    at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
    at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1890)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:245)
    at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
    at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
    at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
    at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
    at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
    at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
    at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1890)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Exception in thread "Thread-1389" java.lang.NullPointerException
    at java.desktop/javax.swing.BufferStrategyPaintManager.copyArea(BufferStrategyPaintManager.java:286)
    at java.desktop/javax.swing.RepaintManager.copyArea(RepaintManager.java:1338)
    at java.desktop/javax.swing.JViewport.blitDoubleBuffered(JViewport.java:1717)
    at java.desktop/javax.swing.JViewport.windowBlitPaint(JViewport.java:1680)
    at java.desktop/javax.swing.JViewport.setViewPosition(JViewport.java:1220)
    at java.desktop/javax.swing.JViewport.scrollRectToVisible(JViewport.java:446)
    at java.desktop/javax.swing.JComponent.scrollRectToVisible(JComponent.java:3133)
    at HackGUI.Utilities.tableCenterScroll(Unknown Source)
    at HackGUI.PointedMemoryComponent.setPointer(Unknown Source)
    at Hack.ComputerParts.PointedMemory.setPointerAddress(Unknown Source)
    at Hack.CPUEmulator.PointerAddressRegisterAdapter.setValueAt(Unknown Source)
    at Hack.CPUEmulator.CPU.executeInstruction(Unknown Source)
    at Hack.CPUEmulator.CPUEmulator.doCommand(Unknown Source)
    at Hack.Controller.HackController.miniStep(Unknown Source)
    at Hack.Controller.HackController.singleStep(Unknown Source)
    at Hack.Controller.HackController.access$000(Unknown Source)
    at Hack.Controller.HackController$SingleStepTask.run(Unknown Source)
    at java.base/java.lang.Thread.run(Thread.java:829)
OccupyMars2025 commented 1 month ago

try to debug: It is most probable that the generared .asm file has bugs in it. So I regenerate nand2tetris/projects/8/FunctionCalls/SimpleFunction/SimpleFunction.asm, and test it, the result is as follows

Screenshot from 2024-05-05 10-22-18

Attention: the PC is 1151, but PC should be 132 or 133 at the end of execution

1. Use CPUEmulator to execute it one line per step, found that writeReturn() generated code @R14 is related to the bug

2. study the source code of def writeReturn(self)

3. find the bug, it has nothing to do with my code, in nand2tetris/projects/8/FunctionCalls/SimpleFunction/SimpleFunction.tst, the preconfiguration (lacking Sys.init) is NOT complete, there are no returnAddress, LCL, ARG, THIS, THAT of the caller saved in betweem the argument segment and the local segment, so in def writeReturn(self):, when you implement the part of # retAddr = *(frame-5) // puts the return address in a temporary variable, store it in R14 , you get a problem

set sp 317,
set local 317,
set argument 310,
set this 3000,
set that 4000,
set argument[0] 1234,
set argument[1] 37,
set argument[2] 9,
set argument[3] 305,
set argument[4] 300,
set argument[5] 3010,
set argument[6] 4010,

4. temporary workaround: in in def writeReturn(self):, replace the original implementation of # retAddr = *(frame-5) // puts the return address in a temporary variable, store it in R14 with the following code

# original implementation
        # retAddr = *(frame-5) // puts the return address in a temporary variable, store it in R14
        self.output.append('@5\n')
        self.output.append('D=A\n')
        self.output.append('@R13\n')
        self.output.append('A=M-D\n')
        self.output.append('D=M\n')
        self.output.append('@R14\n')
        self.output.append('M=D\n')
# modified implementation
        # retAddr = *(frame-5) // puts the return address in a temporary variable, store it in R14
        self.output.append('@END\n')
        self.output.append('D=A\n')
        self.output.append('@R14\n')
        self.output.append('M=D\n')

now the PC will be locked in the infinite loop at the end of execution, but it is just a temporary workaround for SimpleFunction, I still don't solve my original problem

OccupyMars2025 commented 1 month ago

Solution: https://github.com/OccupyMars2025/Nand2Tetris/commit/ec372d197d053e63c630da21214368b1f0022bfc