مصادر الإلهام عند تطوير UDB

حسنًا ، نحن نعرف بالفعل كل ما تحتاجه لبرمجة UDB. ولكن هناك شيء يجب معرفته ، وشيء آخر تمامًا أن نكون قادرين عليه. لذلك ، سنناقش اليوم أين وكيف نستمد الإلهام من أجل تحسين مهاراتنا الخاصة ، أين نكتسب الخبرة. كما يتضح من ترجمة الوثائق ، هناك معرفة جافة ليست مرتبطة دائمًا بالممارسة الحقيقية (لفتت الانتباه إلى ذلك في ملاحظة طويلة إلى آخر ترجمة حتى الآن). في الواقع ، تظهر إحصائيات طرق عرض المقالات أن عددًا أقل وأقل من الناس يقرؤون الترجمات. كان هناك حتى اقتراح لمقاطعة هذه الدورة ، باعتبارها غير مفيدة ، ولكن بقيت جزأين فقط ، لذلك ، في النهاية ، تقرر ببساطة تقليل وتيرة تحضيرها. بشكل عام ، وثائق وحدة تحكم هو شيء ضروري ، ولكن ليس الاكتفاء الذاتي. مكان آخر للحصول على الإلهام؟



بادئ ذي بدء ، يمكنني أن أوصي بالوثيقة الممتازة AN82156 Designing PSoC Creator Components مع UDB Datapaths . ستجد فيه حلولًا نموذجية ، بالإضافة إلى العديد من المشاريع القياسية. علاوة على ذلك ، في بداية الوثيقة ، يتم التطوير باستخدام محرر UDB ، وفي النهاية ، باستخدام أداة تكوين Datapath ، أي أن الوثيقة تغطي جميع جوانب التطوير. لكن لسوء الحظ ، عند النظر إلى سعر شريحة PSoC واحدة ، يمكنني القول أنه إذا كان لا يمكن حل المشكلات الموضحة في هذه الوثيقة إلا بشكل مبالغ فيه. PWMs والمنافذ التسلسلية القياسية يمكن القيام به دون PSoC. لحسن الحظ ، نطاق مهام PSoC أوسع بكثير. لذلك ، بعد الانتهاء من قراءة AN82156 ، نبدأ في البحث عن مصادر أخرى للإلهام.

المصدر المفيد التالي هو الأمثلة التي تأتي مع PSoC Creator. أشرت إليها بالفعل في ملاحظة إلى أحد أجزاء ترجمة وثائق الشركة (يمكنك أن ترى هنا ). يتم تخزينها هنا تقريبًا (قد يختلف القرص):

E: \ ملفات البرنامج (x86) \ Cypress \ PSoC Creator \ 4.2 \ PSoC Creator \ psoc \ content \ CyComponentLibrary.

يجب عليك البحث عن ملفات * .v ، أي النصوص verilog ، أو * .vhd ، نظرًا لأن بناء جملة لغة VHDL يحتاج إلى مزيد من الوصف ، وفي هذه اللغة ، قد تجد أحيانًا فروق دقيقة مثيرة للاهتمام مخفية عن أعين المبرمج في Verilog. المشكلة هي أن هذه ليست أمثلة ، لكنها حلول جاهزة. هذا شيء رائع ، تم تصحيحه تمامًا ، لكننا ، نحن المبرمجون ، لدينا أهداف مختلفة مع مبرمجي Cypress. مهمتنا هي القيام بشيء مساعد في وقت قصير ، وبعد ذلك نبدأ في استخدامه في مشاريعنا ، والتي ستقضي معظم وقتنا عليها. يجب أن يحل بشكل مثالي المهام الموكلة إلينا اليوم ، وإذا أردنا غدًا إدراج نفس الكود في مشروع آخر ، حيث سيكون كل شيء مختلفًا بعض الشيء ، فإننا سننتهي غدًا في ظل هذه الحالة. بالنسبة لمطوري Cypress ، يكون المكون هو المنتج النهائي ، بحيث يمكنهم قضاء معظم الوقت عليه. ويجب أن توفر للجميع. لذلك عندما شاهدت هذه النصوص ، شعرت بالحزن. إنها معقدة للغاية بالنسبة لشخص بدأ للتو البحث عن مكان يستلهم منه التطورات الأولى. ولكن كمراجع هذه النصوص مناسبة تمامًا. هناك العديد من التصاميم القيمة المطلوبة عند إنشاء الأشياء الخاصة بك.

