3 पॉइंट द्वारा GN⁺ 2024-04-10 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • कमर्शियल CPU या डेडिकेटेड नेटवर्क चिप के बिना बनाए गए डिस्क्रीट लॉजिक कंप्यूटर में 10BASE-T Ethernet ट्रांसमिट/रिसीव क्षमता जोड़ने की हार्डवेयर निर्माण कहानी
  • पहले बनाए गए 10BASE-T↔SPI physical layer adapter के ऊपर MAC layer module जोड़कर उसे homebrew computer से जोड़ा गया, और transmitter व receiver को स्वतंत्र full-duplex संरचना में बनाया गया
  • receiver SPI डेटा को bytes में बदलकर 2 kB SRAM में स्टोर करता है, और पहले 6 bytes को हार्डवेयर में जांचकर केवल FE:FA:F6:F2:EE:EA या broadcast MAC स्वीकार करता है
  • transmitter ने circuit को सरल रखने के लिए FCS generation और preamble preparation को software पर छोड़ा, और केवल 1024-byte fixed-length frames सपोर्ट करता है
  • uIP 1.0 compile कर सकने वाला C compiler तक बनाया गया और network apps चलाए गए; नतीजे ping average 85 ms और HTTP static file download 2.6 kB/s के स्तर के रहे

डिस्क्रीट लॉजिक कंप्यूटर में Ethernet जोड़ना

  • एक पूरा computer system discrete logic components से बनाने के काम की अगली कड़ी के रूप में, network applications चला सकने वाला Ethernet adapter लागू किया गया
  • पहले 10BASE-T Ethernet signal को SPI में बदलने और वापस बदलने वाला physical layer adapter बनाया गया था, और उस समय operation testing के लिए STM32 microcontroller इस्तेमाल किया गया था
  • इस बार काम का मुख्य हिस्सा उस adapter को homebrew computer से जोड़ने के लिए MAC layer module है
  • adapter full-duplex संरचना वाला है, जिसमें transmit और receive भाग एक-दूसरे से स्वतंत्र रूप से काम करते हैं

Receiver: SPI डेटा को frame buffer में स्टोर करना

  • receiver SPI serial data को byte-level parallel data में बदलता है और byte clock निकालता है
  • destination MAC address को पहले 6 bytes में जांचा जाता है, और criteria पर खरे न उतरने वाले frames reject कर दिए जाते हैं
  • प्राप्त bytes 6116 2 kB SRAM buffer में लिखे जाते हैं
  • frame खत्म होने पर receiver inactive हो जाता है, और फिर से active होने तक अतिरिक्त frames नहीं लेता
  • byte counter रुकने के बाद भी value बनाए रखता है ताकि CPU received length पढ़ सके
  • FCS को hardware में verify नहीं किया जाता
  • Data collection और buffer access

    • SPI serial data shift register U32 में जाता है, और U30U31 क्रमशः bits और bytes गिनते हैं
    • D flip-flop U29B SRAM write signal recv_buf_we बनाता है, और यह signal input data के हर 8 bits पर थोड़ी देर के लिए low हो जाता है
    • received bytes U20 वाले 6116 SRAM में लिखे जाते हैं
    • U13, U16, U18 address multiplexer बनाते हैं, जो SRAM address input के लिए byte counter या system address bus चुनते हैं
    • U21 received bytes को RAM तक पहुंचाने वाले 3-state buffer की भूमिका निभाता है
    • CPU को received data और length access करने देने के लिए RAM और byte counter system data bus से जुड़े हैं
    • U25 receive RAM को system data bus से जोड़ता है
    • frame complete होने के बाद byte counter की value recv_byte_cnt bus पर बनी रहती है
    • U26, U27 किसी specific address read request आने पर यह value system data bus पर भेजते हैं
    • U27 का बाकी आधा हिस्सा receiver और transmitter status query करने वाला 2-bit read-only status register बनाता है

