2 คะแนน โดย GN⁺ 2024-04-27 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • NAND คือ คอมพิวเตอร์ 16-bit ที่เทียบเท่าทัวริง ซึ่งจำลองบนเว็บ โดยยึดสมมติฐานเชิงการศึกษาว่าประกอบขึ้นจาก clock และ NAND gate เท่านั้น และครอบคลุมตั้งแต่ CPU ไปจนถึง IDE และ UI
  • สแตกของตัวเองอิงจาก แพลตฟอร์ม Jack-VM-Hack โดยมี CPU, ภาษาเครื่อง, assembly, assembler, ภาษา VM, VM translator, ภาษา Jack และ compiler ให้มาด้วย
  • โปรแกรมตัวอย่างมีทั้ง Average, Pong, 2048 รวมถึงเดโม VM escape ที่ใช้ stack overflow และ stack smashing ตลอดจน GeneticAlgorithm ที่ใช้ machine learning แบบง่าย
  • Jack เป็นภาษาเชิงวัตถุแบบ weakly typed ที่มีไวยากรณ์คล้าย Java แต่ภายในพึ่งพา signed 16-bit integer เพียงชนิดเดียว และมีข้อจำกัดมาก เช่น ไม่มีลำดับความสำคัญของ operator, ต้องจัดการหน่วยความจำเอง และมีพฤติกรรมที่ไม่ได้กำหนดไว้
  • โปรเจกต์นี้ไม่ได้หมายความว่าการคำนวณทั้งหมดทำงานบน NAND gate ทางกายภาพจริง ๆ แต่เป็น การใช้งานเพื่อการศึกษาและทฤษฎี ที่ใช้ TypeScript compiler และ VM translator, NAND gate logic simulator ที่เขียนด้วย Rust และ WebAssembly

สแตกคอมพิวเตอร์ทั้งหมดที่ NAND มีให้

  • NAND เป็นคอมพิวเตอร์ 16-bit บนเว็บ ซึ่งแนะนำว่าเป็นตัวย่อของ Not A Nand-powered Device
  • จำลองคอมพิวเตอร์ที่เทียบเท่าทัวริงซึ่งสร้างจาก clock และ NAND gate และมีองค์ประกอบต่อไปนี้อยู่ในตัว
    • CPU
    • ภาษา machine code
    • ภาษา assembly
    • assembler
    • ภาษา virtual machine
    • virtual machine translator
    • ภาษาโปรแกรมมิง
    • compiler
    • IDE
    • user interface
  • มีพื้นฐานจาก คอร์ส Nand to Tetris และ แพลตฟอร์ม Jack-VM-Hack ในหนังสือที่เกี่ยวข้อง
  • มี วิดีโอเดโม NAND ให้ดู

