La mise en œuvre d'algorithmes inertiels sur l'exemple de la modélisation logique des circuits numériques

1. Introduction


Nous passons à la deuxième partie du sujet consacrée aux automates imbriqués. Dans le premier, nous avons examiné des algorithmes récursifs qui, ayant un modèle d'automates imbriqués et connectant des capacités OOP, ne se sont pas révélés si difficiles à mettre en œuvre. Mais les possibilités des automates imbriqués ne se limitent pas à cela. Ainsi, lors de la description du modèle de contrôle des programmes d'automates, des algorithmes inertiels ont été déterminés, qui sont également basés sur l'idée d'incorporer des automates. Les algorithmes inertiels sont difficiles à imaginer dans le cadre du schéma fonctionnel habituel du modèle de calcul, qui ne prévoit pas le retour du contrôle au point précédant l'appel du sous-programme. Mais je dois dire que les automates conventionnels prévoient également l'abolition des transitions "à la volée". Néanmoins, pour les automates, cela peut non seulement être imaginé, mais également implémenté.

Algorithmes inertiels et modélisation logique des thèmes liés aux circuits numériques. Et pas tant parce que le retard inertiel a donné le nom à la classe d'algorithmes considérée, mais combien le sens des actions retardées du retard inertiel, qui a été transféré au sens de leur travail. Bien sûr, ce n'est pas le nom. En UML, des algorithmes similaires sont implémentés en utilisant le concept d'état historique. L'analogie est simple, bien que la modélisation des circuits numériques en UML, en règle générale, soit hors de question. C’est juste que les situations de retour au point de départ, si quelque chose l’y oblige, semblent être les plus naturelles. Les exemples incluent le refus d'acheter des billets, l'annulation des opérations / transactions bancaires, la déconnexion d'une connexion réseau, etc. etc. En fin de compte, comme indiqué dans UML,sans l'utilisation d'états historiques, la mise en œuvre de tels algorithmes ne serait pas si «belle» [1].

Le sujet de la modélisation logique des circuits numériques est vaste et intéressant en soi. Et une nouvelle lecture ne lui fait pas de mal. Comme nous le verrons, la technologie de programmation automatique peut offrir une meilleure façon de décrire, de mettre en œuvre et de modéliser logiquement des circuits numériques. Nous apprendrons tout de même cela, en poursuivant l'objectif principal - considérer une classe d'algorithmes intéressante, utile et, finalement, juste une belle qui est naturelle pour les automates, mais assez difficile à implémenter dans d'autres modèles de calcul.

2. Modélisation logique des circuits numériques


La littérature considère généralement deux méthodes de modélisation des circuits numériques - la compilation et l'événement. La compilation est limitée dans ses capacités, car ne prend pas en compte les retards des éléments, nécessite des éléments de classement et des retours de rupture [2]. La méthode des événements n'a pas de telles restrictions et est basée sur le suivi des événements associés aux changements des valeurs de signal dans le circuit. Nous ne considérerons pas la compilation, mais nous nous concentrerons sur la comparaison de l'événement avec la méthode mise en œuvre dans le cadre des possibilités de programmation automatique, que nous appellerons plus loin, en conséquence, de manière automatique.

À titre d'exemple, prenez le circuit de [2], illustré à la Fig. 1. Des diagrammes de son travail à partir de la source sont montrés à la Fig. 2. Deux options sont envisagées: avec un seul retard, lorsque les éléments logiques du circuit ont le même retard, et avec un retard distribué, lorsque les éléments B et E ont un retard deux fois plus élevé que le reste des éléments du circuit.
image

Figure. 1. Un exemple de circuit.

image

Figure. 2. Exemples de modélisation: a - un seul retard; b - retard distribué.

