कॉनवे के गेम ऑफ लाइफ में टेट्रिस का एक कार्यशील गेम बनाएं


992

यहां एक सैद्धांतिक सवाल है - एक जो किसी भी मामले में एक आसान जवाब नहीं देता है, यहां तक ​​कि तुच्छ भी नहीं।

कॉनवे के गेम ऑफ लाइफ में, मेटीपील जैसे निर्माण मौजूद हैं जो गेम ऑफ लाइफ को किसी भी अन्य गेम-ऑफ-लाइफ नियम प्रणाली के साथ अनुकरण करने की अनुमति देते हैं। इसके अलावा, यह ज्ञात है कि गेम ऑफ लाइफ ट्यूरिंग-पूर्ण है।

आपका कार्य कॉनवे के जीवन के खेल के नियमों का उपयोग करके एक सेलुलर ऑटोमोबोन का निर्माण करना है जो कि टेट्रिस के खेल को खेलने की अनुमति देगा।

आपका कार्यक्रम मैन्युअल रूप से एक विशेष पीढ़ी पर ऑटोमेटन की स्थिति को बदलकर एक रुकावट का प्रतिनिधित्व करने के लिए इनपुट प्राप्त करेगा (उदाहरण के लिए एक टुकड़ा छोड़ दिया या सही चल रहा है, इसे छोड़ने, इसे घुमाने, या बेतरतीब ढंग से ग्रिड पर जगह बनाने के लिए एक नया टुकड़ा पैदा करना), गिनती प्रतीक्षा समय के रूप में पीढ़ियों की एक विशिष्ट संख्या, और ऑटोमेटन पर कहीं न कहीं परिणाम प्रदर्शित करना। प्रदर्शित परिणाम को एक वास्तविक टेट्रिस ग्रिड जैसा दिखना चाहिए।

आपका कार्यक्रम निम्न बातों पर, क्रम में (उच्च मानदंडों के लिए टाईब्रेकर के रूप में अभिनय के साथ) स्कोर किया जाएगा।

  • बाउंडिंग बॉक्स आकार - सबसे छोटे क्षेत्र के साथ आयताकार बॉक्स जिसमें पूरी तरह से दिए गए समाधान जीतते हैं।

  • इनपुट में छोटे परिवर्तन - सबसे छोटी कोशिकाएं (आपके ऑटोमेटन में सबसे खराब स्थिति के लिए) जिसे मैन्युअल रूप से एक बाधा जीत के लिए समायोजित करने की आवश्यकता होती है।

  • सबसे तेज़ निष्पादन - सिमुलेशन जीत में एक टिक को आगे बढ़ाने वाली सबसे कम पीढ़ियां।

  • प्रारंभिक लाइव सेल काउंट - छोटी काउंट जीत।

  • पहली पोस्ट करने के लिए - पहले पोस्ट जीतता है।


95
क्या "demonstrably वर्किंग उदाहरण" का मतलब कुछ ऐसा है जो घंटों के मामले में चलता है, या ऐसा कुछ जिसे सही साबित किया जा सकता है, भले ही इसे खेलने के लिए ब्रह्मांड की गर्मी से मौत हो जाए?
पीटर टेलर

34
मुझे पूरा यकीन है कि ऐसा कुछ संभव और संभव है। यह सिर्फ इतना है कि बहुत कम लोगों के पास दुनिया में अधिक गूढ़ "विधानसभा भाषाओं" में से एक है जो प्रोग्राम करने में सक्षम होने के लिए विशेषज्ञता है।
जस्टिन एल।

58
इस चुनौती पर काम किया जा रहा है! चैट रूम | प्रगति | ब्लॉग
mbomb007

49
आज सुबह 5:10 (9:10 UTC) के अनुसार, यह सवाल PPCG के इतिहास में पहला सवाल है, जिसका जवाब न मिलने पर 100 वोट तक पहुँच सकते हैं! सबने बहुत अच्छा किया।
जो जेड।

76
मैं इसे हल करने की कोशिश कर रहा हूं ... अब, जब मैं बिस्तर पर जाता हूं, तो मुझे हर जगह ग्लाइडर्स दिखाई देते हैं, एक विशाल गंदगी में टकराते हैं। मेरी नींद पूरी तरह से बुरे सपने से भरी हुई है जहाँ स्पंदन करने वाले पेंटाथेक्लोन्स मेरे रास्ते को अवरुद्ध कर देते हैं और हर्शल मुझे अवशोषित करने के लिए विकसित हो रहे हैं। कृपया, जॉन कॉनवे, मेरे लिए प्रार्थना करें ...
मंद

जवाबों:


937

यह एक खोज के रूप में शुरू हुआ लेकिन एक ओडिसी के रूप में समाप्त हुआ।

टेट्रिस प्रोसेसर की खोज, 2,940,928 x 10,295,296

पैटर्न फ़ाइल, इसकी सभी महिमा में, यहाँ देखा जा सकता है , यहाँ ब्राउज़र में देखा जा सकता है

यह परियोजना पिछले 1 और 1/2 वर्षों के दौरान कई उपयोगकर्ताओं के प्रयासों की परिणति है। हालांकि टीम की संरचना में समय के साथ विविधता है, लेखन के रूप में प्रतिभागी निम्नलिखित हैं:

हम अपने धन्यवाद को 7H3_H4CK3R, कॉनर ओ'ब्रायन और कई अन्य उपयोगकर्ताओं को भी देना चाहेंगे जिन्होंने इस चुनौती को हल करने में प्रयास किया है।

इस सहयोग के अभूतपूर्व दायरे के कारण, यह उत्तर इस टीम के सदस्यों द्वारा लिखे गए कई उत्तरों में विभाजित है। प्रत्येक सदस्य विशिष्ट उप-विषयों के बारे में लिखेगा, मोटे तौर पर परियोजना के क्षेत्रों के अनुरूप, जिसमें वे सबसे अधिक शामिल थे।

कृपया टीम के सभी सदस्यों में कोई भी अपवोट या बाउंटी वितरित करें।

विषय - सूची

  1. अवलोकन
  2. मेटापिल्स और वर्लिफ़
  3. हार्डवेयर
  4. QFTASM और Cogol
  5. सभा, अनुवाद और भविष्य
  6. नई भाषा और संकलक

इसके अलावा हमारे GitHub संगठन की जाँच करने पर विचार करें जहाँ हमने अपने समाधान के हिस्से के रूप में लिखे गए सभी कोड डाल दिए हैं। प्रश्नों को हमारे विकास कक्ष में निर्देशित किया जा सकता है ।


भाग 1: अवलोकन

इस परियोजना का अंतर्निहित विचार अमूर्त है । सीधे जीवन में एक टेट्रिस गेम विकसित करने के बजाय, हमने धीरे-धीरे कदमों की एक श्रृंखला में अमूर्तता की पुष्टि की। प्रत्येक परत पर, हम जीवन की कठिनाइयों से दूर हो जाते हैं और एक कंप्यूटर के निर्माण के करीब होते हैं जो किसी अन्य के रूप में प्रोग्राम करना उतना आसान है।

सबसे पहले, हमने अपने कंप्यूटर की नींव के रूप में ओटीसीए मेटीपेसेलस का उपयोग किया । ये मीट्रिक किसी भी "जीवन-समान" नियम का अनुकरण करने में सक्षम हैं। वायरवर्ल्ड और वायरवर्ल्ड कंप्यूटर इस परियोजना के लिए प्रेरणा के महत्वपूर्ण स्रोत के रूप में कार्य करते हैं, इसलिए हमने मेटीपेसेल के साथ एक समान कब्ज बनाने की मांग की। हालांकि ओटीसीए मेटीपेसेल के साथ वायरवर्ल्ड का अनुकरण करना संभव नहीं है, लेकिन अलग-अलग मेटीपेसेलस को अलग-अलग नियमों को सौंपना और तारों के समान कार्य करने वाले मेटापिल व्यवस्था का निर्माण करना संभव है।

अगला कदम कंप्यूटर के आधार के रूप में सेवा करने के लिए विभिन्न प्रकार के मौलिक लॉजिक गेट्स का निर्माण करना था। पहले से ही इस स्तर पर हम वास्तविक दुनिया प्रोसेसर डिजाइन के समान अवधारणाओं के साथ काम कर रहे हैं। यहां OR गेट का एक उदाहरण दिया गया है, इस छवि का प्रत्येक कक्ष वास्तव में एक संपूर्ण OTCA मेटापिल है। आप "इलेक्ट्रॉनों" (प्रत्येक एकल डेटा का प्रतिनिधित्व करने वाले) को देख सकते हैं और गेट को छोड़ सकते हैं। आप हमारे कंप्यूटर में उपयोग किए जाने वाले सभी अलग-अलग मीट्रिक प्रकारों को भी देख सकते हैं: B / S काली पृष्ठभूमि के रूप में, नीले रंग में B1 / S, हरे रंग में B2 / S, और B12 / S1 लाल रंग में।

छवि

यहां से हमने अपने प्रोसेसर के लिए एक आर्किटेक्चर विकसित किया। हमने एक वास्तुकला को डिजाइन करने में महत्वपूर्ण प्रयास किया जो गैर-गूढ़ और यथासंभव आसानी से लागू करने योग्य था। जबकि वायरवर्ल्ड कंप्यूटर ने एक अल्पविकसित परिवहन-ट्रिगर आर्किटेक्चर का उपयोग किया था, यह प्रोजेक्ट कई अधिक लचीले RISC आर्किटेक्चर का उपयोग कई ऑपकोड और एड्रेसिंग मोड के साथ करता है। हमने एक असेंबली भाषा बनाई, जिसे QFTASM (टेट्रिस असेंबली असेंबली) के रूप में जाना जाता है, जिसने हमारे प्रोसेसर के निर्माण को निर्देशित किया।

हमारा कंप्यूटर भी अतुल्यकालिक है, जिसका अर्थ है कि कंप्यूटर को नियंत्रित करने वाली कोई वैश्विक घड़ी नहीं है। बल्कि, डेटा एक घड़ी संकेत के साथ होता है क्योंकि यह कंप्यूटर के चारों ओर बहता है, जिसका अर्थ है कि हमें केवल कंप्यूटर के स्थानीय लेकिन वैश्विक समय पर ध्यान केंद्रित करने की आवश्यकता है।

यहाँ हमारे प्रोसेसर वास्तुकला का एक चित्रण है:

छवि

यहाँ से यह कंप्यूटर पर टेट्रिस को लागू करने की बात है। इसे पूरा करने में मदद करने के लिए, हमने QFTASM में उच्च-स्तरीय भाषा को संकलित करने के कई तरीकों पर काम किया है। हमारे पास एक मूल भाषा है जिसे Cogol कहा जाता है, एक दूसरी, विकास के तहत अधिक उन्नत भाषा, और अंत में हमारे पास एक निर्माणाधीन जीसीसी बैकेंड है। वर्तमान टेट्रिस कार्यक्रम Cogol से / संकलित लिखा गया था।

एक बार जब अंतिम टेट्रिस QFTASM कोड जेनरेट हो जाता था, तो अंतिम चरण इसी कोड से संबंधित ROM में इकट्ठे होते थे, और फिर मेटाप्लाइल्स से लेकर अंतर्निहित गेम ऑफ लाइफ तक हमारे निर्माण को पूरा करते थे।

टेट्रिस चल रहा है

उन लोगों के लिए जो कंप्यूटर के साथ खिलवाड़ किए बिना टेट्रिस खेलना चाहते हैं, आप QFTASM दुभाषिया पर टेट्रिस स्रोत कोड चला सकते हैं । पूरे गेम को देखने के लिए रैम डिस्प्ले एड्रेस को 3-32 पर सेट करें। यहाँ सुविधा के लिए एक पर्मलिंक है : QFTASM में टेट्रिस

खेल की विशेषताएं:

  • सभी 7 tetrominoes
  • आंदोलन, रोटेशन, नरम बूँदें
  • लाइन क्लीयर और स्कोरिंग
  • पूर्वावलोकन टुकड़ा
  • प्लेयर इनपुट यादृच्छिकता इंजेक्षन

प्रदर्शन

हमारा कंप्यूटर अपनी मेमोरी के भीतर टेट्रिस बोर्ड को ग्रिड के रूप में दर्शाता है। पते 10-31 बोर्ड को प्रदर्शित करते हैं, पते का 5-8 पूर्वावलोकन टुकड़ा प्रदर्शित करते हैं, और पते 3 में स्कोर होता है।

इनपुट

गेम के लिए इनपुट रैम एड्रेस की सामग्री को मैन्युअल रूप से संपादित करके किया जाता है। QFTASM दुभाषिया का उपयोग करके, इसका मतलब है कि डायरेक्ट राइट टू एड्रेस 1। इंटरप्रेटर के पेज पर "डायरेक्ट राइट टू रैम" देखें। प्रत्येक चाल में केवल एक बिट रैम का संपादन करने की आवश्यकता होती है, और इनपुट घटना को पढ़ने के बाद यह इनपुट रजिस्टर अपने आप साफ़ हो जाता है।

value     motion
   1      counterclockwise rotation
   2      left
   4      down (soft drop)
   8      right
  16      clockwise rotation

स्कोरिंग प्रणाली

आपको एक ही बारी में कई लाइनों को साफ़ करने के लिए एक बोनस मिलता है।

1 row    =  1 point
2 rows   =  2 points
3 rows   =  4 points
4 rows   =  8 points

14
@ Christopher2EZ4RTZ इस अवलोकन पोस्ट में परियोजना के कई सदस्यों द्वारा किए गए कार्यों का विवरण है (अवलोकन का वास्तविक लेखन सहित)। जैसे, इसके लिए सीडब्ल्यू होना उचित है। हम दो पदों वाले एक व्यक्ति से बचने की कोशिश भी कर रहे थे, क्योंकि इससे उन्हें अनुचित मात्रा में प्रतिनिधि मिलेंगे, क्योंकि हम प्रतिनिधि को भी रखने की कोशिश कर रहे हैं।
Mego

28
सबसे पहले +1, क्योंकि यह एक बहुत ही भयानक उपलब्धि है (विशेषकर जब से आपने जीवन के खेल में कंप्यूटर का निर्माण किया है, बजाय सिर्फ तांत्रिकों के)। दूसरे, कंप्यूटर कितना तेज है और टेट्रिस गेम कितना तेज है? यह भी दूर से खेलने योग्य है? (फिर: यह कमाल है)
सोक्रेटिक फ़ीनिक्स