Hardware MAC address filtering

  • Ethernet traffic analyze करने पर पता चला कि frames आम तौर पर थोड़े delay से अलग किए गए 3–4 units के छोटे batches में आते थे, और एक ही batch के अंदर भी destination MAC address अक्सर अलग होता था
  • computer शायद इतना तेज नहीं था कि software में MAC filtering करके receiver को फिर से active कर सके, इसलिए hardware MAC filtering जरूरी थी
  • custom MAC address store करके पहले 6 bytes से compare करने वाला तरीका बहुत जटिल होने के कारण छोड़ दिया गया
  • single-byte repeated MAC address भी संभव था, लेकिन आखिर में MAC address को byte index के function के रूप में बनाया गया
    • bit 0 को 0 पर fixed रखा गया
    • bit 1 को 1 पर fixed रखा गया
    • bit 2~4 byte index की inverted value हैं
    • bit 5~7 को 1 पर fixed रखा गया
  • इस rule से बना MAC address FE:FA:F6:F2:EE:EA है
  • ARP operation के लिए broadcast MAC FF:FF:FF:FF:FF:FF भी स्वीकार किया जाता है
  • U33 data bit 0 और bit 2~4 को desired values से match करता है या नहीं, यह compare करता है; और U34A output तब high होता है जब ये bits match करते हैं
  • U35A broadcast MAC check लागू करता है, और bit 0 व bit 2~4 सभी 1 हों तो output high हो जाता है
  • दोनों signals को D7 और R6 का उपयोग करने वाले diode OR से combine किया जाता है, और U35B जांचता है कि बाकी bits सभी 1 हैं या नहीं
  • single byte का validity result U10A में accumulate होता है
    • frame receive न करते समय incoming SPI slave select signal ss low होता है और U10A को 1 पर set किया जाता है
    • frame receive के दौरान हर received byte पर value update होती है
    • destination MAC address criteria पर खरा उतरे तो U10A value high बनी रहती है
    • byte address 5 तक पहुंचने पर final value U36B में latch होती है, और destination address match न करे तो frame reception रोक दिया जाता है

Transmitter: fixed-length frames से circuit सरल बनाना

  • transmitter भी receiver की तरह FCS generation को hardware में लागू नहीं करता और software में handle करता है
  • circuit कम करने के लिए transmitter केवल fixed-length frames support करता है
  • frame length 1024 bytes चुनी गई, जो common MTU 1500 bytes के करीब है
  • 10BASE-T के लिए जरूरी preamble कई 0x55 और अंत में 0xD5 से बना होता है, और software को इसे भी इसी 1024-byte में साथ में load करना होता है
  • fixed frame length higher-level protocols को प्रभावित नहीं करती
    • higher-level protocols packet size को header में encode करते हैं
    • actual Ethernet frame length पर निर्भर नहीं करते
  • Transmit data flow

    • transmit data SRAM में stored होता है
    • 20 MHz clock 4-bit counter में input होती है, और overflow output byte clock के रूप में इस्तेमाल होता है
    • किसी specific write-only memory location में value लिखने पर counter active होता है और frame transmission शुरू हो जाता है
    • parallel byte data shift register के जरिए serialize होता है
    • receiver की तरह U12 bits गिनता है और U14 bytes गिनता है
    • 20 MHz clock integrated oscillator से आती है, और सीधे इस्तेमाल नहीं होती; कम से कम divide-by-2 करके इस्तेमाल होती है
    • यह तरीका oscillator के duty cycle को output signal पर असर डालने से रोकता है
  • RAM, shift register, timing

    • RAM U22 के address input selection के लिए receiver की तरह तीन 74HC157 multiplexers इस्तेमाल होते हैं
    • U23 RAM में data load करने के लिए इस्तेमाल होता है
    • U24 current transmit byte के intermediate storage की भूमिका निभाता है
    • byte counter 74HC4040 ripple counter है, इसलिए stabilization धीमा है
    • जब RAM output अभी valid नहीं होता, तब U24 stable output देता है
    • data shift register U28 में जाता है और bit-by-bit shift होता है
    • RAM से shift register में जाने वाले bits का order गलत wire हो गया था, ऐसा hardware bug था; इसलिए software में bits shuffle करके workaround करना पड़ा
    • MOSI और SCK को अच्छे 10BASE-T signal बनाने के लिए ठीक-ठीक synchronize होना चाहिए
    • U11A और U8B यह synchronization संभालते हैं
    • tx_cnt0 bit counter का bit 0 है, और 20 MHz को divide-by-2 किया हुआ signal clock के लिए इस्तेमाल होता है
    • U11A इस signal के अनुसार output बदलता है
    • U8B, U11A द्वारा बनाए गए delay से match करने के लिए clock delay करता है
    • D latch साधारण AND gate से ज्यादा complex होता है और लगभग 5 ns ज्यादा delay रखता है, इसलिए तेज 74LV74A इस्तेमाल किया गया
    • 74LV74A इस board पर fast family का इकलौता chip है

