سؤال

أنا أعمل على جهاز محاكاة للمعالج الدقيق ، مكتوب في C ++.

أنا أبحث عن وسيلة لنمذجة عناصر الحالة في الأجهزة التي تم تشغيلها للتو ولم تتم إعادة ضبطها بأي شكل من الأشكال. سيكون لعنصر الحالة الحقيقي قيمة غير معروفة إما 0 أو 1 ، ولكن في نماذج البرامج ، يتم تصميم هذا عادةً على أنه X, ، المعنى مجهول.

أنا أبحث عن مكتبة في C ++ يمكنها تصميمها X القيم ، بما في ذلك انتشارها. أي أنه يجب أن يعرف كيفية التعامل مع العمليات المنطقية والحساب XES:

1 AND X = X
0 AND X = 0
1  +  X = X

إلخ...

هل هناك أي مكتبة مستقرة وسريعة؟

يحرر:

أهملت أن أذكر أن الكود الحالي يعمل مع BitVectors. بشكل أكثر دقة ، أستخدم المعيار uint_*t أنواع البيانات ، وهذه هي تلك التي أريد استبدالها. مهما كانت المكتبة التي أستخدمها ، فهي يجب دعم الحساب والتحولات والمشغلين المنطقيين ليكون مفيدة.

هل كانت مفيدة؟

المحلول

قد ترغب في التفكير في السماح لأكثر من ثلاث ولايات ، إذا كنت تحاول تصميم خطوط الأجهزة. إليك ما تستخدمه Altera في محاكاة FPGA:

  • 1: ارتفاع قوي (ترانزستور مدفوع إلى VDD)
  • 0: انخفاض قوي (ترانزستور مدفوع إلى VSS)
  • H: ضعيف مرتفع (سحب المقاوم إلى VDD)
  • L: ضعيف منخفض (سحب المقاوم إلى VSS)
  • Z: مقاومة عالية (خط undriven)
  • X: غير معروف
  • W: ضعيف غير معروف
  • u: غير مهيئ
  • العاصمة: لا تهتم

قد لا تحتاج إلى W و U و DC. يمكنك التخلص من H و L و Z إذا كانت حافلاتك مدفوعة دائمًا.

يستخدم Verilog المزيد من المستويات النمذجة على مستوى البوابة, ، مع سبع نقاط قوة في كل مستوى منطقي. المستويات الإضافية نموذج التأثيرات السعة على خطوط الإشارة. ربما يكون هذا أكثر مما تحتاج.

تعديل: نظرًا لأنك ذكرت ناقلات البتات ، يجب أن أقول ذلك ، IMHO ، لن تجد مثل هذه المكتبة في الاستخدام العام واستمرت في محدثة لأن 1) لا يوجد الكثير من المبرمجين الذين يحتاجون إلى مثل هذا الشيء و 2) حتى بينهم ، بسبب الخيارات المذكورة أعلاه لنظمات خط النمذجة ، هناك القليل من التوافق. يمكن الضغط على Tribools في Boost في الخدمة ، لكنها لن تكون سريعة ، لأن العمليات ستكون عنصرًا تلو الآخر ولن يتم تحسين التخزين ، لكنهم قد يكونون خيارك الوحيد إذا كان شخص ما يعاني من حساسية من كتابة مكتبة داخلية يفعل بالضبط ما تحتاجه.

على سبيل المثال ، قل أنك تريد فئة تمثل متجهات البتات بأربعة مستويات محتملة: 1 و 0 و X و Z. أولاً ، عليك تحديد أنماط بت مكافئة لكل مستوى (على سبيل المثال x = 00 ، z = 01 ، 0 = 10 ، 1 = 11 ؛ تم اختيار x كحالة إعادة تعيين)

لكل عملية ، عليك أن تكتب جدول الحقيقة ، ويفضل في خريطة كارنو شكل:

op: &  | X (00) | Z (01) | 1 (11) | 0 (10)
-------+--------+--------+--------+--------
X (00) | X (00) | X (00) | X (00) | X (00)
-------+--------+--------+--------+--------
Z (01) | X (00) | X (00) | X (00) | X (00)
-------+--------+--------+--------+--------
1 (11) | X (00) | X (00) | 1 (11) | 0 (10)
-------+--------+--------+--------+--------
0 (10) | X (00) | X (00) | 0 (10) | 0 (10)

(لاحظ أن X يفوز كثيرًا. هذا صحيح بالنسبة لمعظم العمليات.)

ثم قم بعمل المعادلات المنطقية من خريطة K:

C = A & B
=> C1 = A1 & B1
   C0 = A1 & B1 & A0 & B0 = C1 & A0 & B0

أخيرًا ، قم بترجمة ذلك إلى C ++:

