La bibliothèque de C avec un support pour une valeur logique à 3: 0,1, X

StackOverflow https://stackoverflow.com/questions/3872717

  •  28-09-2019
  •  | 
  •  

Question

Je travaille sur un simulateur pour un microprocesseur, écrit en C ++.

Je cherche un moyen d'éléments d'état modèle dans le matériel qui viennent d'être alimentés et n'ont pas encore été remis à zéro en aucune façon. Un vrai élément d'état aurait une valeur inconnue qui est 0 ou 1, mais dans les modèles de logiciel ce qui est communément modélisé comme un X, ce qui signifie inconnu .

Je cherche une bibliothèque en C ++ qui peut modéliser ces valeurs X, y compris leur propagation. Autrement dit, il faudrait savoir comment gérer les opérations logiques et arithmétiques avec Xes:

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

etc ...

Y at-il une telle bibliothèque qui est à la fois stable et rapide?

Modifier

J'omis de mentionner que mon code actuel fonctionne avec bitvectors. Plus précisément, j'utilise les types de données standard de uint_*t, et ce sont ceux que je veux remplacer. Quelle que soit l'utilisation des bibliothèques I, il doit arithmétique de soutien, les déplacements et les opérateurs logiques pour qu'il soit utile.

Était-ce utile?

La solution

Vous voudrez peut-être penser à permettre plus de trois états, si vous essayez de lignes de matériel de modèle. Voici ce que Altera utilise dans son simulateur FPGA:

  • 1: Faible Elevée (transistor conduit à VDD)
  • 0: Forte Faible (transistor conduit à VSS)
  • H: Faible High (résistance à excursion haute VDD)
  • L: Faible (pulldown de résistance à VSS) Faible
  • Z: haute impédance (ligne non entraînée)
  • X: Inconnu
  • W: Inconnu Faible
  • U: Uninitialized
  • DC: Do not Care

Vous ne pourriez pas besoin W, U et DC. Vous pouvez fossé H, L et Z si vos bus sont toujours entraînés.

Verilog utilise des niveaux encore plus pour modélisation du niveau de la grille , avec sept entraînement les points forts de chaque niveau logique. Les niveaux supplémentaires modéliser les effets capacitifs sur les lignes de signal. Ceci est probablement plus que vous avez besoin.

EDIT: Puisque vous avez mentionné des vecteurs de bits, je dois dire que, à mon humble avis, tu ne vas pas trouver une telle bibliothèque dans l'usage du public et tenues à jour parce que 1) il tout simplement pas que beaucoup de programmeurs qui ont besoin d'une telle chose, et 2) même parmi eux, en raison des possibilités mentionnées ci-dessus pour la modélisation des niveaux de ligne, il y a peu de compatibilité. Les tribools Boost peuvent être pressés en service, mais ils ne seront pas rapides, car les opérations seront élément par élément et le stockage ne sera pas optimisé, mais ils peuvent être votre seul choix si quelqu'un est allergique à écrire une bibliothèque interne qui fait exactement ce dont vous avez besoin.

Par exemple, supposons que vous voulez une classe qui représente des vecteurs de bits avec quatre niveaux possibles: 1, 0, X et Z. Tout d'abord, vous devez définir des modèles de bits équivalents pour chaque niveau (par exemple X = 00, Z = 01, 0 = 10, 1 = 11; X a été choisi comme l'état de remise à zéro)

Pour chaque opération, vous devez écrire la table de vérité, de préférence sous la forme de Karnaugh Carte :

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)

(Notez que X gagne beaucoup. Cela est vrai pour la plupart des opérations.)

Ensuite, travailler les équations booléennes de la K-map:

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

Enfin, traduire en 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;
    }
};   

(Note:. Je ne l'ai pas testé le code ci-dessus, utilisez donc à vos propres risques)

Tous de ce doit être refait à neuf si l'ensemble des changements de niveaux autorisés. Voilà pourquoi ces bibliothèques ont tendance à être trop spécialisés pour mettre dans une bibliothèque d'utilisation générale comme Boost.

EDIT2: Il a juste commencé à me rendre que la classe de modèle est l'un des vecteur de bits rares cas d'utilisation où la surcharge l'opérateur virgule est logique:

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

Cela vous permet de vecteurs de bits concaténer:

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

... ce qui semble être la façon la plus intuitive pad un vecteur jusqu'à la taille d'une autre (il est facile de montrer que ce rembourrage doit pas implicite, jamais ) ou fusion des vecteurs ensemble.

EDIT3: Il vient me vint à l'esprit (oui, je suis lent) que, si vous vraiment voulait faire une version généralisée de cela, vous pouvez le faire avec conception basée sur la politique :

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

Alors, si vous voulez utiliser une autre représentation logique, soit neuf niveaux, ou même deux, alors vous pouvez définir de nouvelles politiques pour soutenir ces formats. De plus, vous pouvez calculer avec des politiques différentes dans les différents domaines de votre problème (par exemple, 4 niveaux pour votre conseil, 9 pour la puce, et 2 pour un simulateur de processeur) et définir des fonctions de conversion pour combler les lacunes.

Encore une fois, je n'ai pas essayé de construire, alors je ne sais pas si ce Optimise parfaitement.

Autres conseils

Boost.Tribool .

  

La classe tribool agit comme le type intégré de bool, mais pour la logique booléenne 3 états. Les trois états sont true, false et indeterminate, où les deux premiers états sont équivalents à ceux du C ++ type bool et le dernier état représente une valeur booléenne inconnue (qui peut être de true ou false, nous ne savons pas).

Vous pouvez voir le costume essai et la documentation d'en-tête pour les règles de cette classe de supports.

bibliothèques Boost sont très haute qualité et bien entretenu, de sorte que vous n'avez pas à vous soucier de sa stabilité. Et « rapide » ... eh bien, il est difficile d'être lent pour les classes simples comme ça :). Les opérations sont mises en œuvre avec 2 à 3 comparaison entier avec 1 ou 2 clauses de if il devrait donc être assez efficace.

Boost a une bibliothèque tribool, mais je ne peux pas commenter sa qualité puisque je jamais utilisé:

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

Je ne suis pas au courant de la bibliothèque Boost mentionné ci-dessus, mais il semble qu'il ne supporte qu'un seul booléenne et non un champ de bits. Vous pouvez le faire vous-même sans trop de bruit en utilisant une technique comme suit:

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

Avis légal - cette vérification des besoins

Si vous projetez de faire beaucoup d'entre eux à un moment, vous êtes mieux d'utiliser des entiers de 64 bits au lieu de tribools individuels.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top