Avec la méthode de simulation automatique, vous n’avez même pas besoin d’inventer quelque chose, car il n'est pas nécessaire de créer un langage suffisamment spécifique pour décrire un circuit et des structures qui mettent en œuvre des relations de circuit, et il n'a pas besoin d'algorithmes suffisamment spécifiques pour détecter les événements dans le processus de modélisation d'un circuit, qui servent ensuite de base à la construction de diagrammes du circuit (pour une description des deux, voir [2] )

Dans le cas des automates, les modèles d'éléments logiques, qui sont habituels pour la technologie des automates de conception de programmes, sont d'abord créés, qui sont inclus dans la bibliothèque d'éléments logiques (BLE). Ensuite, sur la base de cette bibliothèque, un ensemble de processus d'automates parallèles correspondant au nombre d'éléments de circuit est créé, entre lesquels les connexions sont indiquées à l'aide des canaux d'entrée / sortie des modèles d'éléments logiques (pour cela, dans l'environnement VKPA, les variables de processus locales sont souvent assez suffisantes). En conclusion, le modèle de circuit est complété par des processus générateurs de signaux d'entrée et des processus d'affichage de diagrammes de signaux.

Les résultats de simulation de l'exemple considéré dans l'environnement VKPa, qui sont présentés sur la Fig. 3 coïncident complètement avec les diagrammes de la Fig. 2. Certes, il n'a pas été immédiatement possible de réaliser une telle coïncidence. Et non pas à cause de problèmes avec les modèles, mais parce qu'en fait la «méthode de sélection scientifique» a dû calculer la durée des signaux d'entrée, ce qui s'est avéré avoir un impact significatif. Mais dans [2] aucun mot n'a été dit à ce sujet, ni sur les paramètres des signaux d'entrée. Un accord total a été obtenu en découvrant que 1) la durée égale à trois fois le retard est nécessaire, et 2) le décalage du signal (b) par rapport au signal (a) doit être égal au retard unitaire. Pour expliquer ce problème, voir fig. La figure 4 montre les diagrammes de signaux pour différentes durées des signaux d'entrée (et ceci sans tenir compte de leur déplacement).

image

Figure. 3. La simulation aboutit à VKPa: a - un seul retard; b - retard distribué.

image

Figure. 4. Résultats de simulation avec différentes durées de signal d'entrée

Prenons un autre exemple de circuit provenant de la même source [2]. Son schéma et ses chronogrammes de travail sont illustrés à la fig. 5. Dans le cadre de la méthode événementielle, pour «calculer» le chronogramme, 20 étapes de simulation ont été nécessaires (pour plus de détails voir [2]). Mais, comme il est indiqué ici, un algorithme encore plus complexe et, par conséquent, un nombre encore plus grand d'étapes sont nécessaires si le type de retards inertiels est choisi. Dans notre cas (le cas de la méthode de modélisation automatique), ayant le modèle précédent, nous avons besoin de «20 clics» avec la souris pour accéder au diagramme de la Fig. 5, supprimant les éléments inutiles du circuit d'origine. Les résultats de la simulation de circuit obtenue en VKPa sont présentés sur la Fig. 6.

image

Figure. 5. Un exemple de circuit et son chronogramme.

De plus, le diagramme de la Fig. 5, nous avons ajouté parallèlement à l'élément OU élément I. 6 affiche son fonctionnement dans le cas d'un seul retard. Si nous définissons un retard important et définissons le type de retard inertiel, le graphique d se transformera en ligne droite. Par conséquent, l'élément And avec un retard inertiel supérieur à une valeur unique ne manquera pas l'impulsion générée à ses entrées par une combinaison de ces signaux d'entrée a et b. Notez que la manipulation du type de retard n'a de sens que pour les éléments qui ont un retard supérieur à un.

image

Figure. 6. Modélisation du circuit de la Fig. 5 et l'élément And (d).

3. Mise en œuvre des éléments logiques


Dans le cas général, tout élément logique peut être représenté comme une connexion série de deux blocs (voir Fig. 7) - un élément logique idéal sans retard et un bloc, qui peut être considéré comme un retard de propagation (retard de transport) ou un retard inertiel [2].