18
यह ... यह पूरी तरह से पागल है। +1 से सभी जवाब तुरंत।
स्कूटनीट

28
किसी को भी जवाब देने के लिए छोटे इनाम बांटने की इच्छा रखने वालों के लिए एक चेतावनी: आपको हर बार अपनी बाउंटी राशि को दोगुना करना होगा (जब तक कि आप 500 हिट न करें), इसलिए कोई भी व्यक्ति प्रत्येक जवाब के लिए एक ही राशि नहीं दे सकता है जब तक कि वह राशि 500 ​​प्रतिनिधि न हो।
मार्टिन एंडर

23
यह सबसे बड़ी चीज है जिसे मैंने बहुत कम समझ के दौरान कभी स्क्रॉल किया है।
इंजीनियर टोस्ट

678

भाग 2: ओटीसीए मेटापिल और वर्लिफ़

ओटीसीए मेटपेल

OTCA मैट्रिकॉपेल
( स्रोत )

OTCA Metapixel जीवन के कोनवे के खेल में एक निर्माण किसी भी जीवन की तरह सेलुलर ऑटोमेटा अनुकरण करने के लिए इस्तेमाल किया जा सकता है। जैसा कि LifeWiki (उपरोक्त लिंक) कहता है,

ओटीसीए मेटापिल एक 2048 × 2048 अवधि 35328 यूनिट सेल है जिसका निर्माण ब्राइस ड्यू द्वारा किया गया था ... इसके कई फायदे हैं ... जिसमें किसी भी लाइफ-लाइक सेल्युलर ऑटोमेटन का अनुकरण करने की क्षमता और तथ्य यह है कि, ज़ूम आउट होने पर, और बंद कोशिकाओं को भेद करना आसान है ...

यहां जीवन की तरह सेलुलर ऑटोमेटा का अर्थ है कि अनिवार्य रूप से कोशिकाएं पैदा होती हैं और कोशिकाएं अपने आठ पड़ोसी कोशिकाओं में से कितने जीवित हैं, उसके अनुसार जीवित रहती हैं। इन नियमों के लिए सिंटैक्स निम्नानुसार है: एक बी उसके बाद जीवित पड़ोसियों की संख्या जो जन्म का कारण बनेगा, फिर एक स्लैश, फिर एक एस लाइव पड़ोसियों की संख्या के बाद जो सेल को जीवित रखेगा। थोड़ी सी चिंता, इसलिए मुझे लगता है कि एक उदाहरण से मदद मिलेगी। कैनोनिकल गेम ऑफ लाइफ को नियम बी 3 / एस 23 द्वारा दर्शाया जा सकता है, जो कहता है कि तीन जीवित पड़ोसियों के साथ कोई भी मृत कोशिका जीवित हो जाएगी और दो या तीन जीवित पड़ोसियों के साथ कोई भी जीवित सेल जीवित रहेगा। अन्यथा, कोशिका मर जाती है।

२०४ being x २०४ x सेल होने के बावजूद, ओटीसीए मेटापिल वास्तव में २०५ x x २०५ reason सेल का एक बाउंडिंग बॉक्स है, इसका कारण यह है कि यह अपने विकर्ण पड़ोसियों के साथ हर दिशा में पांच कोशिकाओं द्वारा ओवरलैप करता है । ओवरलैपिंग सेल ग्लाइडर को रोकने के लिए काम करते हैं - जो कि मेटाकास्ट पड़ोसियों को संकेत देने के लिए उत्सर्जित होते हैं कि यह चालू है - ताकि वे अन्य मेटीपेसेल के साथ हस्तक्षेप न करें या अनिश्चित काल के लिए उड़ान भरें। जन्म और उत्तरजीविता नियमों को दो कॉलम (जन्म के लिए एक, जीवित रहने के लिए एक) के साथ विशिष्ट स्थितियों में खाने वालों की मौजूदगी या अनुपस्थिति द्वारा, मेटापिक्सेल के बाईं ओर कोशिकाओं के एक विशेष खंड में एन्कोड किया गया है। पड़ोसी कोशिकाओं की स्थिति का पता लगाने के लिए, यहां बताया गया है कि यह कैसे होता है:

एक 9-LWSS स्ट्रीम तब कोशिका के चारों ओर दक्षिणावर्त जाती है, जिससे प्रत्येक कोशिका के लिए एक LWSS खो जाता है, जो 'कोशिका' पर एक हनीबिट प्रतिक्रिया उत्पन्न करता है। लापता LWSSes की संख्या विपरीत दिशा से इसमें एक और LWSS दुर्घटनाग्रस्त करके सामने LWSS की स्थिति का पता लगाकर गिना जाता है। यह टकराव ग्लाइडर्स को छोड़ता है, जो एक या दो हनीबिट प्रतिक्रियाओं को ट्रिगर करता है यदि खाने वाले जो संकेत देते हैं कि जन्म / अस्तित्व की स्थिति अनुपस्थित है।

ओटीसीए मेटापिल के प्रत्येक पहलू का अधिक विस्तृत आरेख इसकी मूल वेबसाइट पर पाया जा सकता है: यह कैसे काम करता है?

VarLife