โปรแกรมตัวอย่างและเดโม

  • Average

    • โปรแกรมง่าย ๆ สำหรับรับตัวเลขและคำนวณค่าเฉลี่ย
    • แสดง control flow, การคำนวณเชิงเลขคณิต, I/O และการจัดสรรหน่วยความจำแบบไดนามิก
    • เป็นโปรแกรมที่ให้มากับ Nand to Tetris software suite
  • Pong

    • เกม Pong ที่แสดงโมเดลเชิงวัตถุ
    • ใช้ปุ่มลูกศรเลื่อน paddle ไปซ้ายขวาเพื่อเด้งลูกบอล
    • ทุกครั้งที่ลูกบอลเด้ง paddle จะเล็กลง และเมื่อบอลแตะด้านล่างของหน้าจอ เกมจะจบ
    • เป็นโปรแกรมที่ให้มากับ Nand to Tetris software suite
  • 2048

    • เกม 2048 ที่แสดง recursion และ application logic ที่ซับซ้อน
    • เลื่อนตัวเลขใน grid 4x4 ด้วยปุ่มลูกศร และตัวเลขที่เหมือนกันจะรวมกัน
    • เมื่อไปถึง tile 2048 จะชนะ แต่ยังเล่นต่อได้จนกว่าจะแพ้
  • Overflow

    • ตั้งใจทำให้เกิด stack overflow ด้วย recursion แบบไม่สิ้นสุด เพื่อทำ virtual machine escape
    • ใช้ประโยชน์จากการที่ runtime ไม่มีการตรวจสอบป้องกัน stack overflow
    • เมื่อค่า stack pointer เกิน 2048 stack จะหลุดออกจากพื้นที่หน่วยความจำที่ตั้งใจไว้และไหลเข้าไปใน heap memory space
    • หากรันบน RAM ที่ว่างอยู่ โปรแกรมอาจถูก reset กลางคันเพราะ instruction ที่ตั้งค่า program counter เป็น 0
    • หากรันทันทีหลังจากรัน GeneticAlgorithm จะสามารถอ่าน RAM memory เดิมที่ยังไม่ถูกเขียนทับได้
  • SecretPassword

    • ใช้ประโยชน์จากการที่ runtime ไม่ป้องกัน stack smashing เพื่อเรียกฟังก์ชันที่เดิมเข้าถึงไม่ได้
    • ผู้ใช้สามารถเขียนทับ memory address หนึ่งใน RAM ด้วยค่าที่ต้องการได้
    • หากเขียนทับ return address ของ stack frame ด้วย address ของฟังก์ชันอื่น ก็สามารถรันโค้ดใด ๆ ภายในโปรแกรมได้
    • ค่าตัวอย่างคือ memory location 267, overwrite value 1743
    • ช่องโหว่ประเภทเดียวกันนี้มีอยู่ใน buffer overflow ของ C ด้วย
  • GeneticAlgorithm

    • เป็น creature simulation ที่ใช้ machine learning แบบง่าย
    • dot แต่ละตัวมี “brain” ของตัวเองซึ่งประกอบด้วย acceleration vector และวิวัฒนาการผ่าน natural selection เพื่อให้ไปถึง goal
    • dot ที่ตายในตำแหน่งใกล้ goal มากกว่าจะมีโอกาสสูงกว่าที่จะถูกเลือกเป็น parent ของ generation ถัดไป
    • ในขั้นตอน reproduction บางส่วนของ brain จะเกิด mutation เพื่อจำลองวิวัฒนาการตามธรรมชาติ
    • มี วิดีโอเดโม Genetic Algorithm ให้ดู

ข้อจำกัดด้านฮาร์ดแวร์ที่ GeneticAlgorithm เผชิญ

  • GeneticAlgorithm เป็นโปรแกรมเดี่ยวที่ใช้เวลาพัฒนานานที่สุดในบรรดาองค์ประกอบต่าง ๆ ของ NAND
  • ด้วยเหตุผลด้านประสิทธิภาพ ปัจจัยที่ dot ใช้ในการวิวัฒนาการมีเพียงว่าตอนตายนั้นอยู่ใกล้ goal แค่ไหน ทำให้ entropy ของอัลกอริทึม natural selection ต่ำ
  • ด้วยปริมาณการใช้หน่วยความจำ จึงมีข้อจำกัดที่ไม่น่าพอใจทั้งจำนวน dot และขนาด brain
  • ด้วยความซับซ้อนทางเทคนิค แม้จะจัดวาง obstacle ใหม่ระหว่าง simulation ก็ไม่อาจรับประกันได้ว่า brain ของ dot จะใหญ่พอที่จะไปถึง goal
    • brain size ถูกกำหนดเฉพาะตอนเริ่มโปรแกรมเท่านั้น
  • การ implement ใช้การปรับแต่งหลายอย่างเพื่อหลบเลี่ยงข้อจำกัดของ NAND
    • ROM instruction memory space มีจำกัด หากโค้ดมากเกินไปจะ compile ไม่ผ่าน
    • GeneticAlgorithm เวอร์ชันสุดท้ายใช้ 99.2% ของ instruction memory space
    • RAM memory space มีจำกัด จึงต้องปรับการใช้ heap memory ให้เหมาะสม
    • เหตุผลที่หน้าจอถูกเติมด้วย static ระหว่าง generation คือมีการใช้ screen memory space เป็น temporary swap memory สำหรับ generation ถัดไป
    • NAND ไม่มี floating point type และช่วง integer ที่แทนค่าได้คือ -32768 ถึง 32767
    • ความแม่นยำของการคำนวณ fitness ลดลง และต้องคำนึงถึง integer overflow ด้วย
  • การปรับแต่งที่เกี่ยวข้องและ insight เพิ่มเติมมีบันทึกไว้ใน codebase ของ GeneticAlgorithm

