Apollo Guidance Computer - logiciel d'architecture et de système. 2e partie

Lien vers la partie 1

Dans cette partie, nous verrons comment l'AGC est organisé du point de vue d'un programmeur. La liste des références et des sources figure à la fin de la première partie de l'article. Le matériel de cette partie est basé sur le matériel du livre [1].



Représentation des nombres en mémoire d'AGC


AGC utilise des mots de 15 bits, avec un signe à la 15e place. Il y a également une décharge de parité, qui est enregistrée et contrôlée par le matériel et est complètement transparente pour le logiciel, avec chaque opération de lecture et d'écriture dans la mémoire.



Les nombres entiers sont présentés au format "addition 1". C'est comme suit:

Les nombres non négatifs de 0 à 16383 sont présentés sous forme de codes de 000 000 000 000 000 à 011 111 111 111 111, respectivement.

Les nombres négatifs sont formés en inversant les nombres positifs, c'est-à-dire -1 est représenté par 111 111 111 111 111 et jusqu'à -16383, représenté par le code binaire 100 000 000 000 000.

Les opérations arithmétiques sont effectuées comme suit:

2: 000 000 000 000 010 -5: 111 111 111 111 010 111 111 111 111 100 (= -3) 

Ajouter deux nombres négatifs est un peu plus compliqué.

Si nous ajoutons selon les règles habituelles, alors rien ne fonctionnera:

 -2: 111 111 111 111 101 -5: 111 111 111 111 010 111 111 111 110 111 (= -8) 

Cependant, vous pouvez remarquer que l'ajout des bits les plus significatifs génère un bit de retenue. Nous avons juste besoin d'ajouter le bit de retenue pour obtenir le résultat correct:

 -2: 111 111 111 111 101 -5: 111 111 111 111 010 111 111 111 110 111 (= -8) Carry 1 111 111 111 111 000 (= -7) 

Vous pouvez également remarquer que zéro positif et négatif sont possibles dans ce système, ce qui crée des difficultés supplémentaires pour les programmeurs, par exemple, lors de la comparaison du résultat d'une opération avec zéro.

Le débordement de la batterie pendant les opérations arithmétiques peut également être surveillé, ce qui sera discuté ci-dessous.

ACG ne prend en charge que l'arithmétique entière et ne peut pas effectuer d'opérations avec des nombres réels dans le matériel, mais peut le faire dans le logiciel. L'AGC utilise une représentation décimale binaire de nombres de 28 bits (9 décimales), qui occupe deux cellules de mémoire, 14 bits chacune. Des chiffres de signe sont également utilisés, et le mot bas et le mot haut peuvent avoir un signe différent! Autrement dit, il peut y avoir un nombre représenté comme, par exemple, +5 * 10000 + -5 * 100 = 49500. Étrange, mais possible.

Les distances et les vitesses de calcul sont présentées dans le système métrique, mais les données pour l'équipage sont affichées dans le système anglais de mesures (pieds, etc.).


Format d'instruction

Modèle de mémoire


Dans la partie précédente, il a déjà été mentionné que la mémoire de l'ordinateur est divisée en 2 Kslov RAM et 36 K mots ROM. Comme l'instruction ne prend que 12 bits pour la valeur d'adresse, le principe de la division de la mémoire en banques est utilisé. Un registre spécial est utilisé pour indiquer la banque actuelle.

Pour basculer vers une nouvelle banque de mémoire, la commande «Transférer dans une nouvelle banque» (TNB) est utilisée, qui effectue les opérations suivantes:

  • Copie le registre bancaire actuel ("Banque") dans le registre "Banque enregistrée"
  • Copie une adresse 12 bits de l'emplacement de mémoire suivant la commande TNB dans le registre "Adresse de retour"
  • Nous chargeons la nouvelle adresse bancaire dans le registre bancaire et chargeons l'offset indiqué par l'instruction TNB dans le compteur d'instructions.

Registres


AGC a des registres mappés à l'espace d'adressage. Ils occupent les 48 premiers mots de la mémoire physique.

La batterie occupe l'adresse 0 8 .