CPU interface और memory mapping

  • programmer के नजरिए से Ethernet adapter memory-mapped interface जैसा दिखता है
  • दोनों frame buffers 0xF000 पर mapped हैं
  • read-only registers दो हैं
    • 0xFB00 का 8-bit status register RX_FULL और TX_BUSY flags रखता है
    • RX_FULL frame reception complete state दिखाता है
    • TX_BUSY frame transmission in progress state दिखाता है
    • 0xFB02 का 16-bit register received data length रखता है
  • write operations control commands के रूप में इस्तेमाल होते हैं
    • 0xFB00 पर कोई भी value लिखने से receiver फिर से active होता है
    • 0xFB01 पर कोई भी value लिखने से transmission शुरू होता है
  • CPU interrupts support नहीं करता, इसलिए interrupts नहीं हैं
  • संबंधित addresses सभी upper 4 bits 1 वाले F से शुरू होते हैं, और इस condition को U2A check करता है
  • buffer address में bit 11 को 0 होना चाहिए, और U1D, D2, R2, U1E इसे check करते हैं
  • register address में दूसरा hexadecimal digit B यानी 1011 होना चाहिए, और U1BU2B इसकी पुष्टि करते हैं
  • U4A, U4B decoders individual functions select करने में इस्तेमाल होते हैं
  • दो LEDs buffer या register access दिखाते हैं

Programming और performance

  • network support चाहिए था, लेकिन TCP/IP stack खुद implement नहीं करना था और assembly programming भी असुविधाजनक थी, इसलिए C compiler बनाया गया
  • यह compiler छोटे TCP/IP library uIP 1.0 को compile कर सकने जितना mature है
  • CPU की code density बहुत कम है, लेकिन uIP RAM में fit हो जाता है और real applications के लिए भी जगह बचती है
  • network performance कम है, लेकिन यह commercial CPU या special chip के बिना लागू किया गया नतीजा है
    • ping round-trip average: 85 ms
    • HTTP server download speed: 2.6 kB/s
    • HTTP server SD card की static files serve करता है
  • model, schematic files और PCB drawings GitHub repository में हैं