أيضا هناك زوايا مثيرة جدا للاهتمام. على سبيل المثال ، يوجد الآن في أسلوب "زيت الزبدة" نماذج لنمذجة (منذ فترة طويلة ، لم يشجعني المعلم القوي على ترجمة المحاكاة بأي طريقة أخرى غير "النمذجة"). يمكن العثور عليها في الكتالوج.
E: \ ملفات البرنامج (x86) \ Cypress \ PSoC Creator \ 4.2 \ PSoC Creator \ warp \ lib \ sim.

الدليل الأكثر إثارة للاهتمام للمبرمج على Verilogue هو:

E: \ ملفات البرنامج (x86) \ Cypress \ PSoC Creator \ 4.2 \ PSoC Creator \ warp \ lib \ sim \ presynth \ vlg.

وصف المكونات في الوثائق جيد. ولكن النماذج السلوكية لجميع المكونات القياسية موصوفة هنا. في بعض الأحيان يكون هذا أفضل من الوثائق (المكتوبة بلغة ثقيلة ، بالإضافة إلى حذف بعض التفاصيل الأساسية). عندما يكون سلوك هذا المكون أو ذاك غير واضح ، فإن الأمر يستحق البدء في محاولة لفهمه بدقة من خلال عرض الملفات من هذا الدليل. في البداية ، حاولت البحث على Google ، لكن في كثير من الأحيان التقيت في المنتديات التي تم العثور عليها فقط للتفكير وليس في التفاصيل. هنا هو بالضبط التفاصيل.

ومع ذلك ، فإن الكتاب المرجعي رائع ، ولكن من أين تبحث عن كتاب مدرسي ، ماذا نتعلم منه؟ بصراحة ، لا يوجد شيء مميز. لا توجد العديد من الأمثلة الجيدة الجاهزة لمحرر UDB. كنت محظوظًا جدًا عندما قررت فجأة تشغيل RGB LEDs ، صادفت مثالًا جميلًا تحت محرر UDB (كتبت عنه في المقالة التي بدأت الدورة بأكملها). ولكن إذا كنت تعمل كثيرًا مع محرك بحث ، فستظل هناك أمثلة لأداة تكوين Datapath ، ولهذا السبب قمت بصياغة المقالة السابقة حتى يفهم الجميع كيفية استخدام هذه الأداة. توجد هنا صفحة رائعة تم جمع الكثير من الأمثلة عليها.

في هذه الصفحة توجد تطورات قام بها مطورو الطرف الثالث ، ولكن تم التحقق منها بواسطة Cypress. هذا هو ما نحتاج إليه تمامًا: نحن أيضًا مطورون تابعون لجهات خارجية ، لكننا نريد أن نتعلم من شيء تم التحقق منه بدقة. دعونا نلقي نظرة على مثال حيث وجدت هذه الصفحة - آلة حاسبة لأجهزة الجذر التربيعي. يقوم المستخدمون النهائيون بإدراجه في مسار معالجة الإشارات ، ورمي أحد المكونات على الدائرة. في هذا المثال ، سنتدرب على تحليل رمز مشابه ، وبعد ذلك سيكون الجميع قادرين على بدء السباحة المستقلة. لذلك ، يمكن تنزيل المثال الضروري من الرابط .

نحن ندرسها. هناك أمثلة (سوف يفكر فيها الجميع بشكل مستقل) وهناك مكتبات موجودة في الدليل \ CJCU_SquareRoot \ Library \ CJCU_SquareRoot.cylib.