image

Figure. 7. Modèle d'élément logique retardé.

Un élément logique idéal est très facilement implémenté par une fonction logique normale, et le modèle de bloc de retard peut être représenté sous la forme d'un modèle d'automate - un modèle universel qui inclut le transport et le retard inertiel. Un modèle d'un tel retard universel est illustré à la Fig. 8, et des modèles d'automates imbriqués pour celui-ci sont représentés sur la Fig. 9. Leur implémentation en C ++ et dans le cadre de la technologie de programmation automatisée est présentée dans le Listing 1.

image

Figure. 8. Le modèle du retard universel.

image

Figure. 9. Modèles d'automates imbriqués pour un retard universel.

Les machines de la Fig. 8 et fig. 9 sont des fusils d'assaut mixtes Mili-Moore. Le fonctionnement de l'automate principal de la Fig. 8. commence par créer des variables locales et initialiser les références dans l'action y12 (le prédicat x12 vérifie tout cela). L'état intermédiaire "ss" est nécessaire pour que le prédicat x3 fonctionne correctement, qui a un lien avec une variable d'entrée, qui peut ne pas être initialisée. A partir de l'état "ss", le modèle passe dans l'état correspondant à la sortie de retard, tout en provoquant un automate imbriqué. Notez que les actions sous les états d'un automate (actions des automates Moore) ne seront lancées qu'après la fin du fonctionnement d'un automate imbriqué. Ils définiront finalement la valeur de retard actuelle et l'état de la variable de sortie.