การเขียนโปรแกรม NAND ด้วย Jack

  • ใน Jack มีการเน้นว่าเหตุผลสำคัญที่สุดที่ทำให้โปรแกรมไม่ทำงานคือ ไม่มีลำดับความสำคัญของตัวดำเนินการ
    • 4 * 2 + 3 ต้องเขียนเป็น (4 * 2) + 3
    • if (~x & y) ต้องเขียนเป็น if ((~x) & y)
    • evaluation value ของ expression ที่กำกวมและไม่มีวงเล็บถือเป็น undefined
  • Jack เป็น weakly typed object-oriented programming language ของ NAND
    • ตามคำอธิบายแล้วใกล้เคียงกับ “C ที่มี Java syntax”
    • เนื่องจาก NAND มี complete tech stack เป็นของตัวเอง จึงสามารถเขียนโปรแกรมได้ด้วย Jack เท่านั้น
  • Jack OS พื้นฐานจะถูก bundle ไปกับโปรแกรมตอน compile
    • ให้ interface กับ strings, memory และ hardware
    • มีฟังก์ชันอย่าง Keyboard.readLine, Keyboard.readInt, Output.printString, Output.println
  • Jack รองรับ primitive type 3 ชนิด ได้แก่ int, char, boolean
    • สามารถนิยาม abstract data type ผ่าน class ได้
    • variable แบบ field ใช้ประกาศ attribute แยกตาม instance
    • variable แบบ field มี private scope และการเข้าถึงจากภายนอกต้องผ่าน method
  • function และ method มีวิธีเรียกใช้ต่างกัน
    • method ของ current object สามารถเรียกใน class เดียวกันได้แบบ do g();
    • function call ต้องใส่ class name นำหน้า
    • object method เรียกผ่าน object เช่น do b.q();

Weak typing และการจัดการหน่วยความจำของ Jack

  • ต่างจาก Java ตรงที่ Jack ไม่รองรับ strong type, down casting, polymorphism และ inheritance
  • ภายในจริง ๆ แล้ว type ที่มีอยู่มีเพียง signed 16-bit integer เท่านั้น
    • compiler ไม่สนใจแม้จะผสม type ใน assignment และ operation
    • ถ้าใส่ 65 ลงใน char ก็สามารถ扱うได้เทียบเท่ากับ 'A'
    • ถ้าใส่ 5000 ลงในตัวแปร Array แล้วรัน a[100] = 77 จะกลายเป็น RAM[5100] = 77
    • array entry สามารถเก็บ data type ต่างชนิดกันได้
    • หาก memory layout ตรงกัน ก็สามารถใช้ Array เหมือนเป็น instance ของ class อื่นได้
  • Jack เป็นภาษาที่ต้อง จัดการหน่วยความจำด้วยตนเอง
    • หากไม่ deallocate memory ที่ไม่ต้องการแล้ว จะเกิด memory leak
    • heap overflow แสดงเป็น ERR6
    • Jack OS เก็บ array และ string ไว้ใน heap ไม่ใช่ stack
  • class ที่แทน object ควรมี method dispose ตาม best practice
    • เรียก dispose ของ field variable ก่อน
    • ท้ายสุด deallocate ตัว object instance เองด้วย do Memory.deAlloc(this);
  • loop ที่สร้างและพิมพ์ string literal ซ้ำ ๆ อาจทำให้เกิด heap overflow ได้
    • dispose string ในแต่ละรอบ หรือ
    • allocate string เพียงครั้งเดียวแล้วนำมาใช้ซ้ำ ก็จะพิมพ์ต่อไปได้เรื่อย ๆ

