Frage

Ich arbeite an einem Simulator für einen Mikroprozessor, in C ++ geschrieben.

Ich bin auf der Suche nach einer Möglichkeit, Modellzustand Elemente in der Hardware, die gerade hat mit Strom versorgt und noch nicht zurückgesetzt in irgendeiner Weise gewesen. Ein echter Zustand Element würde einen unbekannten Wert hat, die entweder 0 oder 1 ist, aber in Softwaremodellen dies wird allgemein als X modelliert, was bedeutet, unbekannt .

Ich bin für eine Bibliothek in C ++, die diese X Werte modellieren können, einschließlich ihrer Vermehrung. Das heißt, hätte es wissen, wie logische und arithmetische Operationen mit Xes behandeln:

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

etc ...

Gibt es eine solche Bibliothek, die sowohl stabil ist und schnell?

Edit:

ich vernachlässigt zu erwähnen, dass meine aktuellen Code arbeitet mit bitvectors. Genauer gesagt, verwende ich die Typen Standard uint_*t Daten, und diese sind diejenigen, die ich ersetzen wollen. Was auch immer Bibliothek, die ich verwende, es muss Unterstützung Arithmetik, Verschiebungen und logische Operatoren für sie nützlich sein.

War es hilfreich?

Lösung

Sie können mehr als drei Zustände erlauben, denken, wenn Sie Modell Hardware-Linien versuchen. Hier ist, was Altera Anwendungen in seinem FPGA-Simulator:

  • 1: Strong High (Transistor auf VDD angetrieben)
  • 0: Starke Low (Transistor VSS angetrieben)
  • H: Schwaches High (Pullup-Widerstand zu VDD)
  • L: Schwach Low (Widerstand Pulldown VSS)
  • Z: High Impedance (nicht angetriebene Linie)
  • X: Unbekannt
  • W: Schwach Unbekannt
  • U: Nicht initialisiert
  • DC: Do not Care

Sie werden vielleicht nicht W, U, und DC benötigen. Sie können Graben H, L und Z, wenn Ihre Busse sind immer angetrieben.

Verilog verwendet noch mehr Ebene für Gate-Level-Modellierung , mit sieben Antrieb Stärken für jeden Logikpegel. Die zusätzlichen Stufen modellieren kapazitive Effekte auf den Signalleitungen. Dies ist wahrscheinlich mehr als Sie benötigen.

EDIT: Da Sie Vektoren von Bits erwähnt, ich habe zu sagen, dass meiner Meinung nach, du wirst doch nicht um eine solche Bibliothek in den öffentlichen Gebrauch und gehalten up-to-date, weil 1 zu finden) es gibt einfach nicht so viele Programmierer für die Modellierung von Leitungsebenen so etwas, und 2) auch unter ihnen, aufgrund der genannten Optionen benötigen, gibt es wenig Kompatibilität ist. Erhöhung des tribools kann in Dienst gedrückt werden, aber sie werden nicht schnell sein, da Operationen Element-für-Element sein und Lagerung nicht optimiert werden, aber sie können Ihre einzige Wahl sein, wenn jemand zu schreiben eine in-house allergisch Bibliothek dass tut genau das, was Sie brauchen.

Zum Beispiel, sagen Sie eine Klasse mögen, die Vektoren von Bits mit vier möglichen Ebenen repräsentiert: 1, 0, X und Z Erstens muss man für jede Ebene äquivalente Bitmuster definieren (zB X = 00, Z = 01, 0 = 10, 1 = 11; X als Rücksetzzustand gewählt wurde)

Für jede Operation, müssen Sie die Wahrheitstabelle schreiben, vorzugsweise in Karnaugh Karte Form :

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)

(Beachten Sie, dass X gewinnt viel. Das ist für die meisten Operationen wahr ist.)

Dann erarbeitet die Booleschen Gleichungen aus der K-Karte:

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

Schließlich übersetzen, dass in 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;
    }
};   

. (Anmerkung: Ich habe nicht den Code oben, so Nutzung auf eigene Gefahr getestet)

Alle dies nochmals gemacht, wenn die Menge der erlaubten Grenzwerte Änderungen sein muss. Aus diesem Grund ist diese Bibliotheken neigen dazu, zu spezialisiert, die in eine allgemeine Verwendung Bibliothek wie Boost zu setzen.

EDIT2: Es mir gerade aufgegangen, dass die Bitvektor Template-Klasse eine der wenigen Anwendungsfälle hat, wo das Komma-Operator sinnvoll ist, eine Überlastung:

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

Auf diese Weise können Sie verketten Bitvektoren:

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

... das scheint, wie die intuitive Art und Weise zu Pad ein Vektor der Größe eines anderen (es ist einfach sollte, dass eine solche Polsterung zeigen nicht implizit sein, immer ) oder merge Vektoren zusammen.

EDIT3: Es ist einfach dämmerte mir (ja, ich bin langsam), dass, wenn Sie wirklich wollte eine verallgemeinerte Version, dies zu tun, man könnte es tun mit richtlinienbasierte Design :

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> {};

Wenn Sie dann eine andere Logik Darstellung verwenden wollen, sagen neun Ebenen, oder sogar zwei, dann könnten Sie neue Richtlinien definieren, diese Formate zu unterstützen. Darüber hinaus können Sie mit verschiedenen Politiken in verschiedenen Bereichen Ihres Problems berechnen (sagen wir, 4 Ebenen für Ihr Brett, 9 für den Chip und 2 für einen Prozessor-Simulator) und Konvertierungsfunktionen zu definieren, um die Lücken überbrücken.

Noch einmal, ich habe nicht versucht, diese zu bauen, so dass ich nicht sicher bin, ob Dies optimiert perfekt.

Andere Tipps

Versuchen Sie Boost.Tribool .

  

Die tribool Klasse verhält sich wie die eingebaute in bool Typ, aber für 3-Zustand der Booleschen Logik. Die drei Zustände sind true, false und indeterminate, wobei die ersten beiden Zustände, die denen der C entsprechen ++ bool Typ und dem letzten Zustand einen unbekannten boolean Wert darstellt (das kann true oder false sein, wissen wir nicht).

Sie sehen die Testanzug und die Header Dokumentation für diese Klasse unterstützt die Regeln.

Boost-Bibliotheken sind ziemlich hohe Qualität und gut gepflegt, so dass Sie sich keine Sorgen machen um seine Stabilität brauchen. Und „schnell“ ... gut ist es schwer, wie diese :) langsam für einfache Klassen zu sein. Die Operationen mit 2 bis 3 Integer-Vergleich mit 1 oder 2 if Klauseln umgesetzt werden, so sollte es effizient genug sein.

-Boost hat eine tribool Bibliothek, aber ich kann auf seiner Qualität nicht kommentieren, da ich es nie benutzt:

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

Ich bin nicht vertraut mit der Boost-Bibliothek oben erwähnt, aber es scheint, es unterstützt nur eine einzige boolean und kein bitfield. Sie könnten selbst tun es, ohne zu viel Aufhebens eine Technik wie die folgenden verwenden:

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));
    }
};

Disclaimer - diese Überprüfung Bedürfnisse

Wenn Sie tun viele von ihnen zu einem Zeitpunkt planen, sind Sie besser dran mit 64-Bit-Integer anstelle von einzelnen tribools.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top