L'action y13, si une valeur de retard est définie, crée l'automate imbriqué nécessaire en fonction du type de retard. L'automate de retard de transport intégré compte simplement la valeur définie des cycles d'horloge à temps discrets (la durée du retard est déterminée par le nombre de cycles d'horloge discrets), et le retard inertiel contrôle en outre le niveau du signal d'entrée. Dans ce cas, nous notons que la valeur retournée du prédicat x3 dépend de l'état actuel de l'automate de niveau supérieur.

L'implémentation des automates sur la Fig. 8, 9 reflète le Listing 3. En considérant le code, vous devez faire attention à la méthode virtuelle f (), qui, d'une part, implémente l'une ou l'autre fonction logique abstraite qui se chevauchent, et, d'autre part, effectue, si spécifié, une inversion. Tout cela est nécessaire pour la mise en œuvre de modèles dérivés d'éléments logiques. Le listing 2 montre l'implémentation d'une telle porte NAND.

Listing 1. Implémentation d'un élément logique de retard universel
#include "lfsaappl.h"

extern LArc TBL_DiscreteTime[];
class FDiscreteTime :											
	public LFsaAppl											
{													
public:													
    enum {cvarINE, cvarExlusiveOR, cvarOrNot};
    void MooreAction();
	bool	FCreationOfLinksForVariables();								
    LFsaAppl* Create(CVarFSA *pCVF) { Q_UNUSED(pCVF) return new FDiscreteTime(nameFsa); }
	bool FInit();											
    FDiscreteTime(string strNam, LArc* pTBL = TBL_DiscreteTime);
	~FDiscreteTime(void);										
	CVar *pVarType;		// delay type 0-transport; 1- inertial
	CVar *pVarX1;		// input variable
	CVar *pVarStrNameX1;	// input variable name
    	CVar *pVarIfNotX1;	// inverse of the first input variable
    	CVar *pVarY1;		// output variable
	CVar *pVarStrNameY1;	// output variable name
	CVar *pVarValue01;	// delay value from 0 to 1
	CVar *pVarValue10;	// delay value from 1 to 0
    	CVar *pVarNegationY;// output inversion 0 - no inversion; 1- inversion
    	virtual int x3();	// input analysis
	virtual int x12();	// link setup analysis
    	virtual bool f();
    	int nTypeElement;
protected:
// predicates												
    int x1();
// actions												
	void y1(); void y4(); void y5(); void y6(); void y7(); void y12(); void y13(); 
    bool bType{false};	// delay type: false - transport; true - inertial;
    bool bX1{false};
    int nCurrent{0};
    int nDelay{0};		// tech. delay counter value
    LFsaAppl	*pFCall{nullptr};
    friend class FCallTransport;
    friend class FCallInertial;
};		

class FCallTransport :
	public LFsaAppl
{
public:
	void MooreAction();
	FCallTransport(FDiscreteTime	*pFDiscreteTime);
	FDiscreteTime	*pFDiscreteTime;
protected:
	int x1();
};

class FCallInertial :
	public LFsaAppl
{
public:
	void MooreAction();
	FCallInertial(FDiscreteTime	*pFDiscreteTime);
	FDiscreteTime	*pFDiscreteTime;
protected:
    int x1(); int x3();
};

#include "stdafx.h"
#include "FDiscreteTime.h"											
#include "VARFSA/SetVarFsaLibrary.h"
//=====================================================================
//		Delay model at the upper structural level of the view
//=====================================================================
LArc TBL_DiscreteTime[] = {
    LArc("st",	"st","^x12","y12"),	//
    LArc("st",	"ss","x12", "--"),	//
    LArc("ss",	"s1","x3",  "y7y6y13"),// transition to a single state
    LArc("ss",	"s0","^x3", "y4y5y13"),// transition to zero state
// creation of a nested automaton at the transition to a single state
    LArc("s0",	"s1","x3",  "y13"),    
// creation of a nested automaton at the transition to the zero state
    LArc("s1",	"s0","^x3", "y13"),    
    LArc()
};
FDiscreteTime::FDiscreteTime(string strNam, LArc* pTBL):
    LFsaAppl(pTBL, strNam, nullptr, nullptr)
{ }
													
FDiscreteTime::~FDiscreteTime(void) { if (pFCall) delete pFCall; }

bool FDiscreteTime::FInit() {										
    FCreationOfLinksForVariables();
    return true;
}

bool FDiscreteTime::FCreationOfLinksForVariables()
{
// Local variables
    pVarNegationY = CreateLocVar("negation", CLocVar::vtBool, "output inversion: 0-without inversion / 1-inversion");
    pVarType = CreateLocVar("type", CLocVar::vtBool, "delay type: 0-transp / 1-inertia");
    pVarY1 = CreateLocVar("y", CLocVar::vtBool, "local output");
    pVarX1 = CreateLocVar("x1", CLocVar::vtBool, "local input");
    pVarValue01 = CreateLocVar("value to 1", CLocVar::vtInteger, "delay value from 0 to 1");
    pVarValue10 = CreateLocVar("value to 0", CLocVar::vtInteger, "delay value from 1 to 0");
    pVarStrNameX1 = CreateLocVar("strNameX1", CLocVar::vtString, "name of external input variable (x)");
    pVarStrNameY1 = CreateLocVar("strNameY", CLocVar::vtString, "name of external output variable (y)");
    pVarIfNotX1 = CreateLocVar("not(x1)", CLocVar::vtBool, "1st input inversion: 0-without inversion / 1-inversion");
    string str;
    str = pVarStrNameX1->strGetDataSrc();
    if (str != "") { pVarX1 = pTAppCore->GetAddressVar(pVarStrNameX1->strGetDataSrc().c_str(), this);	}
    str = pVarStrNameY1->strGetDataSrc();
    if (str != "") { pVarY1 = pTAppCore->GetAddressVar(pVarStrNameY1->strGetDataSrc().c_str(), this);	}
    return true;
}
// predicates
int FDiscreteTime::x1() { return nCurrent == nDelay; }
//  
int FDiscreteTime::x3() {
    if (bool(pVarNegationY->GetDataSrc())) return !f();
    return f();
}
//
int FDiscreteTime::x12() { return pVarX1 != nullptr; }
//
bool FDiscreteTime::f() {
    bX1 = bool(pVarX1->GetDataSrc());
    if (bool(pVarIfNotX1->GetDataSrc())) bX1 = !bX1;
    return bX1;
}
// actions
// +1 to the current delay value
void FDiscreteTime::y1() { nCurrent++; }
// setting the delay value when switching from 0 to 1
void FDiscreteTime::y4() { nDelay = int(pVarValue01->GetDataSrc()); }
// setting output to zero
void FDiscreteTime::y5() { pVarY1->SetDataSrc(nullptr, 0.0); }
// setting output to unit
void FDiscreteTime::y6() { pVarY1->SetDataSrc(nullptr, 1); }
// setting the delay value when switching from 1 to 0
void FDiscreteTime::y7() { nDelay = int(pVarValue10->GetDataSrc()); }
//
void FDiscreteTime::y12() { FInit(); }
// creation, if a delay is determined, of the necessary nested automaton
void FDiscreteTime::y13() {
	nCurrent = 0;
	if (pFCall) { delete pFCall; pFCall = nullptr; }
	if (x1()) return;
	bType = pVarType->GetDataSrc();		// set delay type
	if (bType) pFCall = new FCallInertial(this);
	else pFCall = new FCallTransport(this);
	if (pFCall) pFCall->FCall(this);
}

void FDiscreteTime::MooreAction()
{
	string strState = FGetState();
	if (strState=="s0")	{ 
        y4(); y5();		// y4) setting the delay value when switching from 0 to 1; y5) set the output to zero
    }
	else if (strState=="s1") { 
        y7(); y6();		// y7) setting the delay value when switching from 1 to 0; y6) setting the output to one
    }
}
//=====================================================================
//				Transport delay
//=====================================================================
static LArc TBL_CallTransport[] = {
	LArc("s5","s5","^x1",	"--"),		//
	LArc("s5","00","x1",	"--"),		// 
	LArc()
};

FCallTransport::FCallTransport(FDiscreteTime	*pFI):
    LFsaAppl(TBL_CallTransport, "FCallTransport", nullptr, nullptr)
{
	pFDiscreteTime = pFI;
}
// . == 
int FCallTransport::x1() { return pFDiscreteTime->x1(); }
//
void FCallTransport::MooreAction()
{
	string strState = FGetState();
	if (strState=="s5")	{ pFDiscreteTime->y1(); }
}
//=====================================================================
//				Inertial delay
//=====================================================================
static LArc TBL_CallInertial[] = {
	LArc("s5",	"s5","^x1x3",	"--"),		//
	LArc("s5",	"00","x1x3",	"--"),		//
	LArc("s5",	"XX","^x3",	"--"),		//
	LArc()
};

FCallInertial::FCallInertial(FDiscreteTime	*pFI):
    LFsaAppl(TBL_CallInertial, "FCallInertial", nullptr, nullptr)
{
	pFDiscreteTime = pFI;
}
// . == 
int FCallInertial::x1() { return pFDiscreteTime->x1(); }
// input value (depends on the name of the current state of the main automaton)
int FCallInertial::x3() {
	string strState = FGetStateUp();
	bool bX = pFDiscreteTime->x3();
    if (strState == "s0") return bX;
    if (strState == "s1") return !bX;
	if (strState == "st") {
		string str = pFDiscreteTime->FGetNextState();
		bX = pFDiscreteTime->x3();
		if (!bX) {
			if (x1()) {
                if (str == "s0") return !bX;
                if (str == "s1") return bX;
			}
            else return true;
		}
		return true;
	}
	else return bX; 
}
//
void FCallInertial::MooreAction()
{
	string strState = FGetState();
	if (strState=="s5")	{ pFDiscreteTime->y1(); }
}


Listing 2. Implémentation d'une porte NAND
#include "lfsaappl.h"

#include "../FDiscreteTime.h"
extern LArc TBL_DiscreteTime[];
class FIne :
	public FDiscreteTime
{
public:
    bool	FCreationOfLinksForVariables() override;
    LFsaAppl* Create(CVarFSA *pCVF) override { Q_UNUSED(pCVF) return new FIne(nameFsa); }
    bool FInit() override;
    FIne(string strNam, LArc* TBL = TBL_DiscreteTime);
    ~FIne(void);
	CVar *pVarX2;		//  
	CVar *pVarStrNameX2;	//    
	CVar *pVarIfNotX2;	//    
	virtual bool f() override;
protected:
    	int x12() override;
    	bool bX2;
};

#include "stdafx.h"
#include <Ine/FIne.h>
#include "VARFSA/SetVarFsaLibrary.h"

FIne::FIne(string strNam, LArc* pTBL):
    FDiscreteTime(strNam, pTBL)
{
    nTypeElement = FDiscreteTime::cvarINE;
}

FIne::~FIne(void) { }

bool FIne::FInit() {										
// 	 		
	FCreationOfLinksForVariables();
//	 										
	return true;										
}

bool FIne::FCreationOfLinksForVariables() {
//  
	FDiscreteTime::FCreationOfLinksForVariables();
	//      x1, x2
    pVarIfNotX2 = CreateLocVar("not(x2)", CLocVar::vtBool, " 2- : 0- /1-");
	pVarX2 = CreateLocVar("x2", CLocVar::vtBool, " 2- ");
    //  ,         x2
	pVarStrNameX2 = CreateLocVar("strNameX2", CLocVar::vtString, "  2- .(x)");
	// :   ,     
    string str = pVarStrNameX2->strGetDataSrc();
    if (str != "") { pVarX2 = pTAppCore->GetAddressVar(pVarStrNameX2->strGetDataSrc().c_str(), this); }
//
	return true;
}
//
int FIne::x12() { return FDiscreteTime::x12() && pVarX2 != nullptr; }
//
bool FIne::f() {
    //  1- 
    FDiscreteTime::f();
    //   
    bX2 = bool(pVarX2->GetDataSrc());
    if (bool(pVarIfNotX2->GetDataSrc())) bX2 = !bX2;
    //   : 
    return bX1&&bX2;
}


Grâce à la POO, le code du modèle de l'élément logique ET n'est PAS sensiblement plus petit que le code du délai "parent". De plus, il est largement déterminé par la nécessité de créer une entrée supplémentaire pour le modèle de l'élément AND. Si, au niveau structurel, les modèles correspondent au nombre d'entrées / sorties, alors le code sera encore plus petit. Ainsi, le code d'implémentation de la porte XOR généré à partir d'un modèle structurellement similaire de l'élément AND-NOT est indiqué dans le listing 3.

Listing 3. Implémentation exclusive d'une passerelle OR
#include <Ine/FIne.h>

extern LArc TBL_DiscreteTime[];
class FExlusiveOR :
    public FIne
{
public:
    LFsaAppl* Create(CVarFSA *pCVF) { return new FExlusiveOR(nameFsa); }
    FExlusiveOR(string strNam, LArc* TBL = TBL_DiscreteTime);
    ~FExlusiveOR(void);
protected:												
    bool f();
};

#include "stdafx.h"
#include "FExlusiveOR.h"

FExlusiveOR::FExlusiveOR(string strNam, LArc* pTBL):
    FIne(strNam, pTBL)
{
    nTypeElement = FDiscreteTime::cvarExlusiveOR;
}

FExlusiveOR::~FExlusiveOR(void) { }
//
bool FExlusiveOR::f() {
    FIne::f();
    return (bX1&&bX2)||(!bX1&&!bX2);
}


Ici, la méthode f () de la classe FExlusiveOR appelle la méthode f () de la classe FIne uniquement pour lire les valeurs des variables d'entrée, puis en chevauchant la valeur de la fonction NAND avec la valeur calculée conformément à la fonction logique de la nouvelle classe. Dans l'image et la ressemblance, des modèles de tout autre élément logique à deux entrées peuvent être créés.

3. Conclusions


Pour mettre en œuvre n'importe quel circuit numérique, l'ensemble dit d'éléments fonctionnels complets est suffisant. Il peut s'agir, par exemple, d'un ensemble d'éléments AND, OR, NOT. Nous avons examiné la mise en œuvre des éléments logiques suivants - les retards, qui peuvent être un onduleur, et les éléments ET-NON et OU EXCLUSIF. Ils se rapportent aux éléments de base qui font partie d'un ensemble fonctionnel complet. Pour implémenter et / ou simuler n'importe quel schéma, il reste à ajouter à la bibliothèque, par exemple, un élément OR-NOT ou à implémenter un élément personnalisé universel qui est configuré pour un élément à partir d'un ensemble fonctionnellement complet. Et ce sera déjà assez.

En conséquence, sur la base des modèles ci-dessus, nous avons en la personne de l'environnement VKPa un environnement à part entière pour la modélisation logique des circuits numériques, qui vous permet de générer n'importe quel nombre de processus à partir de n'importe quel élément de bibliothèque, de les configurer et d'établir des connexions entre eux. Dans le même temps, la simulation sera plus détaillée (en tenant compte de tous les types de retards), plus flexible (vous pouvez configurer les éléments individuellement) que dans le cas des deux méthodes de modélisation logique typiques mentionnées ci-dessus - compilation et événement. Et ce ne sera pas un environnement spécialisé, comme le modèle des processus logiciels reste inchangé, il restera aussi universel que tout autre environnement de programmation orienté objet basé sur l'utilisation du langage C ++.

Et plus sur ... douloureux. Il était une fois, face à ce qui ne va pas dans la littérature scientifique ou, plus précisément, la description d'un élément logique clé comme un déclencheur RS est en fait analphabète, ainsi que le fait que même les ingénieurs en électronique ne savent pas comment cela fonctionne en détail déclencheur, j'ai passé beaucoup de temps à comprendre cela. Et je peux signaler qu'en ce moment dans le problème de déclenchement, au moins pour moi il n'y a pas de taches vides (voir détails [3]). Et il ne reste donc qu'à s'étonner que, dans l'ensemble, rien ne change. Comme la description tabulaire du déclencheur a été donnée précédemment, elle est toujours donnée aujourd'hui, car il y avait les états interdits notoires, et ils sont restés les mêmes qu'ils se plaignaient de la commutation imprévisible du déclencheur lors de la sortie de l'état interdit, ils sont donc toujours dans la même ignorance. Et cela malgréque des exemples d'une description suffisamment précise de son comportement sont déjà connus (voir, par exemple, [4]).

Vraiment, "Tes actes sont merveilleux, Seigneur!" Non, semble-t-il, sur la tête de tels «descripteurs de déclenchement RS» ... la programmation automatique et la méthode envisagée de modélisation des circuits logiques dans l'environnement VKPa. Et si vous revenez au sujet de l'article, alors, par exemple, en utilisant le modèle ci-dessus de l'élément NAND, vous pouvez facilement créer un modèle de déclenchement et simuler son fonctionnement en détail. Notamment en tenant compte des propriétés des éléments logiques réels qui n'ont qu'un type de retards inertiels. Eh bien, si vous avez besoin d'une preuve formelle des propriétés d'un déclencheur, elle est donnée dans [5].

Littérature
1. ., ., . UML. . . : , 2007. – 493 .
2. ., ., . : . . – .: , 1988. – 309 .
3. . [ ], : habr.com/ru/post/484588 . . . ( 07.01.2020).
4. . . 2- . – .: , 2004. – 432.
5. .. . [ ], : cloud.mail.ru/public/HwsK/T95PMM8Ed . . . ( 01.02.2020).

All Articles