พฤติกรรมที่ไม่ถูกนิยามและข้อควรระวัง

  • ตัวดำเนินการเปรียบเทียบ

    • a > b และ a < b ไม่ได้ถูกต้องทางคณิตศาสตร์เสมอไป
    • การ implement ของ VM แปลง a > b เป็น a - b > 0
    • a - b อาจ overflow ได้ ทำให้ 20000 > -20000 กลายเป็น false
    • หาก absolute distance ของ a และ b มากกว่า 32767 เครื่องหมาย > และ < อาจผิดได้
    • พฤติกรรมนี้ไม่ถูกแก้ไขเพื่อ compatibility กับ Nand to Tetris
  • -32768

    • -32768 เป็นค่าเดียวที่ -(-32768) = -32768
    • ไม่มี positive counterpart จึงอาจทำให้เกิด unsoundness และ logic error
    • Output.printInt ภายในคาดว่า Math.abs จะคืน positive number แต่ในกรณี -32768 ไม่เป็นเช่นนั้น ทำให้ Jack OS ทำงานผิดพลาด
  • การเรียกฟังก์ชันโดยมี argument น้อยเกินไป

    • หากเรียก function ที่มี parameter โดยไม่ส่ง argument อาจเกิด undefined behavior ได้
    • ในทางกลับกัน function call ที่มี argument มากเกินไปถือว่า valid และสามารถ index extra argument ได้ด้วย keyword arguments
    • ไม่มี argument count indicator
  • type casting ที่ไม่เหมาะสม

    • สามารถใช้ Array เพื่อ cast ตัวแปรเป็น type อื่นได้
    • หากเรียก instance method ที่ไม่มีอยู่จริงบน variable ที่ถูก cast แล้ว จะเป็น undefined behavior
    • compiler ไม่ smart พอที่จะตรวจจับสิ่งนี้
  • การแก้ไข stack frame และ internal register

    • หากแก้ไข stack frame ที่ memory address 256~2047 หรือ internal register ที่ 1~15 อาจเกิด undefined behavior ได้
    • ระบุว่าโดยทั่วไปทำได้ยากหากไม่มีการใช้ Memory.poke ผิดวิธีหรือ negative array indexing
  • การโหลดไฟล์ VM ของผู้ใช้

    • NAND มี program validation สำหรับไฟล์ .jack แต่ไม่มีสำหรับไฟล์ .vm
    • ในไฟล์ .vm สามารถเรียก nonexistent function, อ้างถึง unassigned variable และทำ memory operation ที่ invalid ทางตรรกะได้
    • ในกรณีส่วนใหญ่จะเกิด virtual machine escape และอาจไม่แสดงอะไรบน screen

สเปกฮาร์ดแวร์และการจัดวางหน่วยความจำ

  • RAM ของ NAND ประกอบด้วย 32,768 words โดยแต่ละ word เก็บ 16-bit binary number
  • hardware จอง memory address 8,192 ตำแหน่งสำหรับ screen
    • แต่ละ bit ของแต่ละ address ถูก map แบบ linear ไปยัง pixel ที่สอดคล้องกันบน screen ขนาด 512x256
    • bit numbering เป็นแบบ LSb 0
  • keyboard ถูก map ไปที่ memory address 24576
    • key ที่ถูกกดอยู่ในปัจจุบันจะสะท้อนที่ตำแหน่งนี้
    • แนะนำให้ใช้ class Keyboard ของ Jack OS มากกว่าจัดการ user input โดยตรงผ่าน address นี้
  • keyboard รู้จัก ASCII character และ key พิเศษ
    • new line = 128
    • backspace = 129
    • left/up/right/down arrow = 130~133
    • home/end/page up/page down/insert/delete/ESC = 134~140
    • F1~F12 = 141~152
  • hardware จอง memory address 240 ตำแหน่งสำหรับ static class variable และ 1,792 ตำแหน่งสำหรับ global stack
    • ระบุว่าข้อจำกัดนี้โดยทั่วไปไม่เป็นปัญหา ตราบใดที่ไม่ได้ทำ deep recursion