La batterie est utilisée dans la plupart des opérations arithmétiques et logiques (OR, AND, etc.). Bien que l'AGC fonctionne avec des mots de 15 bits, la batterie a une capacité de 16 bits, car elle stocke une décharge de débordement. Lorsque les données sont chargées dans la batterie, elles tombent dans les bits inférieurs, le bit 14 contenant le signe du nombre. Après avoir effectué l'opération arithmétique, si aucun débordement ne s'est produit, le bit 15 contiendra simplement une copie du signe, et ce bit est invisible pour le programmeur. Nous appelons ces chiffres de signe respectivement S1 et S2. Si un débordement se produit, alors S1 et S2 ne seront pas égaux. Bien que le bit S2 reste invisible pour le programmeur, dans AGC, il existe jusqu'à deux façons de définir l'état de débordement.

Tout d'abord, lorsqu'un débordement se produit, les interruptions sont automatiquement désactivées. Un gestionnaire d'interruption, s'il se produit à ce moment, pourrait réinitialiser ce bit, ce qui serait très indésirable. Les interruptions ne sont autorisées que lorsque l'indicateur de dépassement est effacé. L'indicateur n'est réinitialisé que lorsque la batterie est nettoyée ou lorsqu'une nouvelle valeur est chargée. Pour vérifier l'indicateur de débordement, la commande Transférer vers le stockage (TS) peut être utilisée, qui enregistre la valeur de la batterie en mémoire uniquement s'il n'y a pas eu de débordement, et s'il y a eu un débordement vers le haut ou vers le bas, la valeur dans la batterie est remplacée par +1 ou -1 en conséquence. La commande TS ignore également l'instruction de programme suivante en cas de dépassement. Il est supposé que le programmeur écrira le code qui traite le débordement et le placera à travers une commande du TS, et immédiatement après le TS insérera un saut à l'instruction après le gestionnaire de débordement.

Registre L - Adresse 00001 8

Le registre L est également appelé «accumulateur d'ordre faible» et est destiné à étendre la gamme de nombres avec lesquels les opérations sont effectuées. Il peut également être utilisé pour le stockage temporaire de variables.

Registre Q - Adresse 00002 8

Le registre Q est destiné à stocker l'adresse de retour. Le registre Q contient une adresse de 12 bits qui, avec la banque de mémoire actuelle, donne l'adresse de retour complète du sous-programme.

Registre EBANK (Erasable Storage Bank) - Adresse 00003 8