لكل نوع (عدد صحيح أو نقطة ثابتة) ولكل بت ، هناك حل. ينبغي أن يلاحظ هذا. تعد براعة الاستخدام جيدة عند التطوير في محرر UDB ، ولكن عند التطوير باستخدام Datapath Edit Tool ، كما ترون ، فإن الأشخاص يعذبون مثل هذا. لا تخف إذا لم تتمكن من القيام بذلك عالميًا (ولكن إذا كان ذلك أفضل).

في المستوى الأعلى (الدوائر) ، لن أتوقف ، نحن ندرس عدم العمل مع PSoC ، لكننا نعمل مع UDB. دعونا نلقي نظرة على خيار التعقيد المتوسط ​​- 16 بت ، ولكن عدد صحيح. وهو موجود في الدليل CJCU_B_Isqrt16_v1_0.

أول شيء فعله هو توسيع الرسم البياني انتقال البرامج الثابتة. بدون ذلك ، لن نخمن حتى نوع خوارزمية الجذر التربيعي التي تم تطبيقها ، نظرًا لأن Google تقدم مجموعة من الخوارزميات المختلفة اختلافًا أساسيًا.



حتى الآن ، ليس هناك ما هو واضح ، لكنه يمكن التنبؤ به. تحتاج إلى إضافة المزيد من المعلومات. نحن ننظر إلى الترميز الدولة. من اللافت للنظر أنها غير مشفرة في الكود الثنائي الإضافي المعتاد.



لقد ذكرت بالفعل هذا النهج في مقالاتي ، لكنني لم أتمكن مطلقًا من استخدامه في أمثلة محددة. اسمحوا لي أن أذكرك أن التكوين الديناميكي RAM ALU يحتوي على ثلاثة مدخلات فقط من العناوين. وهذا هو ، يمكن ALU إجراء واحدة من ثماني عمليات. إذا كان الإكمال التلقائي يحتوي على مزيد من الحالات ، فإن القاعدة "لكل ولاية عملياتها الخاصة" تصبح مستحيلة. لذلك ، يتم تحديد الحالات التي تكون فيها عمليات ALU متطابقة ، ولديها ثلاث وحدات بت مقدمة إلى عنوان ذاكرة الوصول العشوائي للتكوين الديناميكي (عادةً ما تكون منخفضة الترتيب) ، ويتم ترميزها بنفس الطريقة ، والباقي بطرق مختلفة. كيفية إضافة ما يصل مثل هذا سوليتير هو بالفعل مشكلة المطور. مطوري الكود المدرسي مطوي تمامًا كما هو موضح أعلاه.

أضف هذه المعلومات إلى الرسم البياني ، بالإضافة إلى تلوين الحالات التي تؤدي نفس الوظيفة في ALU بألوان مماثلة.



لم تظهر أي أنماط حتى الآن ، لكننا نواصل فتح الرسم البياني. نفتح أداة تحرير Datapath ونحن ندرس المنطق الموجود فيها بالفعل.

يرجى ملاحظة أن لدينا كتل Datapath متصلة في سلسلة. عندما نفعل شيئًا من جانبنا ، فقد نحتاج أيضًا إلى ذلك (على الرغم من أن أداة تحرير Datapath يمكنها إنشاء كتل مرتبطة بالفعل في سلسلة ، وهذا ليس مخيفًا):



عند قراءة (وملء) الرسم البياني المقابل لـ ALU ، نفتح دائمًا مستندًا بالشكل التالي:



صحيح أن مطوري هذا المثال اهتموا بنا وأملأوا حقول التعليق. الآن يمكننا استخدامها لفهم ما تم تكوينه من أجل. في الوقت نفسه ، نلاحظ بأنفسنا أن كتابة التعليقات مفيدة دائمًا لأولئك الذين سيرافقون الشفرة ولنا عندما ننسى كل شيء في غضون ستة أشهر.

