Question

J'ai une (un peu) grande table de vérité / machine d'état que je dois implémenter dans mon code (C intégré). Je prévois que la spécification de comportement de cette machine à états changera dans le futur, et j'aimerais donc que cela reste facilement modifiable à l'avenir.

Ma table de vérité comporte 4 entrées et 4 sorties. J'ai tout cela dans une feuille de calcul Excel, et si je pouvais simplement le coller dans mon code avec un petit formatage, ce serait l'idéal.

Je pensais que je voudrais accéder à ma table de vérité comme suit:

u8 newState[] = decisionTable[input1][input2][input3][input4];

Ensuite, je pourrais accéder aux valeurs de sortie avec:

setOutputPin( LINE_0, newState[0] );
setOutputPin( LINE_1, newState[1] );
setOutputPin( LINE_2, newState[2] );
setOutputPin( LINE_3, newState[3] );

Mais pour obtenir cela, il semble que je devrais faire un tableau assez déroutant comme ceci:

static u8 decisionTable[][][][][] =
 {{{{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }},
   {{ 0, 0, 0, 0 },
    { 0, 0, 0, 0 }}},
  {{{ 0, 0, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}},
 {{{{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}},
  {{{ 0, 1, 1, 1 },
    { 0, 1, 1, 1 }},
   {{ 0, 1, 0, 1 },
    { 1, 1, 1, 1 }}}};

Ces crochets imbriqués peuvent être quelque peu déroutants. Quelqu'un a-t-il une meilleure idée de la façon dont je peux conserver un joli tableau dans mon code?

Merci!

Modifier en fonction de la réponse de HUAGHAGUAH:

En combinant les contributions de chacun (merci - j'aimerais pouvoir "accepter" 3 ou 4 de ces réponses), je pense que je vais l'essayer comme un tableau à deux dimensions. Je vais indexer dans mon tableau en utilisant une petite macro à décalage:

#define SM_INPUTS( in0, in1, in2, in3 ) ((in0 << 0) | (in1 << 1) | (in2 << 2) | (in3 << 3))

Et cela laissera mon tableau de tables de vérité ressembler à ceci:

static u8 decisionTable[][] = {
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 1, 1 },
{ 0, 1, 0, 1 },
{ 1, 1, 1, 1 }};

Et je peux alors accéder à ma table de vérité comme suit:

decisionTable[ SM_INPUTS( line1, line2, line3, line4 ) ]

Je vais tenter le coup et voir comment ça marche. Je remplacerai également les 0 et les 1 par des # définitions plus utiles qui expriment la signification de chaque état, ainsi que des commentaires / ** / qui expliquent les entrées pour chaque ligne de sorties. Merci à tous pour votre aide!

Était-ce utile?

La solution

Pas besoin de table multidimensionnelle. Avec un 4 bits = > Mappage 4 bits, vous pouvez avoir un seul tableau u8 [16] mappant les entrées sur les sorties. Les recherches d’état seront beaucoup moins chères et vous pouvez extraire des bits individuels avec des opérations de décalage et de masquage.

Si l'algorithme de remplissage des lignes est facile à codifier, vous pouvez # définir une macro pour remplir chaque ligne par son numéro d'index.

Autres conseils

Je suggérerais soit (approches privilégiées en premier):

  • Utilisez une macro pour initialiser chaque " rangée " - Cela masquera les accolades dans l'appel de macro.
  • Utilisez les commentaires pour séparer les lignes.
  • Utilisez une fonction init pour initialiser le contexte explicitement - utilisez éventuellement des fonctions pour initialiser chaque section. Ceci est similaire à la première option ci-dessus mais présente un inconvénient, à savoir que la fonction init doit être appelée avant que la machine à états ne puisse être utilisée.

Personnellement, je le lirais depuis un fichier de configuration. CSV, peut-être, qui est facile à exporter depuis Excel. Ou vous pouvez simplement copier et coller d'Excel dans du texte brut, ce qui vous donne des valeurs séparées par des espaces, ce qui est également facile à importer.

Cela signifie également, étant donné que vous travaillez avec C, que vous n’aurez pas à recompiler votre code à chaque modification de la table de décision.

si votre table de vérité est entièrement booléenne, vous pouvez simplement la réduire en une liste de paires, par exemple.

1111,0000
1110,0110
...

pour la compression des données, représente les valeurs en octets (deux nybbles) ...

Où / comment le stocker pour le codage logiciel dans votre configuration de système intégré particulière, vous seul pouvez dire; -)

Si la table de vérité est vraiment seulement 4x4x4x4, alors j'utiliserais des macros. Si jamais cela dépassait ce seuil, j'utiliserais Ragel . Il est probable que le code C sera plus petit et plus rapide que vous ne le ferez.

Je ne vois aucune référence à l'état actuel afin d'obtenir votre état de sortie. Cela signifie que ce n'est pas une machine à états, mais seulement une table de vérité. Il y a quatre entrées, il n'y a donc que 16 combinaisons d'entrées possibles. Donc, une table à 16 positions devrait le faire.

Généralement, lorsque vous rencontrez un problème de ce type, on essaie de le réduire à une simple formule booléenne. Je ne vois pas pourquoi cela ne serait pas la meilleure approche ici. Il serait beaucoup plus compact et lisible, en plus d’être potentiellement plus rapide (j’imagine qu’une poignée d’ET et de RUP serait exécutée plus rapidement que la collection de multiplications / déplacements + accès mémoire nécessaires pour l’approche par table de correspondance). Le moyen le plus simple de réduire ce tableau à une formule booléenne consiste à utiliser un K-Map .

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