ก้าวข้าม Jack OS ไปสู่การพัฒนา OS ของตัวเอง

  • โดยพื้นฐานแล้ว Jack OS จะถูก bundle รวมกับโปรแกรมตอน compile เพื่อให้บริการ string, memory และ hardware interface
  • สามารถจัดเตรียม OS implementation ของตัวเองที่มี hardware interface เฉพาะได้
    • IDE จะปฏิบัติกับไฟล์ Jack OS เหมือนไฟล์ program ทั่วไป
    • ไฟล์ OS ก็สามารถ delete หรือ overwrite ได้เช่นกัน
  • แม้จะใช้ OS ของตัวเอง ก็ยังมี core function บางอย่างที่ต้อง implement เพื่อให้ compile ได้
    • Sys.init: ไม่ใช่ Main.main แต่เป็น entry point จริงที่ hardcoded อยู่ใน VM implementation
    • Memory.alloc: เป็น heap memory allocator ที่ class constructor ใช้ภายในเมื่อสร้าง object
    • String.newWithStr: เป็น internal constructor สำหรับ string literal
    • Math.multiply: ถูกเรียกภายในแทน Jack expression x * y
    • Math.divide: ถูกเรียกภายในแทน Jack expression x / y
  • Sys.init ของ Jack OS ที่ให้มาจะ initialize memory, math, screen และ output จากนั้นเรียก Main.main() แล้วเรียก Sys.halt()

การทำงานภายในของ NAND

  • คอมพิวเตอร์ NAND ใช้ Harvard architecture
    • ROM ซึ่งเป็น instruction memory และ RAM ซึ่งเป็น data memory ถูกแยกออกจากกัน
    • CPU ทำให้ทั้งสองส่วนทำงานร่วมกัน
  • CPU เป็น accumulator machine
    • ใน control flow จะพึ่งพา built-in register อย่างมาก
    • ในที่นี้ accumulator คือ register D
  • CPU instruction set มี opcode เพียง สองตัว
    • instruction set ค่อนข้างเรียบง่าย แต่ให้ความสามารถหลากหลาย
    • ALU ถูกระบุด้วย expression ที่คำนวณได้ใน instruction เดียว
  • compiler และ virtual machine ไม่ใช่แนวคิดเฉพาะของ NAND จึงกล่าวถึงแบบสั้น ๆ
    • syntax feature แปลก ๆ บางอย่างเป็นผลจากการทำให้ implement compiler ได้ง่ายขึ้น
    • compiler เป็น recursive descent parser บน LL(1) grammar
    • compiler สร้าง VM code และ VM ถูกใช้เป็น simple stack machine
    • VM instruction แต่ละตัวถูก mapping ไปยัง assembly และ machine code
  • ดู implementation code ได้ที่ core และ compiler implementation

สาระสำคัญของภาษา Jack และ OS Reference

  • โปรแกรม Jack ประกอบด้วย collection ของ class
    • class ถูกนิยามในไฟล์แยกต่างหาก
    • ต้องมี class อย่างน้อยหนึ่งตัว และหนึ่งในนั้นต้องเป็น Main
    • ตาม Jack OS แล้ว entry point คือ function main ของ class Main
  • class สามารถมี declaration ของ field, static, constructor, method, function ได้
    • ลำดับของ declaration field และ static เป็นแบบ arbitrary
    • ลำดับของ subroutine declaration ก็เป็นแบบ arbitrary เช่นกัน
    • type เป็นหนึ่งใน void, int, boolean, char, class name
  • ลักษณะของ syntax
    • whitespace และ comment จะถูก ignored
    • & และ | เป็น bitwise operator และไม่ทำ short-circuit
    • true, false, null มีค่าเป็น -1, 0, 0 ตามลำดับ
    • string constant ไม่สามารถมี newline หรือ quotation mark โดยตรง และ escape ก็ไม่ได้
    • quotation mark และ newline มีให้ผ่าน String.doubleQuote() และ String.newLine() ของ OS
    • identifier เป็นแบบ case-sensitive
  • class หลักของ Jack OS
    • Array: การสร้าง array และ dispose
    • Keyboard: key press, character, line, integer input
    • Math: abs, multiply, divide, sqrt, max, min
    • Memory: peek, poke, alloc, deAlloc
    • Output: การแสดงผล text screen และการย้าย cursor
    • Screen: การวาด pixel, line, rectangle, circle
    • String: การสร้าง string, dispose, การเข้าถึง character, append, การแปลง integer
    • Sys: halt, error, wait
  • invalid state จะแสดง error code ในรูปแบบ "ERR[N]" และยุติ program execution
    • ERR3: division by zero
    • ERR6: heap overflow
    • ERR15, ERR16: string index out of bounds
    • ERR17: string is full
    • ERR20: illegal cursor location