मैंने जीवन-संबंधी नियमों का एक ऑनलाइन सिम्युलेटर बनाया, जहां आप किसी भी जीवन-नियम के अनुसार कोई भी व्यवहार कर सकते थे और इसे "जीवन की विविधताएं" कहा। इस नाम को संक्षिप्त करने के लिए "वरलाइफ" को छोटा कर दिया गया है। इसका स्क्रीनशॉट यहां दिया गया है (इसे यहां लिंक करें: http://play.starmaninnovations.com/varlife/BeeHkfCpNR ):

VarLife स्क्रीनशॉट

उल्लेखनीय विशेषताएं:

  • जीवित / मृत के बीच कोशिकाओं को टॉगल करें और बोर्ड को विभिन्न नियमों के साथ पेंट करें।
  • सिमुलेशन शुरू करने और रोकने की क्षमता, और एक समय में एक कदम करने की क्षमता। टिक-प्रति-सेकंड और मिलीसेकंड-प्रति-टिक बॉक्स में निर्धारित दर पर दिए गए चरणों की संख्या को जितनी जल्दी हो सके या अधिक धीरे-धीरे करना संभव है।
  • सभी जीवित कोशिकाओं को साफ़ करें या बोर्ड को रिक्त स्थिति में पूरी तरह से रीसेट करें।
  • सेल और बोर्ड के आकार को बदल सकते हैं, और क्षैतिज और / या लंबवत रूप से टॉराइडल रैपिंग को सक्षम करने के लिए भी।
  • Permalinks (जो url में सभी जानकारी को एनकोड करता है) और शॉर्ट urls (क्योंकि कभी-कभी बहुत अधिक जानकारी होती है, लेकिन फिर भी वे अच्छे हैं)।
  • नियम सेट, बी / एस विनिर्देश, रंग और वैकल्पिक यादृच्छिकता के साथ।
  • और पिछले लेकिन निश्चित रूप से कम से कम नहीं, gifs प्रतिपादन!

रेंडर-टू-जिफ फीचर मेरा पसंदीदा है क्योंकि इसे लागू करने में एक टन का समय लगा था, इसलिए जब मैं आखिरकार सुबह 7 बजे इसे फटा, तो यह वास्तव में संतोषजनक था, और क्योंकि यह दूसरों के साथ VarLife के निर्माण को साझा करना बहुत आसान बनाता है ।

बेसिक वर्लिफ़ सर्किटरी

सभी में, VarLife कंप्यूटर को केवल चार सेल प्रकारों की आवश्यकता होती है! सभी मृत / जीवित राज्यों की गिनती में आठ राज्य। वो हैं:

  • बी / एस (काला / सफेद), जो बी / एस कोशिकाओं के बाद से सभी घटकों के बीच एक बफर के रूप में कार्य करता है, कभी भी जीवित नहीं हो सकता है।
  • B1 / S (नीला / सियान), जो मुख्य कोशिका प्रकार है जिसका उपयोग संकेतों को फैलाने के लिए किया जाता है।
  • बी 2 / एस (हरा / पीला), जो मुख्य रूप से सिग्नल नियंत्रण के लिए उपयोग किया जाता है, यह सुनिश्चित करता है कि यह बैकप्रोपेगेट नहीं है।
  • B12 / S1 (लाल / नारंगी), जिसका उपयोग कुछ विशेष स्थितियों में किया जाता है, जैसे कि संकेतों को पार करना और थोड़ा डेटा संग्रहीत करना।

इन नियमों के साथ VarLife को खोलने के लिए इस छोटे url का उपयोग पहले से ही इनकोडेड करें: http://play.starmaninnovations.com/varlife/BeeHkfCpNR

तारों

बदलती विशेषताओं के साथ कुछ अलग तार डिजाइन हैं।

यह VarLife में सबसे आसान और सबसे बुनियादी तार है, नीले रंग की एक पट्टी जो हरे रंग की पट्टियों से घिरा है।

मूल तार
लघु यूआरएल: http://play.starmaninnovations.com/varlife/WcsGmjLiBF

यह तार यूनिडायरेक्शनल है। यही है, यह विपरीत दिशा में यात्रा करने के लिए किसी भी संकेत को मार देगा। यह मूल तार की तुलना में एक कोशिका संकरी है।

यूनिडायरेक्शनल तार
लघु url: http://play.starmaninnovations.com/varlife/ARWgUgPTEJ

विकर्ण तार भी मौजूद हैं, लेकिन वे बहुत अधिक उपयोग नहीं किए जाते हैं।

विकर्ण तार
संक्षिप्त यूआरएल: http://play.starmaninnovations.com/varlife/kJotsdSXIj

गेट्स

वास्तव में प्रत्येक व्यक्तिगत गेट के निर्माण के कई तरीके हैं, इसलिए मैं केवल प्रत्येक प्रकार का एक उदाहरण दिखाऊंगा। यह पहला gif क्रमशः, और, XOR और OR गेट प्रदर्शित करता है। यहां मूल विचार यह है कि एक हरे रंग की कोशिका एक और की तरह काम करती है, एक नीले रंग की कोशिका एक XOR की तरह काम करती है, और एक लाल कोशिका एक OR की तरह काम करती है, और उनके आस-पास की अन्य सभी कोशिकाएं केवल प्रवाह को ठीक से नियंत्रित करने के लिए होती हैं।

और, XOR, या तर्क द्वार
लघु यूआरएल: http://play.starmaninnovations.com/varlife/EGTlKktmeI

AND-NOT गेट, जिसे "ANT गेट" के रूप में संक्षिप्त किया गया था, एक महत्वपूर्ण घटक बन गया। यह एक गेट है जो A से एक सिग्नल पास करता है और यदि केवल B. से सिग्नल नहीं है, तो "A और NOT B"।

और नहीं गेट
लघु url: http://play.starmaninnovations.com/varlife/RsZBiNqIUy

एक गेट नहीं है , जबकि एक तार पार टाइल अभी भी बहुत महत्वपूर्ण और उपयोगी है।

तार पार करना
लघु यूआरएल: http://play.starmaninnovations.com/varlife/OXMsPyaNTC

संयोग से, यहाँ कोई गेट नहीं है। ऐसा इसलिए है क्योंकि इनकमिंग सिग्नल के बिना, एक निरंतर आउटपुट का उत्पादन किया जाना चाहिए, जो कि उस समय की विविधता के साथ अच्छी तरह से काम नहीं करता है जो वर्तमान कंप्यूटर हार्डवेयर की आवश्यकता है। हम वैसे भी इसके बिना ही ठीक हो गए।

इसके अलावा, कई घटकों को जानबूझकर 11 से 11 बाउंडिंग बॉक्स (एक टाइल ) के भीतर फिट करने के लिए डिज़ाइन किया गया था, जहां यह टाइल छोड़ने के लिए टाइल में प्रवेश करने से सिग्नल 11 टिक लेता है। यह या तो रिक्ति या समय के लिए तारों को समायोजित करने की चिंता किए बिना घटकों को अधिक मॉड्यूलर और एक साथ थप्पड़ करने के लिए आसान बनाता है।

सर्किट गेटों की खोज की प्रक्रिया में खोजे गए / निर्मित अधिक फाटकों को देखने के लिए, PhiNotPi: बिल्डिंग ब्लॉक्स: लॉजिक गेट्स द्वारा इस ब्लॉग पोस्ट की जाँच करें ।

देरी घटक

कंप्यूटर के हार्डवेयर को डिजाइन करने की प्रक्रिया में, KZhang ने कई देरी घटकों को तैयार किया, जो नीचे दिखाया गया है।

4-टिक देरी: लघु यूआरएल: http://play.starmaninnovations.com/varlife/gebOMIXxdh
4 टिक की देरी

5-टिक की देरी: लघु यूआरएल: http://play.starmaninnovations.com/varlife/JItNjJvnUB
5 टिक की देरी

8-टिक की देरी (तीन अलग-अलग प्रवेश बिंदु): लघु यूआरएल: http://play.starmaninnovations.com/varlife/nSTRaVEDvA
8 टिक की देरी

11-टिक की देरी: लघु यूआरएल: http://play.starmaninnovations.com/varlife/kfoADussXA
11 टिक में देरी

12-टिक देरी: लघु url: http://play.starmaninnovations.com/varlife/bkamAfUfud
12 टिक में देरी

14-टिक की देरी: लघु url: http://play.starmaninnovations.com/varlife/TkwzYIBWln
14 टिक विलम्ब

15-टिक देरी (साथ तुलना द्वारा सत्यापित यह ): लघु यूआरएल: http://play.starmaninnovations.com/varlife/jmgpehYlpT
15 टिक विलम्ब

खैर, यह VarLife में बुनियादी सर्किटरी घटकों के लिए है! कंप्यूटर के प्रमुख सर्किटरी के लिए KZhang के हार्डवेयर पोस्ट देखें !


4
वरलाइफ इस परियोजना के सबसे प्रभावशाली हिस्सों में से एक है; इसकी तुलना में बहुमुखी प्रतिभा और सरलता है, उदाहरण के लिए, वायरवर्ल्ड फिनोमिनल है। ओटीसीए मेटपेलसेल की तुलना में यह बहुत बड़ा प्रतीत होता है, हालांकि क्या इसे नीचे करने की कोई कोशिश की गई है?
प्रिमो

@primo: डेव ग्रीन उस पर काम कर रहा है, ऐसा लगता है। chat.stackexchange.com/transcript/message/40106098#40106098
एल'एंडिया स्ट्रैटन

6
हाँ, इस सप्ताहांत में 512x512 हैशलाइफ-फ्रेंडली मेटासेल ( conwaylife.com/forums/viewtopic.php?f=&p=51287#p51287 ) के दिल में इस सप्ताह के अंत में प्रगति हुई । मेटासेल को कुछ हद तक छोटा किया जा सकता है, यह इस बात पर निर्भर करता है कि "पिक्सेल" क्षेत्र सेल की स्थिति को संकेतित करना चाहता है, जब आप जूम आउट कर चुके होते हैं। यह निश्चित रूप से एक सटीक 2 ^ N- आकार की टाइल पर रुकने लायक लगता है, हालांकि, क्योंकि Golly का HashLife एल्गोरिथ्म कंप्यूटर को बहुत तेज़ी से चलाने में सक्षम होगा।
डेव ग्रीन

2
क्या तारों और फाटकों को कम "बेकार" तरीके से लागू नहीं किया जा सकता है? एक इलेक्ट्रॉन को एक ग्लाइडर या एक स्पेसशिप (दिशा के आधार पर) द्वारा दर्शाया जाएगा। मैंने ऐसी व्यवस्था देखी है जो उन्हें पुनर्निर्देशित करती है (और यदि आवश्यक हो तो एक से दूसरे में बदल जाती है) और ग्लाइडर्स के साथ काम करने वाले कुछ द्वार। हां, वे अधिक स्थान लेते हैं, डिजाइन अधिक जटिल है और समय को सटीक होना चाहिए। लेकिन एक बार जब आपके पास उन बुनियादी बिल्डिंग ब्लॉक होते हैं, तो उन्हें एक साथ रखना काफी आसान होना चाहिए और वे OTCA द्वारा कार्यान्वित VarLife की तुलना में बहुत कम जगह लेंगे। यह तेजी से भी चलेगा।
हेमदॉल

@ हेइमडल हालांकि यह अच्छा काम करेगा, लेकिन यह टेट्रिस खेलते समय अच्छा नहीं दिखेगा।
मिल्कीवेय

649

भाग 3: हार्डवेयर

तर्क गेट्स के हमारे ज्ञान और प्रोसेसर की सामान्य संरचना के साथ, हम कंप्यूटर के सभी घटकों को डिज़ाइन करना शुरू कर सकते हैं।

demultiplexer

एक demultiplexer, या demux, ROM, RAM और ALU का एक महत्वपूर्ण घटक है। यह कुछ दिए गए चयनकर्ता डेटा के आधार पर कई आउटपुट संकेतों में से एक को इनपुट सिग्नल को रूट करता है। यह 3 मुख्य भागों से बना है: समानांतर कनवर्टर के लिए एक धारावाहिक, एक सिग्नल चेकर और एक घड़ी संकेत फाड़नेवाला।

हम सीरियल चयनकर्ता डेटा को "समानांतर" में परिवर्तित करके शुरू करते हैं। यह रणनीतिक रूप से विभाजित करने और डेटा में देरी करने के द्वारा किया जाता है ताकि सबसे बाईं ओर का डेटा घड़ी सिग्नल को सबसे निचले 11x11 वर्ग पर, अगले बिट डेटा को अगले 11x11 वर्ग पर घड़ी सिग्नल को काटता है, और इसी तरह। हालाँकि हर 11x11 वर्ग में हर बिट डेटा को आउटपुट किया जाएगा, लेकिन हर बिट डेटा केवल एक बार क्लॉक सिग्नल के साथ इंटरसेक्ट होगा।

समानांतर कनवर्टर के लिए सीरियल

अगला, हम यह देखने के लिए जांच करेंगे कि समानांतर डेटा प्रीसेट पते से मेल खाता है या नहीं। हम घड़ी और समानांतर डेटा पर AND और ANT फाटकों का उपयोग करके ऐसा करते हैं। हालांकि, हमें यह सुनिश्चित करने की आवश्यकता है कि समानांतर डेटा भी आउटपुट किया जाता है ताकि इसकी फिर से तुलना की जा सके। ये वे द्वार हैं जिनके साथ मैं आया था:

सिग्नल चेकिंग गेट्स

अंत में, हम केवल घड़ी सिग्नल को विभाजित करते हैं, सिग्नल चेकर्स (प्रत्येक पते / आउटपुट के लिए एक) को ढेर करते हैं और हमारे पास एक मल्टीप्लेक्सर होता है!

बहुसंकेतक

रोम

ROM को इनपुट के रूप में एक एड्रेस लेना चाहिए और आउटपुट के रूप में उस पते पर निर्देश भेजना चाहिए। हम निर्देशों में से एक को घड़ी संकेत को निर्देशित करने के लिए एक मल्टीप्लेक्सर का उपयोग करके शुरू करते हैं। इसके बाद, हमें कुछ वायर क्रॉसिंग और OR गेट्स का उपयोग करके एक सिग्नल उत्पन्न करना होगा। वायर क्रॉसिंग निर्देश के सभी 58 बिट्स की यात्रा करने के लिए क्लॉक सिग्नल को सक्षम करता है, और उत्पन्न जेनरेट सिग्नल (वर्तमान में समानांतर में) को आउटपुट होने के लिए रॉम के माध्यम से नीचे जाने की अनुमति देता है।

रॉम बिट्स

अगला हमें बस सीरियल डेटा के समानांतर सिग्नल को बदलने की जरूरत है, और रोम पूरा हो गया है।

सीरियल कन्वर्टर के समानांतर

रोम

रोम वर्तमान में Golly में एक स्क्रिप्ट चलाकर उत्पन्न होता है जो आपके क्लिपबोर्ड से असेंबली कोड को ROM में अनुवाद करेगा।

एसआरएल, एसएल, एसआरए

इन तीन लॉजिक गेट्स का उपयोग बिट शिफ्ट्स के लिए किया जाता है, और ये आपके विशिष्ट AND, OR, XOR, आदि की तुलना में अधिक जटिल होते हैं। इन गेट्स को काम करने के लिए, हम सबसे पहले घड़ी के सिग्नल को एक उपयुक्त समय में "शिफ्ट" का कारण बनने में देरी करेंगे। डेटा में। इन द्वारों को दिया गया दूसरा तर्क यह बताता है कि कितने बिट्स को शिफ्ट करना है।

SL और SRL के लिए, हमें करने की आवश्यकता है

  1. सुनिश्चित करें कि 12 सबसे महत्वपूर्ण बिट्स चालू नहीं हैं (अन्यथा आउटपुट केवल 0 है), और
  2. 4 कम से कम महत्वपूर्ण बिट्स के आधार पर डेटा को सही मात्रा में देरी।

यह AND / ANT फाटकों और एक मल्टीप्लेक्स के एक समूह के साथ उल्लेखनीय है।

SRL

एसआरए थोड़ा अलग है, क्योंकि हमें शिफ्ट के दौरान साइन बिट को कॉपी करने की आवश्यकता है। हम साइन बिट के साथ घड़ी संकेत को एंड्रॉइड द्वारा करते हैं, और फिर उस आउटपुट को वायर स्प्लिटर्स और या गेट्स के साथ कई बार कॉपी करते हैं।

एसआरए

सेट-रीसेट (SR) कुंडी

प्रोसेसर की कार्यक्षमता के कई हिस्से डेटा स्टोर करने की क्षमता पर भरोसा करते हैं। 2 लाल बी 12 / एस 1 कोशिकाओं का उपयोग करना, हम बस यही कर सकते हैं। दोनों कोशिकाएं एक-दूसरे को रख सकती हैं, और एक साथ बंद भी रह सकती हैं। कुछ अतिरिक्त सेट, रीसेट और पढ़े गए सर्किटरी का उपयोग करके, हम एक साधारण एसआर कुंडी बना सकते हैं।

एसआर कुंडी

समकालीन बनानेवाला

सीरियल डेटा को समानांतर डेटा में परिवर्तित करके, फिर एसआर लेचेस का एक समूह सेट करके, हम डेटा के एक पूरे शब्द को स्टोर कर सकते हैं। फिर, डेटा को फिर से प्राप्त करने के लिए, हम सभी लैच को बस पढ़ और रीसेट कर सकते हैं, और तदनुसार डेटा को देरी कर सकते हैं। यह हमें दूसरे के लिए प्रतीक्षा करते समय डेटा के एक (या अधिक) शब्द को संग्रहीत करने में सक्षम बनाता है, जिससे डेटा के दो शब्दों को अलग-अलग समय पर आने की अनुमति मिलती है।

समकालीन बनानेवाला

काउंटर पढ़ें

यह डिवाइस इस बात पर नज़र रखता है कि रैम से इसे कितनी बार पता करने की आवश्यकता है। यह एसआर कुंडी के समान डिवाइस का उपयोग करके ऐसा करता है: एक टी फ्लिप फ्लॉप। हर बार जब टी फ्लिप फ्लॉप एक इनपुट प्राप्त करता है, तो यह स्थिति बदलता है: यदि यह चालू था, तो यह बंद हो जाता है, और इसके विपरीत। जब T फ्लिप फ्लॉप को चालू से बंद किया जाता है, तो यह आउटपुट पल्स भेजता है, जिसे 2 बिट काउंटर बनाने के लिए दूसरे T फ्लिप फ्लॉप में फीड किया जा सकता है।

दो बिट काउंटर

रीड काउंटर बनाने के लिए, हमें काउंटर को दो एएनटी गेट्स के साथ उपयुक्त एड्रेसिंग मोड पर सेट करने की आवश्यकता है, और काउंटर के आउटपुट सिग्नल का उपयोग यह तय करने के लिए करें कि घड़ी सिग्नल को कहां निर्देशित करें: ALU या RAM को।

काउंटर पढ़ें

क्यू पढ़ें

रीड कतार को ट्रैक रखने की आवश्यकता है कि किस काउंटर ने रैम को इनपुट भेजा है, ताकि यह रैम के आउटपुट को सही स्थान पर भेज सके। ऐसा करने के लिए, हम कुछ एसआर कुंडी का उपयोग करते हैं: प्रत्येक इनपुट के लिए एक कुंडी। जब एक रीड काउंटर से रैम को सिग्नल भेजा जाता है, तो क्लॉक सिग्नल विभाजित होता है और काउंटर के एसआर लैच को सेट करता है। RAM का आउटपुट तब SR कुंडी के साथ Anded है, और RAM से घड़ी संकेत SR कुंडी को रीसेट करता है।

क्यू पढ़ें

ALU

ALU रीड क्यू के समान कार्य करता है, जिसमें यह संकेत भेजने के लिए एसआर कुंडी का उपयोग करता है जहां पर नज़र रखने के लिए। सबसे पहले, निर्देश के opcode के अनुरूप तर्क सर्किट के SR कुंडी को एक मल्टीप्लेक्सर का उपयोग करके सेट किया जाता है। अगला, पहले और दूसरे तर्क के मान एसआर कुंडी के साथ एंडेड हैं, और फिर तर्क सर्किट में पारित किए जाते हैं। क्लॉक सिग्नल कुंडी को रीसेट करता है क्योंकि यह गुजर रहा है ताकि ALU को फिर से इस्तेमाल किया जा सके। (ज्यादातर सर्किटरी नीचे से गिली है, और एक टन विलंब प्रबंधन में बहाया गया है, इसलिए यह थोड़ा गड़बड़ लगता है)

ALU

राम

रैम इस परियोजना का सबसे जटिल हिस्सा था। यह डेटा संग्रहीत प्रत्येक SR कुंडी पर बहुत विशिष्ट नियंत्रण के लिए आवश्यक है। पढ़ने के लिए, पता एक मल्टीप्लेक्स में भेजा जाता है और रैम इकाइयों को भेजा जाता है। RAM इकाइयाँ उन डेटा को आउटपुट करती हैं जो वे समानांतर में स्टोर करते हैं, जिसे धारावाहिक और आउटपुट में परिवर्तित किया जाता है। लेखन के लिए, पता एक अलग मल्टीप्लेक्सर में भेजा जाता है, जो लिखा जाना है वह धारावाहिक से समानांतर में परिवर्तित हो जाता है, और रैम इकाइयां पूरे रैम में सिग्नल का प्रचार करती हैं।

प्रत्येक 22x22 मेटापिक्सेल रैम यूनिट में यह मूल संरचना होती है:

रैम यूनिट

पूरी रैम को एक साथ रखने पर, हमें कुछ ऐसा मिलता है जो इस तरह दिखता है:

राम

सब कुछ एक साथ करना

इन सभी घटकों और अवलोकन में वर्णित सामान्य कंप्यूटर वास्तुकला का उपयोग करके , हम एक काम कर रहे कंप्यूटर का निर्माण कर सकते हैं!

डाउनलोड: - समाप्त टेट्रिस कंप्यूटर - रोम निर्माण स्क्रिप्ट, खाली कंप्यूटर और प्राइम फाइंडिंग कंप्यूटर

कंप्यूटर


49
मैं यह कहना चाहूंगा कि इस पोस्ट में जो भी चित्र हैं, जो भी कारण हैं, मेरी राय में बहुत सुंदर हैं। : पी +1
हाइपरनेत्रिनो

7
यह सबसे आश्चर्यजनक बात मैंने कभी देखा है है .... मैं +20 होगा अगर मैं कर सकता
FantaC

3
@tfbninja आप कर सकते हैं, कि एक इनाम कहा जाता है और आप 200 प्रतिष्ठा दे सकते हैं।
फाबियान रोलिंग

10
क्या यह प्रोसेसर स्पेक्टर और मेल्टडाउन हमले के लिए असुरक्षित है? :)
फेरीबिग

5
@Ferrybig कोई शाखा भविष्यवाणी नहीं है, इसलिए मुझे संदेह है।
JAD

621

भाग 4: QFTASM और Cogol

वास्तुकला अवलोकन

संक्षेप में, हमारे कंप्यूटर में 16-बिट एसिंक्रोनस RISC हार्वर्ड आर्किटेक्चर है। हाथ से प्रोसेसर का निर्माण करते समय, RISC ( कम इंस्ट्रक्शन सेट कंप्यूटर ) आर्किटेक्चर व्यावहारिक रूप से एक आवश्यकता है। हमारे मामले में, इसका मतलब है कि ऑपकोड की संख्या छोटी है और, इससे भी महत्वपूर्ण बात यह है कि सभी निर्देशों को एक समान तरीके से संसाधित किया जाता है।

संदर्भ के लिए, वायरवर्ल्ड कंप्यूटर ने एक परिवहन-ट्रिगर वास्तुकला का उपयोग किया , जिसमें केवल निर्देश थे MOVऔर विशेष रजिस्टरों को लिखने / पढ़ने के द्वारा गणना की गई थी। यद्यपि यह प्रतिमान एक बहुत ही आसानी से लागू होने वाली वास्तुकला की ओर ले जाता है, परिणाम भी सीमा-रहित है: सभी अंकगणितीय / तर्क / सशर्त संचालन के लिए तीन निर्देशों की आवश्यकता होती है । यह हमारे लिए स्पष्ट था कि हम बहुत कम गूढ़ वास्तुकला बनाना चाहते थे।

प्रयोज्यता को बढ़ाते हुए हमारे प्रोसेसर को सरल रखने के लिए, हमने कई महत्वपूर्ण डिजाइन निर्णय लिए:

  • कोई रजिस्टर नहीं। रैम में हर पते को समान रूप से व्यवहार किया जाता है और किसी भी ऑपरेशन के लिए किसी भी तर्क के रूप में इस्तेमाल किया जा सकता है। एक मायने में, इसका मतलब है कि सभी रैम को रजिस्टरों की तरह माना जा सकता है। इसका मतलब है कि कोई विशेष लोड / स्टोर निर्देश नहीं हैं।
  • एक समान नस में, मेमोरी-मैपिंग। सब कुछ जो एक एकीकृत पते योजना के शेयरों से लिखा या पढ़ा जा सकता है। इसका मतलब यह है कि प्रोग्राम काउंटर (पीसी) पता 0 है, और नियमित निर्देशों और नियंत्रण-प्रवाह निर्देशों के बीच एकमात्र अंतर यह है कि नियंत्रण-प्रवाह निर्देश पते 0 का उपयोग करते हैं।
  • डेटा ट्रांसमिशन में सीरियल है, स्टोरेज में समानांतर है। हमारे कंप्यूटर के "इलेक्ट्रॉन"-आधारित प्रकृति के कारण, इसके अलावा और घटाव को लागू करने में काफी आसान होता है जब डेटा सीरियल लिटिल-एंडियन (कम से कम महत्वपूर्ण पहले) रूप में प्रसारित होता है। इसके अलावा, धारावाहिक डेटा बोझिल डेटा बसों की आवश्यकता को दूर करता है, जो कि वास्तव में व्यापक और बोझिल दोनों हैं (ठीक से एक साथ रहने के लिए डेटा के लिए, बस के सभी "लेन" को एक ही यात्रा में देरी का अनुभव करना होगा)।
  • हार्वर्ड आर्किटेक्चर, जिसका अर्थ प्रोग्राम मेमोरी (ROM) और डेटा मेमोरी (RAM) के बीच विभाजन है। यद्यपि यह प्रोसेसर के लचीलेपन को कम करता है, इससे आकार के अनुकूलन में मदद मिलती है: कार्यक्रम की लंबाई हमें जितनी मात्रा में रैम की आवश्यकता होती है, उससे बहुत बड़ी होती है, इसलिए हम प्रोग्राम को ROM में विभाजित कर सकते हैं और फिर ROM को संपीड़ित करने पर ध्यान केंद्रित कर सकते हैं। , जो बहुत आसान है जब यह केवल पढ़ने के लिए है।
  • 16-बिट डेटा चौड़ाई। यह दो की सबसे छोटी शक्ति है जो एक मानक टेट्रिस बोर्ड (10 ब्लॉक) की तुलना में व्यापक है। यह हमें -32768 से +32767 तक डेटा रेंज और 65536 निर्देशों की अधिकतम प्रोग्राम लंबाई देता है। (2 ^ 8 = 256 निर्देश सबसे सरल चीजों के लिए पर्याप्त है जो हम चाहते हैं कि एक खिलौना प्रोसेसर करना चाहिए, लेकिन टेट्रिस नहीं।)
  • अतुल्यकालिक डिजाइन। केंद्रीय घड़ी (या, समतुल्य, कई घड़ियों) के बजाय कंप्यूटर के समय को निर्धारित करते हुए, सभी डेटा एक "घड़ी संकेत" के साथ होता है जो डेटा के समानांतर यात्रा करता है क्योंकि यह कंप्यूटर के चारों ओर बहता है। कुछ पथ दूसरों की तुलना में कम हो सकते हैं, और जब यह एक केंद्र-डिज़ाइन किए गए डिज़ाइन के लिए कठिनाइयों का कारण होगा, तो एक अतुल्यकालिक डिज़ाइन आसानी से चर-समय के संचालन से निपट सकता है।
  • सभी निर्देश समान आकार के हैं। हमने महसूस किया कि एक आर्किटेक्चर जिसमें प्रत्येक निर्देश में 3 ऑपरेंड (वैल्यू वैल्यू डेस्टिनेशन) के साथ 1 ओपकोड है, सबसे लचीला विकल्प था। इसमें बाइनरी डेटा ऑपरेशन के साथ-साथ सशर्त चाल शामिल हैं।
  • सिंपल एड्रेसिंग मोड सिस्टम। विभिन्न प्रकार के एड्रेसिंग मोड होने से एरे या रिकर्स जैसे चीजों का समर्थन करने के लिए बहुत उपयोगी है। हम अपेक्षाकृत सरल प्रणाली के साथ कई महत्वपूर्ण एड्रेसिंग मोड को लागू करने में कामयाब रहे।

हमारी वास्तुकला का एक चित्रण अवलोकन पोस्ट में निहित है।

कार्यक्षमता और ALU संचालन

यहां से, यह निर्धारित करने की बात थी कि हमारे प्रोसेसर में क्या कार्यक्षमता होनी चाहिए। कार्यान्वयन की आसानी के साथ-साथ प्रत्येक कमांड की बहुमुखी प्रतिभा पर विशेष ध्यान दिया गया था।

सशर्त चाल

सशर्त चालें बहुत महत्वपूर्ण हैं और छोटे पैमाने पर और बड़े पैमाने पर नियंत्रण प्रवाह दोनों के रूप में काम करती हैं। "स्मॉल-स्केल" एक विशेष डेटा चाल के निष्पादन को नियंत्रित करने की अपनी क्षमता को संदर्भित करता है, जबकि "बड़े पैमाने पर" कोड के किसी भी मनमाने टुकड़े को नियंत्रण प्रवाह स्थानांतरित करने के लिए सशर्त कूदने के ऑपरेशन के रूप में इसके उपयोग को संदर्भित करता है। कोई समर्पित जंप ऑपरेशन नहीं हैं, क्योंकि मेमोरी मैपिंग के कारण, एक सशर्त चाल दोनों डेटा को नियमित रूप से रैम पर कॉपी कर सकते हैं और पीसी पर एक गंतव्य पते की प्रतिलिपि बना सकते हैं। हमने बिना किसी कारण के बिना शर्त और बिना शर्त कूद दोनों को भी चुनने का फैसला किया है: दोनों को एक शर्त के साथ सशर्त कदम के रूप में लागू किया जा सकता है जो TRUE के लिए हार्डकोड है।

हमने दो अलग-अलग प्रकार की सशर्त चालें चुनीं: "शून्य नहीं तो चाल" ( MNZ) और "शून्य से कम चलने पर" ( MLZ)। कार्यात्मक रूप से, MNZयह जाँचने के लिए कि क्या डेटा में कोई बिट 1 है, जबकि MLZसाइन बिट की जाँच करने के लिए मात्रा 1. 1. वे क्रमशः समानता और तुलना के लिए उपयोगी हैं। जिस कारण से हमने इन दोनों को दूसरों के ऊपर चुना है जैसे "कदम अगर शून्य" ( MEZ) या "चाल अगर शून्य से अधिक है" ( MGZ) तो यह था कि MEZखाली सिग्नल से TRUE सिग्नल बनाने की आवश्यकता होती है, जबकि MGZएक अधिक जटिल जांच है, जिसके लिए आवश्यक है साइन बिट 0 होना चाहिए, जबकि कम से कम एक बिट 1 होना चाहिए।

अंकगणित

प्रोसेसर डिजाइन को निर्देशित करने के संदर्भ में अगला-सबसे महत्वपूर्ण निर्देश, बुनियादी अंकगणितीय ऑपरेशन हैं। जैसा कि मैंने पहले उल्लेख किया है, हम छोटे-एंडियन सीरियल डेटा का उपयोग कर रहे हैं, इसके अलावा / घटाव संचालन की आसानी द्वारा निर्धारित एंडियनस की पसंद के साथ। कम से कम महत्वपूर्ण बिट पहले आने से, अंकगणित इकाइयां आसानी से कैरी बिट का ट्रैक रख सकती हैं।

हमने नकारात्मक संख्याओं के लिए 2 के पूरक प्रतिनिधित्व का उपयोग करना चुना, क्योंकि इससे जोड़ और घटाव अधिक सुसंगत हो जाता है। यह ध्यान देने योग्य है कि वायरवर्ल्ड कंप्यूटर ने 1 के पूरक का उपयोग किया।

जोड़ और घटाव हमारे कंप्यूटर की मूल अंकगणित सहायता (बिट शिफ्ट के अलावा जो बाद में चर्चा की जाती है) की सीमा है। गुणा की तरह अन्य ऑपरेशन, हमारी वास्तुकला द्वारा नियंत्रित किए जाने के लिए बहुत जटिल हैं, और सॉफ्टवेयर में लागू किया जाना चाहिए।

बिटवाइज ऑपरेशन

हमारे प्रोसेसर के पास है AND, ORऔर XORनिर्देश जो आप अपेक्षा करते हैं। एक NOTनिर्देश के बजाय , हमने एक "और नहीं" ( ANT) निर्देश चुना है। NOTनिर्देश के साथ कठिनाई फिर से है कि इसे सिग्नल की कमी से संकेत बनाना होगा, जो सेलुलर ऑटोमेटा के साथ मुश्किल है। ANTशिक्षा देता है 1 केवल यदि पहला तर्क बिट 1 है और दूसरा तर्क बिट 0. इस प्रकार है, NOT xके बराबर है ANT -1 x(और साथ ही XOR -1 x)। इसके अलावा, ANTबहुमुखी है और मास्किंग में इसका मुख्य लाभ है: टेट्रिस कार्यक्रम के मामले में हम इसका उपयोग टेट्रोमिनोइन्स को मिटाने के लिए करते हैं।

बिट शिफ्टिंग

बिट-शिफ्टिंग ऑपरेशन ALU द्वारा संचालित सबसे जटिल ऑपरेशन हैं। वे दो डेटा इनपुट लेते हैं: शिफ्ट करने के लिए एक मूल्य और इसे शिफ्ट करने के लिए एक राशि। उनकी जटिलता (स्थानांतरण की चर राशि के कारण) के बावजूद, ये ऑपरेशन कई महत्वपूर्ण कार्यों के लिए महत्वपूर्ण हैं, जिसमें टेट्रिस में शामिल कई "ग्राफिकल" ऑपरेशन शामिल हैं। बिट शिफ्ट्स कुशल गुणा / भाग एल्गोरिदम की नींव के रूप में भी काम करेंगे।

हमारे प्रोसेसर में तीन बिट शिफ्ट ऑपरेशन हैं, "शिफ्ट लेफ्ट" ( SL), "शिफ्ट राईट लॉजिकल" ( SRL), और "शिफ्ट राईट अरिथमेटिक" ( SRA)। पहले दो बिट्स शिफ्ट ( SLऔर SRL) नए बिट्स को सभी शून्य के साथ भरें (जिसका अर्थ है कि एक नकारात्मक संख्या सही स्थानांतरित अब नकारात्मक नहीं होगी)। यदि शिफ्ट का दूसरा तर्क 0 से 15 की सीमा के बाहर है, तो परिणाम सभी शून्य है, जैसा कि आप उम्मीद कर सकते हैं। अंतिम बिट शिफ्ट के लिए, SRAबिट शिफ्ट इनपुट के संकेत को संरक्षित करता है, और इसलिए दो द्वारा एक सच्चे विभाजन के रूप में कार्य करता है।

निर्देश पाइपलाइन

अब वास्तुकला के कुछ बारीक विवरणों के बारे में बात करने का समय है। प्रत्येक CPU चक्र में निम्नलिखित पाँच चरण होते हैं:

1. ROM से वर्तमान निर्देश प्राप्त करें

पीसी का वर्तमान मूल्य ROM से संबंधित निर्देश लाने के लिए उपयोग किया जाता है। प्रत्येक निर्देश में एक ओपकोड और तीन ऑपरेंड होते हैं। प्रत्येक ऑपरेंड में एक डेटा शब्द और एक एड्रेसिंग मोड होता है। रोम से पढ़ते ही ये भाग एक दूसरे से अलग हो जाते हैं।

16 अद्वितीय opcodes का समर्थन करने के लिए opcode 4 बिट्स है, जिनमें से 11 को असाइन किया गया है:

0000  MNZ    Move if Not Zero
0001  MLZ    Move if Less than Zero
0010  ADD    ADDition
0011  SUB    SUBtraction
0100  AND    bitwise AND
0101  OR     bitwise OR
0110  XOR    bitwise eXclusive OR
0111  ANT    bitwise And-NoT
1000  SL     Shift Left
1001  SRL    Shift Right Logical
1010  SRA    Shift Right Arithmetic
1011  unassigned
1100  unassigned
1101  unassigned
1110  unassigned
1111  unassigned

2. रैम को पिछले निर्देश का परिणाम (यदि आवश्यक हो) लिखें

पिछले निर्देश की स्थिति पर निर्भर करता है (जैसे सशर्त चाल के लिए पहले तर्क का मूल्य), एक लेखन किया जाता है। लेखन का पता पिछले अनुदेश के तीसरे ऑपरेंड द्वारा निर्धारित किया जाता है।

यह ध्यान रखना महत्वपूर्ण है कि निर्देश लाने के बाद लेखन होता है। यह एक शाखा विलंब स्लॉट के निर्माण की ओर जाता है जिसमें शाखा निर्देश के तुरंत बाद निर्देश (कोई भी ऑपरेशन जो पीसी को लिखता है) को शाखा लक्ष्य पर पहले निर्देश के बदले निष्पादित किया जाता है।

कुछ मामलों में (बिना शर्त कूद की तरह), शाखा विलंब स्लॉट को दूर अनुकूलित किया जा सकता है। अन्य मामलों में, यह नहीं हो सकता है और एक शाखा के बाद अनुदेश खाली छोड़ दिया जाना चाहिए। इसके अलावा, इस प्रकार की देरी स्लॉट का मतलब है कि शाखाओं को एक शाखा लक्ष्य का उपयोग करना चाहिए जो वास्तविक पीसीआर वृद्धि के लिए 1 पते से कम है, जो कि पीसी वेतन वृद्धि के लिए है।

संक्षेप में, क्योंकि पिछले निर्देश का आउटपुट रैम के लिए लिखा जाता है, अगला निर्देश प्राप्त होने के बाद, सशर्त कूदने के लिए उनके बाद एक खाली निर्देश की आवश्यकता होती है, अन्यथा कूदने के लिए पीसी ठीक से अपडेट नहीं होगा।

3. रैम से वर्तमान अनुदेश के तर्कों के लिए डेटा पढ़ें

जैसा कि पहले उल्लेख किया गया है, तीनों ऑपरेंड्स में से प्रत्येक में डेटा शब्द और एड्रेसिंग मोड दोनों होते हैं। डेटा शब्द 16 बिट्स है, रैम के समान चौड़ाई। एड्रेसिंग मोड 2 बिट्स है।

एड्रेसिंग मोड इस तरह के एक प्रोसेसर के लिए महत्वपूर्ण जटिलता का स्रोत हो सकता है, क्योंकि कई वास्तविक दुनिया के एड्रेसिंग मोड में मल्टी-स्टेप कंप्यूटेशन (जैसे ऑफसेट जोड़ने) शामिल हैं। इसी समय, बहुमुखी संबोधित करने वाले मोड प्रोसेसर की उपयोगिता में महत्वपूर्ण भूमिका निभाते हैं।

हमने ऑपरेंड के रूप में हार्ड-कोडित संख्याओं का उपयोग करने और ऑपरेंड के रूप में डेटा पतों का उपयोग करने की अवधारणाओं को एकजुट करने की मांग की। इससे काउंटर-आधारित एड्रेसिंग मोड का निर्माण हुआ: एक ऑपरेंड का एड्रेसिंग मोड बस एक संख्या है जो यह दर्शाती है कि रैम रीड लूप के आसपास डेटा कितनी बार भेजा जाना चाहिए। इसमें तत्काल, प्रत्यक्ष, अप्रत्यक्ष और दोहरे-अप्रत्यक्ष संबोधन शामिल हैं।

00  Immediate:  A hard-coded value. (no RAM reads)
01  Direct:  Read data from this RAM address. (one RAM read)
10  Indirect:  Read data from the address given at this address. (two RAM reads)
11  Double-indirect: Read data from the address given at the address given by this address. (three RAM reads)

इसके बाद डेरेफ्रेंसिंग की जाती है, निर्देश के तीन ऑपरेंड में अलग-अलग भूमिका होती है। पहला ऑपरेंड आमतौर पर एक बाइनरी ऑपरेटर के लिए पहला तर्क होता है, लेकिन यह भी उस स्थिति के रूप में कार्य करता है जब वर्तमान निर्देश एक सशर्त चाल है। दूसरा ऑपरेंड एक बाइनरी ऑपरेटर के लिए दूसरे तर्क के रूप में कार्य करता है। तीसरा ऑपरेंड निर्देश के परिणाम के लिए गंतव्य पते के रूप में कार्य करता है।

चूंकि पहले दो निर्देश डेटा के रूप में काम करते हैं, जबकि तीसरा एक पते के रूप में कार्य करता है, इसलिए संबोधित करने के तरीकों की थोड़ी अलग व्याख्या होती है कि वे किस स्थिति में उपयोग किए जाते हैं। उदाहरण के लिए, प्रत्यक्ष मोड का उपयोग निश्चित रैम पते से डेटा पढ़ने के लिए किया जाता है (तब से एक रैम रीड की जरूरत है), लेकिन एक निश्चित रैम पते पर डेटा लिखने के लिए तत्काल मोड का उपयोग किया जाता है (क्योंकि कोई रैम रीड आवश्यक नहीं है)।

4. परिणाम की गणना करें

ओपोड और पहले दो ऑपरेंड को बाइनरी ऑपरेशन करने के लिए ALU में भेजा जाता है। अंकगणित, बिटवाइज़ और शिफ्ट ऑपरेशन के लिए, इसका अर्थ है प्रासंगिक ऑपरेशन करना। सशर्त चालों के लिए, इसका मतलब बस दूसरे ऑपरेंड को वापस करना है।

ओपकोड और पहले ऑपरेंड का उपयोग स्थिति की गणना करने के लिए किया जाता है, जो यह निर्धारित करता है कि स्मृति को परिणाम लिखना है या नहीं। सशर्त चालों के मामले में, इसका मतलब या तो यह निर्धारित करना है कि क्या ऑपरेंड में कोई बिट 1 (के लिए MNZ) है, या यह निर्धारित करने के लिए कि साइन बिट 1 (के लिए MLZ) है या नहीं। यदि ओपकोड एक सशर्त चाल नहीं है, तो लेखन हमेशा किया जाता है (शर्त हमेशा सच होती है)।

5. कार्यक्रम काउंटर बढ़ाएँ

अंत में, प्रोग्राम काउंटर को पढ़ा जाता है, इंक्रीमेंट किया जाता है, और लिखा जाता है।

निर्देश पढ़ने और अनुदेश लिखने के बीच पीसी वेतन वृद्धि की स्थिति के कारण, इसका मतलब है कि एक अनुदेश जो पीसी द्वारा 1 बढ़ाता है वह एक नो-ऑप है। एक निर्देश जो पीसी को स्वयं कॉपी करता है, अगले निर्देश को लगातार दो बार निष्पादित किया जाता है। लेकिन, चेतावनी दी जा सकती है, एक पंक्ति में कई पीसी निर्देश अनंत लूपिंग सहित जटिल प्रभाव पैदा कर सकते हैं, यदि आप निर्देश पाइपलाइन पर ध्यान नहीं देते हैं।

टेट्रिस असेंबली के लिए क्वेस्ट

हमने अपने प्रोसेसर के लिए QFTASM नाम से एक नई असेंबली भाषा बनाई। यह असेंबली भाषा कंप्यूटर के रोम में मशीन कोड के साथ 1-टू -1 से मेल खाती है।

किसी भी QFTASM कार्यक्रम को निर्देशों की एक श्रृंखला के रूप में लिखा जाता है, प्रति पंक्ति एक। प्रत्येक पंक्ति इस तरह स्वरूपित है:

[line numbering] [opcode] [arg1] [arg2] [arg3]; [optional comment]

ओपकोड सूची

जैसा कि पहले चर्चा की गई थी, कंप्यूटर द्वारा समर्थित ग्यारह ऑपकोड हैं, जिनमें से प्रत्येक में तीन ऑपरेंड हैं:

MNZ [test] [value] [dest]  – Move if Not Zero; sets [dest] to [value] if [test] is not zero.
MLZ [test] [value] [dest]  – Move if Less than Zero; sets [dest] to [value] if [test] is less than zero.
ADD [val1] [val2] [dest]   – ADDition; store [val1] + [val2] in [dest].
SUB [val1] [val2] [dest]   – SUBtraction; store [val1] - [val2] in [dest].
AND [val1] [val2] [dest]   – bitwise AND; store [val1] & [val2] in [dest].
OR [val1] [val2] [dest]    – bitwise OR; store [val1] | [val2] in [dest].
XOR [val1] [val2] [dest]   – bitwise XOR; store [val1] ^ [val2] in [dest].
ANT [val1] [val2] [dest]   – bitwise And-NoT; store [val1] & (![val2]) in [dest].
SL [val1] [val2] [dest]    – Shift Left; store [val1] << [val2] in [dest].
SRL [val1] [val2] [dest]   – Shift Right Logical; store [val1] >>> [val2] in [dest]. Doesn't preserve sign.
SRA [val1] [val2] [dest]   – Shift Right Arithmetic; store [val1] >> [val2] in [dest], while preserving sign.

मोड्स को संबोधित करते हुए

प्रत्येक ऑपरेंड में डेटा वैल्यू और एड्रेसिंग मूव दोनों होते हैं। डेटा मान को दशमलव संख्या द्वारा -32768 से 32767 में वर्णित किया गया है। डेटा मोड में एक-अक्षर उपसर्ग द्वारा एड्रेसिंग मोड का वर्णन किया गया है।

mode    name               prefix
0       immediate          (none)
1       direct             A
2       indirect           B
3       double-indirect    C 

उदाहरण कोड

पांच लाइनों में फाइबोनैचि अनुक्रम:

0. MLZ -1 1 1;    initial value
1. MLZ -1 A2 3;   start loop, shift data
2. MLZ -1 A1 2;   shift data
3. MLZ -1 0 0;    end loop
4. ADD A2 A3 1;   branch delay slot, compute next term

यह कोड फाइबोनैचि अनुक्रम की गणना करता है, जिसमें रैम पता 1 वर्तमान शब्द होता है। यह 28657 के बाद तेजी से आगे निकल जाता है।

ग्रे कोड:

0. MLZ -1 5 1;      initial value for RAM address to write to
1. SUB A1 5 2;      start loop, determine what binary number to covert to Gray code
2. SRL A2 1 3;      shift right by 1
3. XOR A2 A3 A1;    XOR and store Gray code in destination address
4. SUB B1 42 4;     take the Gray code and subtract 42 (101010)
5. MNZ A4 0 0;      if the result is not zero (Gray code != 101010) repeat loop
6. ADD A1 1 1;      branch delay slot, increment destination address

यह कार्यक्रम ग्रे कोड की गणना करता है और पते 5 पर शुरू होने वाले सुसाइड पतों में कोड को स्टोर करता है। यह प्रोग्राम कई महत्वपूर्ण विशेषताओं जैसे अप्रत्यक्ष पते और सशर्त कूद का उपयोग करता है। यह परिणामी ग्रे कोड होने के बाद रुक जाता है 101010, जो पता 56 पर इनपुट 51 के लिए होता है।

ऑनलाइन दुभाषिया

एल'एंडिया स्ट्रैटन ने यहां एक बहुत उपयोगी ऑनलाइन दुभाषिया बनाया है । आप कोड के माध्यम से कदम बढ़ा सकते हैं, ब्रेकप्वाइंट सेट कर सकते हैं, रैम को मैनुअल लिख सकते हैं और रैम को डिस्प्ले के रूप में देख सकते हैं।

Cogol

एक बार आर्किटेक्चर और असेंबली भाषा को परिभाषित करने के बाद, प्रोजेक्ट के "सॉफ़्टवेयर" पक्ष पर अगला कदम एक उच्च-स्तरीय भाषा का निर्माण था, जो कि टेट्रिस के लिए उपयुक्त है। इस प्रकार मैंने कोगोल बनाया । नाम "COBOL" पर एक वाक्य है और "C of Game of Life" के लिए एक संक्षिप्त नाम है, हालांकि यह ध्यान देने योग्य है कि Cogol C हमारे कंप्यूटर का वास्तविक कंप्यूटर क्या है।

Cogol विधानसभा भाषा के ठीक ऊपर एक स्तर पर मौजूद है। आम तौर पर, एक कोगोल कार्यक्रम में अधिकांश लाइनें प्रत्येक विधानसभा की एक पंक्ति के अनुरूप होती हैं, लेकिन भाषा की कुछ महत्वपूर्ण विशेषताएं हैं:

  • मूल विशेषताओं में असाइनमेंट और ऑपरेटरों के साथ नामित चर शामिल हैं जिनमें अधिक पठनीय वाक्यविन्यास है। उदाहरण के लिए, पते पर कंपाइलर मैपिंग चर के साथ , ADD A1 A2 3बन जाता है z = x + y;
  • जैसे पाशन निर्माणों if(){}, while(){}है, और do{}while();इसलिए संकलक शाखाओं हैंडल।
  • एक आयामी सरणियों (सूचक अंकगणित के साथ), जो कि टेट्रिस बोर्ड के लिए उपयोग किया जाता है।
  • सबरूटीन्स और एक कॉल स्टैक। ये कोड के बड़े हिस्से के दोहराव को रोकने के लिए और पुनरावर्तन का समर्थन करने के लिए उपयोगी हैं।

संकलक (जिसे मैंने स्क्रैच से लिखा है) बहुत ही बुनियादी / भोला है, लेकिन मैंने एक छोटे संकलित कार्यक्रम की लंबाई को प्राप्त करने के लिए भाषा के कई निर्माणों को हाथ से अनुकूलित करने का प्रयास किया है।

यहाँ विभिन्न भाषा सुविधाएँ कैसे काम करती हैं, इसके कुछ संक्षिप्त विवरण दिए गए हैं:

tokenization

स्रोत कोड को रेखीय रूप से (एकल-पास) टोकन किया जाता है, सरल नियमों का उपयोग करके जिनके बारे में पात्रों को टोकन के भीतर समीप होने की अनुमति होती है। जब एक वर्ण का सामना किया जाता है, जो वर्तमान टोकन के अंतिम चरित्र के निकट नहीं हो सकता है, तो वर्तमान टोकन को पूर्ण माना जाता है और नया वर्ण एक नया टोकन प्रारंभ करता है। कुछ वर्ण (जैसे कि {या ,) किसी भी अन्य वर्ण के समीप नहीं हो सकते हैं और इसलिए वे अपने स्वयं के टोकन हैं। अन्य (जैसे >या =) केवल अपने वर्ग के भीतर अन्य पात्रों से सटे होने के लिए अनुमति दी जाती है, और इस तरह की तरह टोकन फार्म कर सकते हैं >>>, ==या >=, लेकिन पसंद नहीं =2। व्हॉट्सएप के चरित्र टोकन के बीच एक सीमा को बाध्य करते हैं लेकिन परिणाम में खुद को शामिल नहीं करते हैं। सबसे कठिन चरित्र टोकन है- क्योंकि यह दोनों घटाव और एकात्मक नकार का प्रतिनिधित्व कर सकता है, और इस प्रकार कुछ विशेष आवरण की आवश्यकता होती है।

पदच्छेद

पारसिंग भी एक एकल-पास फैशन में किया जाता है। कंपाइलर के पास विभिन्न भाषा निर्माणों में से प्रत्येक को संभालने के लिए विधियां हैं, और टोकन वैश्विक संकलित सूची से अलग हैं, क्योंकि वे विभिन्न संकलक विधियों द्वारा उपभोग किए जाते हैं। यदि कंपाइलर कभी भी एक टोकन देखता है जो इसकी अपेक्षा नहीं करता है, तो यह एक सिंटैक्स त्रुटि उठाता है।

ग्लोबल मेमोरी आवंटन

संकलक प्रत्येक वैश्विक चर (शब्द या सरणी) को अपना स्वयं का निर्दिष्ट रैम पता (एस) प्रदान करता है। कीवर्ड का उपयोग करके सभी चर घोषित करना आवश्यक है myताकि कंपाइलर इसके लिए स्थान आवंटित करना जानता हो। नामित वैश्विक चरों की तुलना में बहुत ठंडा खरोंच पता स्मृति प्रबंधन है। कई निर्देशों (विशेष रूप से सशर्त और कई सरणी एक्सेस) को मध्यवर्ती गणनाओं को संग्रहीत करने के लिए अस्थायी "खरोंच" पते की आवश्यकता होती है। संकलन प्रक्रिया के दौरान संकलक आवश्यक के रूप में खरोंच के पते आवंटित करता है और डी-आवंटित करता है। यदि कंपाइलर को अधिक स्क्रैच पते की आवश्यकता है, तो यह स्क्रैच पतों के रूप में अधिक रैम समर्पित करेगा। मेरा मानना ​​है कि एक कार्यक्रम के लिए यह विशिष्ट है कि केवल कुछ स्क्रैच पते की आवश्यकता है, हालांकि प्रत्येक स्क्रैच पते का उपयोग कई बार किया जाएगा।

IF-ELSE बयान

if-elseबयानों के लिए वाक्यविन्यास मानक C रूप है:

other code
if (cond) {
  first body
} else {
  second body
}
other code

QFTASM में परिवर्तित होने पर, कोड को इस तरह व्यवस्थित किया जाता है:

other code
condition test
conditional jump
first body
unconditional jump
second body (conditional jump target)
other code (unconditional jump target)

यदि पहले निकाय को निष्पादित किया जाता है, तो दूसरा शरीर ऊपर छोड़ दिया जाता है। यदि पहले शरीर को छोड़ दिया जाता है, तो दूसरे निकाय को निष्पादित किया जाता है।

विधानसभा में, एक शर्त परीक्षा आमतौर पर सिर्फ एक घटाव होती है, और परिणाम का संकेत यह निर्धारित करता है कि क्या शरीर को कूदना या निष्पादित करना है। एक MLZनिर्देश का उपयोग असमानताओं को संभालने के लिए किया जाता है जैसे >या <=। एक MNZनिर्देश को संभालने के लिए उपयोग किया जाता है ==, क्योंकि यह अंतर शून्य होने पर शरीर पर कूदता है (और इसलिए जब तर्क समान नहीं होते हैं)। बहु-अभिव्यक्ति सशर्त वर्तमान में समर्थित नहीं हैं।

यदि elseकथन छोड़ दिया जाता है, तो बिना शर्त कूद भी छोड़ दिया जाता है, और QFTASM कोड इस तरह दिखता है:

other code
condition test
conditional jump
body
other code (conditional jump target)

WHILE बयान

whileबयानों के लिए वाक्यविन्यास भी मानक C रूप है:

other code
while (cond) {
  body
}
other code

QFTASM में परिवर्तित होने पर, कोड को इस तरह व्यवस्थित किया जाता है:

other code
unconditional jump
body (conditional jump target)
condition test (unconditional jump target)
conditional jump
other code

शर्त परीक्षण और सशर्त कूद ब्लॉक के अंत में हैं, जिसका अर्थ है कि ब्लॉक के प्रत्येक निष्पादन के बाद उन्हें फिर से निष्पादित किया जाता है। जब स्थिति वापस आती है तो शरीर को दोहराया नहीं जाता है और लूप समाप्त हो जाता है। लूप निष्पादन की शुरुआत के दौरान, नियंत्रण प्रवाह लूप बॉडी पर स्थिति कोड में कूदता है, इसलिए पहली बार झूठी होने पर बॉडी को कभी भी निष्पादित नहीं किया जाता है।

एक MLZनिर्देश का उपयोग असमानताओं को संभालने के लिए किया जाता है जैसे >या <=ifबयानों के दौरान इसके विपरीत , एक MNZनिर्देश को संभालने के लिए उपयोग किया जाता है !=, क्योंकि यह अंतर शून्य होने पर शरीर में कूदता है (और इसलिए जब तर्क समान नहीं होते हैं)।

DO-WHILE बयान

के बीच एकमात्र अंतर whileऔर do-whileयह है कि एक do-whileलूप बॉडी को शुरू में छोड़ नहीं दिया जाता है इसलिए इसे हमेशा कम से कम एक बार निष्पादित किया जाता है। मैं आमतौर पर do-whileअसेंबली कोड की कुछ पंक्तियों को सहेजने के लिए बयानों का उपयोग करता हूं जब मुझे पता है कि लूप को पूरी तरह से छोड़ देने की आवश्यकता नहीं होगी।

Arrays

एक आयामी सरणियों को स्मृति के सन्निहित ब्लॉक के रूप में लागू किया जाता है। सभी ऐरे को उनकी घोषणा के आधार पर निर्धारित लंबाई के होते हैं। ऐरे को ऐसे घोषित किया जाता है:

my alpha[3];               # empty array
my beta[11] = {3,2,7,8};   # first four elements are pre-loaded with those values

सरणी के लिए, यह एक संभावित रैम मैपिंग है, जिसमें दिखाया गया है कि सरणी के लिए 15-18 पते कैसे आरक्षित हैं:

15: alpha
16: alpha[0]
17: alpha[1]
18: alpha[2]

लेबल किए गए पते alphaको एक पॉइंटर के स्थान से भरा जाता है alpha[0], इसलिए थाइ केस एड्रेस 15 में मान 16 होता है। alphaचर का उपयोग कोगोल कोड के अंदर किया जा सकता है, संभवतः स्टैक पॉइंटर के रूप में यदि आप इस सरणी को स्टैक के रूप में उपयोग करना चाहते हैं। ।

किसी सरणी के तत्वों को एक्सेस करना मानक array[index]संकेतन के साथ किया जाता है । यदि मान indexएक स्थिर है, तो यह संदर्भ स्वचालित रूप से उस तत्व के पूर्ण पते के साथ भर जाता है। अन्यथा यह वांछित निरपेक्ष पता खोजने के लिए कुछ सूचक अंकगणित (सिर्फ जोड़) करता है। घोंसला अनुक्रमण जैसे कि यह भी संभव है alpha[beta[1]]

सबरूटीन्स और कॉलिंग

सबरूटीन कोड के ब्लॉक हैं जिन्हें कई संदर्भों से बुलाया जा सकता है, कोड के दोहराव को रोकने और पुनरावर्ती कार्यक्रमों के निर्माण के लिए अनुमति देता है। यहां फाइबोनैचि संख्याओं (मूल रूप से सबसे धीमी एल्गोरिदम) उत्पन्न करने के लिए एक पुनरावर्ती सबरूटीन के साथ एक कार्यक्रम है:

# recursively calculate the 10th Fibonacci number
call display = fib(10).sum;
sub fib(cur,sum) {
  if (cur <= 2) {
    sum = 1;
    return;
  }
  cur--;
  call sum = fib(cur).sum;
  cur--;
  call sum += fib(cur).sum;
}

एक सबरूटीन को कीवर्ड के साथ घोषित किया जाता है sub, और एक सबरूटीन को प्रोग्राम के अंदर कहीं भी रखा जा सकता है। प्रत्येक सबरूटीन में कई स्थानीय चर हो सकते हैं, जिन्हें इसके तर्कों की सूची के भाग के रूप में घोषित किया गया है। इन तर्कों को डिफ़ॉल्ट मान भी दिया जा सकता है।

पुनरावर्ती कॉल को संभालने के लिए, सबरूटीन के स्थानीय चर को स्टैक पर संग्रहीत किया जाता है। रैम में अंतिम स्टैटिक वेरिएबल कॉल स्टैक पॉइंटर है, और इसके बाद की सभी मेमोरी कॉल स्टैक के रूप में कार्य करती है। जब एक सबरूटीन कहा जाता है, तो उसने कॉल स्टैक पर एक नया फ्रेम बनाया, जिसमें सभी स्थानीय चर और साथ ही रिटर्न (ROM) पता शामिल है। कार्यक्रम में प्रत्येक सबरूटीन को एक सूचक के रूप में सेवा करने के लिए एक एकल स्थिर रैम पता दिया जाता है। यह पॉइंटर कॉल स्टैक में सबरूटीन के "वर्तमान" कॉल का स्थान देता है। एक स्थानीय चर का संदर्भ इस स्थिर सूचक के मान का उपयोग करके किया जाता है और उस विशेष स्थानीय चर का पता देने के लिए एक ऑफसेट का उपयोग किया जाता है। इसके अलावा कॉल स्टैक में स्थिर सूचक का पिछला मान है। यहाँ'

RAM map:
0: pc
1: display
2: scratch0
3: fib
4: scratch1
5: scratch2
6: scratch3
7: call

fib map:
0: return
1: previous_call
2: cur
3: sum

एक चीज जो सबरूटीन्स के बारे में दिलचस्प है, वह यह है कि वे किसी विशेष मूल्य को वापस नहीं करते हैं। बल्कि, सबरूटीन के सभी स्थानीय वेरिएबल्स को सबरूटीन के प्रदर्शन के बाद पढ़ा जा सकता है, इसलिए सबरूटिन कॉल से विभिन्न प्रकार के डेटा निकाले जा सकते हैं। यह सबरूटीन की उस विशिष्ट कॉल के लिए पॉइंटर को संचय करके पूरा किया जाता है, जिसे तब (हाल ही में-डीलॉलेटेड) स्टैक फ्रेम के भीतर से किसी भी स्थानीय चर को पुनर्प्राप्त करने के लिए उपयोग किया जा सकता है।

सबरूटिन को कॉल करने के कई तरीके हैं, सभी callकीवर्ड का उपयोग कर रहे हैं :

call fib(10);   # subroutine is executed, no return vaue is stored

call pointer = fib(10);   # execute subroutine and return a pointer
display = pointer.sum;    # access a local variable and assign it to a global variable

call display = fib(10).sum;   # immediately store a return value

call display += fib(10).sum;   # other types of assignment operators can also be used with a return value

किसी भी संख्या के मान को सबरूटीन कॉल के लिए तर्क के रूप में दिया जा सकता है। प्रदान किया गया कोई भी तर्क उसके डिफ़ॉल्ट मान के साथ भरा जाएगा, यदि कोई हो। ऐसा तर्क जो प्रदान नहीं किया गया है और जिसका कोई डिफ़ॉल्ट मान नहीं है (निर्देशों / समय को बचाने के लिए) को मंजूरी नहीं दी गई है, इसलिए संभवत: सबरूटीन की शुरुआत में किसी भी मूल्य पर ले सकता है।

प्‍वाइंटर्स सबरूटीन के कई लोकल वैरिएबल को एक्‍सेस करने का एक तरीका है, हालांकि यह ध्‍यान रखना जरूरी है कि प्‍वाइंटर केवल अस्‍थायी है: एक और सबरूटीन कॉल करने पर प्‍वाइंटर प्‍वाइंट तबाह हो जाएगा।

डिबगिंग लेबल

{...}Cogol प्रोग्राम में कोई भी कोड ब्लॉक बहु-शब्द वर्णनात्मक लेबल से पहले हो सकता है। यह लेबल संकलित असेंबली कोड में एक टिप्पणी के रूप में जुड़ा हुआ है, और डिबगिंग के लिए बहुत उपयोगी हो सकता है क्योंकि इससे कोड के विशिष्ट विखंडनों का पता लगाना आसान हो जाता है।

शाखा विलंब स्लॉट अनुकूलन

संकलित कोड की गति में सुधार करने के लिए, Cogol संकलक QFTASM कोड पर अंतिम पास के रूप में कुछ वास्तव में बुनियादी देरी स्लॉट अनुकूलन करता है। खाली शाखा विलंब स्लॉट के साथ किसी भी बिना शर्त के कूदने के लिए, देरी स्लॉट को जंप गंतव्य पर पहले निर्देश द्वारा भरा जा सकता है, और अगले निर्देश को इंगित करने के लिए जंप गंतव्य एक से बढ़ जाता है। यह आमतौर पर एक चक्र को बचाता है हर बार बिना शर्त कूद किया जाता है।

टोगो में टेट्रिस कोड लिखना

अंतिम टेट्रिस कार्यक्रम कोगोल में लिखा गया था, और स्रोत कोड यहां उपलब्ध है । संकलित QFTASM कोड यहां उपलब्ध है । सुविधा के लिए, एक पर्मलिंक यहां प्रदान किया गया है: QFTASM में टेट्रिस । चूंकि लक्ष्य असेंबली कोड (कोगोल कोड नहीं) को गोल्फ करना था, इसलिए परिणामी कोगोल कोड अनिच्छुक है। कार्यक्रम के कई हिस्से सामान्य रूप से सबरूटीन में स्थित होंगे, लेकिन वे सबरूटीन्स वास्तव में काफी कम थे कि कोड को डुप्लिकेट करने से निर्देशों को बचाया गयाcallबयान। अंतिम कोड में मुख्य कोड के अलावा केवल एक सबरूटीन होता है। इसके अतिरिक्त, कई सरणियों को हटा दिया गया था और या तो व्यक्तिगत चर की एक समान-लंबी सूची के साथ या कार्यक्रम में बहुत सारे हार्ड-कोडित संख्याओं के साथ बदल दिया गया था। अंतिम संकलित QFTASM कोड 300 निर्देशों के तहत है, हालांकि यह केवल Cogol स्रोत की तुलना में थोड़ा लंबा है।


22
मुझे यह पसंद है कि असेंबली लैंग्वेज निर्देशों का चुनाव आपके सब्सट्रेट हार्डवेयर द्वारा परिभाषित किया जाता है (कोई MEZ नहीं क्योंकि दो फाल्स से एक असेम्बलिंग हार्ड है)। शानदार पढ़ा।
एलेक्सा

1
आपने कहा कि =केवल अपने बगल में खड़े हो सकते हैं, लेकिन वहाँ एक है !=
फेबियन रोइंग

@ फैबियन और एक+=
ओलिपहंट

@Oliphaunt हाँ मेरा वर्णन काफी सटीक नहीं था, यह एक चरित्र-श्रेणी की चीज़ से अधिक है, जहाँ वर्णों का एक निश्चित वर्ग एक-दूसरे के निकट हो सकता है।
PhiNotPi

606

भाग 5: सभा, अनुवाद, और भविष्य

संकलक से हमारे असेंबली प्रोग्राम के साथ, यह वारीफ़ाइ कंप्यूटर के लिए एक ROM को इकट्ठा करने का समय है, और सब कुछ बड़े गोएल पैटर्न में अनुवाद करता है!

सभा

रॉम में असेंबली प्रोग्राम को असेंबल करना पारंपरिक प्रोग्रामिंग की तरह ही किया जाता है: प्रत्येक निर्देश को एक बाइनरी समकक्ष में अनुवादित किया जाता है, और फिर उन्हें एक बड़े बाइनरी ब्लॉब में संक्षिप्त किया जाता है जिसे हम एक निष्पादन योग्य कहते हैं। हमारे लिए, एकमात्र अंतर यह है कि बाइनरी ब्लॉब को Varlife सर्किट में अनुवादित करने और कंप्यूटर से संलग्न करने की आवश्यकता है।

के झांग ने गोल्डी के लिए पाइथन स्क्रिप्ट बनाई , जो असेंबली और ट्रांसलेशन करती है। यह काफी सीधा है: यह क्लिपबोर्ड से एक विधानसभा कार्यक्रम लेता है, इसे एक बाइनरी में इकट्ठा करता है, और उस बाइनरी को सर्किट्री में अनुवाद करता है। यहाँ स्क्रिप्ट के साथ शामिल एक सरल मौलिकता परीक्षक के साथ एक उदाहरण दिया गया है:

#0. MLZ -1 3 3;
#1. MLZ -1 7 6; preloadCallStack
#2. MLZ -1 2 1; beginDoWhile0_infinite_loop
#3. MLZ -1 1 4; beginDoWhile1_trials
#4. ADD A4 2 4;
#5. MLZ -1 A3 5; beginDoWhile2_repeated_subtraction
#6. SUB A5 A4 5;
#7. SUB 0 A5 2;
#8. MLZ A2 5 0;
#9. MLZ 0 0 0; endDoWhile2_repeated_subtraction
#10. MLZ A5 3 0;
#11. MNZ 0 0 0; endDoWhile1_trials
#12. SUB A4 A3 2;
#13. MNZ A2 15 0; beginIf3_prime_found
#14. MNZ 0 0 0;
#15. MLZ -1 A3 1; endIf3_prime_found
#16. ADD A3 2 3;
#17. MLZ -1 3 0;
#18. MLZ -1 1 4; endDoWhile0_infinite_loop

यह निम्नलिखित बाइनरी का उत्पादन करता है:

0000000000000001000000000000000000010011111111111111110001
0000000000000000000000000000000000110011111111111111110001
0000000000000000110000000000000000100100000000000000110010
0000000000000000010100000000000000110011111111111111110001
0000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000011110100000000000000100000
0000000000000000100100000000000000110100000000000001000011
0000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000110100000000000001010001
0000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000001010100000000000000100001
0000000000000000100100000000000001010000000000000000000011
0000000000000001010100000000000001000100000000000001010011
0000000000000001010100000000000000110011111111111111110001
0000000000000001000000000000000000100100000000000001000010
0000000000000001000000000000000000010011111111111111110001
0000000000000000010000000000000000100011111111111111110001
0000000000000001100000000000000001110011111111111111110001
0000000000000000110000000000000000110011111111111111110001

जब वरलाइक सर्किट का अनुवाद किया जाता है, तो यह इस तरह दिखता है:

रोम

क्लोज़अप रोम

ROM को तब कंप्यूटर के साथ जोड़ा जाता है, जो Varlife में पूरी तरह से कार्य करने का कार्यक्रम बनाता है। लेकिन हम अभी तक नहीं किया है ...

जीवन के खेल में अनुवाद

इस पूरे समय, हम खेल के जीवन के आधार के ऊपर अमूर्तता की विभिन्न परतों में काम कर रहे हैं। लेकिन अब, यह अमूर्तन के पर्दे को वापस खींचने का समय है और हमारे काम को गेम ऑफ लाइफ पैटर्न में अनुवाद करना है। जैसा कि पहले उल्लेख किया गया है, हम ओटीसीए मेट्रापिक्सल को वरलाइफ़ के लिए आधार के रूप में उपयोग कर रहे हैं । तो, अंतिम चरण है कि Varlife में प्रत्येक सेल को गेम ऑफ़ लाइफ में एक मेटापिक्सेल में परिवर्तित करना है।

शुक्र है, गोली एक स्क्रिप्ट ( मेटाफ़ायरहोम ) के साथ आता है, जो विभिन्न नियमों में पैटर्न को ओटीसीए मेटपेल के माध्यम से गेम ऑफ़ लाइफ पैटर्न में बदल सकता है। दुर्भाग्य से, यह केवल एकल वैश्विक नियमों के साथ पैटर्न बदलने के लिए डिज़ाइन किया गया है, इसलिए यह वरलाइफ़ पर काम नहीं करता है। मैंने एक संशोधित संस्करण लिखा था जो उस मुद्दे को संबोधित करता है, ताकि प्रत्येक मेटापिल के लिए नियम सेल-बाय-सेल के आधार पर वैरलाइफ़ के लिए उत्पन्न हो।

तो, हमारे कंप्यूटर (Tetris ROM के साथ) में 1,436 x 5,082 का बाउंडिंग बॉक्स है। उस बॉक्स में 7,297,752 कोशिकाओं में से, 6,075,811 रिक्त स्थान हैं, जिससे 1,221,941 की वास्तविक जनसंख्या गणना होती है। उन कोशिकाओं में से प्रत्येक को एक ओटीसीए मेटापिल में अनुवादित करने की आवश्यकता है, जिसमें 2048x2048 का एक बाउंडिंग बॉक्स है और 64,691 (ऑन मैटलिपल के लिए) या 23,920 (एक ऑफ मेटापिल के लिए) की आबादी है। इसका मतलब है कि अंतिम उत्पाद में 29,228,828,720 और 79,0,5,585,231 के बीच की आबादी के साथ 2,940,928 x 10,407,936 (साथ ही साथ कुछ हद तक अतिरिक्त मीटर की सीमा) के लिए एक बाउंडिंग बॉक्स होगा। 1 बिट प्रति लाइव सेल के साथ, यह 27 और 74 GiB के बीच पूरे कंप्यूटर और ROM का प्रतिनिधित्व करने के लिए आवश्यक है।

मैंने उन गणनाओं को यहां शामिल किया क्योंकि मैंने स्क्रिप्ट शुरू करने से पहले उन्हें चलाने की उपेक्षा की, और बहुत जल्दी अपने कंप्यूटर पर स्मृति से बाहर भाग गया। killघबराई हुई आज्ञा के बाद , मैंने मेटाफ़ियर स्क्रिप्ट में संशोधन किया। हर 10 मीटर की लाइन, पैटर्न डिस्क (एक gzipped आरएलई फ़ाइल के रूप में) में सहेजा जाता है, और ग्रिड को फ्लश किया जाता है। यह अनुवाद में अतिरिक्त रनटाइम जोड़ता है और अधिक डिस्क स्थान का उपयोग करता है, लेकिन स्वीकार्य सीमा के भीतर मेमोरी का उपयोग करता है। क्योंकि Golly एक विस्तारित RLE प्रारूप का उपयोग करता है जिसमें पैटर्न का स्थान शामिल है, यह पैटर्न के लोडिंग में कोई अधिक जटिलता नहीं जोड़ता है - बस एक ही परत पर सभी पैटर्न फ़ाइलों को खोलें।

के झांग ने इस काम का निर्माण किया, और एक अधिक कुशल मेटाफियर स्क्रिप्ट बनाई , जो मैक्रोसेल फ़ाइल प्रारूप का उपयोग करती है, जो बड़े पैटर्न के लिए RLE की तुलना में अधिक कुशल है। यह स्क्रिप्ट काफी तेजी से चलती है (मूल मेटाफ़ियर स्क्रिप्ट के लिए कई घंटों की तुलना में कुछ सेकंड), बड़े पैमाने पर छोटे आउटपुट (121 केबी बनाम 1.7 जीबी) बनाता है, और पूरे कंप्यूटर को मेटाफ़ी कर सकता है और एक बड़ी मात्रा का उपयोग किए बिना एक ही बार में झपट्टा मारता है स्मृति का। यह इस तथ्य का लाभ उठाता है कि मैक्रोसेल फाइलें उन पेड़ों को एनकोड करती हैं जो पैटर्न का वर्णन करते हैं। कस्टम टेम्प्लेट फ़ाइल का उपयोग करके, मेटीपेसेल को पेड़ में पहले से लोड किया जाता है, और पड़ोसी की पहचान के लिए कुछ संगणनाओं और संशोधनों के बाद, वरलाइफ़ पैटर्न को बस जोड़ा जा सकता है।

गेम ऑफ लाइफ में संपूर्ण कंप्यूटर और ROM की पैटर्न फाइल यहां पाई जा सकती है


परियोजना का भविष्य

अब जब हमने टेट्रिस बना लिया है, तो हम कर रहे हैं, है ना? आस - पास भी नहीं। इस परियोजना के लिए हमारे पास कई और लक्ष्य हैं, जिनके लिए हम काम कर रहे हैं:

  • मैडीफ़िश और क्रिति लिथोस उच्च स्तरीय भाषा पर काम जारी रखे हुए हैं जो QFTASM से संकलित है।
  • एल'एंडिया स्ट्रोमैन ऑनलाइन QFTASM दुभाषिया के उन्नयन पर काम कर रहा है।
  • quartata एक GCC बैकएंड पर काम कर रही है, जो GCC के माध्यम से QFTASM में फ्रीस्टैंडिंग C और C ++ कोड (और संभवतः अन्य भाषाएँ, जैसे Fortran, D, या Object-C) का संकलन करने की अनुमति देगा। यह अधिक परिष्कृत कार्यक्रमों के लिए एक अधिक परिचित भाषा में बनाने की अनुमति देगा, भले ही एक मानक पुस्तकालय के बिना।
  • सबसे बड़ी बाधाओं में से एक जिसे हमें दूर करना होगा इससे पहले कि हम अधिक प्रगति कर सकें तथ्य यह है कि हमारे उपकरण स्थिति-स्वतंत्र कोड (जैसे रिश्तेदार कूदता) का उत्सर्जन नहीं कर सकते हैं। PIC के बिना, हम कोई लिंकिंग नहीं कर सकते हैं, और इसलिए हम उन लाभों को याद करते हैं जो मौजूदा पुस्तकालयों से लिंक करने में सक्षम होने से आते हैं। हम PIC को सही तरीके से करने का एक तरीका खोजने की कोशिश कर रहे हैं।
  • हम अगले प्रोग्राम के बारे में चर्चा कर रहे हैं जो हम QFT कंप्यूटर के लिए लिखना चाहते हैं। अभी, पोंग एक अच्छा लक्ष्य की तरह लग रहा है।

2
बस भविष्य के उप-भाग को देखते हुए, क्या एक सापेक्ष छलांग सिर्फ एक नहीं है ADD PC offset PC? मेरी भोली को माफ करना अगर यह गलत है, तो विधानसभा प्रोग्रामिंग कभी भी मेरे लिए नहीं थी।
MBraedley

3
@ टिम्मम हां, लेकिन बहुत धीरे-धीरे। (आपको हैशलाइफ का भी इस्तेमाल करना होगा)।
एक

75
अगला कार्यक्रम जो आप इसके लिए लिखते हैं, वह कॉनवे का गेम ऑफ लाइफ होना चाहिए।
ACK_stoverflow

13
@ACK_stoverflow कुछ बिंदु पर होने जा रहा है।
Mego

13
क्या आपके पास इसका वीडियो चल रहा है?
प्युर्लेज़

583

भाग 6: QFTASM के लिए नया संकलक

हालांकि कॉडोल एक अल्पविकसित टेट्रिस कार्यान्वयन के लिए पर्याप्त है, यह आसानी से पढ़ने योग्य स्तर पर सामान्य-प्रयोजन प्रोग्रामिंग के लिए बहुत सरल और निम्न स्तर का है। हमने सितंबर 2016 में एक नई भाषा पर काम शुरू किया। बग्स के साथ-साथ वास्तविक जीवन को समझने में कठिन होने के कारण भाषा पर प्रगति धीमी थी।

हमने पायथन के समान सिंटैक्स के साथ एक निम्न स्तर की भाषा का निर्माण किया, जिसमें एक सरल प्रकार की प्रणाली, पुनरावृत्ति और इनलाइन ऑपरेटरों का समर्थन करने वाले सबरूटीन्स शामिल हैं। QFTASM के लिए पाठ से संकलक 4 चरणों के साथ बनाया गया था: टोकनर, ग्रामर ट्री, एक उच्च स्तरीय संकलक और एक निम्न स्तर संकलक।

टोकने वाला

अंतर्निहित टोकन लाइब्रेरी का उपयोग करके पायथन का उपयोग करके विकास शुरू किया गया था, जिसका अर्थ है कि यह कदम बहुत सरल था। स्ट्रिपिंग कमेंट्स (लेकिन #includeएस नहीं ) सहित डिफ़ॉल्ट आउटपुट में केवल कुछ बदलाव की आवश्यकता थी ।

व्याकरण का वृक्ष

व्याकरण वृक्ष को किसी भी स्रोत कोड को संशोधित किए बिना आसानी से विस्तार योग्य बनाया गया था।

ट्री संरचना एक XML फ़ाइल में संग्रहीत होती है जिसमें नोड्स की संरचना शामिल होती है जो पेड़ को बना सकती है और वे अन्य नोड्स और टोकन के साथ कैसे बनाई जाती हैं।

व्याकरण को बार-बार नोड्स के साथ-साथ वैकल्पिक वाले का समर्थन करने की आवश्यकता होती है। टोकनों को कैसे पढ़ा जाए, यह वर्णन करने के लिए मेटा टैग शुरू करके यह हासिल किया गया था।

तब उत्पन्न होने वाले टोकन व्याकरण के नियमों के माध्यम से पार्स हो जाते हैं जैसे कि आउटपुट व्याकरण तत्वों का एक पेड़ बनाता है जैसे कि subएस और generic_variables, जिसमें बदले में अन्य व्याकरण तत्व और टोकन होते हैं।

उच्च स्तरीय कोड में संकलन

भाषा की प्रत्येक विशेषता को उच्च स्तरीय निर्माणों में संकलित करने में सक्षम होना चाहिए। इनमें शामिल हैं assign(a, 12) और call_subroutine(is_prime, call_variable=12, return_variable=temp_var)। इस सेगमेंट में तत्वों की इनलाइनिंग जैसी विशेषताएं निष्पादित की जाती हैं। इन्हें operatorएस के रूप में परिभाषित किया गया है और इसमें विशेष है कि वे हर बार ऐसे ऑपरेटर के रूप में इनलाइन किए जाते हैं +या %उपयोग किए जाते हैं। इस वजह से, वे नियमित कोड की तुलना में अधिक प्रतिबंधित हैं - वे अपने स्वयं के ऑपरेटर का उपयोग नहीं कर सकते हैं और न ही कोई भी ऑपरेटर जो परिभाषित होने पर निर्भर करता है।

इनलाइनिंग प्रक्रिया के दौरान, आंतरिक चरों को प्रतिस्थापित किया जाता है, जिन्हें कॉल किया जाता है। यह प्रभाव में बदल जाता है

operator(int a + int b) -> int c
    return __ADD__(a, b)
int i = 3+3

में

int i = __ADD__(3, 3)

यह व्यवहार हालांकि हानिकारक और बग प्रवण हो सकता है यदि इनपुट चर और आउटपुट चर स्मृति में एक ही स्थान पर इंगित करते हैं। 'सुरक्षित' व्यवहार का उपयोग करने के लिए, unsafeकीवर्ड संकलन प्रक्रिया को समायोजित करता है जैसे कि अतिरिक्त चर बनाए जाते हैं और जरूरत के अनुसार इनलाइन से कॉपी किए जाते हैं।

खरोंच चर और जटिल संचालन

गणितीय कार्य जैसे कि a += (b + c) * 4अतिरिक्त मेमोरी कोशिकाओं का उपयोग किए बिना गणना नहीं की जा सकती। उच्च स्तरीय संकलक विभिन्न वर्गों में परिचालन को अलग करके इससे संबंधित है:

scratch_1 = b + c
scratch_1 = scratch_1 * 4
a = a + scratch_1

यह स्क्रैच चर की अवधारणा का परिचय देता है जो गणना की मध्यवर्ती जानकारी को संग्रहीत करने के लिए उपयोग किया जाता है। उन्हें आवश्यकतानुसार आवंटित किया जाता है और एक बार समाप्त होने के बाद सामान्य पूल में लगाया जाता है। यह उपयोग के लिए आवश्यक खरोंच स्मृति स्थानों की संख्या कम कर देता है। स्क्रैच चर को ग्लोबल्स माना जाता है।

प्रत्येक सबरूटीन का अपना वैरिएबलस्टोर होता है, जो सब-वेरिएंट के उपयोग के साथ-साथ सभी प्रकार के संदर्भों का संदर्भ रखता है। संकलन के अंत में, उन्हें स्टोर की शुरुआत से रिश्तेदार ऑफसेट में अनुवाद किया जाता है और फिर रैम में वास्तविक पते दिए जाते हैं।

रैम संरचना

Program counter
Subroutine locals
Operator locals (reused throughout)
Scratch variables
Result variable
Stack pointer
Stack
...

निम्न स्तर का संकलन

केवल बातें निम्न स्तर संकलक है कर रहे हैं से निपटने के लिए sub, call_sub, return, assign, ifऔर while। यह उन कार्यों की एक बहुत कम सूची है जिन्हें QFTASM निर्देशों में अधिक आसानी से अनुवादित किया जा सकता है।

sub

यह नामांकित सबरूटीन की शुरुआत और अंत का पता लगाता है। निम्न स्तर के कंपाइलर लेबल जोड़ता है और mainसबरूटीन के मामले में , एक निकास निर्देश (रॉम के अंत में कूद) जोड़ता है।

if तथा while

निम्न whileऔर ifनिम्न स्तर के दुभाषिए दोनों ही बहुत सरल हैं: वे अपनी शर्तों पर संकेत प्राप्त करते हैं और उनके आधार पर कूदते हैं। whileलूप थोड़े अलग हैं जिसमें वे संकलित हैं

...
condition
jump to check
code
condition
if condtion: jump to code
...

call_sub तथा return

अधिकांश आर्किटेक्चर के विपरीत, हम जिस कंप्यूटर के लिए संकलन कर रहे हैं, उसमें स्टैक से धक्का और पॉपिंग के लिए हार्डवेयर समर्थन नहीं है। इसका मतलब यह है कि स्टैक से धक्का और पॉपिंग दोनों दो निर्देश लेते हैं। पॉपिंग के मामले में, हम स्टैक पॉइंटर को घटाते हैं और मूल्य को एक पते पर कॉपी करते हैं। धक्का देने के मामले में, हम वर्तमान स्टैक पॉइंटर पर एक पते से एक पते की मान कॉपी करते हैं और फिर इंक्रीमेंट करते हैं।

सबरूटीन के लिए सभी स्थानीय लोगों को संकलन समय पर निर्धारित रैम में एक निश्चित स्थान पर संग्रहीत किया जाता है। पुनरावर्तन कार्य करने के लिए, किसी फ़ंक्शन के लिए सभी स्थानीय लोगों को कॉल की शुरुआत में स्टैक पर रखा जाता है। फिर सबरूटीन के तर्कों को स्थानीय स्टोर में उनकी स्थिति पर कॉपी किया जाता है। वापसी पते का मूल्य स्टैक पर डाला जाता है और सबरूटीन निष्पादित होता है।

जब कोई returnस्टेटमेंट सामने आता है, तो स्टैक के ऊपर का हिस्सा बंद हो जाता है और प्रोग्राम काउंटर उस मान पर सेट हो जाता है। कॉलिंग सबरूटिन के स्थानीय लोगों के लिए मूल्य स्टैक से पॉपअप और उनकी पिछली स्थिति में हैं।

assign

परिवर्तनीय असाइनमेंट संकलित करने के लिए सबसे आसान चीजें हैं: वे एक चर लेते हैं और एक पंक्ति में एक मूल्य और संकलन करते हैं: MLZ -1 VALUE VARIABLE

जम्प टार्गेट असाइन करना

अंत में, कंपाइलर निर्देशों से जुड़े लेबल के लिए जंप टारगेट को पूरा करता है। लेबल की पूर्ण स्थिति निर्धारित की जाती है और फिर उन मानों के साथ उन लेबल को संदर्भित किया जाता है। लेबल स्वयं कोड से हटा दिए जाते हैं और अंत में संकलित कोड में निर्देश संख्याएं जोड़ दी जाती हैं।

उदाहरण कदम दर कदम संकलन

अब जब हम सभी चरणों से गुजर चुके हैं, तो चलिए एक वास्तविक कार्यक्रम के लिए एक वास्तविक संकलन प्रक्रिया के माध्यम से चलते हैं।

#include stdint

sub main
    int a = 8
    int b = 12
    int c = a * b

ठीक है, काफी सरल। यह कार्यक्रम के अंत में यह स्पष्ट होना चाहिए, , a = 8, ।b = 12 c = 96सबसे पहले, के प्रासंगिक भागों को शामिल करने देता है stdint.txt:

operator (int a + int b) -> int
    return __ADD__(a, b)

operator (int a - int b) -> int
    return __SUB__(a, b)

operator (int a < int b) -> bool
    bool rtn = 0
    rtn = __MLZ__(a-b, 1)
    return rtn

unsafe operator (int a * int b) -> int
    int rtn = 0
    for (int i = 0; i < b; i+=1)
        rtn += a
    return rtn

sub main
    int a = 8
    int b = 12
    int c = a * b

ठीक है, थोड़ा और अधिक जटिल। चलिए टोकनर पर जाते हैं और देखते हैं कि क्या निकलता है। इस स्तर पर, हमारे पास केवल संरचना के किसी भी रूप के बिना टोकन का एक रैखिक प्रवाह होगा

NAME NAME operator
LPAR OP (
NAME NAME int
NAME NAME a
PLUS OP +
NAME NAME int
NAME NAME b
RPAR OP )
OP OP ->
NAME NAME int
NEWLINE NEWLINE
INDENT INDENT     
NAME NAME return
NAME NAME __ADD__
LPAR OP (
NAME NAME a
COMMA OP ,
NAME NAME b
RPAR OP )
...

अब सभी टोकन व्याकरण पार्सर के माध्यम से डाल दिए जाते हैं और प्रत्येक अनुभाग के नाम के साथ एक पेड़ का उत्पादन करते हैं। यह कोड द्वारा पढ़ी गई उच्च स्तरीय संरचना को दर्शाता है।

GrammarTree file
 'stmts': [GrammarTree stmts_0
  '_block_name': 'inline'
  'inline': GrammarTree inline
   '_block_name': 'two_op'
   'type_var': GrammarTree type_var
    '_block_name': 'type'
    'type': 'int'
    'name': 'a'
    '_global': False

   'operator': GrammarTree operator
    '_block_name': '+'

   'type_var_2': GrammarTree type_var
    '_block_name': 'type'
    'type': 'int'
    'name': 'b'
    '_global': False
   'rtn_type': 'int'
   'stmts': GrammarTree stmts
    ...

यह व्याकरण का पेड़ उच्च स्तर के संकलक द्वारा पार्स किए जाने के लिए जानकारी सेट करता है। इसमें संरचना के प्रकार और चर की विशेषताओं जैसी जानकारी शामिल है। व्याकरण का पेड़ तब इस जानकारी को लेता है और उन चरों को असाइन करता है जो उप-खंडों के लिए आवश्यक होते हैं। पेड़ भी सभी इनलाइनों को सम्मिलित करता है।

('sub', 'start', 'main')
('assign', int main_a, 8)
('assign', int main_b, 12)
('assign', int op(*:rtn), 0)
('assign', int op(*:i), 0)
('assign', global bool scratch_2, 0)
('call_sub', '__SUB__', [int op(*:i), int main_b], global int scratch_3)
('call_sub', '__MLZ__', [global int scratch_3, 1], global bool scratch_2)
('while', 'start', 1, 'for')
('call_sub', '__ADD__', [int op(*:rtn), int main_a], int op(*:rtn))
('call_sub', '__ADD__', [int op(*:i), 1], int op(*:i))
('assign', global bool scratch_2, 0)
('call_sub', '__SUB__', [int op(*:i), int main_b], global int scratch_3)
('call_sub', '__MLZ__', [global int scratch_3, 1], global bool scratch_2)
('while', 'end', 1, global bool scratch_2)
('assign', int main_c, int op(*:rtn))
('sub', 'end', 'main')

अगला, निम्न स्तर के कंपाइलर को इस उच्च स्तरीय प्रतिनिधित्व को QFTASM कोड में बदलना होगा। चर को RAM में ऐसे स्थान दिए गए हैं:

int program_counter
int op(*:i)
int main_a
int op(*:rtn)
int main_c
int main_b
global int scratch_1
global bool scratch_2
global int scratch_3
global int scratch_4
global int <result>
global int <stack>

सरल निर्देश तब संकलित किए जाते हैं। अंत में, निर्देश संख्याएं जोड़ी जाती हैं, जिसके परिणामस्वरूप निष्पादन योग्य QFTASM कोड होता है।

0. MLZ 0 0 0;
1. MLZ -1 12 11;
2. MLZ -1 8 2;
3. MLZ -1 12 5;
4. MLZ -1 0 3;
5. MLZ -1 0 1;
6. MLZ -1 0 7;
7. SUB A1 A5 8;
8. MLZ A8 1 7;
9. MLZ -1 15 0;
10. MLZ 0 0 0;
11. ADD A3 A2 3;
12. ADD A1 1 1;
13. MLZ -1 0 7;
14. SUB A1 A5 8;
15. MLZ A8 1 7;
16. MNZ A7 10 0;
17. MLZ 0 0 0;
18. MLZ -1 A3 4;
19. MLZ -1 -2 0;
20. MLZ 0 0 0;

सिंटेक्स

अब जब हमें नंगे भाषा मिल गई है, तो हमें वास्तव में एक छोटा सा कार्यक्रम लिखना है। हम तार्किक ब्लॉक और नियंत्रण प्रवाह को विभाजित करते हुए पाइथन की तरह इंडेंटेशन का उपयोग कर रहे हैं। इसका मतलब है कि व्हाट्सएप हमारे कार्यक्रमों के लिए महत्वपूर्ण है। प्रत्येक पूर्ण कार्यक्रम में एक mainसबरूटीन होता है जो main()सी-लाइक भाषाओं में फ़ंक्शन की तरह कार्य करता है । कार्यक्रम की शुरुआत में फ़ंक्शन चलाया जाता है।

चर और प्रकार

जब चर को पहली बार परिभाषित किया जाता है, तो उनके साथ एक प्रकार जुड़ा होना चाहिए। वर्तमान में परिभाषित प्रकार हैं intऔर boolसरणियों के लिए सिंटैक्स के साथ परिभाषित हैं, लेकिन संकलक नहीं।

पुस्तकालय और संचालक

एक पुस्तकालय stdint.txtउपलब्ध है जो मूल संचालकों को परिभाषित करता है। यदि यह शामिल नहीं है, तो भी सरल ऑपरेटरों को परिभाषित नहीं किया जाएगा। हम इस पुस्तकालय का उपयोग कर सकते हैं #include stdintstdintजैसे ऑपरेटरों को परिभाषित करता है +, >>और यहां तक कि *और %, जिनमें से न तो प्रत्यक्ष QFTASM opcodes हैं।

भाषा QFTASM opcodes को भी सीधे कॉल करने की अनुमति देती है __OPCODENAME__

में जोड़ के stdintरूप में परिभाषित किया गया है

operator (int a + int b) -> int
    return __ADD__(a, b)

जो परिभाषित करता है कि +दो intएस दिए जाने पर ऑपरेटर क्या करता है ।


1
मैं पूछ सकता हूँ, क्यों यह जीवन के कोनवे के खेल में एक wireworld की तरह सीए बना सकते हैं और नहीं बल्कि पुन: उपयोग की तुलना में इस सर्किट का उपयोग कर एक नए प्रोसेसर बनाने का फैसला किया गया था / एक सार्वभौमिक कंप्यूटर cgol मौजूदा ऐसे पुनः स्थापित यह एक ?
eaglgenes101

4
@ eaglgenes101 शुरुआत के लिए, मुझे नहीं लगता कि हम में से अधिकांश अन्य प्रयोग करने योग्य सार्वभौमिक कंप्यूटरों के अस्तित्व के बारे में जानते थे। एक वायरवर्ल्ड की तरह सीए के लिए कई मिश्रित नियमों के साथ विचार मेटकाल्स के साथ खेलने के परिणामस्वरूप आया था (मेरा मानना ​​है - फी वही था जो विचार के साथ आया था)। वहां से, यह एक तार्किक प्रगति थी कि हमने क्या बनाया।
मेगो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.