template<size_t NBits> class BitVector
{private:
    enum { NWords = (NBits+31)/32 };
    int32_t storage[NWords][2];
public:
    BitVector<NBits> operator &(BitVector<NBits>& rhs)
    {    BitVector<NBits> result;
         for(unsigned k = 0; k < NWords; ++k)
         {   int32_t x = storage[k][1] & rhs.storage[k][0];
             result.storage[k][1] = x;
             result.storage[k][0] = storage[k][0] & rhs.storage[k][0] & x;
         }
         return result;
    }
};   

(ملاحظة: لم أختبر الرمز أعلاه ، لذا استخدم على مسؤوليتك الخاصة.)

الجميع من هذا يجب إعادة تشكيله إذا تغيرت مجموعة من المستويات المسموح بها. هذا هو السبب في أن هذه المكتبات تميل إلى أن تكون متخصصة جدًا في وضعها في مكتبة الاستخدام العام مثل Boost.

EDIT2: لقد بزغت علي أن فئة قالب BitVector لديها واحدة من حالات الاستخدام القليلة التي يكون فيها الحمل الزائد لمشغل الفاصلة منطقيًا:

template<size_t NBitsR>
BitVector<NBits+NBitsR> operator ,(const BitVector<NBitsR>& rhs);

هذا يتيح لك تسلسل ناقلات بت:

BitVector<8> a("1110 0111");
BitVector<4> b("0000");
BitVector<12> c = (a, b); // == BitVector<12>("0000 1110 0111")

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

EDIT3: لقد بزغت علي فقط (نعم ، أنا بطيء) ، إذا كنت حقًا أردت أن تفعل نسخة معممة من هذا ، يمكنك القيام بذلك مع التصميم القائم على السياسة:

struct TwoLevelLogic
{   enum
    {   kNumPlanes = 1
    };
    static void And(int32_t[] result, int32_t[] lhs, int32_t[] rhs)
    {    result[0] = lhs[0] & rhs[0];
    }
};

struct FourLevelLogic
{   enum
    {   kNumPlanes = 2
    };
    static void And(int32_t[] result, int32_t[] lhs, int32_t[] rhs)
    {    int32_t x = lhs[1] & rhs[1];
         result[1] = x;
         result[0] = lhs[0] & rhs[0] & x;
    }
};

template<typename LogicType, size_t NBits>
class BitVector
{private:
    enum { NWords = (NBits+31)/32 };
    int32_t storage[NWords][LogicType::kNumPlanes];
public:
    BitVector<LogicType, NBits> operator &(BitVector<LogicType, NBits>& rhs)
    {    BitVector<LogicType, NBits> result;
         for(unsigned k = 0; k < NWords; ++k)
             LogicType::And(result.storage[k], storage[k], rhs.storage[k]);
         return result;
    }
};

template<size_t NBits> 
class BitVector4L: public BitVector<FourLevelLogic, NBits> {};

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

مرة أخرى ، لم أحاول بناء هذا ، لذلك لست متأكدًا مما إذا كان هذا يتحسن تمامًا.

نصائح أخرى

محاولة Boost.tribool.

ال tribool أعمال الطبقة مثل المدمجة bool اكتب ، ولكن للمنطق المنطقي من 3 حالات. الدول الثلاث true, false, ، و indeterminate, ، حيث تكون الدولتين الأولين مكافئًا لتلك الموجودة في C ++ bool النوع والدولة الأخيرة تمثل قيمة منطقية غير معروفة (قد تكون هذه true أو false, ، لا نعرف).

يمكنك ان ترا ال بدلة اختبار و ال وثائق الرأس للقواعد التي تدعمها هذه الفئة.

تعتبر المكتبات Boost عالية الجودة وصيانتها جيدًا ، لذلك لا داعي للقلق بشأن استقرارها. و "Fast" ... حسنًا ، من الصعب أن تكون بطيئًا في فصول بسيطة مثل هذا :). يتم تنفيذ العمليات بمقارنة 2 إلى 3 عدد صحيح مع 1 أو 2 if الجمل لذلك يجب أن تكون فعالة بما فيه الكفاية.

يحتوي Boost على مكتبة Tribool ، لكن لا يمكنني التعليق على جودتها لأنني لم أستخدمها أبدًا:

http://www.boost.org/doc/libs/1_44_0/doc/html/tribool.html

لست على دراية بمكتبة Boost المذكورة أعلاه ، لكن يبدو أنها تدعم منطقية واحدة فقط وليس Bitfield. يمكنك أن تفعل ذلك بنفسك دون الكثير من الضجة باستخدام تقنية مثل ما يلي:

class Logic
{
    unsigned x, xu;

public:
    Logic(unsigned x, unsigned xu)
    {
        this->x = x;
        this->xu = xu;
    }

    Logic operator&(const Logic &rhs) const
    {
        return Logic(
            x & rhs.x,
            xu & (rhs.x | rhs.xu) | rhs.xu & (x | xu));
    }

    Logic operator|(const Logic &rhs) const
    {
        return Logic(
            x | rhs.x,
            xu & (~rhs.x | rhs.xu) | rhs.xu & (~x | xu));
    }
};

إخلاء المسئولية - هذا يحتاج إلى التحقق!

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top