La RAM (également appelée «mémoire effaçable» dans l'AGC) contient 2048 mots, divisés en 8 banques de 256 mots chacune. L'adresse de la banque RAM est de 3 bits et est contenue dans le registre EBANK.

Registre FBAN K (Banque de stockage fixe) - Adresse 00004 8

La ROM a des banques de 1024 mots et contient 36 banques. Le registre FBANK a 5 bits et vous permet d'adresser 32 banques.

Bit d'extension fixe (Superbank Bit)

Utilisé pour adresser la dernière ROM 4Kslov.

Registre BBANK ( Registre des deux banques) - Adresse 00006 8

Lors du transfert du contrôle vers un autre programme, les registres FBANK et EBANK doivent être modifiés en même temps. Le registre BBANK contient les deux adresses - les numéros de banque de RAM et de ROM. L'écriture met automatiquement à jour les registres FBANK et EBANK.

Registre Z (le compteur de programmes) - 00005 8

Le registre Z est le compteur de programme, c'est-à-dire qu'il détermine l'adresse de la commande en cours d'exécution. Il a une capacité de 12 bits.

Registre zéro (une source de zéros) - Adresse 00007 8

Contient la constante 0.

Registres des gestionnaires d'interruptions - Adresse 00008 8 - 00012 8

Les registres ZRUPT, BRUPT, ARUPT, LRUPT, QRUPT et BANKRUPT sont situés respectivement à ces adresses.

Registres ZRUPT et BRUPT - sauvegardent automatiquement le contenu du registre Z (compteur d'instructions) et du registre B (registre interne, qui contient l'adresse de la commande qui sera exécutée ensuite).

Les registres ARUPT, LRUPT, QRUPT et BANKRUPT sont utilisés pour économiser la batterie et les registres L, Q et BB. Ces registres doivent être sauvegardés et restaurés manuellement jusqu'à l'exécution de l'instruction RESUME, qui sert à revenir de l'interruption.

Pendant le traitement des interruptions, l'AGC désactive les interruptions jusqu'à ce que l'instruction RESUME soit exécutée. Ainsi, le gestionnaire d'interruption seul ne peut pas être interrompu.

Plus tôt, il a été mentionné que la batterie a une capacité de 16 bits, et le bit le plus significatif est utilisé pour détecter le débordement et n'est pas disponible par programme. Cependant, le registre ARUPT, qui stocke la batterie pendant une interruption, a 15 bits. Chaque fois qu'une condition de dépassement se produit, les interruptions sont désactivées jusqu'à ce que l'indicateur de dépassement soit effacé.

Les registres ARUPT, LRUPT, QRUPT et BANKRUPT ne peuvent pas être utilisés en dehors du gestionnaire d'interruption. Physiquement, ils restent accessibles, mais du point de vue du programme principal, leur état change à des moments arbitraires.

Edition des registres - adresses 00020 8 - 00023 8

Les trois premiers registres sont des registres à décalage: cycle à droite, décalage à droite, cycle à gauche, c'est-à-dire un décalage cyclique à droite, un décalage à droite et un décalage cyclique à gauche. Le système d'instruction AGC n'a pas d'opérations de décalage, et pour décaler un nombre d'un bit, il doit être écrit dans l'un de ces registres puis compté. Chaque enregistrement est décalé d'un bit.

Le registre EDOP (EDit Interpretive OPcode) est le quatrième des registres d'édition.

Les commandes d'interprétation, qui seront discutées ci-dessous, sont stockées dans deux en un mot et occupent 7 bits chacune. Une opération ET avec un masque suffit pour lire la commande d'ordre faible, mais l'ordre élevé nécessitera un décalage de 7 bits. Le registre EDOP effectue ce décalage en une seule opération.

La modification des registres ne peut pas être utilisée dans les gestionnaires d'interruption, et voici pourquoi. Les registres réguliers doivent être enregistrés au début du gestionnaire et restaurés lors de sa fermeture. Mais les registres d'édition effectuent des opérations sur les données lors de leur écriture, ce qui entraînera un fonctionnement incorrect du programme interrompu.

Minuteries et horloges


Horloge temps réel


AGC n'utilise pas le calendrier, les jours, les mois et l'année. Au lieu de cela, le compte à rebours est à partir du point «zéro», qui commence quelques heures avant le début. L'horloge est affichée en deux mots en mémoire, aux adresses 00024 8 (T2), 00025 8 (T1). Le mot T1 est incrémenté toutes les 10 ms, le mot T2 est d'environ toutes les 164 secondes, lorsque le mot T1 est plein.

Minuteries


00026 8 (T3) Liste d'attente - incrément toutes les 10 ms., Décalé de 5 ms par rapport au T4RUPT
00027 8 (T4) T4RUPT - incrément toutes les 10 ms.
00030 8 (T5) Pilote automatique - incrément toutes les 100 ms.
00031 8 (T6) horloge haute résolution - incrément toutes les 1/1600 s = 0,625 ms.

Le premier temporisateur, T3, est nécessaire pour que la liste des tâches fonctionne (liste d'attente). La liste d'attente est une liste de tâches très courtes, chacune prenant peu de temps, et peut être exécutée directement dans le gestionnaire d'interruption. La liste contient jusqu'à sept tâches, chacune commençant à un certain intervalle. Le temps d'exécution de la tâche est strictement limité à 4 ms. Pendant ce temps, l'ordinateur parvient à exécuter environ 160 instructions.

Le temporisateur T4 exécute des tâches périodiques critiques allant de 20 à 120 ms, y compris l'échange de données avec DSKY, les commutateurs d'interrogation sur les panneaux de commande du navire et d'autres tâches.

Unité de mesure inertielle IMU (L'unité de mesure inertielle)


L'IMU est une plate-forme stabilisée gyroscopiquement avec des accéléromètres, qui sert à déterminer la position et les accélérations du navire dans l'espace.



Nous ne décrirons pas ici le principe de fonctionnement du gyroscope, nous notons seulement que la position des axes du gyroscope est mesurée par le dispositif CDU (Coupling Data Unit). Cet appareil génère des impulsions lorsque les gyroscopes tournent, produisant 32 768 impulsions par tour, ce qui correspond à une résolution de 39,55 secondes d'arc par impulsion.

La CDU transmet également à l'AGC la position des axes du sextant et du radar d'approche. Étant donné que le sextant est uniquement dans le module de commande et que le radar est uniquement dans le module lunaire, ils utilisent le même port AGC.

L'IMU dispose également de trois accéléromètres à pendule (accéléromètres pendulaires à intégration pulsée, PIPA). Mais il y a une légère subtilité. Malgré le fait que le module lunaire et le module de commande ont le même IMU, leurs plages de mesure de vitesse sont différentes. La plage de vitesse IMU du module de commande est de 0 à 11000 m / s, et pour le module lunaire - jusqu'à 1700 m / s. La résolution IMU du module de commande est de 5,85 cm / s, pour le module lunaire - 1 cm / s.

Compteurs CDUS (X, Y, Z, OPTIS, OPTT) et PIPAS (X, Y, Z)


Le transfert de données de la CDU vers l'AGC est le suivant: les impulsions des capteurs peuvent incrémenter et décrémenter les compteurs. Le nombre dans le compteur a un signe indiquant la direction du mouvement. Les compteurs sont situés à des adresses spécifiques en mémoire et peuvent être lus par programmation. Un total de 8 compteurs sont utilisés, dont six affichent des vitesses et des angles, et deux sont utilisés pour afficher la position angulaire du sextant dans le module de commande ou du radar d'approche dans le module lunaire.

Gestion des appareils via des compteurs


Le CDU fonctionnait dans les deux sens, par exemple, il pouvait non seulement déterminer la position du radar de proximité, mais aussi lire le contenu du registre dans la mémoire de l'ordinateur et appliquer une tension aux moteurs d'entraînement du radar jusqu'à ce que le radar soit installé à l'angle requis.

Autres interfaces informatiques


Le module lunaire possède une poignée (Attitude Controller Assembly, ACA) dont la position peut être lue par programmation. Chaque axe de ce contrôleur a envoyé des valeurs aux variables P_RHCCTR, Q_RHCCTR et R_RHCCTR.


Contrôleur ACA


Apparence du contrôleur ACA

Contrôleur ACA installé uniquement dans le module lunaire

INLINK (canal de transmission de télémétrie)


Le dispositif INLINK permet une communication bidirectionnelle avec la Terre et sert à transmettre des informations télémétriques et à recevoir des données du centre de contrôle de vol. Les astronautes peuvent entrer les données nécessaires pour le vol via DSKY, mais ce processus est lent et semé d'erreurs. Grâce au registre INLINK, les données peuvent être saisies directement depuis la Terre dans l'ordinateur.

Gestion moteur


Pendant le processus d'atterrissage du module lunaire, l'AGC calcule en continu les valeurs nécessaires de la force de traction et envoie des signaux de commande aux moteurs. Pendant les 12 minutes que dure l'atterrissage, le moteur brûle environ la moitié du carburant et le programme doit prendre en compte la réduction de masse. La poussée du moteur varie de 92,5%, ce qui équivaut à 46 700 N, jusqu'à 10% de la pleine poussée. Mais une poussée supérieure à 65% provoque une usure sévère de la chambre de combustion et de la buse, de sorte que le programme AGC devrait minimiser le temps lorsque le moteur est dans ce mode.

L'ordinateur est connecté aux moteurs de la plate-forme d'atterrissage via l'ensemble de commande du moteur de descente (DECA). La gestion s'effectue via le registre THRUST. L'équipage peut régler manuellement la valeur de poussée via le contrôleur de poussée / translation manuelle (TTHC).


Contrôleur manuel de poussée / translationnel (TTHC).


Contrôleur manuel de poussée / translationnel (TTHC). Apparence

La poignée du contrôleur est connectée directement à DECA, l'ordinateur ne voit pas les valeurs saisies manuellement.

Appareils analogiques


Des indicateurs analogiques, ALTM (affichages analogiques: altimètre et débitmètres), sont également utilisés pour indiquer l'altitude et le taux de changement de hauteur que l'AGC contrôle via le registre ALTM. Les indicateurs analogiques sont réalisés sous forme d'échelles verticales (tapemètres).


Indicateurs de hauteur et de vitesse verticale

Adressage et banques de mémoire


Comme déjà mentionné, AGC dispose de deux types de mémoire, la RAM, également appelée «mémoire effaçable», et la ROM (mémoire fixe). La capacité mémoire est de 38 Kslov, ce qui ne permet pas d'adresser directement toute la mémoire, car la longueur d'adresse dans le mot de commande est de 12 bits.

Pour séparer la mémoire en banques, les registres de banque EBANK et FBANK sont utilisés, qui spécifient la banque de RAM et ROM, respectivement. Cela étend l'espace d'adressage de 32 K mots, et pour étendre davantage l'espace d'adressage ROM, le bit d'extension fixe est utilisé, ce qui permet d'accéder à 36 K mots.

Banques RAM


La RAM a un volume de 2K mots et est divisée en 8 banques de 256 mots.


Décryptage d'adresse RAM

Pour adresser un mot dans une banque RAM, 8 bits sont nécessaires. Deux bits supplémentaires sont nécessaires pour déterminer le type de banque: non commutable (non commutée) ou commutable (commutée). Les bits 9 et 10 de la figure ci-dessus en sont responsables (notez que les bits sont numérotés à partir de 1). Si ces bits contiennent 00, 01 et 10, alors le registre EBANK n'est pas utilisé, si 11 est utilisé, alors le contenu d'EBANK est combiné avec l'adresse 8 bits enregistrée dans le mot de commande, comme illustré dans la figure ci-dessous. Si le registre EBANK n'est pas utilisé, alors les trois premières banques de mémoire sont appelées, ce qui est appelé un terme un peu trompeur «Fixed Erasable». Pour accéder à la RAM, les bits 11 et 12 doivent être mis à 0.


Décryptage de l'adresse RAM à l'aide du registre EBANK

ROM


Pour accéder à la ROM, une approche similaire est utilisée. Les bits 11 et 12 du mot de contrôle déterminent quelles banques sont utilisées, si ces bits contiennent 00, alors la RAM est utilisée, comme indiqué dans la section précédente, si 10 ou 11, alors les 12 bits sont utilisés comme une adresse dans la ROM, le registre FBANK n'est pas utilisé, si 01, alors l'adresse composée des 10 bits inférieurs du mot de contrôle et du contenu du registre FBANK est utilisée.


Décryptage de l'adresse ROM


Décryptage de l'adresse ROM à l'aide du registre FBANK

Banques communes


Un sous-produit important du schéma de séparation de mémoire pour les banques est la possibilité de connecter des banques de ROM et de RAM au même espace d'adressage et d'utiliser la RAM sans avoir à changer de registre de banque. La figure explique le fonctionnement d'un tel schéma.


Le schéma d'utilisation de la RAM et de la ROM dans le même espace d'adressage

Mémoire au-delà de 32 mots


Pour accéder à la mémoire au-dessus de 32 mots, le bit d'extension ROM, Fixed Extension Bit, est utilisé comme Superbank Bit. Le bit superbank est situé dans le bit 7 du canal d'entrée / sortie 7. Le canal 7 diffère des autres canaux en ce qu'il prend en charge la lecture et l'écriture. Bien sûr, le bit d'extension ROM doit être enregistré à la fois pendant la gestion des interruptions et lors des tâches de commutation.

Transfert de contrôle entre banques


Notez l'ordre dans lequel les registres FBANK, Z et BB sont situés dans la mémoire inférieure. Il semblerait, pourquoi ne pas les combiner en un seul mot? Mais cela est fait exprès pour créer un mécanisme de transfert de contrôle. Lorsque vous passez à une autre banque, les nouvelles valeurs doivent être définies sur FBANK et EBANK ou BBANK. Cependant, cela pose un problème. Supposons, par exemple, que le programme s'exécute à l'adresse 01033 8 dans la banque de ROM 07 et que vous deviez aller à l'adresse 02371 8 dans la banque de ROM 13. Si vous modifiez le registre Z, il transfère le contrôle à l'adresse 02371 8 dans la banque actuelle, dont nous n'avons pas besoin. Si nous changeons d'abord de banque actuelle, une situation similaire se produira. Une commutation simultanée du registre Z et de la banque de mémoire est nécessaire. Pour ce faire, utilisez l'instruction DXCH, qui lit la batterie et enregistre L, et échange leur contenu avec deux emplacements consécutifs en mémoire. Ainsi, il est possible d'échanger la batterie et d'enregistrer L soit avec une paire de FBANK, Z, soit avec une paire de Z, BB. Ces options sont codées par deux mnémoniques: Double Transfer Control Switching Both Banks (DTCB) et Double Transfer Control Switching Fixed Bank (DTCF). La commande DTCB vous permet non seulement d'aller à une autre adresse, mais également de changer la banque de RAM, et la commande DTCF transfère le contrôle, laissant la banque de RAM la même. Le retour de la fonction est le suivant. Les valeurs initiales de Z et BBANK (ou FBANK) sont écrites sur l'accumulateur et le registre L. La fonction appelée doit sauvegarder ces valeurs puis effectuer l'opération inverse en échangeant les valeurs avec les registres des banques et Z.

Quelques inconvénients de l'architecture AGC


La plupart des architectures informatiques ont un pointeur de pile et / ou des registres d'index (au moins un). Mais pas chez AGC. La prise en charge du pointeur de pile nécessiterait du matériel supplémentaire. Il n'y a pas de registres d'index qui permettraient d'organiser l'accès aux structures de données à l'adresse (pointeur + décalage), mais il existe une commande INDEX qui élimine le besoin d'un tel registre.De plus, bien qu'il n'y ait pas de registres d'index matériel, ils sont émulés par la machine virtuelle Interpreter, qui sera discutée ci-dessous.

L'une des caractéristiques d'AGC est l'utilisation d'un système d'exploitation en temps réel multithread. Pour qu'un tel système fonctionne, en règle générale, un mécanisme de verrouillage des données partagées (mutex) est requis. Mais dans AGC il n'y a pas un tel mécanisme, donc les développeurs de logiciels devraient vérifier soigneusement tous les cas d'accès partagé aux données de divers processus afin d'exclure la possibilité d'un accès simultané à ces données.

Interruptions


4000 8 Startup
AGC

4004 8 T6RUPT
TIME6 0. .

4010 8 T5RUPT
TIME5 . .

4014 8 T3RUPT
TIME3 . WAITLIST.

4020 8 T4RUPT
TIME4 . DSKY

4024 8 KEYRUPT1
DSKY. DSKY 15

4030 8 KEYRUPT2
DSKY. DSKY 16 ( )

4034 8 UPRUPT
INLINK
DSKY

4040 8 DOWNRUPT
Downlink . AGC

4044 8 RADARUPT
RNRAD.

4050 8 RUPT10
LM P64


, Order Code, , , , . . , Q-Code.

000 , 011, 100 111 , 001, 010, 101 110 Q-.


Q-

. , , . , TC (transfer control), , , (Enable Interrupts).

, . 00006 8 , , 00006 8 . , , , . , .



AGC 41 . 6 :

  • -
  • -
  • Divers

AGC. [1].

: -


AGC n'a pas de disques durs ou de lecteurs de bande, et toutes les communications avec le monde extérieur se résument à la définition et à la lecture de bits dans les ports d'entrée / sortie. Les périphériques AGC comprennent la plate-forme inertielle, les moteurs, le radar, le DSKY et les commutateurs du panneau de commande. L'échange de données à grande vitesse n'est pas requis et la vitesse d'échange n'est pas un facteur limitant significatif.

Pour l'entrée et la sortie sont les soi-disant canaux. L'écriture et la lecture d'un canal sont similaires à l'écriture et à la lecture d'une cellule RAM, mais contrairement à la RAM, la plupart des canaux sont unidirectionnels. Il existe également des ports de comptage, qui sont utilisés pour lire les positions des axes de l'IMU, du radar et du sextant. Les impulsions des capteurs d'angle incrémentent et décrémentent les compteurs, qui peuvent ensuite être lues par AGC.


Périphériques AGC

- EXTEND . 000, PCode. PCode , PCode . 9 — . AGC, , 512 , 16. 15- , , - AND, OR Exclusive OR. -. WOR (Write with OR), WAND (Write with AND), ROR (Read and OR) RXOR (Read and XOR).

- . L (low-order accumulator), , , , . AND, OR XOR.

- . , DSKY 5 . DSKY KEYRUPT, .

, , uplink downlink, 51 /c 1900 / ( ).

Logiciels




Le logiciel AGC est basé sur le système d'exploitation Executive en temps réel et la machine virtuelle Interpreter. Nous les examinerons en détail dans la prochaine partie.

Source: https://habr.com/ru/post/fr462421/


All Articles