ไม่ใช่โปรเจกต์ที่สร้างจาก NAND gate จริง ๆ เท่านั้น

  • FAQ ยอมรับว่าคำอธิบายและ title ที่ว่า “everything made from NAND gates” นั้น misleading แต่เป็นไปโดย good faith
  • compiler และ virtual machine translator เขียนด้วย TypeScript
  • emulated kernel และ emulated hardware ไม่ได้แทนวิธีทำงานของ real computer แบบตรงตัว
  • NAND gate logic simulator จริงเขียนด้วย Rust และเป็นเพียงส่วนเล็ก ๆ ของ codebase ทั้งหมด
    • Rust code ถูก compile เป็น WebAssembly เพื่อให้รันใน browser
    • มีการระบุว่าประเด็นนี้ทำให้สมมติฐานที่ว่า computation ทั้งหมดรันบน NAND gate ถูกตัดออกไปโดยพฤตินัย
  • NAND ทำหน้าที่เป็น educational and theoretical project
    • ในทางทฤษฎี CPU logic เดียวกันสามารถทำงานได้ใน real-world manifestation ของ emulated hardware ด้วย
    • มีการยกตัวอย่าง FPGA hardware project ที่อิงกับ nand2tetris คือ https://gitlab.com/x653/nand2tetris-fpga/

ขอบเขตการ implement และข้อจำกัดของ IDE

  • NAND ทำตาม specification ของคอร์ส Nand to Tetris และหนังสือที่เกี่ยวข้อง
  • ผู้ implement ได้ implement specification ของ CPU, assembler, virtual machine translator และ compiler เอง และเมื่อ port platform ไปยัง web ก็เพิ่ม IDE และ UI ของตัวเองเข้าไป
  • เหตุผลที่ Jack ต้องระบุ type คือเพื่อให้ compiler ตัดสินได้ว่า instance method เป็นของ class ใด
    • s.appendChar(33) ของ s ที่ประกาศเป็น type String จะถูกแปลงระหว่าง compile เป็น String.appendChar(s, 33)
  • IDE ยอมสละ user experience เพื่อความเรียบง่ายของ implementation
    • ใช้ contenteditable และ cursor positioning logic เพื่อทำ syntax highlighting
    • ผลคือทำงานช้า มี bug ที่เห็นได้ชัด และ common keybind ไม่ทำงาน
  • หากต้องการ compile และรัน code ให้กด “Start”
    • โดยทั่วไป OS ใช้เวลาน้อยกว่า 1 วินาทีเล็กน้อยในการ initialize memory และ setup service