ننظر إلى رمز X000 المطابق للحالات 0 و 12:



من التعليق ، من الواضح بالفعل ما يحدث هناك (يتم نسخ محتويات السجل D0 للتسجيل A0 ، ويتم نسخ محتويات D1 للتسجيل A1. مع العلم بذلك ، نقوم بتدريب حدسنا للمستقبل وإيجاد إدخال مماثل في حقول الإعدادات:



هناك نرى أن ALU تعمل في وضع PASS ، كما أن سجل التحول هو PASS ، بحيث لا يتم تنفيذ أي إجراءات أخرى بالفعل.

على طول الطريق ، ننظر إلى النص في فيريلوج ونرى أين تساوي قيمة السجلات D0 و D1:



إذا رغبت في ذلك ، يمكن رؤية الشيء نفسه في أداة تكوين Datapath ، عن طريق اختيار عرض> قيم التسجيل الأولية:





للعرض ، من الأنسب تحليل شفرة Verilog مباشرةً ، لإنشاء نسختك الخاصة - العمل من خلال المحرر حتى لا تضع صيغة الجملة في الاعتبار.

وبالمثل ، نقوم بتحليل (أولاً ، استعراض التعليقات) جميع الوظائف الأخرى لـ ALU:



نعيد رسم الرسم البياني للتحول الآلي مع مراعاة المعرفة الجديدة:



هناك شيء ما يلوح في الأفق بالفعل ، ولكن حتى الآن لا يمكنني وضع أي من الخوارزميات التي عثرت عليها Google على هذا الرسم البياني بثقة. بدلاً من ذلك ، بالنسبة للبعض ، يمكنك أن تقول بثقة أنه ليس كذلك ، ولكن حتى بالنسبة إلى المتصدقين ، ما زلت لا أستطيع إعطاء إجابة واثقة بأنها هذه. يخلط بين الاستخدام الفعال للسجلات FIFO F0 و F1. عموما في الملف

\ CJCU_SquareRoot \ Library \ CJCU_SquareRoot.cylib \ CJCU_Isqrt_v1_0 \ API \ CJCU_Isqrt.c

يمكن ملاحظة أن F1 يستخدم لتمرير الوسيطة وإرجاع النتيجة:



نفس النص:
void `$INSTANCE_NAME`_ComputeIsqrtAsync(uint`$regWidth` square) { /* Set up FIFOs, start the computation. */ CY_SET_REG`$dpWidth`(`$INSTANCE_NAME`_F1, square); CY_SET_REG8(`$INSTANCE_NAME`_CTL, 0x01); } … uint`$resultWidth` `$INSTANCE_NAME`_ReadIsqrtAsync() { /* Read back result. */ return CY_GET_REG`$dpWidth`(`$INSTANCE_NAME`_F1); } 


لكن حجة واحدة ونتيجة واحدة. ولماذا هناك الكثير من المكالمات إلى FIFO في سياق العمل؟ وما علاقة FIFO0 به؟ اقتطعني إلى أجزاء ، ولكن يبدو أن المؤلفين استفادوا من الوضع الذي تمت مصادفته في ترجمة الوثائق ، عندما تم استخدام هذه المجموعة كسجل واحد بدلاً من سجل FIFO كامل. لنفترض أن المؤلفين قرروا توسيع مجموعة السجلات. إذا كان الأمر كذلك ، فعندئذ ستكون منهجيتهم مفيدة لنا في عملنا العملي ، دعنا ندرس التفاصيل. في الواقع ، تتحدث الوثائق عن الطرق المختلفة للعمل مع FIFO. يمكنك - لذلك ، يمكنك - لذلك ، ولكن يمكنك - نوع من. ولا تفاصيل. مرة أخرى ، لدينا فرصة للتعرف على أفضل الممارسات الدولية. ماذا يفعل المؤلفون مع FIFO؟

أولاً ، هذه هي تخصيصات الإشارة:

  wire f0_load = (state == B_SQRT_STATE_1 || state == B_SQRT_STATE_4); wire f1_load = (state == B_SQRT_STATE_1 || state == B_SQRT_STATE_3 || state == B_SQRT_STATE_9 || state == B_SQRT_STATE_11); wire fifo_dyn = (state == B_SQRT_STATE_0 || state == B_SQRT_STATE_12); 

ثانيا ، هنا هو اتصال Datapath:

  /* input */ .f0_load(f0_load), /* input */ .f1_load(f1_load), /* input */ .d0_load(1'b0), /* input */ .d1_load(fifo_dyn), 

من وصف وحدة التحكم فإنه ليس من الواضح بشكل خاص ما يعنيه كل هذا. ولكن من "ملاحظة التطبيق" ، اكتشفت أن هذا الإعداد هو السبب في كل شيء:



بالمناسبة ، وبسبب هذا الإعداد بالتحديد ، لا يمكن وصف هذه الكتلة باستخدام محرر UDB. عندما تكون وحدات التحكم هذه في حالة ON ، يمكن لـ FIFO العمل على مصادر وأجهزة استقبال مختلفة. إذا كانت Dx_LOAD تساوي واحدًا ، فإن Fx تتبادل مع ناقل النظام ، إذا كان صفرًا ، ثم مع السجل المحدد هنا:



اتضح أن F0 يتبادل دائمًا مع السجل A0 و F1 في الحالات 12 و 0 - مع ناقل النظام (لتحميل النتيجة وتحميل الوسيطة) ، في حالات أخرى - مع A1.
علاوة على ذلك ، من كود Verilog ، اكتشفنا أنه في F0 سيتم تحميل البيانات في الحالات 1 و 4 ، وفي F1 - في الحالات 1 و 3 و 9 و 11.

أضف المعرفة المكتسبة إلى الرسم البياني. لتفادي اللبس أثناء تسلسل العمليات ، فقد حان الوقت أيضًا لاستبدال علامة التعيين "محرر UDB" بسهام Verilogov للتأكيد على أن المصدر هو قيمة الإشارة التي كانت موجودة قبل الدخول إلى الكتلة.



من وجهة نظر تحليل الخوارزمية ، كل شيء واضح بالفعل. أمامنا هو تعديل لهذه الخوارزمية:

 uint32_t SquareRoot(uint32_t a_nInput) { uint32_t op = a_nInput; uint32_t res = 0; uint32_t one = 1uL << 30; // The second-to-top bit is set: use 1u << 14 for uint16_t type; use 1uL<<30 for uint32_t type // "one" starts at the highest power of four <= than the argument. while (one > op) { one >>= 2; } while (one != 0) { if (op >= res + one) { op -= res + one; res += one << 1; } res >>= 1; one >>= 2; } return res; } 

فيما يتعلق بنظامنا فقط ، سيبدو كما يلي:

 uint32_t SquareRoot(uint32_t a_nInput) { uint32_t op = a_nInput; uint32_t res = 0; uint32_t one = 1uL << 14; // The second-to-top bit is set while (one != 0) { if (op >= res + one) { op -= res + one; res += one << 1; } res >>= 1; one >>= 2; } return res; } 

الولايات 4 و 10 ترميز السلسلة بشكل صريح:

  res >>= 1; 

لفروع مختلفة.

الخط هو:

  one >>= 2; 

تم ترميزه صراحة إما عن طريق زوج من الدولتين 6 و 7 ، أو زوج من الدولتين 9 و 7. في الوقت الحالي ، أريد أن أعلن: "حسنًا ، المخترعون هم نفس المؤلفين!" ، لكن قريبًا سيتضح سبب وجود مثل هذه الصعوبة في فرعين (يوجد في الفرع جيم والحل).

الدولة 2 ترميز فرع الشرطي. الدولة 7 يشفر بيان حلقة. عملية المقارنة في الخطوة 2 مكلفة للغاية. بشكل عام ، في معظم الخطوات ، يحتوي السجل A0 على المتغير. ولكن في الخطوة 1 ، يتم إلغاء تحميل المتغير إلى F0 ، وبدلاً من ذلك يتم تحميل القيمة res + one ، ثم في الخطوة 2 يتم تنفيذ الطرح لغرض المقارنة ، وفي الخطوتين 3 و 8 ، يتم استعادة قيمة واحد . لماذا ، في الخطوة 4 ، يتم نسخ A0 إلى F0 مرة أخرى ، لم أفهم. ربما هذا هو نوع من الأساس.

يبقى لمعرفة من هو الدقة ومن هو المرجع . نحن نعلم أن الحالة تقارن المرجع و الدقة + واحد. في الحالة 1 ، تتم إضافة A0 ( واحد ) و A1. لذلك هناك A1 هو الدقة . اتضح أنه في الحالة 11 A1 هي الدقة أيضًا ، وهو الذي يحصل على F1 ، والذي يتم تغذيته لإخراج الوظيفة. F1 في الحالة 1 هو المرجع بوضوح. أقترح إدخال تمايز اللون من السراويل المتغيرات. نشير إلى الدقة باللون الأحمر ، والمرجع باللون الأخضر ، والأخرى باللون البني (وليس متناقضًا تمامًا ، ولكن الألوان الأخرى أقل تباينًا).



في الواقع ، يتم كشف الحقيقة كاملة. نرى كيف يتغير A1 بشكل مؤقت من F1 للمقارنة والحسابات ، وكيف يتم استخدام نفس الاختلاف للمقارنة (في الواقع ، توليد بت C) ، وللمشاركة في الصيغة. نلاحظ أيضًا لماذا يتم تشفير المساحة الفارغة (الالتفافية) في خوارزمية C بواسطة فرع طويل من الرسم البياني الانتقالي للأوتوماتون (في هذا الفرع ، يتم تبادل السجلات مطابقة للتبادل الذي يحدث في فرع الشفرة الرئيسي). نحن نرى كل شيء.

والسؤال الوحيد الذي لا يتوقف أبدا عن عذاب هو كيف تحول المؤلفون إلى FIFO إلى وضع أحادي البايت؟ تشير الوثائق إلى أنك تحتاج إلى رفع بتات CLR في سجل التحكم الإضافي في وحدة ، لكن لا أرى أن API لديه مثل هذه السجلات. ربما شخص ما سوف يفهم هذا ويكتب في التعليقات.

حسنًا ، ولتطوير شيء خاص بهم - بالترتيب العكسي ، باستخدام المهارات المكتسبة.

استنتاج


لتطوير مهارات تطوير "البرامج الثابتة" القائمة على UDB ، من المفيد ليس فقط قراءة الوثائق ، ولكن أيضًا لاستلهام تصاميم الآخرين. يمكن أن تكون التعليمة البرمجية المرفقة مع PSoC Creator مفيدة كمرجع ، وسوف تساعدك النماذج السلوكية المتضمنة في برنامج التحويل البرمجي على فهم معنى المقصود في الوثائق بشكل أفضل. توفر المقالة أيضًا ارتباطًا لمجموعة من الأمثلة من الشركات المصنعة لجهات خارجية وتُظهر عملية تحليل أحد هذه الأمثلة.

في هذا الصدد ، يمكن اعتبار دورة مقالات حقوق الطبع والنشر المتعلقة بالعمل مع UDB مكتملة. سأكون سعيدًا إذا ساعد شخصًا ما في الحصول على المعرفة المفيدة في الممارسة العملية. هناك ترجمتان من الوثائق ، لكن الإحصائيات تظهر أنه لا يوجد أحد يقرأها تقريبًا. يتم التخطيط لها بشكل نظيف حتى لا تترك الموضوع باختصار.

Source: https://habr.com/ru/post/ar449960/


All Articles