1 टिप्पणियां

 
GN⁺ 2024-04-10
Hacker News की राय
  • शेयर करने के लिए शानदार काम। तर्क-प्रक्रिया का stack trace खास तौर पर अच्छा लगा, और बहुत-सी चीज़ों को first principles से समझाना या beginner के नज़रिए से समझाने की कोशिश करना शैक्षिक रूप से बेहतरीन है
    वास्तविक networking के लिए भले ही यह व्यावहारिक न हो, लेकिन मुझे नहीं लगता कि यह सिर्फ़ कोई खिलवाड़ है। ऐसे दौर में जब बेहद जटिल network chips में backdoor मिल रहे हैं, आगे चलकर इसके लिए अधिक गंभीर पाठक-वर्ग या project motivation बन सकती है

    • सोचता हूँ आधुनिक silicon के अंदर छिपी vulnerabilities कितनी होंगी। कुछ हज़ार lines के code में भी लगभग रोज़ vulnerabilities निकलती हैं, जबकि hardcoded silicon के अंदर मौजूद microchips असल में अरबों lines के code के बराबर हैं
  • यह तो पूरी तरह custom computer के लिए है, इसलिए अपने-आप में कहीं ज़्यादा प्रभावशाली है, और “तो मैंने C compiler बना लिया” वाली बात तो अलग ही है। फिर भी यह सोचने पर मजबूर करता है कि “सामान्य” PC के लिए Ethernet card का minimum implementation कितना होगा
    काफ़ी हिस्सा मिलता-जुलता होगा, और checksum को PC CPU से handle कराया जा सकता है। Connection या तो raw serial होगा, या अधिक व्यावहारिक रूप से USB चाहिए होगा, और अंत में शायद “real” driver इस्तेमाल करना पड़ेगा या user space में भेजकर process करना होगा
    मिलती-जुलती चीज़ें देखते हुए लगा कि अगर device https://en.wikipedia.org/wiki/USB_communications_device_clas... implement करे, तो क्या यह अपने driver के बिना “बस चल” सकता है, लेकिन यह सभी checksums को host side पर handle करने के साथ शायद ठीक से मेल नहीं खाएगा
    खोजते हुए https://en.wikipedia.org/wiki/Ethernet_over_USB भी मिला, शायद इसका मतलब है कि ऐसा adapter बनाया जा सकता है जो सिर्फ़ physical connection को USB में बदल दे और बाकी computer खुद handle करे

    • USB को बहुत पहले आए 10base2 Ethernet से कहीं ज़्यादा जटिल माना जा सकता है। अगर 10base2 Ethernet network से PCIe या USB के ज़रिए जुड़ने की कोशिश करें, तो दोनों ही Ethernet side की तुलना में कहीं ज़्यादा काम बन जाते हैं
      शायद किसी FTDI-style USB device को 10base2 Ethernet bit-banging करने के लिए मनाया जा सके। तरीका यह होगा कि line traffic को साफ़ bitstream में बदलने और frame start align करने वाला “PHY” हिस्सा ही implement किया जाए, फिर PC बाकी सब software में process करे
    • अगर सामान्य PC में 30 साल पहले की तरह ISA bus होती, तो मेरा network card थोड़े-से बदलाव के साथ उससे जोड़ा जा सकता था
    • FPGA में NIC implement करना, आम तौर पर PCIe connection के साथ, बहुत common है
      USB side पर CDC-NCM खुद किसी भी MCU पर implement करना मुश्किल नहीं है, लेकिन USB HS PHY implementation के लिए व्यवहार में ASIC hardware चाहिए
      0.30 डॉलर वाले USB HS ULPI PHY का इस्तेमाल करें तो FPGA में USB CDC-NCM काफ़ी आसानी से implement किया जा सकता है
  • अंत में इस project के लिए बनाए गए C compiler का link है: https://github.com/imihajlow/ccpu-cc
    लगता है linker और libc भी हैं। Hardware design कितना जटिल है, यह ठीक से नहीं जानता, लेकिन C compiler को हल्के-फुल्के अंदाज़ में बनाकर जोड़ देना कमाल है

    • यह Rust में लिखा C compiler है, और language parsing के लिए lang_c crate इस्तेमाल करता है
  • सच में प्रभावशाली। ऐसा project खुद करके देखना चाहता हूँ, और system को समझने से लेकर उसे बनाने तक लगी लगन और अनगिनत घंटों के लिए सम्मान महसूस होता है
    retirement की कोई ख़ास इच्छा नहीं है, लेकिन शायद तब इस तरह के hardware-software projects में समय लगाऊँ

  • तो क्या यह Etherlink 3c501 से बेहतर है, या उससे भी खराब? :-D
    https://mirror.math.princeton.edu/pub/oldlinux/Linux.old/net...
    अगर याद सही है, तो network से आया नया packet उसी buffer को overwrite कर देता था जिसे CPU पढ़ने वाला था। मैंने इसे कुछ समय Linux में इस्तेमाल किया था, और performance सच में बहुत खराब थी

    • मुझे याद है 3c590(https://github.com/torvalds/linux/blob/20cb38a7af88dc40095da...) में भी कुछ भयानक behavior था। घातक error से बचने के लिए PCI latency setting को 32 से 248 करना पड़ता था
      Driver और firmware updates हमारी नज़र से कितना कुछ छिपा देते हैं, यह हैरान करने वाला है
    • इस चीज़ का विवरण मिला: https://www.os2museum.com/wp/emulating-etherlink/
      मेरे वाले में दो buffers हैं, इसलिए यह बेहतर है :) फिर भी received frame सिर्फ़ एक ही रखा जाता है
  • “Frame length fixed कर देने से higher-level protocols पर असर नहीं पड़ता। क्योंकि higher-level protocols header में packet size encode करते हैं और actual Ethernet frame length पर निर्भर नहीं करते” वाला हिस्सा दिलचस्प है
    हाल में मैंने packet decoder बनाया था, और हर layer पर explicitly verify किया कि lower-layer length सही है या नहीं। IP के मामले में मेरे decoder में IP datagram length को Ethernet frame length और link-layer header length से बिल्कुल match करना होता है
    यह ज़रूरत से ज़्यादा सावधानी के लिए नहीं था, बल्कि short frames detect करने के लिए था, और बाद में long frames को भी error मानने का फैसला किया। लेखक uIP इस्तेमाल कर रहे हैं, लेकिन Linux या दूसरे modern OS इसे कैसे handle करते हैं, यह जानना चाहूँगा। यह भी जानना चाहूँगा कि interoperability testing की गई थी या नहीं

    • Long frames network पर भेजे जा रहे हैं, और मेरे पास मौजूद किसी भी OS ने कोई problem नहीं दिखाई। कहीं पढ़ा था कि कुछ routers packets के पीछे metadata store करने के लिए सचमुच long frames इस्तेमाल करते हैं
    • Timestamps और अन्य तरह की in-band network telemetry भी trailer के रूप में frames में insert की जाती है। तब नया FCS जोड़ा जाता है
      अगर application L2 data नहीं देखती, तो Linux IP stack इसे बस ignore कर देता है
  • DEC के पहले SSI Ethernet card set की तुलना में यह physically काफी छोटा है: https://i.ebayimg.com/images/g/NEYAAOSw-mZlg0lZ/s-l1600.jpg
    DEC DEUNA boards की लंबाई 1 foot से ज़्यादा है, लेकिन उनमें features भी बहुत ज़्यादा हैं। DEUNA एक “real” NIC है, जिसमें send/receive queues हैं, वह उन्हें autonomously handle करता है और DMA भी करता है। बेशक, card पर अपना PDP-11 भी है, जो उसे चलाता है

  • सच में शानदार। जानना चाहूँगा इसमें कितना समय लगा

    • Network module बनाने में लगभग एक महीना लगा, लेकिन compiler लिखने में उससे कहीं ज़्यादा समय लगा
  • यह दिखाता है कि network port से जुड़े chip के अंदर backdoor लगाना कितना आसान है

  • Communication Systems Engineering course में Ethernet signal processing implement किया था, और फिर ARP और switching सहित TCP/IP stack को Motorola 68k QUIC assembly में implement किया
    वह मेरी ज़िंदगी के सबसे लंबे 18 महीने थे