1 ความคิดเห็น

 
GN⁺ 2024-04-27
ความคิดเห็นจาก Hacker News
  • เป็นโปรเจกต์เสริมที่ยอดเยี่ยมมาก และ README ก็ดีมากด้วย กำลังคิดว่าจะลองทำตาม Nand to Tetris หลังจากได้ลองเล่นกับ 6502 Computer ของ Ben Eater(https://eater.net/) มาบ้าง

    • จะเป็นไปได้ไหมที่จะสร้าง คอมพิวเตอร์ NAND-to-Tetris แบบกายภาพ? หรือว่านี่เป็นแค่แบบฝึกหัดในสภาพแวดล้อมเสมือนล้วน ๆ?
  • แค่จากสื่อนี้อย่างเดียวก็น่าจะทำเป็น วิชาในมหาวิทยาลัยได้หลายวิชา เลย เป็นสื่อที่ทำมาดีมาก

    • นี่มันก็แค่ Nand2Tetris ไม่ใช่เหรอ? ฉันเคยทำตามกระบวนการนั้นมาแล้ว และดูคร่าว ๆ แล้วเหมือนว่าจะเหมือนกันไปจนถึงภาษา Jack เลย
  • ทำได้ดีมากจริง ๆ เหมือนได้เดินผ่าน ชั้นของ abstraction ด้วยตัวเอง ซึ่งโปรแกรมเมอร์ส่วนใหญ่ทั้งอาชีพอาจไม่มีวันได้เห็น

  • งานเจ๋งมาก NAND to Tetris ช่วยให้ฉันได้งานแรกหลังเรียนจบมหาวิทยาลัย

    • อยากรู้ว่ามันช่วยอย่างไรบ้าง
  • ตอนสอบ คุณวุฒิด้านฮาร์ดแวร์คอมพิวเตอร์ ของ UC Berkeley ช่วงต้นทศวรรษ 1990 ก็มีโจทย์แกนหลักที่คล้ายกันมาก
    พูดให้เฉพาะเจาะจงคือเป็นโจทย์ให้ออกแบบ โปรเซสเซอร์ RISC แบบ pipeline ที่ใช้ microcode ตั้งแต่พื้นฐานโดยใช้แค่ NAND gate เท่านั้น ไม่ต้องสร้างจริงแต่ต้องส่งแบบออกแบบอย่างละเอียดบนกระดาษ

  • งานนี้น่าทึ่งจริง ๆ ตอนที่เรียนคอร์ส Nand2Tetris ฉันก็อยากลองทำ implementation แบบเสมือน คล้าย ๆ กันเหมือนกัน
    ที่น่าประทับใจคือคุณทำมันสำเร็จจริง และตอนนี้ก็น่าจะเข้าใจการทำงานของคอมพิวเตอร์ได้ลึกมากแล้ว

    • เช้านี้ฉันเองก็เพิ่งคิดอะไรคล้าย ๆ กันเกี่ยวกับการ โมเดลชิ้นส่วนพื้นฐานด้วย SVG
      แต่ก็น่าทึ่งที่มีคนทำสิ่งที่ยิ่งใหญ่กว่าที่ฉันจินตนาการไว้อีกเป็นระดับหนึ่งแล้ว
  • งานยอดเยี่ยมมาก ช่วงนี้ฉันก็เพิ่งเริ่ม Nand2Tetris และอยากจะเรียนส่วนที่ 1 ซึ่งเป็นพาร์ตฮาร์ดแวร์ของคอร์สให้จบภายในไม่กี่เดือนข้างหน้า
    ฉันเขียนความคืบหน้าไว้ในบล็อกนี้: https://gurudas.dev/blog/2024/04/13/nand-to-tetris-2024-proj...

  • ไม่จริงหรอก คุณใช้ทั้ง NAND gate และ clock นี่นา

    • clock นั้นก็ทำจาก ring oscillator ได้ และ ring oscillator ก็ทำได้โดยเอา NAND gate มาต่อเป็น NOT gate แล้วเรียงกันเป็นจำนวนคี่
  • งานเจ๋งมาก เดี๋ยวจะบุ๊กมาร์กไว้กลับมาดูแบบละเอียดทีหลัง
    ฉันชอบ NAND-to-Tetris แต่ยังไม่เคยทำจนจบ เลยตั้งตารอที่จะได้ดูโปรเจกต์นี้

  • สงสัยว่าจำนวน NAND gate ทั้งหมดมีเท่าไหร่?

    • ฉันไปดูโค้ดละเอียดมาแล้ว พบว่าในแต่ละ clock cycle มีการใช้ NAND gate 3,234 ครั้ง :)