Wikilivres frwikibooks https://fr.wikibooks.org/wiki/Accueil MediaWiki 1.46.0-wmf.24 first-letter Média Spécial Discussion Utilisateur Discussion utilisateur Wikilivres Discussion Wikilivres Fichier Discussion fichier MediaWiki Discussion MediaWiki Modèle Discussion modèle Aide Discussion aide Catégorie Discussion catégorie Transwiki Discussion Transwiki Wikijunior Discussion Wikijunior TimedText TimedText talk Module Discussion module Event Event talk Introduire la biodiversité dans la construction et l'urbanisme/Annexes/Bibliographie 0 32478 764200 686999 2026-04-21T08:44:28Z Lamiot 1916 /* Accueil de la nature dans le bâti */ complément (marc barra 764200 wikitext text/x-wiki Bibliographie Page provisoire ; à compléter, organiser et wikifier en suivant les [[Wikilivres:Conventions bibliographiques|conventions bibliographiques]]) {{...}} = Généralités sur l'écologie, les services écosystémiques, les solutions fondées sur la nature = * Robert E. Ricklefs, Gary L. Miller '''''Écologie ; Écologie - Environnement''''' ; Éditeur De Boeck Université ; 2005 ; ISBN:274450145X, 9782744501456 ; 858 pages * Comité français de l’UICN (2013), [http://www.uicn.fr/IMG/pdf/Panorama-ecosystemes_urbains-m4.pdf Panorama des services écosystémiques fournis par les milieux naturels en France ; Les écosystèmes urbains], vol 2.3 ; PDF, 20 pages * ([http://www.mission-economie-biodiversite.com/downloads/biodiv2050-n17-evaluation-socioeconomique-des-sfn/ ''"solutions fondées sur la nature"''] Guide visant à démontrer que les Solutions fondées sur la Nature sont vertueuses écologiquement mais aussi socio-économiquement, avec de réels avantages économiques sur le long terme (investissements dans l’économie locale, création d’emplois non délocalisables, réduction des coûts, etc.) =Monographies sur les relations entre Écologie ou environnement et architecture= * '''''SNARC : Méthode pour l'évaluation de l'écologie dans les projets d'architecture''''' (prenant en compte le système suisse SEL (Système d'évaluation de logements) ; <br />Éditeur et auteur : SIA (Société suisse des ingénieurs et des architectes) ; 2004 ; ISBN:3908483794, 9783908483793 ; 51 pages. <br />Remarque|''« SNARC »'' est l'acronyme de ''« Systematik zu Beurteilung der Nachhaltigkeit von Architekturprojekten für den Bereich Umwelt »''. ---- * Sujet connexe : '''''Traité d'architecture et d'urbanisme bioclimatiques''''' (inclue un CDROM) ; 368 fiches didactiques ; 776 pages ; <br />Auteur : Alain Liébard ; Éditeur : Le Moniteur ; ---- * Sujet connexe : '''''Bâtir éthique et responsable''''' ; <br>Editeur : Le Moniteur <br>Auteur : Alain Farel ---- * '''''Projeter et construire en assurant un développement durable: catalogue des critères''''' ; Editeur : SIA (Société suisse des ingénieurs et des architectes) ; 1996 Part 137 of Documentation SIA ; <br />Auteurs SIA, Diane construction écologique, Bernard Stofer, Susanna Fassbind ; 43pages ; ---- * '''''Le profil: une approche graphique et quantifiée de l'architecture et de l'écologie en forêts et agroforêts tropicales''''' Éditeur : Université des sciences et techniques du Languedoc, 1988 <br />Auteur : Frantz Limier ;122 pages ---- * '''''L'esthétique et le rapport à l'environnement dans l'art des jardins : à la recherche d'une conciliation entre esthétique et écologie en architecture de paysage''''' ; Éditeur : Université de Montréal ; 1995 ; <br />Auteure : Daniella Dittmar ; 262 pages ---- * '''''Droit de Fenêtre, devoir d'arbre: sans créativité pas d’Écologie ni d'architecture''''' Auteur Hundertwasser ; 1977 ; 17 pages ---- * Sujet connexe : '''''Les Américains et leur architecture''''' (Numérisé par google le 12 nov 2007) Auteur Hélène Trocmé <br />Éditeur : Aubier-Montaigne, 1981 ; ISBN:2700702387, 9782700702385 ; 172 pages ---- * Sujet connexe : '''''Architecture écologique: une histoire critique''''' Auteur : James Steele ; Éditeur : Actes Sud ; 2005 ISBN:2742757872, 9782742757879 ; 269 pages ---- * Sujet connexe : '''''L'écologie urbaine? Études et recherches''''' (Numérisé par google le 24 juil 2009) Auteur : François Séguret ; Rédacteurs : François Séguret, Henri-Pierre Jeudy <br />Éditeur: Éditions de la Villette, 2000 ; ISBN:2903539510, 9782903539511 ; 135 pages ---- * Sujet connexe : '''''L'architecture écologique du Vorarlberg : Le panorama complet d'un modèle européen de développement durable'''''. Auteur : Dominique Gauzin-Müller ; 2009, [http://www.editionsdumoniteur.com/pages/recsimp/FramesUne.asp?IsNouveaute=1&PRO_ID=917 Éditions du Moniteur] ---- === Accueil de la nature dans le bâti=== * Barra, Marc (2022) [https://www.arb-idf.fr/fileadmin/DataStorageKit/ARB/Articles/fichiers/integrerbiodivprojets/Integrer_la_biodiversite_dans_les_projets_de_construction_et_de_renovation.pdf Intégrer la biodiversité dans les projets de construction et de rénovation ; Techniques de construction] ; Septembre/Décembre 2022 ---- * CEREMA (2018), '''[http://www.plan-actions-chiropteres.fr/IMG/pdf_Chiro_isolation_thermique_FNowicki.pdf ''"Préservation des chiroptères et isolation thermique des Bâtiments ; État des lieux des connaissances et premières pistes d'action"'']''' ; Document commandé par le ministère de la Transition Écologique et Solidaire ; commandé par le ministère de la transition écologique et solidaire ; piloté par François NOWICKI (Cerema Direction Est), septembre 2018 ---- * LPO - CAUE, [http://www.biodiversiteetbati.fr/ '''''Guide technique : Biodiversité et Bâti - Comment concilier nature et habitat ?'''''], 2012<br />Voir aussi la [http://multimedia.ademe.fr/catalogues/CTecosystemes/fiches/outil12p65.pdf ''fiche Ademe : Biodiversité et Bâti''] ---- * Bernier, Christophe , Vigouroux, Jean-Pierre ; [http://edition.euziere.info/wakka.php?wiki=InViteZ '''''Invitez la nature dans votre jardin, sur votre terrasse ou votre balcon'''''] ; Collectif ; Écologistes de l'Euzière ; Éditions Écologistes de l'Euzière, 36 pages, 2008 ---- * Bretagne vivante... [http://www.mce-info.org/upload/File/vegetalisons_nos_murs.pdf ''Guide végétalisons nos murs''], PDF, 15 pages ---- * Galand G, Autissier I & Germa P (2015) '''La ville renaturée''', Éditions de La Martinière, 90 x 255 mm - 224 pages ; 12 novembre 2015 9782732453552 ---- * Hafa J (2015) '''''[http://gmb.bzh/wp-content/uploads/2015/11/recueilCS-23-10-2015_3.pdf Recueil d'expériences des aménagements pour une meilleure cohabitation chiroptères]''''' - homme en milieu bâti. / Conservatoire d'espaces naturels | 82 p. ---- * Marnell F & Pesetnik P (2010) '''''[Protection des gîtes épigés de chauves-souris (en particulier dans les bâtiments d'intérêt patrimonial culturel'''''). Eurobats publication series n°4. 59 p. ---- * Noblet Jean-François, '''''La nature sous son toit, Hommes et bêtes : Comment cohabiter ?''''' (réédition complétée d'un précédent ouvrage intitulé ''La Maison-Nichoir - Hommes Et Bêtes, Comment Cohabiter'') Éditions Delachaux et Niestlé, 2005 ---- * Nougaret, Marie-Paule '''''La cité des plantes''''', Éditions Actes Sud , Octobre 2010 , 300 pages ; ISBN:978-2-7427-8589-6 ---- * CERTU, '''''Aménager avec le végétal pour des espaces verts durables'''''<br /> éditions du CERTU ; Co-production ministère du développement durable, CNVVF, FNCAUE, CERTU en collaboration avec l’AFDJEV, l’UNCPIE, Plantes et cité, la RN2D, la SNHF ([http://www.developpement-durable.gouv.fr/IMG/pdf/DGALN_Amenager_avec_le_vegetal.pdf présentation/résumé] ;PDF - 326.4 ko]) ---- * Haddad, Yael, '''''Biodiversité urbaine : les toitures végétales passées au crible''''' ; Lien horticole n° de revue 747 du 06/04/2011, pp. 10-11 (relatif à une étude du conseil général de Seine Saint Denis qui a étudié 134 toits verts en 2010 pour voir quelle était la "contribution des toits verts dans la mise en place de la trame verte urbaine". ---- * Ville, Frédéric, '''''Comment Nantes a appris à maîtriser le pâturage en milieu urbain''''' (vaches et chevaux utilisés en 2010 sur 15 hectares). La Gazette des communes n°2056 du 06/12/10, p. 35 ---- * Gary Grant, Kelly Gunnell , Carol Williams (2012), '''''[http://www.nhbs.com/title.php?bkfno=200543&ad_id=1386 Landscape and Urban Design for Bats and Biodiversity]''''' (Design urbain et des paysages pour les chauves-souris et la biodiversité), Bat Conservation Trust, Landscape Institute ; 35 pp, Ed:NHBS ---- * Kelly Gunnel, Brian Murphy et Dr Carol Williams (2nd edition), '''''Designig for biodiversity, a technical guide for new and existing buildings''''', Bat Conservation Trust ; 162 pp, Ed:NHBS ([http://www.bats.org.uk/pages/httpwww.bats.org.ukpagesdesigning_for_biodiversitya_technical_guide_for_new_and_existing_buildings.h résumé] et [http://www.ribabookshops.com/item/designing-for-biodiversity-a-technical-guide-for-new-and-existing-buildings-2nd-edition/79859/ présentation de l'ouvrage]) ---- * Parc naturel régional de Camargue. '''''Cahier des clauses techniques et particulières'''''. Travaux d'aménagement dans le cadre du programme Life + chiro med. Aménagements de trois bâtiments dans la propriété de la tour du Valat. 14 p. ---- * Wildlife Trust (2013) [http://www.nottinghamshirewildlife.org/images/uploads/Architects_Guide_reduced_filesize.pdf '''''Biodiversity and Urban Design ; an Architect’s Guide'''''], wildlife trust, (www.nottinghamshirewildlife.org) PDF, 36 pp ---- * Soprema (2017) '''''Guide des « solutions pour bâtiments responsables »''''', destiné aux architectes, bureaux d’études et maîtres d’ouvrage, autour de 20 problématiques. ===Écologie urbaine ; Nature en ville === * ADEUS (2013). ''Comment concevoir un projet d’aménagement pour qu’il prenne en compte la biodiversité ?'' TVB Fiche 8 [en ligne]. Disponible sur : http://www.adeus.org/productions/fiches - trame - verte - et - bleue/files/tvb_fiche - 8 - web.pdf (consulté le 17/08/2015) ---- * AFDJEVP (Association Française des Directeurs de Jardins et d'Espaces Verts Publics), '''''Les collectivités face au défi de la biodiversité'''''; Congrès de Limoges, 10, 11 et 12 octobre 2008 Magazine : « De ville en ville » n°35, janvier 2009 ---- * Aggeri Gaelle (2009), ''La Biodiversité, une nouvelle donne urbaine'' : Techni.cités numéro 163 du 8 février 2009, pp. 27-33 * Aggeri Gaelle (2008),'' Dossier -Espaces verts dans la ville'' Espaces naturels n° de revue 21 du 01/2008, pp. 9-21 * Aggeri Gaelle (2004). ''La nature sauvage et champêtre dans nos villes : Origine et construction de la gestion différenciée des espaces verts urbains.'' La cas de la ville de Montpellier [en ligne]. Thèse Sciences de l'Environnement, ENGREF, Paris, 323 p. |URL:https://tel.archives-ouvertes.fr/pastel-00001564/document ---- * APUR [https://www.apur.org/fr/file/47112/download?token=N7j8IsKu Développer le végétal à Paris. Les nouvelles règles du Plan local d'urbanisme de Paris]. Spécial PLU. Format : pdf, 2.79 Mo ---- * Ministère de l’Écologie, [http://www.biodiversite2010.fr/IMG/pdf/guide_de_la_biodiversite_a_l_usage_des_maires_ecomaires_.pdf Guide de la biodiversité à l'usage des maires], Avril 2010, Ministère en charge de l'Écologie, coordonné par Maud Lelièvre, avec Noé Conservation Déléguée générale des Eco Maires(PDF, 16 pages) ---- * Erickson Donna L. (2006 ) '''''MetroGreen : connecting open space in North American cities''''' ; Éditeur : Island Press ; ISBN:1559638435, 9781559638432 ; 333 pages ---- * CERTU (2009), '''''Composer avec la nature en ville''''', CERTU en collaboration avec divers centres d'études techniques de l'équipement (éléments de théorie et exemples de terrain, pour renforcer la nature en ville). * CERTU (2006), '''''Ville, changement de nature ?''''' : ou comment l'envie de nature influence l'urbain / CERTU * CERTU, '''''La ville et son assainissement : principes, méthodes et outils pour une meilleure intégration dans le cycle de l'eau''''' ---- * Conseil Régional Nord-Pas-de-Calais, '''''Gestion des espaces verts et Biodiversité''''', Ecologie Urbaine, Ed : Conseil Régional-Nord-Pas-de-Calais ---- * Clergeau, Philippe (écologue, Inra Rennes) '''''« Une écologie du paysage urbain »''''', Éditeur : Apogée, Sept 2007, 136 pages, ISBN10:2-84398-288-X, ISBN13:978-2-84398-288-0, EAN13:9782843982880 ---- * CES, «''''' La Nature dans la ville ; Biodiversité et urbanisme''''' », Avis & Rapport du [[w:Conseil économique et social|Conseil économique et social (France)|Conseil économique et social]] français, Éditions des Journaux officiels. ([http://www.ces.fr/rapport/Etude_BREYGROBELLET.pdf Télécharger ce rapport]) ---- * D. A. Goode, Article intitulé '''''« Urban Nature Conservation in Britain »''''', The Journal of Applied Ecology, Vol. 26, No. 3 (Dec., 1989), pp. 859-873, doi:10.2307/2403697 ([http://links.jstor.org/sici?sici=0021-8901(198912)26%3A3%3C859%3AUNCIB%3E2.0.CO%3B2-F Lien]) ---- * Yves Grafmeyer et Isaac Joseph (1979), '''''L'École de Chicago : naissance de l'écologie urbaine''''', Éditeur : Armand Colin, Paris, ---- * Ekhart Hahn (1987), '''''Okologische Stadtplanung''''', Éditeur : Haag & Herchen, Frankfurt ---- * Hahn, Ekhart , '''''Ecological Urban Restructuring, Theoretical foundation and concept for action''''', Éditeur Wissenschaftszentrum - Paper FS II 91-402, Berlin, 1991 ([http://www.biopolitics.gr/HTML/pubs/vol3/qi-sim.htm Lien]) ---- * Rudlin David & Falk Nicholas (1999) '''''Building the 21st Century Home - The Sustainable Urban Neighbourhood''''', Éditeur : Architectural Press, Oxford ---- * Farr Douglas (2008), '''''Sustainable Urbanism - urban design with nature''''', Wiley, Hoboken, 304 pages, ISBN13:978-0-471-77751-9 ---- * Mollie, Caroline (2009), '''''Des arbres dans la ville ; L'urbanisme végétal''''' ([http://www.actes-sud.fr/ficheisbn.php?isbn=9782742785797 Lien]) Éditeur : Actes Sud (Coédition : Val'hor), Novembre ; 260 pages ; ISBN 978-2-7427-8579-7 (ouvrage soutenu par ''Cité verte'' (centre de ressources et outil de lobbying, présidé en France par [[w:Erik Orsenna|Erik Orsenna]] et lancé le 27 octobre 2009 au Conseil de l’Europe, lors des 4èmes assises européennes du Paysage) ---- * Reygrobellet, Bernard (2007 ), '''''La nature dans la ville, Biodiversité et urbanisme''''' ; Avis et rapports du conseil économique et social, Éditeur : Les éditions des Journaux officiels ([http://lesrapports.ladocumentationfrancaise.fr/BRP/074000752/0000.pdf Lien (PDF, 182 pages)]. ---- * Conseil général de la Nièvre (2010) « '''''Guide pour la gestion écologique des dépendances vertes '''''» version Mars 2010 Source : Conseil général de la Nièvre ---- * OREE « [http://www.oree.org/_script/ntsp-document-file_download.php?document_file_id=3528 Mémento "bâtiment et biodiversité" »] issu d'un groupe de travail « bâtiment et biodiversité » co-animé par l'Association HQE et ORÉE (PDF, 6p.). ---- * Mission Économie de la biodiversité '''''[http://www.mission-economie-biodiversite.com/downloads/Cahier_n5_Comprendre_ville Infrastructures vertes urbaines et développement : vers une évaluation des impacts socio-économiques de la nature en ville]''''' ; Cahier n°5 de la collection "Cahiers Biodiv'2050". ---- * Torres A.C (2017) ''[https://tel.archives-ouvertes.fr/tel-01956207/document Initiatives citoyennes de conservation de la nature en milieu urbain: rôle des jardins partagés]'' (Thèse de Doctorat, en anglais). ---- ==Actes de colloques== * Colloque européen territorial : ''Les Villes - nature, vers le zéro pesticide : cohérences territoriales, paysagères et sociales'' . - CNFPT / AITF, Versailles déc. 2010, avec comme partenaires : Ville de Versailles - CERTU - Plante&cité - ENSP - MSA - Technicités - IFPRA - Conseil Général Yvelines - Versailles grand parc - Végépolys - Eau Seine Normandie - ADEME - Les éco Maires - FFP - UNEP - Villes et villages fleuris - UPFP - HQE association - Muséum national d'histoire naturelle * [Dossier "Zéro phyto"] (veille scientifique, juridique, territorial du CNFPT et Plante&cité) ---- * Colloque : ''Biodiversité en milieu urbain''. - Plante et cité / CNFPT / Ville de Montpellier, 20 mai 2010 ; avec comme partenaires : CERTU – Agropolis international ---- * Colloque : ''[http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/syntheses_nantes.pdf Quel management stratégique pour les services espaces verts]'' .- CNFPT / A.F.D.J.E.V.P. ; Ville de Nantes- Nantes, septembre 2009, avec comme partenaires : Plante&cité – CERTU – ENTPE- Les Machines de Nantes ---- * Colloque européen : ''http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/ville_bioclimatique_dec2008/synthese.pdf Vers une ville bioclimatique]''.- CNFPT / AITF- Montpellier, décembre 2008, avec comme partenaires : CERTU - Plante&cité – ADEME – SupAgro Montpellier – Agropolis International – Ville de Montpellier – ENTPE – Atelier technique des espaces naturels- Conseil français des urbanistes – Volubilis – Conseil général de l’Hérault – Fédération française du paysage – Maison de l’architecture du Languedoc-Roussillon =Interactions négatives entre faune et architecture, et moyens d'y remédier ou de les atténuer= * '''''[http://www.windowcollisions.info/public/leitfaden-voegel-und-glas_fz.pdf Les oiseaux, le verre et la lumière dans la construction]''''', Auteur : Schmid, H., P. Waldburger & D. Heynen (2008) (Adapté en français par Eva Inderwildi): <br /> Éditeur : Station ornithologique suisse ; Sempach, FSC Verweis, 2008. ---- =Génie écologique, mesures compensatoires et Entreprises= * '''''[http://www.medef.com/fileadmin/www.medef.fr/documents/Biodiversite/EntreprisesETbiodiversite.pdf Entreprises et biodiversité ; Exemples de bonnes pratiques] ; ''''' Auteurs : Guide technique du MEDEF, avec la contribution de la Fédération des Conservatoires d'Espaces Naturels (FCEN). <br>MEDEF, Janvier 2010 (PDF, 273 pages) ---- * « '''''Quand l'écologie, science d’observation, devient science de l’action. Remarques sur le génie écologique''''' », Auteurs : Raphaël Larrère, <br>in ''Les biodiversités''. Objets, théories, pratiques, (CNRS éditions, 2005). ---- * '''''[http://www.bafu.admin.ch/publikationen/publikation/00812/index.html?lang=fr&download=NHzLpZig7t,lnp6I0NTU042l2Z6ln1ae2IZn4Z2qZpnO2Yuq2Z6gpJCGdoB9fmym162dpYbUzd,Gpd6emK2Oz9aGodetmqaN19XI2IdvoaCVZ,s-.pdf Méthodes de construction du génie biologique]'''''; Auteur : Office fédéral de l'environnement OFEV <br>2004, ; N°DIV-7522-F, PDF =Fragmentation/défragmentation écologique= * '''''Road ecology: science and solutions''''' ; Auteur : Forman ; Richard T. T. ; Éditeur : Island Press, 2003 ; ISBN;1559639334, 9781559639330 ; 481 pages ([http://books.google.fr/books?id=HMKuZ2ScnbkC&vq=%22Prairie+conservation%22&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_navlinks_s Présentation en ligne avec Google]) ---- * ''''' Green infrastructure: linking landscapes and communities''''' Auteurs : Mark A. Benedict, Edward McMahon, Conservation Fund (Arlington, Va.) <br /> Éditeur : Island Press ; 2006 ; ISBN:1559635584, 9781559635585 ; 299 pages (([http://books.google.fr/books?id=2xTJvYqzFNkC&printsec=frontcover&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_book_other_versions_r&cad=9#v=onepage&q=&f=false Présentation en ligne avec Google]). Cet ouvrage présente notamment des critères de sélection permettant de hiérarchiser les enjeux de conservation (forme d'un site, intérêt par rapport au contexte, valeur patrimoniale, etc). ---- * ''''' Modification of the effective mesh size for measuring landscape fragmentation to solve the boundary problem''''' , Auteurs : Moser B., Jaeger J. et alii, 2005, Landscape Ecology DOI 10.1007/s10980-006-9023-0123 ---- * '''''[http://www.glel.carleton.ca/RESEARCH/HABITAT/AccessibleHabitat%20Eigenbrod%20et%20al.pdf Accessible habitat: an improved measure of the effects of habitat loss and roads on wildlife populations]''''' Auteurs : Felix Eigenbrod, Stephen J. Hecnar, and Lenore Fahrig. (2008), Landscape Ecology 23 : 159-168. ---- * Landscape Institute (2013° ''[ Green Infrastructure An integrated approach to land use Landscape Institute Position Statement]'', PDF, 32 pp =Écopotentialité (potentialités écologiques)= * Net Landscape Ecological Potential of Europe and change 1990-2000 (Synthèse avec cartes concernantl'écopotentialité des territoires européens pour le réseau écologique paneuropéen (et la méthode de calcul, sur la base d'un indice NLEP (pour ''« Net Landscape Ecological Potential »''décrivant l'état de l'[[w:Intégrité écologique|intégrité écologique]], à macro-échelle. Cet indice, traduit en cartographie sur [[w:SIG|SIG]]) ; publiée le 21 April 2008 ; JLW-SSP ; Jean-Louis Weber, Rania Spyropoulou, Tomas Soukup, Ferran Páramo ; AEE (Agence européenne de l'environnement), EIONET, ETCLUSI; [http://eea.eionet.europa.eu/Public/irc/eionet-circle/leac/library?l=/ecological_21042008doc/_EN_1.0_&a=d Télécharger]; ---- =Flore, puits de carbone et microclimats urbains= * Djedjig R (2013). ''[https://tel.archives-ouvertes.fr/tel-01141046/document Impacts des enveloppes végétales à l’interface bâtiment microclimat urbain]'' (Doctoral dissertation, Université de La Rochelle). * ''[http://web.archive.org/web/20110124052753/http://www.cremtl.qc.ca/fichiers-cre/files/pdf891.pdf Rôles des arbres et des plantes grimpantes en milieu urbain]: revue de littérature et tentative d’extrapolation au contexte montréalais;'' <br /> Rapport d’étape destiné au Conseil régional de l'environnement de Montréal, Janvier 2007, par Yann Vergriete et Michel Labrecque, ;</ref>. ---- [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Annexes]] [[Catégorie:Architecture]] i2r5x46qu629zp1qp4o48mkk1s8kpdr 764202 764200 2026-04-21T08:48:41Z Lamiot 1916 forme 764202 wikitext text/x-wiki Bibliographie Page provisoire ; à compléter, organiser et wikifier en suivant les [[Wikilivres:Conventions bibliographiques|conventions bibliographiques]]) {{...}} = Généralités sur l'écologie, les services écosystémiques, les solutions fondées sur la nature = * Robert E. Ricklefs, Gary L. Miller '''''Écologie ; Écologie - Environnement''''' ; Éditeur De Boeck Université ; 2005 ; ISBN:274450145X, 9782744501456 ; 858 pages ---- * Comité français de l’UICN (2013), [http://www.uicn.fr/IMG/pdf/Panorama-ecosystemes_urbains-m4.pdf Panorama des services écosystémiques fournis par les milieux naturels en France ; Les écosystèmes urbains], vol 2.3 ; PDF, 20 pages ---- * ([http://www.mission-economie-biodiversite.com/downloads/biodiv2050-n17-evaluation-socioeconomique-des-sfn/ ''"solutions fondées sur la nature"''] Guide visant à démontrer que les Solutions fondées sur la Nature sont vertueuses écologiquement mais aussi socio-économiquement, avec de réels avantages économiques sur le long terme (investissements dans l’économie locale, création d’emplois non délocalisables, réduction des coûts, etc.) = Monographies sur les relations entre Écologie ou environnement et architecture = * '''''SNARC : Méthode pour l'évaluation de l'écologie dans les projets d'architecture''''' (prenant en compte le système suisse SEL (Système d'évaluation de logements) ; <br />Éditeur et auteur : SIA (Société suisse des ingénieurs et des architectes) ; 2004 ; ISBN:3908483794, 9783908483793 ; 51 pages. <br />Remarque|''« SNARC »'' est l'acronyme de ''« Systematik zu Beurteilung der Nachhaltigkeit von Architekturprojekten für den Bereich Umwelt »''. ---- * Sujet connexe : '''''Traité d'architecture et d'urbanisme bioclimatiques''''' (inclue un CDROM) ; 368 fiches didactiques ; 776 pages ; <br />Auteur : Alain Liébard ; Éditeur : Le Moniteur ; ---- * Sujet connexe : '''''Bâtir éthique et responsable''''' ; <br>Editeur : Le Moniteur <br>Auteur : Alain Farel ---- * '''''Projeter et construire en assurant un développement durable: catalogue des critères''''' ; Editeur : SIA (Société suisse des ingénieurs et des architectes) ; 1996 Part 137 of Documentation SIA ; <br />Auteurs SIA, Diane construction écologique, Bernard Stofer, Susanna Fassbind ; 43pages ; ---- * '''''Le profil: une approche graphique et quantifiée de l'architecture et de l'écologie en forêts et agroforêts tropicales''''' Éditeur : Université des sciences et techniques du Languedoc, 1988 <br />Auteur : Frantz Limier ;122 pages ---- * '''''L'esthétique et le rapport à l'environnement dans l'art des jardins : à la recherche d'une conciliation entre esthétique et écologie en architecture de paysage''''' ; Éditeur : Université de Montréal ; 1995 ; <br />Auteure : Daniella Dittmar ; 262 pages ---- * '''''Droit de Fenêtre, devoir d'arbre: sans créativité pas d’Écologie ni d'architecture''''' Auteur Hundertwasser ; 1977 ; 17 pages ---- * Sujet connexe : '''''Les Américains et leur architecture''''' (Numérisé par google le 12 nov 2007) Auteur Hélène Trocmé <br />Éditeur : Aubier-Montaigne, 1981 ; ISBN:2700702387, 9782700702385 ; 172 pages ---- * Sujet connexe : '''''Architecture écologique: une histoire critique''''' Auteur : James Steele ; Éditeur : Actes Sud ; 2005 ISBN:2742757872, 9782742757879 ; 269 pages ---- * Sujet connexe : '''''L'écologie urbaine? Études et recherches''''' (Numérisé par google le 24 juil 2009) Auteur : François Séguret ; Rédacteurs : François Séguret, Henri-Pierre Jeudy <br />Éditeur: Éditions de la Villette, 2000 ; ISBN:2903539510, 9782903539511 ; 135 pages ---- * Sujet connexe : '''''L'architecture écologique du Vorarlberg : Le panorama complet d'un modèle européen de développement durable'''''. Auteur : Dominique Gauzin-Müller ; 2009, [http://www.editionsdumoniteur.com/pages/recsimp/FramesUne.asp?IsNouveaute=1&PRO_ID=917 Éditions du Moniteur] ---- === Accueil de la nature dans le bâti=== * Barra, Marc (2022) [https://www.arb-idf.fr/fileadmin/DataStorageKit/ARB/Articles/fichiers/integrerbiodivprojets/Integrer_la_biodiversite_dans_les_projets_de_construction_et_de_renovation.pdf Intégrer la biodiversité dans les projets de construction et de rénovation ; Techniques de construction] ; Septembre/Décembre 2022 ---- * CEREMA (2018), '''[http://www.plan-actions-chiropteres.fr/IMG/pdf_Chiro_isolation_thermique_FNowicki.pdf ''"Préservation des chiroptères et isolation thermique des Bâtiments ; État des lieux des connaissances et premières pistes d'action"'']''' ; Document commandé par le ministère de la Transition Écologique et Solidaire ; commandé par le ministère de la transition écologique et solidaire ; piloté par François NOWICKI (Cerema Direction Est), septembre 2018 ---- * LPO - CAUE, [http://www.biodiversiteetbati.fr/ '''''Guide technique : Biodiversité et Bâti - Comment concilier nature et habitat ?'''''], 2012<br />Voir aussi la [http://multimedia.ademe.fr/catalogues/CTecosystemes/fiches/outil12p65.pdf ''fiche Ademe : Biodiversité et Bâti''] ---- * Bernier, Christophe , Vigouroux, Jean-Pierre ; [http://edition.euziere.info/wakka.php?wiki=InViteZ '''''Invitez la nature dans votre jardin, sur votre terrasse ou votre balcon'''''] ; Collectif ; Écologistes de l'Euzière ; Éditions Écologistes de l'Euzière, 36 pages, 2008 ---- * Bretagne vivante... [http://www.mce-info.org/upload/File/vegetalisons_nos_murs.pdf ''Guide végétalisons nos murs''], PDF, 15 pages ---- * Galand G, Autissier I & Germa P (2015) '''La ville renaturée''', Éditions de La Martinière, 90 x 255 mm - 224 pages ; 12 novembre 2015 9782732453552 ---- * Hafa J (2015) '''''[http://gmb.bzh/wp-content/uploads/2015/11/recueilCS-23-10-2015_3.pdf Recueil d'expériences des aménagements pour une meilleure cohabitation chiroptères]''''' - homme en milieu bâti. / Conservatoire d'espaces naturels | 82 p. ---- * Marnell F & Pesetnik P (2010) '''''[Protection des gîtes épigés de chauves-souris (en particulier dans les bâtiments d'intérêt patrimonial culturel'''''). Eurobats publication series n°4. 59 p. ---- * Noblet Jean-François, '''''La nature sous son toit, Hommes et bêtes : Comment cohabiter ?''''' (réédition complétée d'un précédent ouvrage intitulé ''La Maison-Nichoir - Hommes Et Bêtes, Comment Cohabiter'') Éditions Delachaux et Niestlé, 2005 ---- * Nougaret, Marie-Paule '''''La cité des plantes''''', Éditions Actes Sud , Octobre 2010 , 300 pages ; ISBN:978-2-7427-8589-6 ---- * CERTU, '''''Aménager avec le végétal pour des espaces verts durables'''''<br /> éditions du CERTU ; Co-production ministère du développement durable, CNVVF, FNCAUE, CERTU en collaboration avec l’AFDJEV, l’UNCPIE, Plantes et cité, la RN2D, la SNHF ([http://www.developpement-durable.gouv.fr/IMG/pdf/DGALN_Amenager_avec_le_vegetal.pdf présentation/résumé] ;PDF - 326.4 ko]) ---- * Haddad, Yael, '''''Biodiversité urbaine : les toitures végétales passées au crible''''' ; Lien horticole n° de revue 747 du 06/04/2011, pp. 10-11 (relatif à une étude du conseil général de Seine Saint Denis qui a étudié 134 toits verts en 2010 pour voir quelle était la "contribution des toits verts dans la mise en place de la trame verte urbaine". ---- * Ville, Frédéric, '''''Comment Nantes a appris à maîtriser le pâturage en milieu urbain''''' (vaches et chevaux utilisés en 2010 sur 15 hectares). La Gazette des communes n°2056 du 06/12/10, p. 35 ---- * Gary Grant, Kelly Gunnell , Carol Williams (2012), '''''[http://www.nhbs.com/title.php?bkfno=200543&ad_id=1386 Landscape and Urban Design for Bats and Biodiversity]''''' (Design urbain et des paysages pour les chauves-souris et la biodiversité), Bat Conservation Trust, Landscape Institute ; 35 pp, Ed:NHBS ---- * Kelly Gunnel, Brian Murphy et Dr Carol Williams (2nd edition), '''''Designig for biodiversity, a technical guide for new and existing buildings''''', Bat Conservation Trust ; 162 pp, Ed:NHBS ([http://www.bats.org.uk/pages/httpwww.bats.org.ukpagesdesigning_for_biodiversitya_technical_guide_for_new_and_existing_buildings.h résumé] et [http://www.ribabookshops.com/item/designing-for-biodiversity-a-technical-guide-for-new-and-existing-buildings-2nd-edition/79859/ présentation de l'ouvrage]) ---- * Parc naturel régional de Camargue. '''''Cahier des clauses techniques et particulières'''''. Travaux d'aménagement dans le cadre du programme Life + chiro med. Aménagements de trois bâtiments dans la propriété de la tour du Valat. 14 p. ---- * Wildlife Trust (2013) [http://www.nottinghamshirewildlife.org/images/uploads/Architects_Guide_reduced_filesize.pdf '''''Biodiversity and Urban Design ; an Architect’s Guide'''''], wildlife trust, (www.nottinghamshirewildlife.org) PDF, 36 pp ---- * Soprema (2017) '''''Guide des « solutions pour bâtiments responsables »''''', destiné aux architectes, bureaux d’études et maîtres d’ouvrage, autour de 20 problématiques. ===Écologie urbaine ; Nature en ville === * ADEUS (2013). ''Comment concevoir un projet d’aménagement pour qu’il prenne en compte la biodiversité ?'' TVB Fiche 8 [en ligne]. Disponible sur : http://www.adeus.org/productions/fiches - trame - verte - et - bleue/files/tvb_fiche - 8 - web.pdf (consulté le 17/08/2015) ---- * AFDJEVP (Association Française des Directeurs de Jardins et d'Espaces Verts Publics), '''''Les collectivités face au défi de la biodiversité'''''; Congrès de Limoges, 10, 11 et 12 octobre 2008 Magazine : « De ville en ville » n°35, janvier 2009 ---- * Aggeri Gaelle (2009), ''La Biodiversité, une nouvelle donne urbaine'' : Techni.cités numéro 163 du 8 février 2009, pp. 27-33 * Aggeri Gaelle (2008),'' Dossier -Espaces verts dans la ville'' Espaces naturels n° de revue 21 du 01/2008, pp. 9-21 * Aggeri Gaelle (2004). ''La nature sauvage et champêtre dans nos villes : Origine et construction de la gestion différenciée des espaces verts urbains.'' La cas de la ville de Montpellier [en ligne]. Thèse Sciences de l'Environnement, ENGREF, Paris, 323 p. |URL:https://tel.archives-ouvertes.fr/pastel-00001564/document ---- * APUR [https://www.apur.org/fr/file/47112/download?token=N7j8IsKu Développer le végétal à Paris. Les nouvelles règles du Plan local d'urbanisme de Paris]. Spécial PLU. Format : pdf, 2.79 Mo ---- * Ministère de l’Écologie, [http://www.biodiversite2010.fr/IMG/pdf/guide_de_la_biodiversite_a_l_usage_des_maires_ecomaires_.pdf Guide de la biodiversité à l'usage des maires], Avril 2010, Ministère en charge de l'Écologie, coordonné par Maud Lelièvre, avec Noé Conservation Déléguée générale des Eco Maires(PDF, 16 pages) ---- * Erickson Donna L. (2006 ) '''''MetroGreen : connecting open space in North American cities''''' ; Éditeur : Island Press ; ISBN:1559638435, 9781559638432 ; 333 pages ---- * CERTU (2009), '''''Composer avec la nature en ville''''', CERTU en collaboration avec divers centres d'études techniques de l'équipement (éléments de théorie et exemples de terrain, pour renforcer la nature en ville). * CERTU (2006), '''''Ville, changement de nature ?''''' : ou comment l'envie de nature influence l'urbain / CERTU * CERTU, '''''La ville et son assainissement : principes, méthodes et outils pour une meilleure intégration dans le cycle de l'eau''''' ---- * Conseil Régional Nord-Pas-de-Calais, '''''Gestion des espaces verts et Biodiversité''''', Ecologie Urbaine, Ed : Conseil Régional-Nord-Pas-de-Calais ---- * Clergeau, Philippe (écologue, Inra Rennes) '''''« Une écologie du paysage urbain »''''', Éditeur : Apogée, Sept 2007, 136 pages, ISBN10:2-84398-288-X, ISBN13:978-2-84398-288-0, EAN13:9782843982880 ---- * CES, «''''' La Nature dans la ville ; Biodiversité et urbanisme''''' », Avis & Rapport du [[w:Conseil économique et social|Conseil économique et social (France)|Conseil économique et social]] français, Éditions des Journaux officiels. ([http://www.ces.fr/rapport/Etude_BREYGROBELLET.pdf Télécharger ce rapport]) ---- * D. A. Goode, Article intitulé '''''« Urban Nature Conservation in Britain »''''', The Journal of Applied Ecology, Vol. 26, No. 3 (Dec., 1989), pp. 859-873, doi:10.2307/2403697 ([http://links.jstor.org/sici?sici=0021-8901(198912)26%3A3%3C859%3AUNCIB%3E2.0.CO%3B2-F Lien]) ---- * Yves Grafmeyer et Isaac Joseph (1979), '''''L'École de Chicago : naissance de l'écologie urbaine''''', Éditeur : Armand Colin, Paris, ---- * Ekhart Hahn (1987), '''''Okologische Stadtplanung''''', Éditeur : Haag & Herchen, Frankfurt ---- * Hahn, Ekhart , '''''Ecological Urban Restructuring, Theoretical foundation and concept for action''''', Éditeur Wissenschaftszentrum - Paper FS II 91-402, Berlin, 1991 ([http://www.biopolitics.gr/HTML/pubs/vol3/qi-sim.htm Lien]) ---- * Rudlin David & Falk Nicholas (1999) '''''Building the 21st Century Home - The Sustainable Urban Neighbourhood''''', Éditeur : Architectural Press, Oxford ---- * Farr Douglas (2008), '''''Sustainable Urbanism - urban design with nature''''', Wiley, Hoboken, 304 pages, ISBN13:978-0-471-77751-9 ---- * Mollie, Caroline (2009), '''''Des arbres dans la ville ; L'urbanisme végétal''''' ([http://www.actes-sud.fr/ficheisbn.php?isbn=9782742785797 Lien]) Éditeur : Actes Sud (Coédition : Val'hor), Novembre ; 260 pages ; ISBN 978-2-7427-8579-7 (ouvrage soutenu par ''Cité verte'' (centre de ressources et outil de lobbying, présidé en France par [[w:Erik Orsenna|Erik Orsenna]] et lancé le 27 octobre 2009 au Conseil de l’Europe, lors des 4èmes assises européennes du Paysage) ---- * Reygrobellet, Bernard (2007 ), '''''La nature dans la ville, Biodiversité et urbanisme''''' ; Avis et rapports du conseil économique et social, Éditeur : Les éditions des Journaux officiels ([http://lesrapports.ladocumentationfrancaise.fr/BRP/074000752/0000.pdf Lien (PDF, 182 pages)]. ---- * Conseil général de la Nièvre (2010) « '''''Guide pour la gestion écologique des dépendances vertes '''''» version Mars 2010 Source : Conseil général de la Nièvre ---- * OREE « [http://www.oree.org/_script/ntsp-document-file_download.php?document_file_id=3528 Mémento "bâtiment et biodiversité" »] issu d'un groupe de travail « bâtiment et biodiversité » co-animé par l'Association HQE et ORÉE (PDF, 6p.). ---- * Mission Économie de la biodiversité '''''[http://www.mission-economie-biodiversite.com/downloads/Cahier_n5_Comprendre_ville Infrastructures vertes urbaines et développement : vers une évaluation des impacts socio-économiques de la nature en ville]''''' ; Cahier n°5 de la collection "Cahiers Biodiv'2050". ---- * Torres A.C (2017) ''[https://tel.archives-ouvertes.fr/tel-01956207/document Initiatives citoyennes de conservation de la nature en milieu urbain: rôle des jardins partagés]'' (Thèse de Doctorat, en anglais). ---- == Actes de colloques == * Colloque européen territorial : ''Les Villes - nature, vers le zéro pesticide : cohérences territoriales, paysagères et sociales'' . - CNFPT / AITF, Versailles déc. 2010, avec comme partenaires : Ville de Versailles - CERTU - Plante&cité - ENSP - MSA - Technicités - IFPRA - Conseil Général Yvelines - Versailles grand parc - Végépolys - Eau Seine Normandie - ADEME - Les éco Maires - FFP - UNEP - Villes et villages fleuris - UPFP - HQE association - Muséum national d'histoire naturelle * [Dossier "Zéro phyto"] (veille scientifique, juridique, territorial du CNFPT et Plante&cité) ---- * Colloque : ''Biodiversité en milieu urbain''. - Plante et cité / CNFPT / Ville de Montpellier, 20 mai 2010 ; avec comme partenaires : CERTU – Agropolis international ---- * Colloque : ''[http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/syntheses_nantes.pdf Quel management stratégique pour les services espaces verts]'' .- CNFPT / A.F.D.J.E.V.P. ; Ville de Nantes- Nantes, septembre 2009, avec comme partenaires : Plante&cité – CERTU – ENTPE- Les Machines de Nantes ---- * Colloque européen : ''http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/ville_bioclimatique_dec2008/synthese.pdf Vers une ville bioclimatique]''.- CNFPT / AITF- Montpellier, décembre 2008, avec comme partenaires : CERTU - Plante&cité – ADEME – SupAgro Montpellier – Agropolis International – Ville de Montpellier – ENTPE – Atelier technique des espaces naturels- Conseil français des urbanistes – Volubilis – Conseil général de l’Hérault – Fédération française du paysage – Maison de l’architecture du Languedoc-Roussillon = Interactions négatives entre faune et architecture, et moyens d'y remédier ou de les atténuer = * '''''[http://www.windowcollisions.info/public/leitfaden-voegel-und-glas_fz.pdf Les oiseaux, le verre et la lumière dans la construction]''''', Auteur : Schmid, H., P. Waldburger & D. Heynen (2008) (Adapté en français par Eva Inderwildi): <br /> Éditeur : Station ornithologique suisse ; Sempach, FSC Verweis, 2008. ---- = Génie écologique, mesures compensatoires et Entreprises = * '''''[http://www.medef.com/fileadmin/www.medef.fr/documents/Biodiversite/EntreprisesETbiodiversite.pdf Entreprises et biodiversité ; Exemples de bonnes pratiques] ; ''''' Auteurs : Guide technique du MEDEF, avec la contribution de la Fédération des Conservatoires d'Espaces Naturels (FCEN). <br>MEDEF, Janvier 2010 (PDF, 273 pages) ---- * « '''''Quand l'écologie, science d’observation, devient science de l’action. Remarques sur le génie écologique''''' », Auteurs : Raphaël Larrère, <br>in ''Les biodiversités''. Objets, théories, pratiques, (CNRS éditions, 2005). ---- * '''''[http://www.bafu.admin.ch/publikationen/publikation/00812/index.html?lang=fr&download=NHzLpZig7t,lnp6I0NTU042l2Z6ln1ae2IZn4Z2qZpnO2Yuq2Z6gpJCGdoB9fmym162dpYbUzd,Gpd6emK2Oz9aGodetmqaN19XI2IdvoaCVZ,s-.pdf Méthodes de construction du génie biologique]'''''; Auteur : Office fédéral de l'environnement OFEV <br>2004, ; N°DIV-7522-F, PDF = Fragmentation/défragmentation écologique = * '''''Road ecology: science and solutions''''' ; Auteur : Forman ; Richard T. T. ; Éditeur : Island Press, 2003 ; ISBN;1559639334, 9781559639330 ; 481 pages ([http://books.google.fr/books?id=HMKuZ2ScnbkC&vq=%22Prairie+conservation%22&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_navlinks_s Présentation en ligne avec Google]) ---- * ''''' Green infrastructure: linking landscapes and communities''''' Auteurs : Mark A. Benedict, Edward McMahon, Conservation Fund (Arlington, Va.) <br /> Éditeur : Island Press ; 2006 ; ISBN:1559635584, 9781559635585 ; 299 pages (([http://books.google.fr/books?id=2xTJvYqzFNkC&printsec=frontcover&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_book_other_versions_r&cad=9#v=onepage&q=&f=false Présentation en ligne avec Google]). Cet ouvrage présente notamment des critères de sélection permettant de hiérarchiser les enjeux de conservation (forme d'un site, intérêt par rapport au contexte, valeur patrimoniale, etc). ---- * ''''' Modification of the effective mesh size for measuring landscape fragmentation to solve the boundary problem''''' , Auteurs : Moser B., Jaeger J. et alii, 2005, Landscape Ecology DOI 10.1007/s10980-006-9023-0123 ---- * '''''[http://www.glel.carleton.ca/RESEARCH/HABITAT/AccessibleHabitat%20Eigenbrod%20et%20al.pdf Accessible habitat: an improved measure of the effects of habitat loss and roads on wildlife populations]''''' Auteurs : Felix Eigenbrod, Stephen J. Hecnar, and Lenore Fahrig. (2008), Landscape Ecology 23 : 159-168. ---- * Landscape Institute (2013° ''[ Green Infrastructure An integrated approach to land use Landscape Institute Position Statement]'', PDF, 32 pp = Écopotentialité (potentialités écologiques) = * Net Landscape Ecological Potential of Europe and change 1990-2000 (Synthèse avec cartes concernantl'écopotentialité des territoires européens pour le réseau écologique paneuropéen (et la méthode de calcul, sur la base d'un indice NLEP (pour ''« Net Landscape Ecological Potential »''décrivant l'état de l'[[w:Intégrité écologique|intégrité écologique]], à macro-échelle. Cet indice, traduit en cartographie sur [[w:SIG|SIG]]) ; publiée le 21 April 2008 ; JLW-SSP ; Jean-Louis Weber, Rania Spyropoulou, Tomas Soukup, Ferran Páramo ; AEE (Agence européenne de l'environnement), EIONET, ETCLUSI; [http://eea.eionet.europa.eu/Public/irc/eionet-circle/leac/library?l=/ecological_21042008doc/_EN_1.0_&a=d Télécharger]; ---- = Flore, puits de carbone et microclimats urbains = * Djedjig R (2013). ''[https://tel.archives-ouvertes.fr/tel-01141046/document Impacts des enveloppes végétales à l’interface bâtiment microclimat urbain]'' (Doctoral dissertation, Université de La Rochelle). * ''[http://web.archive.org/web/20110124052753/http://www.cremtl.qc.ca/fichiers-cre/files/pdf891.pdf Rôles des arbres et des plantes grimpantes en milieu urbain]: revue de littérature et tentative d’extrapolation au contexte montréalais;'' <br /> Rapport d’étape destiné au Conseil régional de l'environnement de Montréal, Janvier 2007, par Yann Vergriete et Michel Labrecque. ---- [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Annexes]] [[Catégorie:Architecture]] hfw8n4ba3xam6sm3py3afynseiss4uu 764208 764202 2026-04-21T09:08:39Z Lamiot 1916 /* Actes de colloques */ compl (friches 764208 wikitext text/x-wiki Bibliographie Page provisoire ; à compléter, organiser et wikifier en suivant les [[Wikilivres:Conventions bibliographiques|conventions bibliographiques]]) {{...}} = Généralités sur l'écologie, les services écosystémiques, les solutions fondées sur la nature = * Robert E. Ricklefs, Gary L. Miller '''''Écologie ; Écologie - Environnement''''' ; Éditeur De Boeck Université ; 2005 ; ISBN:274450145X, 9782744501456 ; 858 pages ---- * Comité français de l’UICN (2013), [http://www.uicn.fr/IMG/pdf/Panorama-ecosystemes_urbains-m4.pdf Panorama des services écosystémiques fournis par les milieux naturels en France ; Les écosystèmes urbains], vol 2.3 ; PDF, 20 pages ---- * ([http://www.mission-economie-biodiversite.com/downloads/biodiv2050-n17-evaluation-socioeconomique-des-sfn/ ''"solutions fondées sur la nature"''] Guide visant à démontrer que les Solutions fondées sur la Nature sont vertueuses écologiquement mais aussi socio-économiquement, avec de réels avantages économiques sur le long terme (investissements dans l’économie locale, création d’emplois non délocalisables, réduction des coûts, etc.) = Monographies sur les relations entre Écologie ou environnement et architecture = * '''''SNARC : Méthode pour l'évaluation de l'écologie dans les projets d'architecture''''' (prenant en compte le système suisse SEL (Système d'évaluation de logements) ; <br />Éditeur et auteur : SIA (Société suisse des ingénieurs et des architectes) ; 2004 ; ISBN:3908483794, 9783908483793 ; 51 pages. <br />Remarque|''« SNARC »'' est l'acronyme de ''« Systematik zu Beurteilung der Nachhaltigkeit von Architekturprojekten für den Bereich Umwelt »''. ---- * Sujet connexe : '''''Traité d'architecture et d'urbanisme bioclimatiques''''' (inclue un CDROM) ; 368 fiches didactiques ; 776 pages ; <br />Auteur : Alain Liébard ; Éditeur : Le Moniteur ; ---- * Sujet connexe : '''''Bâtir éthique et responsable''''' ; <br>Editeur : Le Moniteur <br>Auteur : Alain Farel ---- * '''''Projeter et construire en assurant un développement durable: catalogue des critères''''' ; Editeur : SIA (Société suisse des ingénieurs et des architectes) ; 1996 Part 137 of Documentation SIA ; <br />Auteurs SIA, Diane construction écologique, Bernard Stofer, Susanna Fassbind ; 43pages ; ---- * '''''Le profil: une approche graphique et quantifiée de l'architecture et de l'écologie en forêts et agroforêts tropicales''''' Éditeur : Université des sciences et techniques du Languedoc, 1988 <br />Auteur : Frantz Limier ;122 pages ---- * '''''L'esthétique et le rapport à l'environnement dans l'art des jardins : à la recherche d'une conciliation entre esthétique et écologie en architecture de paysage''''' ; Éditeur : Université de Montréal ; 1995 ; <br />Auteure : Daniella Dittmar ; 262 pages ---- * '''''Droit de Fenêtre, devoir d'arbre: sans créativité pas d’Écologie ni d'architecture''''' Auteur Hundertwasser ; 1977 ; 17 pages ---- * Sujet connexe : '''''Les Américains et leur architecture''''' (Numérisé par google le 12 nov 2007) Auteur Hélène Trocmé <br />Éditeur : Aubier-Montaigne, 1981 ; ISBN:2700702387, 9782700702385 ; 172 pages ---- * Sujet connexe : '''''Architecture écologique: une histoire critique''''' Auteur : James Steele ; Éditeur : Actes Sud ; 2005 ISBN:2742757872, 9782742757879 ; 269 pages ---- * Sujet connexe : '''''L'écologie urbaine? Études et recherches''''' (Numérisé par google le 24 juil 2009) Auteur : François Séguret ; Rédacteurs : François Séguret, Henri-Pierre Jeudy <br />Éditeur: Éditions de la Villette, 2000 ; ISBN:2903539510, 9782903539511 ; 135 pages ---- * Sujet connexe : '''''L'architecture écologique du Vorarlberg : Le panorama complet d'un modèle européen de développement durable'''''. Auteur : Dominique Gauzin-Müller ; 2009, [http://www.editionsdumoniteur.com/pages/recsimp/FramesUne.asp?IsNouveaute=1&PRO_ID=917 Éditions du Moniteur] ---- === Accueil de la nature dans le bâti=== * Barra, Marc (2022) [https://www.arb-idf.fr/fileadmin/DataStorageKit/ARB/Articles/fichiers/integrerbiodivprojets/Integrer_la_biodiversite_dans_les_projets_de_construction_et_de_renovation.pdf Intégrer la biodiversité dans les projets de construction et de rénovation ; Techniques de construction] ; Septembre/Décembre 2022 ---- * CEREMA (2018), '''[http://www.plan-actions-chiropteres.fr/IMG/pdf_Chiro_isolation_thermique_FNowicki.pdf ''"Préservation des chiroptères et isolation thermique des Bâtiments ; État des lieux des connaissances et premières pistes d'action"'']''' ; Document commandé par le ministère de la Transition Écologique et Solidaire ; commandé par le ministère de la transition écologique et solidaire ; piloté par François NOWICKI (Cerema Direction Est), septembre 2018 ---- * LPO - CAUE, [http://www.biodiversiteetbati.fr/ '''''Guide technique : Biodiversité et Bâti - Comment concilier nature et habitat ?'''''], 2012<br />Voir aussi la [http://multimedia.ademe.fr/catalogues/CTecosystemes/fiches/outil12p65.pdf ''fiche Ademe : Biodiversité et Bâti''] ---- * Bernier, Christophe , Vigouroux, Jean-Pierre ; [http://edition.euziere.info/wakka.php?wiki=InViteZ '''''Invitez la nature dans votre jardin, sur votre terrasse ou votre balcon'''''] ; Collectif ; Écologistes de l'Euzière ; Éditions Écologistes de l'Euzière, 36 pages, 2008 ---- * Bretagne vivante... [http://www.mce-info.org/upload/File/vegetalisons_nos_murs.pdf ''Guide végétalisons nos murs''], PDF, 15 pages ---- * Galand G, Autissier I & Germa P (2015) '''La ville renaturée''', Éditions de La Martinière, 90 x 255 mm - 224 pages ; 12 novembre 2015 9782732453552 ---- * Hafa J (2015) '''''[http://gmb.bzh/wp-content/uploads/2015/11/recueilCS-23-10-2015_3.pdf Recueil d'expériences des aménagements pour une meilleure cohabitation chiroptères]''''' - homme en milieu bâti. / Conservatoire d'espaces naturels | 82 p. ---- * Marnell F & Pesetnik P (2010) '''''[Protection des gîtes épigés de chauves-souris (en particulier dans les bâtiments d'intérêt patrimonial culturel'''''). Eurobats publication series n°4. 59 p. ---- * Noblet Jean-François, '''''La nature sous son toit, Hommes et bêtes : Comment cohabiter ?''''' (réédition complétée d'un précédent ouvrage intitulé ''La Maison-Nichoir - Hommes Et Bêtes, Comment Cohabiter'') Éditions Delachaux et Niestlé, 2005 ---- * Nougaret, Marie-Paule '''''La cité des plantes''''', Éditions Actes Sud , Octobre 2010 , 300 pages ; ISBN:978-2-7427-8589-6 ---- * CERTU, '''''Aménager avec le végétal pour des espaces verts durables'''''<br /> éditions du CERTU ; Co-production ministère du développement durable, CNVVF, FNCAUE, CERTU en collaboration avec l’AFDJEV, l’UNCPIE, Plantes et cité, la RN2D, la SNHF ([http://www.developpement-durable.gouv.fr/IMG/pdf/DGALN_Amenager_avec_le_vegetal.pdf présentation/résumé] ;PDF - 326.4 ko]) ---- * Haddad, Yael, '''''Biodiversité urbaine : les toitures végétales passées au crible''''' ; Lien horticole n° de revue 747 du 06/04/2011, pp. 10-11 (relatif à une étude du conseil général de Seine Saint Denis qui a étudié 134 toits verts en 2010 pour voir quelle était la "contribution des toits verts dans la mise en place de la trame verte urbaine". ---- * Ville, Frédéric, '''''Comment Nantes a appris à maîtriser le pâturage en milieu urbain''''' (vaches et chevaux utilisés en 2010 sur 15 hectares). La Gazette des communes n°2056 du 06/12/10, p. 35 ---- * Gary Grant, Kelly Gunnell , Carol Williams (2012), '''''[http://www.nhbs.com/title.php?bkfno=200543&ad_id=1386 Landscape and Urban Design for Bats and Biodiversity]''''' (Design urbain et des paysages pour les chauves-souris et la biodiversité), Bat Conservation Trust, Landscape Institute ; 35 pp, Ed:NHBS ---- * Kelly Gunnel, Brian Murphy et Dr Carol Williams (2nd edition), '''''Designig for biodiversity, a technical guide for new and existing buildings''''', Bat Conservation Trust ; 162 pp, Ed:NHBS ([http://www.bats.org.uk/pages/httpwww.bats.org.ukpagesdesigning_for_biodiversitya_technical_guide_for_new_and_existing_buildings.h résumé] et [http://www.ribabookshops.com/item/designing-for-biodiversity-a-technical-guide-for-new-and-existing-buildings-2nd-edition/79859/ présentation de l'ouvrage]) ---- * Parc naturel régional de Camargue. '''''Cahier des clauses techniques et particulières'''''. Travaux d'aménagement dans le cadre du programme Life + chiro med. Aménagements de trois bâtiments dans la propriété de la tour du Valat. 14 p. ---- * Wildlife Trust (2013) [http://www.nottinghamshirewildlife.org/images/uploads/Architects_Guide_reduced_filesize.pdf '''''Biodiversity and Urban Design ; an Architect’s Guide'''''], wildlife trust, (www.nottinghamshirewildlife.org) PDF, 36 pp ---- * Soprema (2017) '''''Guide des « solutions pour bâtiments responsables »''''', destiné aux architectes, bureaux d’études et maîtres d’ouvrage, autour de 20 problématiques. ===Écologie urbaine ; Nature en ville === * ADEUS (2013). ''Comment concevoir un projet d’aménagement pour qu’il prenne en compte la biodiversité ?'' TVB Fiche 8 [en ligne]. Disponible sur : http://www.adeus.org/productions/fiches - trame - verte - et - bleue/files/tvb_fiche - 8 - web.pdf (consulté le 17/08/2015) ---- * AFDJEVP (Association Française des Directeurs de Jardins et d'Espaces Verts Publics), '''''Les collectivités face au défi de la biodiversité'''''; Congrès de Limoges, 10, 11 et 12 octobre 2008 Magazine : « De ville en ville » n°35, janvier 2009 ---- * Aggeri Gaelle (2009), ''La Biodiversité, une nouvelle donne urbaine'' : Techni.cités numéro 163 du 8 février 2009, pp. 27-33 * Aggeri Gaelle (2008),'' Dossier -Espaces verts dans la ville'' Espaces naturels n° de revue 21 du 01/2008, pp. 9-21 * Aggeri Gaelle (2004). ''La nature sauvage et champêtre dans nos villes : Origine et construction de la gestion différenciée des espaces verts urbains.'' La cas de la ville de Montpellier [en ligne]. Thèse Sciences de l'Environnement, ENGREF, Paris, 323 p. |URL:https://tel.archives-ouvertes.fr/pastel-00001564/document ---- * APUR [https://www.apur.org/fr/file/47112/download?token=N7j8IsKu Développer le végétal à Paris. Les nouvelles règles du Plan local d'urbanisme de Paris]. Spécial PLU. Format : pdf, 2.79 Mo ---- * Ministère de l’Écologie, [http://www.biodiversite2010.fr/IMG/pdf/guide_de_la_biodiversite_a_l_usage_des_maires_ecomaires_.pdf Guide de la biodiversité à l'usage des maires], Avril 2010, Ministère en charge de l'Écologie, coordonné par Maud Lelièvre, avec Noé Conservation Déléguée générale des Eco Maires(PDF, 16 pages) ---- * Erickson Donna L. (2006 ) '''''MetroGreen : connecting open space in North American cities''''' ; Éditeur : Island Press ; ISBN:1559638435, 9781559638432 ; 333 pages ---- * CERTU (2009), '''''Composer avec la nature en ville''''', CERTU en collaboration avec divers centres d'études techniques de l'équipement (éléments de théorie et exemples de terrain, pour renforcer la nature en ville). * CERTU (2006), '''''Ville, changement de nature ?''''' : ou comment l'envie de nature influence l'urbain / CERTU * CERTU, '''''La ville et son assainissement : principes, méthodes et outils pour une meilleure intégration dans le cycle de l'eau''''' ---- * Conseil Régional Nord-Pas-de-Calais, '''''Gestion des espaces verts et Biodiversité''''', Ecologie Urbaine, Ed : Conseil Régional-Nord-Pas-de-Calais ---- * Clergeau, Philippe (écologue, Inra Rennes) '''''« Une écologie du paysage urbain »''''', Éditeur : Apogée, Sept 2007, 136 pages, ISBN10:2-84398-288-X, ISBN13:978-2-84398-288-0, EAN13:9782843982880 ---- * CES, «''''' La Nature dans la ville ; Biodiversité et urbanisme''''' », Avis & Rapport du [[w:Conseil économique et social|Conseil économique et social (France)|Conseil économique et social]] français, Éditions des Journaux officiels. ([http://www.ces.fr/rapport/Etude_BREYGROBELLET.pdf Télécharger ce rapport]) ---- * D. A. Goode, Article intitulé '''''« Urban Nature Conservation in Britain »''''', The Journal of Applied Ecology, Vol. 26, No. 3 (Dec., 1989), pp. 859-873, doi:10.2307/2403697 ([http://links.jstor.org/sici?sici=0021-8901(198912)26%3A3%3C859%3AUNCIB%3E2.0.CO%3B2-F Lien]) ---- * Yves Grafmeyer et Isaac Joseph (1979), '''''L'École de Chicago : naissance de l'écologie urbaine''''', Éditeur : Armand Colin, Paris, ---- * Ekhart Hahn (1987), '''''Okologische Stadtplanung''''', Éditeur : Haag & Herchen, Frankfurt ---- * Hahn, Ekhart , '''''Ecological Urban Restructuring, Theoretical foundation and concept for action''''', Éditeur Wissenschaftszentrum - Paper FS II 91-402, Berlin, 1991 ([http://www.biopolitics.gr/HTML/pubs/vol3/qi-sim.htm Lien]) ---- * Rudlin David & Falk Nicholas (1999) '''''Building the 21st Century Home - The Sustainable Urban Neighbourhood''''', Éditeur : Architectural Press, Oxford ---- * Farr Douglas (2008), '''''Sustainable Urbanism - urban design with nature''''', Wiley, Hoboken, 304 pages, ISBN13:978-0-471-77751-9 ---- * Mollie, Caroline (2009), '''''Des arbres dans la ville ; L'urbanisme végétal''''' ([http://www.actes-sud.fr/ficheisbn.php?isbn=9782742785797 Lien]) Éditeur : Actes Sud (Coédition : Val'hor), Novembre ; 260 pages ; ISBN 978-2-7427-8579-7 (ouvrage soutenu par ''Cité verte'' (centre de ressources et outil de lobbying, présidé en France par [[w:Erik Orsenna|Erik Orsenna]] et lancé le 27 octobre 2009 au Conseil de l’Europe, lors des 4èmes assises européennes du Paysage) ---- * Reygrobellet, Bernard (2007 ), '''''La nature dans la ville, Biodiversité et urbanisme''''' ; Avis et rapports du conseil économique et social, Éditeur : Les éditions des Journaux officiels ([http://lesrapports.ladocumentationfrancaise.fr/BRP/074000752/0000.pdf Lien (PDF, 182 pages)]. ---- * Conseil général de la Nièvre (2010) « '''''Guide pour la gestion écologique des dépendances vertes '''''» version Mars 2010 Source : Conseil général de la Nièvre ---- * OREE « [http://www.oree.org/_script/ntsp-document-file_download.php?document_file_id=3528 Mémento "bâtiment et biodiversité" »] issu d'un groupe de travail « bâtiment et biodiversité » co-animé par l'Association HQE et ORÉE (PDF, 6p.). ---- * Mission Économie de la biodiversité '''''[http://www.mission-economie-biodiversite.com/downloads/Cahier_n5_Comprendre_ville Infrastructures vertes urbaines et développement : vers une évaluation des impacts socio-économiques de la nature en ville]''''' ; Cahier n°5 de la collection "Cahiers Biodiv'2050". ---- * Torres A.C (2017) ''[https://tel.archives-ouvertes.fr/tel-01956207/document Initiatives citoyennes de conservation de la nature en milieu urbain: rôle des jardins partagés]'' (Thèse de Doctorat, en anglais). ---- == Renaturation de friches == * Chateau, Laurent ; Piquant, Maximilien ; Bestieu, Adrien et al. (2020) Outil Bénéfriches – Évaluer les bénéfices socio-économiques de la reconversion de friches pour lutter contre l’artificialisation, Ademe, coll. « Expertises », août 2020, https:// librairie.ademe.fr/urbanisme-et-batiment/3772-evaluer-lesbenefices-socio-economiques-de-la-reconversion-de-frichespour-lutter-contre-l-artificialisation-outil-benefriches.html ---- * Ademe (2014) Guide à l’attention des collectivités, des aménageurs et des promoteurs, Biodiversité et reconversion des friches urbaines polluées, Ademe, coll. « Clés pour agir », février 2014, https://librairie.ademe.fr/recherche-et-innovation/3089-biodiversiteet-reconversion-des-friches-urbaines-polluees-9782358385275.html. ---- * Gauthier, Cécile (2018) Contribution de la compensation écologique à un modèle économique de renaturation des friches urbaines et périurbaines – Renaturation des friches urbaines et construction | Techniques de construction périurbaines par la mise en œuvre de mesures de compensation écologique, Humanité & Biodiversité ; Septembre/Décembre 2022 | https://webissimo-ide.developpement-durable.gouv.fr/IMG/pdf/etude_friches_et_compensation_urbaines-web_cle77c96c.pdf ---- * Muratet, Audrey ; Muratet, Myr et Pellaton, Marie (2017) Flore des friches urbaines, Éd. Xavier Barral, 2017 ---- * Huguet, Aurélien « Un suivi écologique de la biodiversité », Chartier Dalix, www.chartier-dalix.com/fr/ressources/suiviecologique-biodiversite. == Actes de colloques == * Colloque européen territorial : ''Les Villes - nature, vers le zéro pesticide : cohérences territoriales, paysagères et sociales'' . - CNFPT / AITF, Versailles déc. 2010, avec comme partenaires : Ville de Versailles - CERTU - Plante&cité - ENSP - MSA - Technicités - IFPRA - Conseil Général Yvelines - Versailles grand parc - Végépolys - Eau Seine Normandie - ADEME - Les éco Maires - FFP - UNEP - Villes et villages fleuris - UPFP - HQE association - Muséum national d'histoire naturelle * [Dossier "Zéro phyto"] (veille scientifique, juridique, territorial du CNFPT et Plante&cité) ---- * Colloque : ''Biodiversité en milieu urbain''. - Plante et cité / CNFPT / Ville de Montpellier, 20 mai 2010 ; avec comme partenaires : CERTU – Agropolis international ---- * Colloque : ''[http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/syntheses_nantes.pdf Quel management stratégique pour les services espaces verts]'' .- CNFPT / A.F.D.J.E.V.P. ; Ville de Nantes- Nantes, septembre 2009, avec comme partenaires : Plante&cité – CERTU – ENTPE- Les Machines de Nantes ---- * Colloque européen : ''http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/ville_bioclimatique_dec2008/synthese.pdf Vers une ville bioclimatique]''.- CNFPT / AITF- Montpellier, décembre 2008, avec comme partenaires : CERTU - Plante&cité – ADEME – SupAgro Montpellier – Agropolis International – Ville de Montpellier – ENTPE – Atelier technique des espaces naturels- Conseil français des urbanistes – Volubilis – Conseil général de l’Hérault – Fédération française du paysage – Maison de l’architecture du Languedoc-Roussillon = Interactions négatives entre faune et architecture, et moyens d'y remédier ou de les atténuer = * '''''[http://www.windowcollisions.info/public/leitfaden-voegel-und-glas_fz.pdf Les oiseaux, le verre et la lumière dans la construction]''''', Auteur : Schmid, H., P. Waldburger & D. Heynen (2008) (Adapté en français par Eva Inderwildi): <br /> Éditeur : Station ornithologique suisse ; Sempach, FSC Verweis, 2008. ---- = Génie écologique, mesures compensatoires et Entreprises = * '''''[http://www.medef.com/fileadmin/www.medef.fr/documents/Biodiversite/EntreprisesETbiodiversite.pdf Entreprises et biodiversité ; Exemples de bonnes pratiques] ; ''''' Auteurs : Guide technique du MEDEF, avec la contribution de la Fédération des Conservatoires d'Espaces Naturels (FCEN). <br>MEDEF, Janvier 2010 (PDF, 273 pages) ---- * « '''''Quand l'écologie, science d’observation, devient science de l’action. Remarques sur le génie écologique''''' », Auteurs : Raphaël Larrère, <br>in ''Les biodiversités''. Objets, théories, pratiques, (CNRS éditions, 2005). ---- * '''''[http://www.bafu.admin.ch/publikationen/publikation/00812/index.html?lang=fr&download=NHzLpZig7t,lnp6I0NTU042l2Z6ln1ae2IZn4Z2qZpnO2Yuq2Z6gpJCGdoB9fmym162dpYbUzd,Gpd6emK2Oz9aGodetmqaN19XI2IdvoaCVZ,s-.pdf Méthodes de construction du génie biologique]'''''; Auteur : Office fédéral de l'environnement OFEV <br>2004, ; N°DIV-7522-F, PDF = Fragmentation/défragmentation écologique = * '''''Road ecology: science and solutions''''' ; Auteur : Forman ; Richard T. T. ; Éditeur : Island Press, 2003 ; ISBN;1559639334, 9781559639330 ; 481 pages ([http://books.google.fr/books?id=HMKuZ2ScnbkC&vq=%22Prairie+conservation%22&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_navlinks_s Présentation en ligne avec Google]) ---- * ''''' Green infrastructure: linking landscapes and communities''''' Auteurs : Mark A. Benedict, Edward McMahon, Conservation Fund (Arlington, Va.) <br /> Éditeur : Island Press ; 2006 ; ISBN:1559635584, 9781559635585 ; 299 pages (([http://books.google.fr/books?id=2xTJvYqzFNkC&printsec=frontcover&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_book_other_versions_r&cad=9#v=onepage&q=&f=false Présentation en ligne avec Google]). Cet ouvrage présente notamment des critères de sélection permettant de hiérarchiser les enjeux de conservation (forme d'un site, intérêt par rapport au contexte, valeur patrimoniale, etc). ---- * ''''' Modification of the effective mesh size for measuring landscape fragmentation to solve the boundary problem''''' , Auteurs : Moser B., Jaeger J. et alii, 2005, Landscape Ecology DOI 10.1007/s10980-006-9023-0123 ---- * '''''[http://www.glel.carleton.ca/RESEARCH/HABITAT/AccessibleHabitat%20Eigenbrod%20et%20al.pdf Accessible habitat: an improved measure of the effects of habitat loss and roads on wildlife populations]''''' Auteurs : Felix Eigenbrod, Stephen J. Hecnar, and Lenore Fahrig. (2008), Landscape Ecology 23 : 159-168. ---- * Landscape Institute (2013° ''[ Green Infrastructure An integrated approach to land use Landscape Institute Position Statement]'', PDF, 32 pp = Écopotentialité (potentialités écologiques) = * Net Landscape Ecological Potential of Europe and change 1990-2000 (Synthèse avec cartes concernantl'écopotentialité des territoires européens pour le réseau écologique paneuropéen (et la méthode de calcul, sur la base d'un indice NLEP (pour ''« Net Landscape Ecological Potential »''décrivant l'état de l'[[w:Intégrité écologique|intégrité écologique]], à macro-échelle. Cet indice, traduit en cartographie sur [[w:SIG|SIG]]) ; publiée le 21 April 2008 ; JLW-SSP ; Jean-Louis Weber, Rania Spyropoulou, Tomas Soukup, Ferran Páramo ; AEE (Agence européenne de l'environnement), EIONET, ETCLUSI; [http://eea.eionet.europa.eu/Public/irc/eionet-circle/leac/library?l=/ecological_21042008doc/_EN_1.0_&a=d Télécharger]; ---- = Flore, puits de carbone et microclimats urbains = * Djedjig R (2013). ''[https://tel.archives-ouvertes.fr/tel-01141046/document Impacts des enveloppes végétales à l’interface bâtiment microclimat urbain]'' (Doctoral dissertation, Université de La Rochelle). * ''[http://web.archive.org/web/20110124052753/http://www.cremtl.qc.ca/fichiers-cre/files/pdf891.pdf Rôles des arbres et des plantes grimpantes en milieu urbain]: revue de littérature et tentative d’extrapolation au contexte montréalais;'' <br /> Rapport d’étape destiné au Conseil régional de l'environnement de Montréal, Janvier 2007, par Yann Vergriete et Michel Labrecque. ---- [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Annexes]] [[Catégorie:Architecture]] t9zshi1dg38hja4tzzthfl4wl44vzuv 764210 764208 2026-04-21T09:11:10Z Lamiot 1916 /* Accueil de la nature dans le bâti */ compl (Yohan Tison 764210 wikitext text/x-wiki Bibliographie Page provisoire ; à compléter, organiser et wikifier en suivant les [[Wikilivres:Conventions bibliographiques|conventions bibliographiques]]) {{...}} = Généralités sur l'écologie, les services écosystémiques, les solutions fondées sur la nature = * Robert E. Ricklefs, Gary L. Miller '''''Écologie ; Écologie - Environnement''''' ; Éditeur De Boeck Université ; 2005 ; ISBN:274450145X, 9782744501456 ; 858 pages ---- * Comité français de l’UICN (2013), [http://www.uicn.fr/IMG/pdf/Panorama-ecosystemes_urbains-m4.pdf Panorama des services écosystémiques fournis par les milieux naturels en France ; Les écosystèmes urbains], vol 2.3 ; PDF, 20 pages ---- * ([http://www.mission-economie-biodiversite.com/downloads/biodiv2050-n17-evaluation-socioeconomique-des-sfn/ ''"solutions fondées sur la nature"''] Guide visant à démontrer que les Solutions fondées sur la Nature sont vertueuses écologiquement mais aussi socio-économiquement, avec de réels avantages économiques sur le long terme (investissements dans l’économie locale, création d’emplois non délocalisables, réduction des coûts, etc.) = Monographies sur les relations entre Écologie ou environnement et architecture = * '''''SNARC : Méthode pour l'évaluation de l'écologie dans les projets d'architecture''''' (prenant en compte le système suisse SEL (Système d'évaluation de logements) ; <br />Éditeur et auteur : SIA (Société suisse des ingénieurs et des architectes) ; 2004 ; ISBN:3908483794, 9783908483793 ; 51 pages. <br />Remarque|''« SNARC »'' est l'acronyme de ''« Systematik zu Beurteilung der Nachhaltigkeit von Architekturprojekten für den Bereich Umwelt »''. ---- * Sujet connexe : '''''Traité d'architecture et d'urbanisme bioclimatiques''''' (inclue un CDROM) ; 368 fiches didactiques ; 776 pages ; <br />Auteur : Alain Liébard ; Éditeur : Le Moniteur ; ---- * Sujet connexe : '''''Bâtir éthique et responsable''''' ; <br>Editeur : Le Moniteur <br>Auteur : Alain Farel ---- * '''''Projeter et construire en assurant un développement durable: catalogue des critères''''' ; Editeur : SIA (Société suisse des ingénieurs et des architectes) ; 1996 Part 137 of Documentation SIA ; <br />Auteurs SIA, Diane construction écologique, Bernard Stofer, Susanna Fassbind ; 43pages ; ---- * '''''Le profil: une approche graphique et quantifiée de l'architecture et de l'écologie en forêts et agroforêts tropicales''''' Éditeur : Université des sciences et techniques du Languedoc, 1988 <br />Auteur : Frantz Limier ;122 pages ---- * '''''L'esthétique et le rapport à l'environnement dans l'art des jardins : à la recherche d'une conciliation entre esthétique et écologie en architecture de paysage''''' ; Éditeur : Université de Montréal ; 1995 ; <br />Auteure : Daniella Dittmar ; 262 pages ---- * '''''Droit de Fenêtre, devoir d'arbre: sans créativité pas d’Écologie ni d'architecture''''' Auteur Hundertwasser ; 1977 ; 17 pages ---- * Sujet connexe : '''''Les Américains et leur architecture''''' (Numérisé par google le 12 nov 2007) Auteur Hélène Trocmé <br />Éditeur : Aubier-Montaigne, 1981 ; ISBN:2700702387, 9782700702385 ; 172 pages ---- * Sujet connexe : '''''Architecture écologique: une histoire critique''''' Auteur : James Steele ; Éditeur : Actes Sud ; 2005 ISBN:2742757872, 9782742757879 ; 269 pages ---- * Sujet connexe : '''''L'écologie urbaine? Études et recherches''''' (Numérisé par google le 24 juil 2009) Auteur : François Séguret ; Rédacteurs : François Séguret, Henri-Pierre Jeudy <br />Éditeur: Éditions de la Villette, 2000 ; ISBN:2903539510, 9782903539511 ; 135 pages ---- * Sujet connexe : '''''L'architecture écologique du Vorarlberg : Le panorama complet d'un modèle européen de développement durable'''''. Auteur : Dominique Gauzin-Müller ; 2009, [http://www.editionsdumoniteur.com/pages/recsimp/FramesUne.asp?IsNouveaute=1&PRO_ID=917 Éditions du Moniteur] ---- === Accueil de la nature dans le bâti=== * Barra, Marc (2022) [https://www.arb-idf.fr/fileadmin/DataStorageKit/ARB/Articles/fichiers/integrerbiodivprojets/Integrer_la_biodiversite_dans_les_projets_de_construction_et_de_renovation.pdf Intégrer la biodiversité dans les projets de construction et de rénovation ; Techniques de construction] ; Septembre/Décembre 2022 ---- Tison, Yohan (2017) « Intégrer la biodiversité dans le bâti – Caractéristiques et prise en compte », présentation faite sur « Biodiversité et bâti » lors de l’atelier au Centre national de la fonction publique territoriale (CNFPT) de Lille, 2 mars 2017, www.capitale-biodiversite.fr/sites/default/files/Ateliers/documents/2-yohan-tison-02032017-lille.pdf. ---- * CEREMA (2018), '''[http://www.plan-actions-chiropteres.fr/IMG/pdf_Chiro_isolation_thermique_FNowicki.pdf ''"Préservation des chiroptères et isolation thermique des Bâtiments ; État des lieux des connaissances et premières pistes d'action"'']''' ; Document commandé par le ministère de la Transition Écologique et Solidaire ; commandé par le ministère de la transition écologique et solidaire ; piloté par François NOWICKI (Cerema Direction Est), septembre 2018 ---- * LPO - CAUE, [http://www.biodiversiteetbati.fr/ '''''Guide technique : Biodiversité et Bâti - Comment concilier nature et habitat ?'''''], 2012<br />Voir aussi la [http://multimedia.ademe.fr/catalogues/CTecosystemes/fiches/outil12p65.pdf ''fiche Ademe : Biodiversité et Bâti''] ---- * Bernier, Christophe , Vigouroux, Jean-Pierre ; [http://edition.euziere.info/wakka.php?wiki=InViteZ '''''Invitez la nature dans votre jardin, sur votre terrasse ou votre balcon'''''] ; Collectif ; Écologistes de l'Euzière ; Éditions Écologistes de l'Euzière, 36 pages, 2008 ---- * Bretagne vivante... [http://www.mce-info.org/upload/File/vegetalisons_nos_murs.pdf ''Guide végétalisons nos murs''], PDF, 15 pages ---- * Galand G, Autissier I & Germa P (2015) '''La ville renaturée''', Éditions de La Martinière, 90 x 255 mm - 224 pages ; 12 novembre 2015 9782732453552 ---- * Hafa J (2015) '''''[http://gmb.bzh/wp-content/uploads/2015/11/recueilCS-23-10-2015_3.pdf Recueil d'expériences des aménagements pour une meilleure cohabitation chiroptères]''''' - homme en milieu bâti. / Conservatoire d'espaces naturels | 82 p. ---- * Marnell F & Pesetnik P (2010) '''''[Protection des gîtes épigés de chauves-souris (en particulier dans les bâtiments d'intérêt patrimonial culturel'''''). Eurobats publication series n°4. 59 p. ---- * Noblet Jean-François, '''''La nature sous son toit, Hommes et bêtes : Comment cohabiter ?''''' (réédition complétée d'un précédent ouvrage intitulé ''La Maison-Nichoir - Hommes Et Bêtes, Comment Cohabiter'') Éditions Delachaux et Niestlé, 2005 ---- * Nougaret, Marie-Paule '''''La cité des plantes''''', Éditions Actes Sud , Octobre 2010 , 300 pages ; ISBN:978-2-7427-8589-6 ---- * CERTU, '''''Aménager avec le végétal pour des espaces verts durables'''''<br /> éditions du CERTU ; Co-production ministère du développement durable, CNVVF, FNCAUE, CERTU en collaboration avec l’AFDJEV, l’UNCPIE, Plantes et cité, la RN2D, la SNHF ([http://www.developpement-durable.gouv.fr/IMG/pdf/DGALN_Amenager_avec_le_vegetal.pdf présentation/résumé] ;PDF - 326.4 ko]) ---- * Haddad, Yael, '''''Biodiversité urbaine : les toitures végétales passées au crible''''' ; Lien horticole n° de revue 747 du 06/04/2011, pp. 10-11 (relatif à une étude du conseil général de Seine Saint Denis qui a étudié 134 toits verts en 2010 pour voir quelle était la "contribution des toits verts dans la mise en place de la trame verte urbaine". ---- * Ville, Frédéric, '''''Comment Nantes a appris à maîtriser le pâturage en milieu urbain''''' (vaches et chevaux utilisés en 2010 sur 15 hectares). La Gazette des communes n°2056 du 06/12/10, p. 35 ---- * Gary Grant, Kelly Gunnell , Carol Williams (2012), '''''[http://www.nhbs.com/title.php?bkfno=200543&ad_id=1386 Landscape and Urban Design for Bats and Biodiversity]''''' (Design urbain et des paysages pour les chauves-souris et la biodiversité), Bat Conservation Trust, Landscape Institute ; 35 pp, Ed:NHBS ---- * Kelly Gunnel, Brian Murphy et Dr Carol Williams (2nd edition), '''''Designig for biodiversity, a technical guide for new and existing buildings''''', Bat Conservation Trust ; 162 pp, Ed:NHBS ([http://www.bats.org.uk/pages/httpwww.bats.org.ukpagesdesigning_for_biodiversitya_technical_guide_for_new_and_existing_buildings.h résumé] et [http://www.ribabookshops.com/item/designing-for-biodiversity-a-technical-guide-for-new-and-existing-buildings-2nd-edition/79859/ présentation de l'ouvrage]) ---- * Parc naturel régional de Camargue. '''''Cahier des clauses techniques et particulières'''''. Travaux d'aménagement dans le cadre du programme Life + chiro med. Aménagements de trois bâtiments dans la propriété de la tour du Valat. 14 p. ---- * Wildlife Trust (2013) [http://www.nottinghamshirewildlife.org/images/uploads/Architects_Guide_reduced_filesize.pdf '''''Biodiversity and Urban Design ; an Architect’s Guide'''''], wildlife trust, (www.nottinghamshirewildlife.org) PDF, 36 pp ---- * Soprema (2017) '''''Guide des « solutions pour bâtiments responsables »''''', destiné aux architectes, bureaux d’études et maîtres d’ouvrage, autour de 20 problématiques. ===Écologie urbaine ; Nature en ville === * ADEUS (2013). ''Comment concevoir un projet d’aménagement pour qu’il prenne en compte la biodiversité ?'' TVB Fiche 8 [en ligne]. Disponible sur : http://www.adeus.org/productions/fiches - trame - verte - et - bleue/files/tvb_fiche - 8 - web.pdf (consulté le 17/08/2015) ---- * AFDJEVP (Association Française des Directeurs de Jardins et d'Espaces Verts Publics), '''''Les collectivités face au défi de la biodiversité'''''; Congrès de Limoges, 10, 11 et 12 octobre 2008 Magazine : « De ville en ville » n°35, janvier 2009 ---- * Aggeri Gaelle (2009), ''La Biodiversité, une nouvelle donne urbaine'' : Techni.cités numéro 163 du 8 février 2009, pp. 27-33 * Aggeri Gaelle (2008),'' Dossier -Espaces verts dans la ville'' Espaces naturels n° de revue 21 du 01/2008, pp. 9-21 * Aggeri Gaelle (2004). ''La nature sauvage et champêtre dans nos villes : Origine et construction de la gestion différenciée des espaces verts urbains.'' La cas de la ville de Montpellier [en ligne]. Thèse Sciences de l'Environnement, ENGREF, Paris, 323 p. |URL:https://tel.archives-ouvertes.fr/pastel-00001564/document ---- * APUR [https://www.apur.org/fr/file/47112/download?token=N7j8IsKu Développer le végétal à Paris. Les nouvelles règles du Plan local d'urbanisme de Paris]. Spécial PLU. Format : pdf, 2.79 Mo ---- * Ministère de l’Écologie, [http://www.biodiversite2010.fr/IMG/pdf/guide_de_la_biodiversite_a_l_usage_des_maires_ecomaires_.pdf Guide de la biodiversité à l'usage des maires], Avril 2010, Ministère en charge de l'Écologie, coordonné par Maud Lelièvre, avec Noé Conservation Déléguée générale des Eco Maires(PDF, 16 pages) ---- * Erickson Donna L. (2006 ) '''''MetroGreen : connecting open space in North American cities''''' ; Éditeur : Island Press ; ISBN:1559638435, 9781559638432 ; 333 pages ---- * CERTU (2009), '''''Composer avec la nature en ville''''', CERTU en collaboration avec divers centres d'études techniques de l'équipement (éléments de théorie et exemples de terrain, pour renforcer la nature en ville). * CERTU (2006), '''''Ville, changement de nature ?''''' : ou comment l'envie de nature influence l'urbain / CERTU * CERTU, '''''La ville et son assainissement : principes, méthodes et outils pour une meilleure intégration dans le cycle de l'eau''''' ---- * Conseil Régional Nord-Pas-de-Calais, '''''Gestion des espaces verts et Biodiversité''''', Ecologie Urbaine, Ed : Conseil Régional-Nord-Pas-de-Calais ---- * Clergeau, Philippe (écologue, Inra Rennes) '''''« Une écologie du paysage urbain »''''', Éditeur : Apogée, Sept 2007, 136 pages, ISBN10:2-84398-288-X, ISBN13:978-2-84398-288-0, EAN13:9782843982880 ---- * CES, «''''' La Nature dans la ville ; Biodiversité et urbanisme''''' », Avis & Rapport du [[w:Conseil économique et social|Conseil économique et social (France)|Conseil économique et social]] français, Éditions des Journaux officiels. ([http://www.ces.fr/rapport/Etude_BREYGROBELLET.pdf Télécharger ce rapport]) ---- * D. A. Goode, Article intitulé '''''« Urban Nature Conservation in Britain »''''', The Journal of Applied Ecology, Vol. 26, No. 3 (Dec., 1989), pp. 859-873, doi:10.2307/2403697 ([http://links.jstor.org/sici?sici=0021-8901(198912)26%3A3%3C859%3AUNCIB%3E2.0.CO%3B2-F Lien]) ---- * Yves Grafmeyer et Isaac Joseph (1979), '''''L'École de Chicago : naissance de l'écologie urbaine''''', Éditeur : Armand Colin, Paris, ---- * Ekhart Hahn (1987), '''''Okologische Stadtplanung''''', Éditeur : Haag & Herchen, Frankfurt ---- * Hahn, Ekhart , '''''Ecological Urban Restructuring, Theoretical foundation and concept for action''''', Éditeur Wissenschaftszentrum - Paper FS II 91-402, Berlin, 1991 ([http://www.biopolitics.gr/HTML/pubs/vol3/qi-sim.htm Lien]) ---- * Rudlin David & Falk Nicholas (1999) '''''Building the 21st Century Home - The Sustainable Urban Neighbourhood''''', Éditeur : Architectural Press, Oxford ---- * Farr Douglas (2008), '''''Sustainable Urbanism - urban design with nature''''', Wiley, Hoboken, 304 pages, ISBN13:978-0-471-77751-9 ---- * Mollie, Caroline (2009), '''''Des arbres dans la ville ; L'urbanisme végétal''''' ([http://www.actes-sud.fr/ficheisbn.php?isbn=9782742785797 Lien]) Éditeur : Actes Sud (Coédition : Val'hor), Novembre ; 260 pages ; ISBN 978-2-7427-8579-7 (ouvrage soutenu par ''Cité verte'' (centre de ressources et outil de lobbying, présidé en France par [[w:Erik Orsenna|Erik Orsenna]] et lancé le 27 octobre 2009 au Conseil de l’Europe, lors des 4èmes assises européennes du Paysage) ---- * Reygrobellet, Bernard (2007 ), '''''La nature dans la ville, Biodiversité et urbanisme''''' ; Avis et rapports du conseil économique et social, Éditeur : Les éditions des Journaux officiels ([http://lesrapports.ladocumentationfrancaise.fr/BRP/074000752/0000.pdf Lien (PDF, 182 pages)]. ---- * Conseil général de la Nièvre (2010) « '''''Guide pour la gestion écologique des dépendances vertes '''''» version Mars 2010 Source : Conseil général de la Nièvre ---- * OREE « [http://www.oree.org/_script/ntsp-document-file_download.php?document_file_id=3528 Mémento "bâtiment et biodiversité" »] issu d'un groupe de travail « bâtiment et biodiversité » co-animé par l'Association HQE et ORÉE (PDF, 6p.). ---- * Mission Économie de la biodiversité '''''[http://www.mission-economie-biodiversite.com/downloads/Cahier_n5_Comprendre_ville Infrastructures vertes urbaines et développement : vers une évaluation des impacts socio-économiques de la nature en ville]''''' ; Cahier n°5 de la collection "Cahiers Biodiv'2050". ---- * Torres A.C (2017) ''[https://tel.archives-ouvertes.fr/tel-01956207/document Initiatives citoyennes de conservation de la nature en milieu urbain: rôle des jardins partagés]'' (Thèse de Doctorat, en anglais). ---- == Renaturation de friches == * Chateau, Laurent ; Piquant, Maximilien ; Bestieu, Adrien et al. (2020) Outil Bénéfriches – Évaluer les bénéfices socio-économiques de la reconversion de friches pour lutter contre l’artificialisation, Ademe, coll. « Expertises », août 2020, https:// librairie.ademe.fr/urbanisme-et-batiment/3772-evaluer-lesbenefices-socio-economiques-de-la-reconversion-de-frichespour-lutter-contre-l-artificialisation-outil-benefriches.html ---- * Ademe (2014) Guide à l’attention des collectivités, des aménageurs et des promoteurs, Biodiversité et reconversion des friches urbaines polluées, Ademe, coll. « Clés pour agir », février 2014, https://librairie.ademe.fr/recherche-et-innovation/3089-biodiversiteet-reconversion-des-friches-urbaines-polluees-9782358385275.html. ---- * Gauthier, Cécile (2018) Contribution de la compensation écologique à un modèle économique de renaturation des friches urbaines et périurbaines – Renaturation des friches urbaines et construction | Techniques de construction périurbaines par la mise en œuvre de mesures de compensation écologique, Humanité & Biodiversité ; Septembre/Décembre 2022 | https://webissimo-ide.developpement-durable.gouv.fr/IMG/pdf/etude_friches_et_compensation_urbaines-web_cle77c96c.pdf ---- * Muratet, Audrey ; Muratet, Myr et Pellaton, Marie (2017) Flore des friches urbaines, Éd. Xavier Barral, 2017 ---- * Huguet, Aurélien « Un suivi écologique de la biodiversité », Chartier Dalix, www.chartier-dalix.com/fr/ressources/suiviecologique-biodiversite. == Actes de colloques == * Colloque européen territorial : ''Les Villes - nature, vers le zéro pesticide : cohérences territoriales, paysagères et sociales'' . - CNFPT / AITF, Versailles déc. 2010, avec comme partenaires : Ville de Versailles - CERTU - Plante&cité - ENSP - MSA - Technicités - IFPRA - Conseil Général Yvelines - Versailles grand parc - Végépolys - Eau Seine Normandie - ADEME - Les éco Maires - FFP - UNEP - Villes et villages fleuris - UPFP - HQE association - Muséum national d'histoire naturelle * [Dossier "Zéro phyto"] (veille scientifique, juridique, territorial du CNFPT et Plante&cité) ---- * Colloque : ''Biodiversité en milieu urbain''. - Plante et cité / CNFPT / Ville de Montpellier, 20 mai 2010 ; avec comme partenaires : CERTU – Agropolis international ---- * Colloque : ''[http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/syntheses_nantes.pdf Quel management stratégique pour les services espaces verts]'' .- CNFPT / A.F.D.J.E.V.P. ; Ville de Nantes- Nantes, septembre 2009, avec comme partenaires : Plante&cité – CERTU – ENTPE- Les Machines de Nantes ---- * Colloque européen : ''http://www.inset-montpellier.cnfpt.fr/images/file/poles/pole%20EV/ville_bioclimatique_dec2008/synthese.pdf Vers une ville bioclimatique]''.- CNFPT / AITF- Montpellier, décembre 2008, avec comme partenaires : CERTU - Plante&cité – ADEME – SupAgro Montpellier – Agropolis International – Ville de Montpellier – ENTPE – Atelier technique des espaces naturels- Conseil français des urbanistes – Volubilis – Conseil général de l’Hérault – Fédération française du paysage – Maison de l’architecture du Languedoc-Roussillon = Interactions négatives entre faune et architecture, et moyens d'y remédier ou de les atténuer = * '''''[http://www.windowcollisions.info/public/leitfaden-voegel-und-glas_fz.pdf Les oiseaux, le verre et la lumière dans la construction]''''', Auteur : Schmid, H., P. Waldburger & D. Heynen (2008) (Adapté en français par Eva Inderwildi): <br /> Éditeur : Station ornithologique suisse ; Sempach, FSC Verweis, 2008. ---- = Génie écologique, mesures compensatoires et Entreprises = * '''''[http://www.medef.com/fileadmin/www.medef.fr/documents/Biodiversite/EntreprisesETbiodiversite.pdf Entreprises et biodiversité ; Exemples de bonnes pratiques] ; ''''' Auteurs : Guide technique du MEDEF, avec la contribution de la Fédération des Conservatoires d'Espaces Naturels (FCEN). <br>MEDEF, Janvier 2010 (PDF, 273 pages) ---- * « '''''Quand l'écologie, science d’observation, devient science de l’action. Remarques sur le génie écologique''''' », Auteurs : Raphaël Larrère, <br>in ''Les biodiversités''. Objets, théories, pratiques, (CNRS éditions, 2005). ---- * '''''[http://www.bafu.admin.ch/publikationen/publikation/00812/index.html?lang=fr&download=NHzLpZig7t,lnp6I0NTU042l2Z6ln1ae2IZn4Z2qZpnO2Yuq2Z6gpJCGdoB9fmym162dpYbUzd,Gpd6emK2Oz9aGodetmqaN19XI2IdvoaCVZ,s-.pdf Méthodes de construction du génie biologique]'''''; Auteur : Office fédéral de l'environnement OFEV <br>2004, ; N°DIV-7522-F, PDF = Fragmentation/défragmentation écologique = * '''''Road ecology: science and solutions''''' ; Auteur : Forman ; Richard T. T. ; Éditeur : Island Press, 2003 ; ISBN;1559639334, 9781559639330 ; 481 pages ([http://books.google.fr/books?id=HMKuZ2ScnbkC&vq=%22Prairie+conservation%22&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_navlinks_s Présentation en ligne avec Google]) ---- * ''''' Green infrastructure: linking landscapes and communities''''' Auteurs : Mark A. Benedict, Edward McMahon, Conservation Fund (Arlington, Va.) <br /> Éditeur : Island Press ; 2006 ; ISBN:1559635584, 9781559635585 ; 299 pages (([http://books.google.fr/books?id=2xTJvYqzFNkC&printsec=frontcover&dq=%22total+quality%22+biodiversity&lr=&client=firefox-a&source=gbs_book_other_versions_r&cad=9#v=onepage&q=&f=false Présentation en ligne avec Google]). Cet ouvrage présente notamment des critères de sélection permettant de hiérarchiser les enjeux de conservation (forme d'un site, intérêt par rapport au contexte, valeur patrimoniale, etc). ---- * ''''' Modification of the effective mesh size for measuring landscape fragmentation to solve the boundary problem''''' , Auteurs : Moser B., Jaeger J. et alii, 2005, Landscape Ecology DOI 10.1007/s10980-006-9023-0123 ---- * '''''[http://www.glel.carleton.ca/RESEARCH/HABITAT/AccessibleHabitat%20Eigenbrod%20et%20al.pdf Accessible habitat: an improved measure of the effects of habitat loss and roads on wildlife populations]''''' Auteurs : Felix Eigenbrod, Stephen J. Hecnar, and Lenore Fahrig. (2008), Landscape Ecology 23 : 159-168. ---- * Landscape Institute (2013° ''[ Green Infrastructure An integrated approach to land use Landscape Institute Position Statement]'', PDF, 32 pp = Écopotentialité (potentialités écologiques) = * Net Landscape Ecological Potential of Europe and change 1990-2000 (Synthèse avec cartes concernantl'écopotentialité des territoires européens pour le réseau écologique paneuropéen (et la méthode de calcul, sur la base d'un indice NLEP (pour ''« Net Landscape Ecological Potential »''décrivant l'état de l'[[w:Intégrité écologique|intégrité écologique]], à macro-échelle. Cet indice, traduit en cartographie sur [[w:SIG|SIG]]) ; publiée le 21 April 2008 ; JLW-SSP ; Jean-Louis Weber, Rania Spyropoulou, Tomas Soukup, Ferran Páramo ; AEE (Agence européenne de l'environnement), EIONET, ETCLUSI; [http://eea.eionet.europa.eu/Public/irc/eionet-circle/leac/library?l=/ecological_21042008doc/_EN_1.0_&a=d Télécharger]; ---- = Flore, puits de carbone et microclimats urbains = * Djedjig R (2013). ''[https://tel.archives-ouvertes.fr/tel-01141046/document Impacts des enveloppes végétales à l’interface bâtiment microclimat urbain]'' (Doctoral dissertation, Université de La Rochelle). * ''[http://web.archive.org/web/20110124052753/http://www.cremtl.qc.ca/fichiers-cre/files/pdf891.pdf Rôles des arbres et des plantes grimpantes en milieu urbain]: revue de littérature et tentative d’extrapolation au contexte montréalais;'' <br /> Rapport d’étape destiné au Conseil régional de l'environnement de Montréal, Janvier 2007, par Yann Vergriete et Michel Labrecque. ---- [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Annexes]] [[Catégorie:Architecture]] rsv860ja0mszf199vok0bxy34ablnoa Introduire la biodiversité dans la construction et l'urbanisme/Préalables ; principes généraux et transversaux 0 32598 764204 685275 2026-04-21T08:55:42Z Lamiot 1916 /* Introduction */ complément 764204 wikitext text/x-wiki =='''Introduction'''== Certaines notions et principes propres à l'architecture, à l'urbanisme, à l'écologie ou encore à la psyché humaine sont « par nature » associés aux sujets traités dans ce livre. <br />Certains d’entre eux sont des conditions nécessaires (et hélas non suffisantes) à la réussite de toute démarche visant à restaurer les conditions d'un réconciliation profonde de l'urbanisme, de l'architecture et de la Nature. Ils peuvent aussi s'inscrire dans l'approche ZAN ([[w:fr:zéro artificialisation nette|zéro artificialisation nette]])<ref>Barra (Marc), Clergeau (Philippe), « “Zéro artificialisation nette” : des questions écologiques se posent », Diagonal, Blog, 30 juin 2020, https://diagonal.hypotheses.org/files/2020/06/ZAN-et-Biodiversité-Vdef.pdf.</ref>. <br />Ils seront rappelés ou seront transversalement présents dans l'ensemble des chapitres. ='''Principes généraux :'''= L'[[w:écologie du paysage|écologie du paysage]], la biologie de la conservation, appliquées à l'espace urbain, périurbain ou construit offrent maintenant un cadre théorique et pratique à l'analyse de la nature et naturalité des milieux construits, et de leurs impacts sur les milieux naturels. ===Développement durable et soutenable=== [[Image:Schéma du développement durable.svg|thumb|left|350px|'''''Figure 1 :''''' Les thèmes et enjeux généraux, mais majeurs, de [[w:Développement durable|soutenabilité du développement]], et leurs interelations]] [[File:3x3 rondsLamiotWikimediaCommons.jpg|thumb|right|350px|'''''Figure 2 : ''''' Comment agir, et avec quelles ressources pour quels objectifs ? Ce graphique présente les interrelations qui lient les grands domaines (ou enjeux) du développement durable.]] [[Image:Ukraine. Kamenets-Podolsky.jpg|thumb|350px|Un principe de base est - dans une certaine mesure (dans les limites qu'autorisent la préservation de l'infrastructure bâtie, et la sécurité notamment) - l'imitation des processus naturels. Si dans la nature, même des parois verticales et minérales ultrapauvres en nutriments peuvent abriter la vie (ici sur des falaises en Ukraine), l'architecte et l'urbaniste doivent pouvoir aménager le bâti pour y intégrer plus de biodiversité que dans le bâti tratitionnel]] [[image:EVA- Lanxmeer Greenhouse7 2009.jpg|thumb|350px|Tout en restant, dans une certaine mesure, ''sous contrôle'' la nature peut entrer dans une partie de l'espace habité (écoquartier d'[[w:fr:Eva-Lanxmeeer|Eva-Lanxmeer]], aux Pays-Bas]] Un premiers cadre, très général, est transversal à la plupart des démarches de prise en compte du Vivant dans l'urbanisme et le bâti. C'est celui du '''''« [[w:Développement soutenable|développement soutenable]] »''''' (ou ''« durable »''), désormais classiquement représenté comme à l'interface des trois sphères représentées par la '''''figure 1 ''''' (trois sphères ; environnementales, sociales et écologiques.. certains y ajoutant un 4ème pilier qui serait la culture, ici intégré dans la sphère du social). La '''''figure 1''''' (ci-contre à gauche) présente l'intérêt de rappeler que tout projet se voulant soutenable devrait au minimum répondre, et de manière équilibrée à ces préoccupations. <br />Concernant le sujet de cet ouvrage, les interfaces '''''« Vivable »''''' et '''''« Viable »''''' prendront une importance particulière, à la fois comme « condition » et « résultat » des projets réussis. La '''''figure 2 ''''', un peu plus complexe, mais plus précise, ajoute d'autres enjeux et thèmes aux précédents. Tous les thèmes qu'elle présente sont au moins pour partie fonctionnellement interdépendants. <br />Les zones d'intersections entre les sphères ou groupes de sphères du graphique représentent les interfaces (deux à deux, ou trois à trois) entre les items de base. par exemple la zone d'interface entre la spère «''''' Gérer '''''» et la sphère «''''' Restaurer'''''» est à comprendre comme représentant le domaine de la « '''''[[w:Gestion restauratoire|gestion restauratoire]]''''' ». <br />Ce diagramme décrit dans la ''« sphère des actions »'' la nécessité de '''restaurer''', '''protéger''' et '''gérer''' des '''ressources'''. Ces ressources (eau, air, sol, faune, flore, fonge...) sont toutes vitales pour l'homme et les autres espèces. Elles sont produites ou entretenues par la biodiversité, via les écosystèmes. Dans chaque projet, ces ressources peuvent, selon le contexte et les impacts du projet être classées et hiérarchisées comme étant : pas, peu, difficilement, coûteusement ou lentement renouvelables. Ces ressources sont nécessaires à l'atteinte des objectifs qui sont à la fois sociaux, économiques et donc environnementaux. <br />Tout projet se voulant cohérent du point de vue environnemental et durable, devrait prendre en compte chacun des aspects figuré par une sphère ainsi que par chaque intersection entre deux ou trois sphère. <br />Ce graphique, assez facile à mémoriser. Dans le domaine complexe de l'[[w:Évaluation environnementale|évaluation environnementale]], il permet de garder une vue globale et systémique d'un problème (une étude d'impact, un projet, un agenda 21, une situation individuelle ou collective, etc.). Il peut à ce titre -pour partie - servir de première check-list dans l'exploration des enjeux environnementaux de n'importe quel projet (architectural ou urbain dans les cas qui nous préoccupe dans cet ouvrage). Ce diagrame ne prend tout son sens et toute son utilité que si son utilisateur analyse les impacts positifs et négatifs, immédiats et différés dans le temps (court, moyen et long terme) et dans l'espace (impacts locaux à globaux). Il est en quelque sorte conçu pour aider à faire ce travail sans rien oublier d'important. On peut d'aussi y associer le ''« triangle éthique »'' (voir chapitre [[Pourquoi intégrer la biodiversité dans l'architecture/Approche éthique|Approche éthique]]) qui pourra aider le porteur de projet à hiérarchiser certains enjeux ; par exemple dans ou sur une crèche, d'une maternité, d'un hôpital, d'une maison de retraite, d'une école, la contribution de la biodiversité à épurer l'air et l'eau pourra être surpondérée dans l'évaluation des enjeux et priorités. Les principes du développement dit ''« soutenable »'', incluent la restauration, protection et gestion de la biodiversité. Ils semblent relever souvent du simple bon sens mais les architectes habitants, et usagers du patrimoine bâti ne savent pas toujours comment les transcrire ou les appliquer au mieux. Plus précisément les principes et critères de la [[w:Haute qualité environnementale|Haute qualité environnementale]] des éléments construits seront fréquemment évoqués. ===Chaque projet est un cas particulier, mais toujours à lier à l'environnement global=== Parce que portant sur le vivant, et s'inscrivant dans des contextes toujours différents, chaque projet d'intégration de la biodiversité dans la construction sera différent des autres, sans pour autant pouvoir être autonome car devant s'inscrire dans le ''réseau écologique local'' ou ce qui en reste, ce qui nécessite la prise en compte de l’environnement proche (atout, contraintes) et de l'écopotentialité du site ; En France, on pourra par exemple s'appuyer sur les [[w:fr:Inventaire communal de la biodiversité|inventaires communaux de la biodiversité]] (quand ils existent), sur les documents nationaux et régionaux ([[w:fr:SRCE|SRCE]]) la [[w:fr:Trame verte et bleue|trame verte et bleue]] en s'intéressant notamment au travail de prise en compte de la biodiversité (ordinaire ou non) dans les SCOTs (par exemple, dans le nord de la France, l'observatoire de la biodiversité du Nord-Pas-de-Calais a publié fin 2014 un ''{{Citation|État des lieux de la biodiversité dans les territoires des Schémas de cohérence territoriale}}''<ref>L’Observatoire de la biodiversité du Nord - Pas-de-Calais ; [http://www.observatoire-biodiversite-npdc.fr/fichiers/documents/biodiversite-dans-les-scot-orb-npdc-2014-light.pdf ''État des lieux de la biodiversité dans les territoires des Schémas de cohérence territoriale (SCoT)''], PDF, 300p) , 2014 </ref> librement consultable et utilisable par les habitants et collectivités pour mieux repérer les [[w:fr:enjeu|enjeux]] locaux de biodiversité. === L'approche écosystémique === Elle relève des sciences de la complexité et fonde l'approche écologique. Elle ne semble jamais avoir clairement et profondément guidé l'ensemble d'un projet urbain ou architectural, même si l'on parle parfois d'écosystème urbain et souvent d'écologie urbaine. <br />L'architecte et l'urbaniste n'en étant pas coutumiers, ils pourront utilement s'adjoindre les services d'écologues compétents. La ville ou d'autres milieux construits peuvent être considérés comme un écosystème unique ou comme une mosaïque d'écosystèmes plus ou moins artificialisés (vision pratique pour étudier, décrire et gérer la nature en ville<ref>Mission Économie de la biodiversité '''''[http://www.mission-economie-biodiversite.com/downloads/Cahier_n5_Comprendre_ville Infrastructures vertes urbaines et développement : vers une évaluation des impacts socio-économiques de la nature en ville]''''' ; Cahier n°5 de la collection "Cahiers Biodiv'2050". </ref>, à condition d'aussi bien comprendre les liens qui unissent ces milieux particuliers aux écosystèmes périphériques qui leur sont fonctionnellement reliés (via des corridors biologiques ou couloirs migratoires notamment). Bolund et Hunhammar ont proposé en 1999 sept catégories d' « ''écosystèmes urbains naturels'' » (qu'on pourra encore subdiviser en sous-unités)<ref>Bolund, P., Hunhammar, S. (1999), ''Ecosystem services in urban areas'', Ecological Economics, 29 (2), p. 293-301.</ref>. ===La renaturation=== Cette notion évoque un certain retour ou une certaine acceptation des processus naturels, auto-entretenus, et donc du "sauvage", nécessaire pour une ''« naturalité »'' plus élevée (et donc des équilibres écologiques moins perturbés). ===La notion de ''« qualité environnementale »'' === Elle couvre un domaine bien plus large que celui de la biodiversité, mais l'oubliant trop souvent. En France, on la résume souvent aux 14 cibles de la HQE, certains proposant depuis quelques années une quinzième cible (pour l'instant volontaire) et plus spécifiquement consacrée à la biodiversité. ===Le "Zéro impact"=== [[File:3x3rondMesuresCompensatoires.jpg|thumb|350px|Diagramme présentant quelques mots-clé et les relations et interrelations entre 3 modes de compensation d'impacts écologiques, tels que devant ou pouvant être compensés suite aux études d'impacts]] [[File:Palmanova dal satellite 2004.jpg|thumb|250px|Le bâti ancien, militaire et fortifié notamment (ici la citadelle de Palmanova en Italie), peut abriter une biodiversité significative (y compris en terme génétique), qu'il conviendrait de protéger au même titre que le patrimoine bâti, ce qui demande aux architectes du patrimoine de travailler avec des écologues, et inversement afin de trouver les compromis les plus intéressant. C'est ce qui est fait à Lille pour la Citadelle de Vauban]] C'est une "cible", un but qu'on cherche à atteindre, notamment par des mesures d'atténuation et de réparation des impacts, visant : * la diminution de l’empreinte écologique (et donc énergétique) du bâti ; c'est une approche globale prenant mieux en compte une partie des impacts initiés ou différés dans l'espace et le temps * la diminution de l’impact écologique du bâti lui-même et de son fonctionnement (chauffage, ventilation, circulation, réseaux..) * la diminution de l’impact écologique des occupants (y compris via une gestion, et un fonctionnement moins nuisants pour l'environnement) Ceci peut se faire en combinant trois grands types de mesures ou approches * des mesures conservatoires, * des mesures compensatoires (en cherchant à appliquer le principe de "juste compensation") * des mesures restauratoires Ou, quand une restauration totale n'est pas possible (ce qui est souvent le cas) par le double principe de ''« restauration d'habitats » (génie écologique)'' et d'offre d' ''« habitats de substitution »'' (une mare alimentée par les eaux de gouttières, un nichoir intégré dans mur, une terrasse ou mur végétalisé par exemple) …pour répondre aux critères de "Haute qualité", ces mesures doivent être "justes, réelles, fonctionnelles et efficaces " ("Juste" signifie ici qu'on cherche à restaurer l'écopotentiel du site et donc les fonctionnalités écologiques qui devraient normalement s'exprimer dans la zone biogéographique considérée, en l'absence d'impacts des activités humaines, ce qui implique une approche préalable de type "étude d'impact", rigoureuse et intégrant les aspects quantitatifs et qualitatifs de la biodiversité) ; <br />Ces approches sont théoriquement aussi celles des méthodes développées pour les études d'impacts qui peuvent – en amont – inspirer l'architecte et l'urbaniste, de même que les techniques et outils d'écobilan et d'ACV (Analyse du cycle de vie). Le zéro impact ne peut généralement pas être atteint directement, il appelle donc une autre notion : celle de "Remboursement de la dette écologique" ; c’est une cible et une exigence, dont nous ignorons si elle peut vraiment être tout à fait atteinte, notamment parce que c'est une notion relative au degré d'exigence du porteur de projet (quelle niveau de qualité environnementale cherchera-t-on à retrouver ?). Cette cible serait théoriquement atteinte (100 points sur 100) quand la biodiversité peut s’exprimer sur le bâti et son environnement proche, comme elle le ferait dans une "nature sauvage" (où l’influence humaine ne se ferait pas sentir). Les indicateurs utilisables sont la "biomasse équivalente", la "diversité spécifique", une diversité "génétique supposée comparable", etc). ====Le concept de bâti (ou construction) ''« à biodiversité positive »''. ==== Il prolonge la cible précédente. C'est un des moyens de rembourser une dette écologique en matière de biodiversité. <br />Des indicateurs de réalisation objectifs et validés manquent encore pour cette cible (en partie théorique) mais elle est très motivante et offre d'intéressants défis à relever pour les architectes, urbanistes et usagers du patrimoine bâti. ===La gouvernance=== Dans le domaine de la biodiversité urbaine ou intégrée dans le bâti, l'expérience a montré qu'une grande partie des projets réussis sur le long terme se sont tous appuyés sur une gouvernance s'appuyant sur les principes d' ''« écocitoyenneté »'', et de ''« participation ("proactive" dans la mesure du possible) des parties prenantes »'' ; c'est un des facteurs de réussite sur le moyen et long terme. ===L'évaluation=== Des indicateurs d'état, de pression, d'impacts, de réponse ; quantitatifs et qualitatif, sont utiles et nécessaires pour le suivi et l'évaluation des projets, et pour affiner et améliorer les stratégies décrites dans cet ouvrage. De tels indicateurs peuvent être notamment fournis par * des dispositifs automatiques d'acquisition de données environnementales (réseau d'alerte et de mesure de la qualité de l'eau, de l'air, des sols, etc), mesures satellitales des surfaces "naturelles" et de leur connectivité écologique ou degré de fragmentation écopaysagère ; * des études spécifiques, * un observatoire collaboratif de la biodiversité, * des sentinelles de l’environnement * des écogardes, ou autres corps spécialisés dans le suivi ou la protecion de l'environnement * La bio-indication (outil encore peu utilisé mais disponible). Elle peut être sophistiquée ou grossière mais efficace (ex : présence/absence de papillons, abeilles, hirondelles, moineaux, anguilles, brochet, saumons, vers de terre, etc… ou présence/absence d'espèces invasives ou indicatrices de déséquilibres écologiques) * etc.. Les évaluateurs devraient chercher à mieux prendre en compte le cycle du vivant, dont la ''« nécromasse »'' et son recyclage. == Notes et références == {{Références|colonnes=2}} [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Préalables ; principes généraux et transversaux]] a31diqing4wtue80ab5mfkvir31bpzm Introduire la biodiversité dans la construction et l'urbanisme/Les étapes dans l'élaboration d'un projet de prise en compte de la biodiversité dans la construction/Étudier l'existant (état des lieux, sur et autour du site) 0 34478 764198 463854 2026-04-21T08:40:08Z Lamiot 1916 /* Notes et références */ 764198 wikitext text/x-wiki Dans notre approche, l'architecte et l'urbaniste, voire les usagers veulent permettre aux espèces ''« normalement, c'est à dire potentiellement présentes sur le site »'' de vivre en harmonie avec le bâti et ses usages. Une première étape sera donc la connaissance de la biodiversité existante et potentielle sur le lieu de travail (construction ou réhabilitation). Ce travail est généralement rendu sous forme de cartes (dont cartes de synthèse). Il peut notamment s'appuyer sur la [[w:fr:Cartographie des corridors biologiques|cartographie des corridors biologiques]] quand elle est disponible, par exemple dans le cadre d'une [[w:fr:trame verte et bleue|trame verte et bleue]]. Se rapprocher des [[w:fr:observatoire de la biodiversité|observatoires de la biodiversité]], [[w:fr:Conservatoire botanique|conservatoires botaniques]] ou [[w:fr:Conservatoire faunistique|faunistiques]] les plus proches quand ils existent. Une double évaluation est nécessaire, avec : ==Un inventaire écologique de l'existant== === Inventaire des espaces potentiellement végétalisables === Une première étape peut être d'inventorier les objets urbains susceptibles de se végétaliser spontanément ou d'être végétalisés, éventuellement avec une démarche de participation citoyenne. Ainsi, en juillet 2014, la ville de Paris a lancé une opération « ''Du vert près de chez moi'' » qui propose aux Parisiens de signaler les espaces « végétalisables » qu'ils ont observé<ref name=Figar2015>Article du Figaro, de Quentin Périnel, intitulé [http://immobilier.lefigaro.fr/article/voici-les-209-lieux-qui-vont-etre-vegetalises-a-paris-en-2015-_1f52a866-b38b-11e4-9968-6ccd5602338b/ ''L’opération inédite de la ville de Paris « Du vert près de chez moi» invite les Parisiens à signaler les espaces «végétalisables ». Elle s’inscrit dans une logique environnementale et prônant la notion de «vivre ensemble»''], 13-02-15, consulté 13-03-2015</ref>. Sur 1500 sites proposés par les parisiens, la ville en a retenu 209 ont été retenues (pour 200 prévues dans un premier temps) sur la base de critères de faisabilité technique, et de ''{{Citation|priorisation des projets par les mairies d’arrondissements, la répartition par type de projets, la superficie et le nombre d’habitants, la présence d’espaces verts, les projets pouvant faire l’objet d’un entretien participatif et ceux pouvant faire l’objet d’un entretien municipal}}''<ref name=Figar2015/>. Dans ce cas, 81 pots ou bacs à fleurs, 53 murs végétalisés, 20 jardinières de pleine terre et 35 zones à arborer sont prévus. Cette opération s'inscrit aussi dans le projet « Paris Smart City 2050 »<ref name=Figar2015/>. === Inventaire de la biodiversité === Cet inventaire qu'il sera utile de périodiquement remettre à jour et tenir à disposition des usagers et aménageurs doit être fait par un écologue et si possible une équipe pluridisciplinaire, en utilisant l'observation directe du terrain et toutes les bases de données disponibles. Cet inventaire ne saurait être exhaustif concernant les espèces les plus discrètes (microbes et insectes en particulier), mais il doit prendre en compte les mammifères, oiseaux, plantes supérieures, mousses et lichens, et considérer leur valeur en tant que '''''[[w:fr:Bioindicateur|bioindicateur]]'''''. Au sein des espèces existantes, il faut identifier celles qui sont [[w:fr:espèce menacée|menacées]], et lorsque possibles les tendances et les facteurs explicatifs expliquant leur régression (par exemple si l'absence de boue est une des explication au fait que des hirondelles ne peuvent plus faire leur nid, l'urbaniste pourra restaurer des zones humides à pentes douces avec des zones de boue utiles aux hirondelles) Objectif : Cet inventaire doit pouvoir orienter l'architecte et l'écologue dans leurs choix de [[w:fr:mesure conservatoire|mesures conservatoires]] et [[w:fr:mesure compensatoire|compensatoires]] et dans l'offre en habitat de substitution qu'ils pourront intégrer dans le bâti ; <br>Il serait par exemple tout à fait inutile de prévoir des parois sableuses utilisables par des [[w:fr:hirondelle de rivage|hirondelles de rivage]], même si l'environnement est naturellement sableux, s'il n'y a pas à proximité de zone humides où elles peuvent se nourrir. Par contre de petites zones sableuses judicieusement exposées sont généralement utiles pour certains insectes fouisseurs. La première étape, qui devrait être intégrée dans toute bonne étude d'impact est celle de l'inventaire écologique du site et de son environnement proche. Le travail d'inventaire de terrain reste nécessaire, mais de nouveaux outils utilisant l'imagerie aérienne et satellitale, les SIG, la modélisation, etc. facilitent et enrichissent du travail, y compris en ville pour l'appréciation de l'état de la végétation urbaine et des services qu'elle rend, notamment en termes de qualité de l'air<ref>Wania, A. (2007), ''[http://scd-theses.u-strasbg.fr/1442/ Urban vegetation – detection and function evaluation for air quality assessment]'', Thèses de doctorat, Université Louis Pasteur, Strasbourg, [http://scd-theses.u-strasbg.fr/1442/01/WANIA_Annett_2007.pdf PDF en ligne] URL : http://scd-theses.u-strasbg.fr/1442/01/WANIA_Annett_2007.pdf, consulté le 1 mai 2012</ref>. === Analyse des corridors écologiques === Dans un premier temps, le lieu d’implantation d’un nouvel aménagement urbain doit être choisi de manière à perturber le moins possible le réseau de corridors écologiques environnant. Pour cela, une approche graphique de type SIG permet de mettre en évidence les espaces qui doivent rester préservés en raison de leur rôle dans le réseau. Puis dans un second temps, cette même approche SIG, une fois le lieu choisi pour le site, permet de déterminer où placer les espaces verts au sein de celle-ci afin de former des corridors les plus fonctionnels possibles. Les résultats apportés par ce type d’approche graphique doivent être intégrés aux processus de décisions, au même titre que les données économiques ou sociales<ref name="Serret & al., 2014"> [Serret & al., 2014, Potential contributions of green spaces at business sites to the ecological network in an urban agglomeration : the case of the Ile-de-France region, France. Landscape and Urban Planning 131, 27-35.].</ref>. De plus, ces zones vertes doivent avoir une grande surface. Plus une zone urbaine verte est grande, plus sa richesse spécifique sera susceptible d’être grande. Pour améliorer l’impact d’une zone urbaine sur la biodiversité, il ne faut pas hésiter à renforcer ses espaces verts par des zones vertes additionnelles<ref name="Snep and al., 2008"> [Snep and al., 2008, Enhancing biodiversity at business sites : What are the options and which of thse do stakeholdres prefer ? Landscape and Urban Planning 91, 26-35.].</ref>. Enfin, il conviendra, autour de ces espaces verts, de prendre en compte et de réduire au maximum les barrières physiques, tels que les grillages ou les murs, qui peuvent empêcher le mouvement d’espèces terrestres<ref name="Serret & al., 2014" />. ==Une évaluation de l' ''écopotentiel'' du site== Ce travail peut être fait après l'évaluation de l'existant ou en parallèle. <br>Il nécessite une approche [[w:fr:Holistique|holistique]], et un peu d'[[w:fr:écologie rétrospective|écologie rétrospective]]. Il s'agit de répondre à la question : quelle était la biodiversité sur ce site ? il y a 10, 50, 100, 300 ou 1000 ans, et quelles espèces seraient susceptibles de revenir ? et à quelles conditions ? La notion d'[[w:fr:écopotentialité|écopotentialité]] du site est traité plus loin (au chapitre ''[https://fr.wikibooks.org/wiki/Introduire_la_biodiversit%C3%A9_dans_la_construction_et_l%27urbanisme/Principes_%C3%A9cologiques_de_bases/%C3%89copotentialit%C3%A9 Principes écologiques de bases]''). ==Mises à jour == La mise à jour de l'évaluation environnementale du site pourra * contribuer à l'évaluation générale de la qualité du projet (réhabilitation individuelle, [[w:frécoquartier|écoquartier]]...) * contribuer à l'[[w:fr:Amélioration continue|amélioration continue]] d'une la quinzième cible HQE == Notes et références == {{Références|colonnes=2}} == Bibliographie == * Marc Barra (2022) Intégrer la biodiversité dans les projets de construction et de rénovation ; Techniques de construction ; Septembre/Décembre 2022 https://www.arb-idf.fr/fileadmin/DataStorageKit/ARB/Articles/fichiers/integrerbiodivprojets/Integrer_la_biodiversite_dans_les_projets_de_construction_et_de_renovation.pdf [[Catégorie:Introduire la biodiversité dans la construction et l'urbanisme (livre)|Les étapes dans l'élaboration d'un projet de prise en compte de la biodiversité dans la construction]] rwh62z6fuqdlrpmmjtnkme4h2yi3m7i Fonctionnement d'un ordinateur/Contrôleur mémoire externe 0 65796 764089 732286 2026-04-20T15:07:20Z Mewtow 31375 764089 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Le contrôleur mémoire externe est relié au CPU par un bus, et est connecté aux barrettes ou boitiers de DRAM via le bus mémoire proprement dit. Les anciens contrôleurs mémoire étaient des composants séparés du processeur, du ''chipset'' ou du reste de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire, à savoir ses broches d'entrées/sorties et leur signification, est généralement très simple. Il se connecte au processeur et à la mémoire, ce qui fait qu'il a deux ports : un qui a la même interface mémoire que le processeur, un autre qui a la même interface que la mémoire. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. En effet, les requêtes du processeur ne sont pas forcément compatibles avec les entrées de la mémoire. Un accès mémoire typique venant du processeur contient juste une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Notons que cette fonction d’interfaçage implique beaucoup de choses, la première étant que les adresses du processeur sont traduites en adresses compatibles avec la mémoire. Sur les mémoires DRAM, cela signifie que l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Mais ce n'est pas la seule opération de conversion possible. Il y a aussi le cas où le bus d'adresse et le bus de données sont fusionnés. Nous avions vu cela dans le chapitre sur l'interface des mémoires. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. Une autre possibilité est la gestion de l'entrelacement, qui intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Une autre possibilité est le cas où les adresses du processeur n'ont pas la même taille que les adresses du bus mémoire, le contrôleur peut se charger de tronquer les adresses mémoires pour les faire rentrer dans le bus d'adresse. Cela arrive quand la mémoire a des mots mémoires plus longs que le byte du processeur. Prenons l'exemple où le processeur gère des bytes de 1 octet, alors que la mémoire a des mots mémoires de 4 octets. Lors d'une lecture, le contrôleur mémoire va lire des blocs de 4 octets et récupérera l'octet demandé par le processeur. En conséquence, la lecture dans la mémoire utilise une adresse différente, plus courte que celle du processeur : il faut tronquer les bits de poids faible lors de la lecture, mais les utiliser lors de la sélection de l'octet. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Les autres fonctions (résumé)=== Pour résumer, le contrôleur mémoire externe gère au minimum la traduction des accès mémoires en suite de commandes (ACT, sélection de ligne, etc.), le rafraîchissement mémoire, ainsi que l’interfaçage électrique. Mais il peut aussi incorporer diverses optimisations pour rendre la mémoire plus rapide. Par exemple, c'est lui qui s'occupe de l'entrelacement. Il gère aussi le séquencement des accès mémoires et peut parfois réorganiser les accès mémoires pour mieux utiliser les capacités de ''pipelining'' d'une mémoire synchrone, ou pour mieux utiliser les accès en rafale. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre. Si les commandes mémoires sont envoyées dans un ordre différent de celui du processeur, le contrôleur mémoire fait en sorte que cela ne se voit pas. Notamment, il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> mf831z9q1q3xo3city8skw9cjhp9pq2 764090 764089 2026-04-20T15:14:41Z Mewtow 31375 /* Les rôles et l'interface du contrôleur mémoire */ 764090 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Une autre possibilité est le cas où les adresses du processeur n'ont pas la même taille que les adresses du bus mémoire, le contrôleur peut se charger de tronquer les adresses mémoires pour les faire rentrer dans le bus d'adresse. Cela arrive quand la mémoire a des mots mémoires plus longs que le byte du processeur. Prenons l'exemple où le processeur gère des bytes de 1 octet, alors que la mémoire a des mots mémoires de 4 octets. Lors d'une lecture, le contrôleur mémoire va lire des blocs de 4 octets et récupérera l'octet demandé par le processeur. En conséquence, la lecture dans la mémoire utilise une adresse différente, plus courte que celle du processeur : il faut tronquer les bits de poids faible lors de la lecture, mais les utiliser lors de la sélection de l'octet. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Les autres fonctions (résumé)=== Pour résumer, le contrôleur mémoire externe gère au minimum la traduction des accès mémoires en suite de commandes (ACT, sélection de ligne, etc.), le rafraîchissement mémoire, ainsi que l’interfaçage électrique. Mais il peut aussi incorporer diverses optimisations pour rendre la mémoire plus rapide. Par exemple, c'est lui qui s'occupe de l'entrelacement. Il gère aussi le séquencement des accès mémoires et peut parfois réorganiser les accès mémoires pour mieux utiliser les capacités de ''pipelining'' d'une mémoire synchrone, ou pour mieux utiliser les accès en rafale. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre. Si les commandes mémoires sont envoyées dans un ordre différent de celui du processeur, le contrôleur mémoire fait en sorte que cela ne se voit pas. Notamment, il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> t8hzv90hqteht6zlkxsh00iyrjyxulh 764091 764090 2026-04-20T15:15:27Z Mewtow 31375 /* La traduction d'adresse */ 764091 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Les autres fonctions (résumé)=== Pour résumer, le contrôleur mémoire externe gère au minimum la traduction des accès mémoires en suite de commandes (ACT, sélection de ligne, etc.), le rafraîchissement mémoire, ainsi que l’interfaçage électrique. Mais il peut aussi incorporer diverses optimisations pour rendre la mémoire plus rapide. Par exemple, c'est lui qui s'occupe de l'entrelacement. Il gère aussi le séquencement des accès mémoires et peut parfois réorganiser les accès mémoires pour mieux utiliser les capacités de ''pipelining'' d'une mémoire synchrone, ou pour mieux utiliser les accès en rafale. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre. Si les commandes mémoires sont envoyées dans un ordre différent de celui du processeur, le contrôleur mémoire fait en sorte que cela ne se voit pas. Notamment, il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 2xfds9yztv16d2xocft6xvbtuoma1hm 764092 764091 2026-04-20T15:15:50Z Mewtow 31375 /* Les séquencement des commandes mémoires */ 764092 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Les autres fonctions (résumé)=== Pour résumer, le contrôleur mémoire externe gère au minimum la traduction des accès mémoires en suite de commandes (ACT, sélection de ligne, etc.), le rafraîchissement mémoire, ainsi que l’interfaçage électrique. Mais il peut aussi incorporer diverses optimisations pour rendre la mémoire plus rapide. Par exemple, c'est lui qui s'occupe de l'entrelacement. Il gère aussi le séquencement des accès mémoires et peut parfois réorganiser les accès mémoires pour mieux utiliser les capacités de ''pipelining'' d'une mémoire synchrone, ou pour mieux utiliser les accès en rafale. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre. Si les commandes mémoires sont envoyées dans un ordre différent de celui du processeur, le contrôleur mémoire fait en sorte que cela ne se voit pas. Notamment, il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 6iscg9atn7cl04kz60n3wk7v5tddhi6 764093 764092 2026-04-20T15:40:47Z Mewtow 31375 /* La traduction des signaux et l’horloge */ 764093 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. ===Les autres fonctions (résumé)=== Pour résumer, le contrôleur mémoire externe gère au minimum la traduction des accès mémoires en suite de commandes (ACT, sélection de ligne, etc.), le rafraîchissement mémoire, ainsi que l’interfaçage électrique. Mais il peut aussi incorporer diverses optimisations pour rendre la mémoire plus rapide. Par exemple, c'est lui qui s'occupe de l'entrelacement. Il gère aussi le séquencement des accès mémoires et peut parfois réorganiser les accès mémoires pour mieux utiliser les capacités de ''pipelining'' d'une mémoire synchrone, ou pour mieux utiliser les accès en rafale. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre. Si les commandes mémoires sont envoyées dans un ordre différent de celui du processeur, le contrôleur mémoire fait en sorte que cela ne se voit pas. Notamment, il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 02xzx7o087ilq55q7fwv28ezfn9mc6v 764094 764093 2026-04-20T15:42:49Z Mewtow 31375 /* Les autres fonctions (résumé) */ 764094 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> rvcc930d82w4mqhwun63q8raxkbp7nv 764095 764094 2026-04-20T15:43:24Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764095 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 2q29ko9iafi0p5o50a2rlj489skt9tq 764096 764095 2026-04-20T15:48:10Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764096 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> chx22b66zpqt07ikd3smt9nmqd26987 764097 764096 2026-04-20T15:54:39Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764097 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. Cette dernière s'occupe, comme dit haut, de la traduction des tensions entre processeur et mémoire, ainsi que de la génération de l'horloge. Si la mémoire est une mémoire série, elle contient un registre à décalage pour transformer un mot mémoire de N bits en signal série transmis bit par bit. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le séquenceur peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, il prévient le processeur quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le rôle principal du contrôleur est la traduction des requêtes processeurs en une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, le contrôleur mémoire contient un circuit séquentiel appelé une '''machine à état fini''', aussi appelée '''séquenceur''', qui s'occupe de cette traduction. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la traduction des requêtes en suite de commandes, et la gestion des timings d'envoi de ces commandes à la mémoire. S'il y a séparation, le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier reçoit les commandes du circuit de traduction, les mets en attente et les envoie à la mémoire quand les timings le permettent. Notons que cela implique une fonction de mise en attente des commandes. Les raisons à cela sont multiples. Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> qn8wz5gwxncpiagz80lr2n3cqa6evhp 764098 764097 2026-04-20T16:00:39Z Mewtow 31375 /* L'architecture du contrôleur */ 764098 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, la génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une '''machine à état fini''', aussi appelée '''séquenceur'''. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Le cas le plus simple est celui des requêtes processeur qui correspondent à plusieurs commandes. Prenons l'exemple d'une requête de lecture se traduit en une série de deux commandes : ACT et READ. La commande ACT peut être envoyée directement à la mémoire si elle est libre, mais la commande READ doit être envoyée deux cycles plus tard. Cette dernière doit donc être mise en attente durant deux cycles. Et on pourrait aussi citer le cas où plusieurs requêtes processeur arrivent très vite, plus vite que la mémoire ne peut les traiter. Si des requêtes arrivent avant que la mémoire n'ait pu terminer la précédente, elles doivent être mises en attente. Notons que pour les mémoires SDRAM et DDR, ce circuit décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ha7tkukyvbek9ck6wd6edpecj0z8gel 764099 764098 2026-04-20T16:03:13Z Mewtow 31375 /* Le séquenceur mémoire */ 764099 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, la génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une '''machine à état fini''', aussi appelée '''séquenceur'''. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. ===Le circuit de gestion du rafraichissement et le circuit d'arbitrage=== La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> blksjxg0fznrp5ta2qsm3ekoza5qlhq 764100 764099 2026-04-20T16:03:52Z Mewtow 31375 /* Le circuit de gestion du rafraichissement et le circuit d'arbitrage */ 764100 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. Dans le cas le plus simple, la génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une '''machine à état fini''', aussi appelée '''séquenceur'''. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Mais cette organisation marche assez mal avec la gestion du rafraichissement. Aussi, il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> krm8mfqm51v4t282eb9f00rhyc7bn53 764101 764100 2026-04-20T16:04:51Z Mewtow 31375 /* Le séquenceur mémoire */ 764101 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== En clair, le contrôleur mémoire contient notamment un circuit de traduction des requêtes processeur en commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 4b2cwh8yvb011onw5dutjgmvrrl14fv 764102 764101 2026-04-20T16:06:35Z Mewtow 31375 /* L'architecture complète du contrôleur mémoire externe */ 764102 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===La politique de la page fermée=== Dans le premier cas, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. ===La politique de la page ouverte=== Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 98aj2msypoaoby480cr2ej86mmmosaw 764103 764102 2026-04-20T16:07:24Z Mewtow 31375 /* La politique de gestion du tampon de ligne */ 764103 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ezi0iqsh44y8fxhqohp0jpe81o2d2mq 764104 764103 2026-04-20T16:12:01Z Mewtow 31375 764104 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> tl29btcfy6djz45628mcdupr72kxuvn 764105 764104 2026-04-20T16:12:15Z Mewtow 31375 764105 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Les rôles et l'interface du contrôleur mémoire== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> inam61r76sg9n0ligvcv1upzdbqsbnp 764106 764105 2026-04-20T16:15:17Z Mewtow 31375 /* Les rôles et l'interface du contrôleur mémoire */ 764106 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur mémoire pour une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ly035hkgpb253xg58aqp34yl0a5s95c 764107 764106 2026-04-20T16:16:32Z Mewtow 31375 /* Le contrôleur mémoire pour une DRAM simple, asynchrone */ 764107 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur mémoire pour une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> d5vv4ry948ee7r9akgz5k2vtc7qvvx2 764108 764107 2026-04-20T16:16:49Z Mewtow 31375 /* L'architecture du contrôleur */ 764108 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur mémoire pour une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. ===Les séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==L'architecture du contrôleur de SDRAM== Dans les grandes lignes, on peut découper le contrôleur mémoire externe en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge,n entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. L'interface électrique est presque toujours présente, alors que le gestionnaire mémoire peut parfois être réduit à peu de chagrin sur certaines mémoires. le gestionnaire mémoire est découpé en deux : un circuit qui s'occupe de la gestion des commandes mémoires proprement dit, et un circuit qui s'occupe des échanges de données avec le processeur. Ce dernier prévient le processeur quand une donnée lue est disponible et lui fournit la donnée avec, quand une écriture est terminée, etc. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Le séquenceur mémoire=== Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 123694tbpdjc0rvp8edtvpngqi07vf2 764109 764108 2026-04-20T16:18:39Z Mewtow 31375 764109 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur mémoire pour une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le proesseur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 9pp1asju0oajnb9nrtm7kzsaije3lik 764110 764109 2026-04-20T16:21:28Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764110 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur mémoire pour une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l'interface électrique et la gestion de l'horloge. Rappelons que la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont presque équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Il va de soi qu'un générateur de fréquence est beaucoup plus complexe qu'une simple PLL. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. Un autre point est que la mémoire peut avoir une interface série, à savoir que les données sont transmises bit par bit. Dans ce cas, les mots mémoire sont transférés bit par bit à la mémoire ou vers le processeur. La traduction d'un mot mémoire de N bits en une transmission bit par bit est réalisée par cette interface électrique. Un simple registre à décalage suffit dans les cas les plus simples. Enfin, n'oublions pas l’interfaçage électrique, qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> apxdgfddm688cw0wp7de88u50nq8x5z 764111 764110 2026-04-20T16:27:01Z Mewtow 31375 /* Le contrôleur mémoire pour une DRAM simple, asynchrone */ 764111 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un bus d'adresse multiplexé, l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envois chaque morceau au bon moment. Avec un bus totalement multiplexé, le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> odtkl0i4v74hfj6t5t8fsp99me3avbk 764112 764111 2026-04-20T16:33:47Z Mewtow 31375 /* La traduction d'adresse */ 764112 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> qwymu97cbtpil1zsycy0nbr9dpy0nit 764113 764112 2026-04-20T16:40:52Z Mewtow 31375 /* La traduction d'adresse */ 764113 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 5qjpew975pgbqeurlb6j8x8s1vqbzhg 764114 764113 2026-04-20T16:41:34Z Mewtow 31375 /* La traduction d'adresse */ 764114 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 2r2gzdfgtx63h41legc0gfacoi3y887 764115 764114 2026-04-20T16:41:55Z Mewtow 31375 /* L'architecture complète du contrôleur mémoire externe */ 764115 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== A cela, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> p7v5x6nlnbn0z90x9icd4lmudfi3r5h 764116 764115 2026-04-20T16:43:05Z Mewtow 31375 /* La traduction des signaux et l’horloge */ 764116 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ===La traduction des signaux et l’horloge=== Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. De plus, la mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 4w971063jlz0dx1h1t8dqv7mr9ufq4u 764117 764116 2026-04-20T16:43:39Z Mewtow 31375 /* Le contrôleur d'une DRAM simple, asynchrone */ 764117 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> nlq698yocwhul1b970ocyebwl9vyi7s 764118 764117 2026-04-20T16:43:57Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764118 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence mémoire-CPU=== La mémoire ne va pas à la même fréquence que le processeur et qu'il y a donc une adaptation à faire. Soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> luqe06bsyocdnlevcsn5lvbem4s3jsb 764119 764118 2026-04-20T16:45:11Z Mewtow 31375 /* La gestion de la fréquence mémoire-CPU */ 764119 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence mémoire-CPU=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> idrubvxakv24trwc735112x986cx5u6 764120 764119 2026-04-20T16:45:34Z Mewtow 31375 /* La gestion de la fréquence mémoire-CPU */ 764120 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence mémoire-CPU=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> bkp6ik45h1irrurc9zz4utzduzsyu13 764121 764120 2026-04-20T16:45:44Z Mewtow 31375 /* La gestion de la fréquence mémoire-CPU */ 764121 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions et de l'horloge, entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 0uwad0x33dfd0gkmm2zz9k940a6lped 764122 764121 2026-04-20T16:46:22Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764122 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ev7eunhpoyuwao1jblax0wq16l2o7c9 764123 764122 2026-04-20T16:52:18Z Mewtow 31375 /* La traduction d'adresse */ 764123 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== N'oublions pas non plus la gestion du rafraichissement mémoire, qui est dévolue au contrôleur mémoire ! Il pourrait être réalisé par le processeur, mais ce ne serait pas pratique. Il faudrait que le processeur lui-même incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il dispose de la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Et le processeur devrait régulièrement s'interrompre pour s'occuper du rafraichissement, ce qui perturberait l’exécution des programmes en cours d'une manière assez subtile, mais pas assez pour ne pas poser de problèmes. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> jv4m07bqi5r90eve0xkv6vpcbp61hn9 764124 764123 2026-04-20T16:55:01Z Mewtow 31375 /* Le rafraichissement mémoire */ 764124 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 5d1kv4qnom3dyuk45icoyfnuxwbpgk4 764125 764124 2026-04-20T16:59:19Z Mewtow 31375 /* Le contrôleur d'une DRAM simple, asynchrone */ 764125 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===La traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> qy12qm4rgbt6dznf1ehabup2ch7ovo7 764126 764125 2026-04-20T16:59:32Z Mewtow 31375 /* La traduction d'adresse */ 764126 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> qib2hsb30jr6tcp5gen1kukfix0bkcd 764127 764126 2026-04-20T19:35:06Z Mewtow 31375 /* Le rafraichissement mémoire */ 764127 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre un compteur d'adresse. Le '''compteur d'adresse''' contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Il est incrémenté à intervalle régulier. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un circuit de rafraichissement, qui est souvent séparé du séquenceur mémoire. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 9sihn0hhaptyeqrt45wyvyv9i6y1nw4 764128 764127 2026-04-20T19:44:39Z Mewtow 31375 /* Le rafraichissement mémoire */ 764128 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timing'' est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un le compteur de rafraichissement, qui est souvent séparé du séquenceur mémoire. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, la sortie du compteur de rafraichissement ne commande pas directement le multiplexeur de rafraichissement. A la place, le séquenceur mémoire utilise la sortie du compteur de rafraichissement pour configurer tous les multiplexeurs. ===Exemple : l'Intel 8202-8203== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. On pouvait le connecter sur 4 chip mémoire, qui sont accédés en parallèle. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> o83kwrtgrn5dfq8qpo04gmk0r5zq6yz 764129 764128 2026-04-20T19:45:54Z Mewtow 31375 /* Le générateur de timings et la traduction d'adresse */ 764129 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un le compteur de rafraichissement, qui est souvent séparé du séquenceur mémoire. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, la sortie du compteur de rafraichissement ne commande pas directement le multiplexeur de rafraichissement. A la place, le séquenceur mémoire utilise la sortie du compteur de rafraichissement pour configurer tous les multiplexeurs. ===Exemple : l'Intel 8202-8203== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. On pouvait le connecter sur 4 chip mémoire, qui sont accédés en parallèle. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> iiudypbct3llx1gi1sz1nnl47ahk8r0 764130 764129 2026-04-20T19:50:47Z Mewtow 31375 /* Le rafraichissement mémoire */ 764130 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un le compteur de rafraichissement, qui est souvent séparé du séquenceur mémoire. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, la sortie du compteur de rafraichissement ne commande pas directement le multiplexeur de rafraichissement. A la place, le séquenceur mémoire utilise la sortie du compteur de rafraichissement pour configurer tous les multiplexeurs. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. On pouvait le connecter sur 4 chip mémoire, qui sont accédés en parallèle. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 14gh6z3g7vl1jz2p491nc78h2ty74rg 764131 764130 2026-04-20T19:54:34Z Mewtow 31375 /* =Exemple : l'Intel 8202-8203 */ 764131 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un le compteur de rafraichissement, qui est souvent séparé du séquenceur mémoire. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, la sortie du compteur de rafraichissement ne commande pas directement le multiplexeur de rafraichissement. A la place, le séquenceur mémoire utilise la sortie du compteur de rafraichissement pour configurer tous les multiplexeurs. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> gc36ovbd1zco26ucjcxofwv757nvbjg 764132 764131 2026-04-20T20:01:04Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764132 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur est commandé par un le compteur de rafraichissement, qui est souvent séparé du séquenceur mémoire. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, la sortie du compteur de rafraichissement ne commande pas directement le multiplexeur de rafraichissement. A la place, le séquenceur mémoire utilise la sortie du compteur de rafraichissement pour configurer tous les multiplexeurs. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Il avait donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202/8203 avait aussi une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> i59qnck7pomtmsx7krorcmnlxyfskr1 764133 764132 2026-04-20T20:03:57Z Mewtow 31375 /* Le rafraichissement mémoire */ 764133 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Il avait donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202/8203 avait aussi une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> q8a1bhnpyv1mgov3w779l7pqsy40jmm 764134 764133 2026-04-20T20:08:21Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764134 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Il avait donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202/8203 avait aussi une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> py7yf5xa6d6269v6f780j6jswl20tzm 764135 764134 2026-04-20T20:13:25Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764135 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Il avait donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202/8203 avait aussi une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> m591h7tbx0ea5n4xsn7ydue7y13o78o 764136 764135 2026-04-20T20:14:10Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764136 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Il fournissait en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Il avait donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202/8203 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202/8203 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202/8203 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 69n5gsnbg7v1uqrrj59jrsqa7d8g9hy 764137 764136 2026-04-20T20:16:25Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764137 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoire étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégré au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 64qo11hxg1qhv31b5urmduw1u24d3as 764138 764137 2026-04-20T20:16:58Z Mewtow 31375 /* Le contrôleur d'une DRAM simple, asynchrone */ 764138 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. Mettre en attente des requêtes processeur n'est pas seulement utile pour les lectures/écritures non-bloquantes. C'est très utile dans les systèmes multiprocesseurs ou multicœurs. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ahq0kjorxeucmcj0zzlhqveforbda84 764139 764138 2026-04-20T20:29:17Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764139 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 5istplgqvqluj7kkiddbtmivg4if2cp 764140 764139 2026-04-20T20:33:50Z Mewtow 31375 /* Exemple : l'Intel 8202-8203 */ 764140 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===Exemple : l'Intel 8207=== L'intel 8207 était un controleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203 : ses adresses étaient mémorisées dans des registres, il pouvait gérer jusqu'à 256 kibioctets de DRAM, il gérait l'ECC nativement, et il avait deux ports séparés. Voyons ces quatres fonctionnalités en détail. Le fait de mémoriser les adresses dans des registres permettait de meilleures performances. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le controleur mémoire pour cela. L'usage de deux ports séparés est nettement plus intéressant. Il permettait de partager le contrôleur mémoire entre deux processeurs, chacun étant connecté à un port. Il se trouve que de tels systèmes utilisent une mémoire partagée entre les processeurs/cœurs, ce qui fait qu'ils n'ont qu'un seul contrôleur mémoire. Le contrôleur mémoire doit alors arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il exécutait un accès mémoire à la fois. Les deux processeurs pouvaient envoyer une requête en même temps, mais celles-ci étaient mémorisées dans des registres et l'une d'entre elle était mise en attente. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 46gvy8733vwpmcpe4gw0xjf26khybt1 764141 764140 2026-04-20T20:40:20Z Mewtow 31375 /* Exemple : l'Intel 8207 */ 764141 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===Exemple : l'Intel 8207=== L'intel 8207 était un controleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203 : ses adresses étaient mémorisées dans des registres, il pouvait gérer jusqu'à 256 kibioctets de DRAM, il gérait l'ECC nativement, et il avait deux ports séparés. Le fait de mémoriser les adresses dans des registres permettait de meilleures performances. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. L'usage de deux ports séparés est nettement plus intéressant. Il permettait de partager une unique mémoire entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire entre deux processeurs, chacun étant connecté à un port. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il exécutait un accès mémoire à la fois. Les deux processeurs pouvaient envoyer une requête en même temps, mais celles-ci étaient mémorisées dans des registres et l'une d'entre elle était mise en attente. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que tous les processeurs/cœurs aient accès à la mémoire à tour de rôle. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne. Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 957s6snqzykfvg325850x1418kkue4z 764142 764141 2026-04-20T20:44:10Z Mewtow 31375 /* Exemple : l'Intel 8207 */ 764142 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===Exemple : l'Intel 8207=== L'intel 8207 était un controleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203 : ses adresses étaient mémorisées dans des registres, il pouvait gérer jusqu'à 256 kibioctets de DRAM, il gérait l'ECC nativement, et il avait deux ports séparés. Le fait de mémoriser les adresses dans des registres permettait de meilleures performances. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage précédent, qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne. Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. Dans de tels systèmes chaque processeur/cœur fait des accès mémoire dans son coin, sans se préoccuper des autres. Il est fréquent que deux processeurs/cœurs fassent des accès mémoire en même temps, ou dans un intervalle de temps très court. Ainsi, pendant un processeur/cœur peut démarrer un accès mémoire, pour qu'un autre processeur/cœur lance un nouvel accès quelques cycles plus tard. Dans ce cas, le contrôleur mémoire peut procéder de deux manières : bloquer le second processeur/cœur, ou accepter la seconde requête et la mettre en attente. Bloquer les processeurs aurait un cout en performance trop important, ce qui fait que la seconde solution est utilisée. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> qcudlvrlkxfmohqll6l0936gi7bezf9 764143 764142 2026-04-20T20:51:52Z Mewtow 31375 /* Exemple : l'Intel 8207 */ 764143 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Un point très important est qu'il avait deux ports séparés. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> a1ywyendp1h78zdpw9d1wt85iiy1kby 764144 764143 2026-04-20T20:53:46Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764144 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Un point très important est qu'il avait deux ports séparés. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ddo8e4hgpitvsijrddih5ditwgz1q09 764145 764144 2026-04-20T21:02:54Z Mewtow 31375 /* L'Intel 8207 : ECC et systèmes bi-processeurs */ 764145 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La gestion de l'ECC était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> mnlnm39fxgwa0fiaye3ug7ybsu24zcz 764146 764145 2026-04-20T21:03:26Z Mewtow 31375 /* L'Intel 8207 : ECC et systèmes bi-processeurs */ 764146 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Une demande de lecture/écriture faite par le processeur se fait en plusieurs étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. Chaque requête du processeur correspond donc à une séquence de commandes envoyées à des timings bien précis. Le contrôleur mémoire s'occupe de faire cette traduction des requêtes en commandes si besoin. Notons que cette traduction demande deux choses : traduire une requête processeur en une série de commandes à faire dans un ordre bien précis, et la gestion des timings. Les deux sont parfois effectués par des circuits séparés, comme nous le verrons plus bas. Le gestionnaire mémoire reçoit une requête processeur et génère en réaction une suite de commandes mémoire. Pour faire cette traduction, il y a plusieurs méthodes. La génération des commandes mémoire est réalisée par un circuit séquentiel, appelé une ''machine à état fini'', aussi appelée ''séquenceur''. Nous l’appellerons le '''séquenceur mémoire''' pour éviter toute confusion. Il s'occupe à la fois de la traduction des requêtes en suite de commande et des timings d'envoi des commandes à la mémoire. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> q1q8628vjvcxhc2a2bwt2ypg1qdf9a1 764147 764146 2026-04-20T21:14:49Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764147 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le '''générateur de ''timings'''''. Le générateur de ''timings'' est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Une demande de lecture/écriture faite par le processeur se fait en plus que deux étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. le générateur de ''timings'' est donc beaucoup plus complexe. Mais sur le principe, il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> cru2s6ry25r23hsmorr9egp8cuj7318 764148 764147 2026-04-20T21:15:35Z Mewtow 31375 /* Le générateur de timings et la traduction d'adresse */ 764148 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le générateur de ''timings'' ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Une demande de lecture/écriture faite par le processeur se fait en plus que deux étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. le générateur de ''timings'' est donc beaucoup plus complexe. Mais sur le principe, il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ifhjxm6jcm8c92hb290hlkgz83smb2u 764149 764148 2026-04-20T21:16:02Z Mewtow 31375 /* Le rafraichissement mémoire */ 764149 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au générateur de ''timings'' à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Une demande de lecture/écriture faite par le processeur se fait en plus que deux étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. le générateur de ''timings'' est donc beaucoup plus complexe. Mais sur le principe, il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> sslln420m0rr97y67y2jmxbnmagk912 764150 764149 2026-04-20T21:16:32Z Mewtow 31375 /* L'Intel 8207 : ECC et systèmes bi-processeurs */ 764150 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Une demande de lecture/écriture faite par le processeur se fait en plus que deux étapes sur une mémoire SDRAM. Il faut d'abord précharger le tampon de ligne avec une commande PRECHARGE, puis envoyer une commande ACT qui fixe l'adresse de ligne, et enfin envoyer une commande READ/WRITE. Et encore, ce cas est simple : il y a des opérations mémoires qui sont beaucoup plus compliquées. Et outre l'ordre d'envoi des commandes pour chaque requête, il faut aussi tenir compte des timings mémoire, à savoir le fait que ces commandes doivent être séparées par des temps d'attentes bien précis. Par exemple, sur certaines mémoires, il faut attendre 2 cycles entre une commande ACT et une commande READ, il faut attendre 6 cycles avant deux commandes WRITE consécutives, etc. le générateur de ''timings'' est donc beaucoup plus complexe. Mais sur le principe, il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Pour les mémoires SDRAM et DDR, le séquenceur mémoire s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. C'est aussi lui qui détecte les accès en rafale et envoie les commandes adaptées. Notons que quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. C'est le séquenceur mémoire qui se charge de cela, et qui détecte les accès en rafale et/ou les accès à des données consécutives. Nous en parlerons plus en détail dans la suite du chapitre, dans la section sur la politique de gestion du tampon de ligne. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 3xzzijhi8q79082h2nj5fmt00wpbgf7 764151 764150 2026-04-20T21:24:01Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764151 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Il est parfois préférable de séparer la génération des commandes, et la gestion des timings mémoire. Le séquenceur est alors séparé en deux : un circuit de traduction et un circuit d’ordonnancement des commandes. Ce dernier envoie les commandes à la mémoire quand les timings le permettent, quitte à les mettre en attente si besoin. Prenons l'exemple d'une requête de lecture, qui se traduit avec une commande ACT, suivie d'une commande READ deux cycles plus tard. La commande READ doit être mise en attente durant deux cycles, après le lancement de la commande ACT. : Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 6zxle8iqnjoz23kywh8zc9atydnv4kd 764152 764151 2026-04-20T21:26:43Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764152 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Notons que la mise en attente des commandes mémoire n'a rien à voir avec la mise en attente des requêtes processeur. Le générateur de commande ne gère qu'une seule requête à la fois (sauf optimisation qu'on passe sous silence). Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> jvnbmfx5qsu1p2y9d9mz5xinc8y7ko7 764153 764152 2026-04-20T21:26:53Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764153 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. La gestion du rafraichissement est souvent séparée de la gestion des commandes de lecture/écriture, et est effectuée dans un circuit dédié, même si ce n'est pas une obligation. Si les deux sont séparés, le circuit de gestion des commandes et le circuit de rafraichissement sont secondés par un circuit d'arbitrage, qui décide qui a la priorité. Ainsi, cela permet que les commandes de rafraichissement et les commandes mémoires ne se marchent pas sur les pieds. Notamment quand une commande mémoire et une commande de rafraichissement sont envoyées en même temps, la commande de rafraichissement a la priorité. Le circuit d'arbitrage est aussi utilisé quand la mémoire est connectée à plusieurs composants, plusieurs processeurs notamment. Dans ce cas, les commandes des deux processeurs ont tendance à se marcher sur les pieds et le circuit d'arbitrage doit répartir le bus mémoire entre les deux processeurs. Il doit gérer de manière la plus neutre possible les commandes des deux processeurs, de manière à empêcher qu'un processeur monopolise le bus pour lui tout seul. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 4yp6n80rknn8hbykrvkiw3e02f7c9jd 764154 764153 2026-04-20T21:27:56Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764154 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> j6mg6hgvualysa4d9ncet9qlby43kio 764155 764154 2026-04-20T21:31:14Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764155 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''gestionnaire mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ojx9g15wu4igxcp9npfqzkwgv675oee 764156 764155 2026-04-20T21:38:52Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764156 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Il ne suffit pas d'envoyer l'adresse en deux fois et d'attendre que la donnée arrive sur le bus de données. Il faut envoyer une série de commandes mémoires PRECHARGE, ACT, READ, WRITE et autres, à des moments bien précis. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> mh0mbixu7lr9do7hsr208a9b23aes9p 764157 764156 2026-04-20T21:49:19Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764157 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. Elle s'occupe aussi de la correction et de la détection d'erreur si la mémoire gère cette fonctionnalité. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le gestionnaire mémoire gère tout le reste. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 79kqkpzc7qwki8efuza0rlr8yg6hbm0 764158 764157 2026-04-20T21:50:44Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764158 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. Il est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> sfgpldg0sd2va4tk18dl7swml8t9sj4 764159 764158 2026-04-20T21:52:21Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764159 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings'', ou encore le '''séquenceur mémoire'''. Le séquenceur mémoire est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. Il est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 0mm03l5yfxqxacnlxdfbajtlghfyi8a 764160 764159 2026-04-20T21:57:04Z Mewtow 31375 /* Le générateur de timings et la traduction d'adresse */ 764160 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. Il est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 9mw3tlgohrtxmlv58rncemcvufjoh98 764161 764160 2026-04-20T22:03:56Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764161 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. Il est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> gtoafoym6ifbpdcziamjovag2jjwa9t 764162 764161 2026-04-20T22:04:26Z Mewtow 31375 /* Le rafraichissement mémoire */ 764162 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Les mémoires SDRAM ont un contrôleur mémoire plus complexe que pour les mémoires DRAM simples. il faut dire que le protocole de communication avec une mémoire synchrone est plus complexe. Dans les grandes lignes, un contrôleur de SDRAM est découpé en deux grands ensembles : un '''séquenceur mémoire''' et une '''interface physique'''. L'interface physique s'occupe, comme dit haut, de la conversion des tensions entre processeur et mémoire. En clair, elle gère tout ce qui a trait à la transmission des bits, au niveau électronique voire électrique. Le séquenceur mémoire gère tout le reste. Il est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> lm6qshe83nyquldj8xo5dxnuh6mqku5 764163 764162 2026-04-20T22:05:48Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764163 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ah6s0i89guvvtgqxo7dxzuikqssampv 764164 764163 2026-04-20T22:06:51Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764164 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===Le séquencement des commandes mémoires=== Le générateur de ''timings'' existe toujours pour les mémoires SDRAM, mais il est beaucoup plus complexe. Il reste un '''séquenceur mémoire''' classique, à savoir un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> lwxon5v6vkap9udfmjjuc7ysr85w4wt 764165 764164 2026-04-20T22:07:27Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764165 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> n1mtnjg7njrp71hd1t9f5osmbfkuclu 764166 764165 2026-04-20T22:07:39Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764166 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===L'architecture complète du contrôleur mémoire externe=== Pour résumer, le contrôleur mémoire contient un générateur de commandes mémoire, suivi par une FIFO pour mettre en attente les commandes mémoires, un module de rafraichissement, ainsi qu'un circuit d'arbitrage (qui décide quelle requête envoyer à la mémoire). Ajoutons à cela des FIFO pour mettre en attente les requêtes processeur, ainsi que les données lues ou à écrire, afin qu'elles soient synchronisées par les commandes mémoires correspondantes. Si une commande mémoire est mise en attente, alors les données qui vont avec le sont aussi. Ces FIFOS sont couplées à quelques circuits annexes, le tout formant le circuit d'échange de données avec le processeur, dans le gestionnaire mémoire, vu dans les schémas plus haut. Le contrôleur mémoire gère aussi l'entrelacement. Pour cela, il intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Module d'interface avec la mémoire.png|centre|vignette|upright=3|Module d'interface avec la mémoire.]] Le contrôleur mémoire externe est schématiquement composé de quatre modules séparés. * Le '''module d'interface avec le processeur''' gère la traduction d’adresse ; * Le '''module de génération des commandes''' traduit les accès mémoires en une suite de commandes ACT, READ, PRECHARGE, etc. * Le '''module d’ordonnancement des commandes''' contrôle le rafraîchissement, l'arbitrage entre commandes/rafraichissement et les timings des commandes mémoires. * Le '''module d'interface physique''' se charge de la conversion de tension, de la génération d’horloge et de la détection et la correction des erreurs. Si la mémoire (et donc le contrôleur) est partagée entre plusieurs processeurs, certains circuits sont dupliqués. Dans le pire des cas, tout ce qui précède le circuit d'arbitrage, circuit de rafraichissement mis à part, est dupliqué en autant d’exemplaires qu'il y a de processeurs. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> fz9uqr0jss22kcmwl6yln0spd0s2x4t 764167 764166 2026-04-20T22:08:35Z Mewtow 31375 /* L'architecture complète du contrôleur mémoire externe */ 764167 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit qui modifie les adresses mémoire pour gérer l'entrelacement, non mentionné dans le schéma du dessus. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> gqy4qmrjsdcinrlssuxaelybwe8mqaq 764168 764167 2026-04-20T22:09:11Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764168 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> j4u84zgqz69xuj3o008iwu07qrlnm3z 764169 764168 2026-04-20T22:09:25Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764169 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La gestion de la fréquence de la mémoire=== Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge, il faut qu'il vienne de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 1jeigf9n84klrg7u52oghkz98y19wei 764170 764169 2026-04-20T22:15:35Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764170 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ==La politique de gestion du tampon de ligne== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. ===Les politiques statiques=== Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. ===Les politiques dynamiques=== Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. La plus simple décide s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente dans le contrôleur. La politique de ce type la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Dans le cas où aucun accès mémoire ne lit une ligne ouverte, le contrôleur prend l'accès le plus ancien, celui qui attend depuis le plus longtemps comparé aux autres. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] ===Les politiques prédictives=== Les techniques prédictives prédisent s'il faut fermer ou laisser ouvertes les pages ouvertes. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une autre solution consiste à mémoriser les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 712rfbfiuh029asvr4yx9t0j0tk2p22 764171 764170 2026-04-20T22:19:14Z Mewtow 31375 /* La politique de gestion du tampon de ligne */ 764171 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ==Le ré-ordonnancement des commandes mémoires== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> ip1y7mjlq1f1lil1fm8g42h7xebwnef 764172 764171 2026-04-20T22:19:20Z Mewtow 31375 /* Le ré-ordonnancement des commandes mémoires */ 764172 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui o* deux accès consécutifs atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> fw4kxbrmd9opur2ym7zuzuk90mp9rq4 764173 764172 2026-04-20T22:21:36Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764173 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> iljlisbsl1nk0veubsb2k0c9z83x45d 764174 764173 2026-04-20T22:23:38Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764174 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 6jht8ba52p4ryhruzuoiwo7wep18ps5 764175 764174 2026-04-20T22:24:57Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764175 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 7cj6lvoj3qxsvcn1w4cgdra60sq5a7k 764176 764175 2026-04-20T22:25:49Z Mewtow 31375 /* Le contrôleur mémoire pour une SDRAM */ 764176 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter plusieurs accès mémoire provenant de plusieurs processeurs, même s'ils arrivent en même temps. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. En clair : il accepte plusieurs accès mémoire simultannés, mais en met certains en attente. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Du moins, ce serait le cas s'il n'intégrait pas d'optimisations particulières, qu'on décrira dans les chapitres adéquats. Mais les anciens processeurs n'avaient pas de telles optimisations, et ils attendaient vraiment. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, les contrôleurs mémoires et les processeurs sont plus malins que ça. Le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur peut très bien les exécuter en avance. Il poursuit l'exécution du programme, prend de l'avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Les instructions qui suivent l'écriture sont alors exécutées, le processeur prend de l'avance. On dit que le processeur gère des '''écritures non-bloquantes'''. Il en est de même pour les lectures : les processeurs modernes supportent des '''lectures non-bloquantes''', à savoir qu'il exécute les instructions suivant la lecture en attendant que celle-ci fournissent son résultat. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2.5|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2.5|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2.5|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> hssyaq8n5qa29at3l6ovfmhbx1uwoxy 764177 764176 2026-04-20T22:28:56Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764177 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter deux accès mémoire simultanés, provenant de deux processeurs. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, ces ''wait state'' ont cependant disparu, grâce à de nombreuses optimisations. De nos jours, le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur les exécute en avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Il en est de même pour les lectures : les processeurs modernes exécutent les instructions suivant la lecture en attendant que celle-ci fournisse son résultat. On dit que le processeur gère des '''lectures/écritures non-bloquantes''' La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2.5|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2.5|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2.5|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 42a4y03l3rncr3ubzcuzusjd238cxgy 764178 764177 2026-04-20T22:29:47Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764178 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter deux accès mémoire simultanés, provenant de deux processeurs. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, ces ''wait state'' ont cependant disparu, grâce à de nombreuses optimisations. La présence d'un contrôleur mémoire facilite l'implémentation des lectures/écritures non-bloquantes. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, il envoie l'adresse et la donnée, et c'est le contrôleur mémoire qui s'en charge. Le processeur peut se déconnecter du bus mémoire et faire son travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Une autre optimisation est celle des '''lectures/écritures non-bloquantes'''. Avec elles, le processeur ne se bloque pas lors d'un accès mémoire. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur les exécute en avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Il en est de même pour les lectures : les processeurs modernes exécutent les instructions suivant la lecture en attendant que celle-ci fournisse son résultat. Le problème est que parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. On parle alors de '''''pipelining'' mémoire'''. Les accès mémoire sont mémorisés dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2.5|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2.5|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2.5|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 18xm7lrblm2h3zvler2315d31r3k86q 764179 764178 2026-04-20T22:34:13Z Mewtow 31375 /* La mise en attente des accès mémoire */ 764179 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquencement des commandes mémoires=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter deux accès mémoire simultanés, provenant de deux processeurs. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, ces ''wait state'' ont cependant disparu, grâce à de nombreuses optimisations. La présence d'un contrôleur mémoire a permet d'éliminer les ''wait state'', dans une certaine mesure. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, le processeur envoie l'adresse, et c'est le contrôleur mémoire qui la maintient sur le bus d'adresse. Le processeur peut se déconnecter du bus mémoire et faire du travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le fait de laisser le processeur faire du travail dans son coin est lié à une optimisation : les '''lectures/écritures non-bloquantes'''. Avec elles, le processeur ne se bloque pas lors d'un accès mémoire, sous certaines conditions. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur les exécute en avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Il en est de même pour les lectures : les processeurs modernes exécutent les instructions suivant la lecture en attendant que celle-ci fournisse son résultat. Et parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés. Et là, il y a deux mécanismes pour gérer ces accès simultanés. Il peut accepter ces accès simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Une autre solution exécute plusieurs acc_s mémoire en même temps, à condition qu'ils se fassent soit dans des banques différentes, soit dans la même banque mais à des étapes différentes. Dans les deux cas, on parle de '''''pipelining'' mémoire'''. Dans les deux cas, les accès mémoire sont mis en attente dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2.5|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2.5|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2.5|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> 7c1wh4jmn8llwdlwk3fa0cv8uoifkgw 764180 764179 2026-04-20T22:53:10Z Mewtow 31375 /* Le séquencement des commandes mémoires */ 764180 wikitext text/x-wiki Les mémoires ROM ou SRAM ont généralement une interface simple, à laquelle le processeur peut s'interfacer directement. Mais pour les DRAM, ce n'est pas le cas. Les DRAM utilisent un bus d'adresse multiplexé, où l'adresse est envoyée en deux fois. Connecter le processeur directement sur une DRAM n'est pas pratique : le bus d'adresse du processeur et celui de la mémoire ne collent pas. Les DRAM doivent aussi être rafraichies régulièrement. Le rafraichissement mémoire peut être délégué au processeur, mais c'est loin d'être idéal. Et il y a bien d'autres raisons qui font que le processeur ne peut pas s'interfacer facilement avec les mémoires DRAM. Pour gérer ces problèmes, les mémoires DRAM ne sont pas connectées directement au processeur. À la place, on ajoute un intermédiaire entre le processeur et la mémoire : le '''contrôleur mémoire externe'''. Il est placé sur la carte mère ou dans le processeur, et ne doit pas être confondu avec le contrôleur mémoire intégré dans la mémoire. Ce chapitre va voir quels sont les rôles du contrôleur mémoire, son interface et ce qu'il y a à l'intérieur. : Dans ce chapitre, quand nous parlerons de ''contrôleur mémoire'', cela fera systématiquement référence au contrôleur mémoire externe. Il est difficile de faire des généralités sur les contrôleurs mémoire. La raison est que les mémoires DRAM elle-mêmes sont assez différentes les unes des autres. Entre une mémoire EDO, une mémoire SDR, une mémoire DDR et une DRAM asynchrone, les controleurs mémoires seront fortement différents. ==Le contrôleur d'une DRAM simple, asynchrone== Les anciens contrôleurs mémoires étaient des composants séparés du processeur et du ''chipset'' de la carte mère. Par exemple, les composants Intel 8202, Intel 8203 et Intel 8207 étaient des contrôleurs mémoire pour DRAM qui étaient vendus dans des boitiers DIP et étaient soudés sur la carte mère. Par la suite, ils ont été intégrés au ''chipset'' de la carte mère pendant les décennies 90-2000. Après les années 2000, ils ont été intégrés dans les processeurs. ===L'interface d'un contrôleur de DRAM asynchrone=== L'interface du contrôleur mémoire décrit ses broches d'entrées/sorties et leur signification. Elle est généralement très simple et contient deux ports : un connecté au processeur, un autre connecté à la DRAM. Cela trahit d'ailleurs son rôle principal, qui est de transformer les requêtes de lecture/écriture provenant du processeur en une suite de commandes acceptée par la mémoire. Le port connecté à la DRAM est connecté ua bus d'adresse et au bus de commande, le bus de données est lui relié au processeur et/ou au bus système. Un accès mémoire provenant du processeur contient une adresse à lire/écrire, le bit R/W qui indique s'il faut faire une lecture ou une écriture, et éventuellement une donnée à écrire. Mais, nous avons vu que les accès mémoires sur une DRAM sont multiplexés : on envoie l'adresse en deux fois : la ligne d'abord, puis la colonne. De plus, il faut générer les signaux RAS, CAS et bien d'autres. Le tout est illustré ci-dessous. [[File:Contrôleur mémoire.png|centre|vignette|upright=2|Contrôleur mémoire externe.]] Pour certains contrôleurs de DRAM, il faut ajouter l''''interface électrique''', qui traduit les signaux du processeur en signaux compatibles avec la mémoire. Il est en effet très fréquent que la mémoire et le processeur n'utilisent pas les mêmes tensions pour coder un bit, ce qui fait qu'elles ne sont pas compatibles. Dans ce cas, le contrôleur mémoire fait la conversion. ===Le générateur de ''timings'' et la traduction d'adresse=== Le contrôleur mémoire doit traduire les adresses du processeur en adresses compatibles avec la mémoire. Et la traduction est assez variable, suivant que le bus mémoire est un bus normal, un bus multiplexé, ou partiellement multiplexé. Nous avons vu ces trois types de bus mémoire dans le chapitre sur l'interface des mémoires, mais nous ferons quelques rappels rapides. Avec un ''bus totalement multiplexé'', le bus d'adresse et le bus de données sont fusionnés. Dans ce cas, on peut envoyer soit une adresse, soit lire/écrire une donnée sur le bus, mais on ne peut pas faire les deux en même temps. Un bit ALE indique si le bus est utilisé en tant que bus d'adresse ou bus de données. Le contrôleur mémoire gère cette situation, en fixant le bit ALE et en envoyant séparément adresse et donnée pour les écritures. [[File:Bus multiplexé avec bit ALE.png|centre|vignette|upright=2|Bus multiplexé avec bit ALE.]] Avec un ''bus d'adresse multiplexé'', l'adresse est découpée en une adresse de ligne et une adresse de colonne, envoyées l'une après l'autre. Le contrôleur mémoire prend en entrée une adresse mémoire complète, la découpe en deux, et envoie chaque morceau au bon moment. Pour cela, il suffit d'un registre pour mémoriser l'adresse et d'un multiplexeur. Le multiplexeur choisit soit les bits de poids fort de l'adresse, soit ceux de poids faible. Les premiers correspondent à l'adresse de ligne, les autres à l'adresse de colonne. La commande du multiplexeur est le fait d'un petit circuit séquentiel, qui génère aussi les signaux CAS et RAS. Au premier cycle, il met le signal RAS à 1, met le CAS à 0, et configure le MUX pour sélectionner les bits de poids fort. Au second cycle, il génère un signal CAS à 1, met le RAS à 0 et configure le MUX pour sélectionner les bits de poids faible. Le circuit en question est appelé le générateur de ''timings''. [[File:Controleur de DRAM simple, sans rafraichissement mémoire.png|centre|vignette|upright=2|Contrôleur de DRAM simple, sans rafraichissement mémoire.]] Le générateur de ''timings''est un circuit séquentiel qui implémente une petite machine à état. Il est très simple sur une mémoire DRAM asynchrone basique, mais il est plus complexe sur les mémoires FPM, EDO, quartet, et autres. Le regroupement des multiplexeurs d'adresse et du générateur de ''timings'' est appelé le '''séquenceur mémoire''' ===Le rafraichissement mémoire=== Pour rappel, la gestion du rafraichissement mémoire est dévolue soit au processeur, soit à la DRAM elle-même, soit au contrôleur mémoire. Quand elle est le fait du processeur, celui-ci incorpore un compteur dédié pour le rafraichissement des lignes, et qu'il active la circuiterie pour envoyer un signal de rafraichissement à intervalles réguliers. Il peut aussi y avoir un système à base d'interruptions pour rafraichir la mémoire régulièrement, ou un système de rafraichissement logiciel. Pour éviter cela, on préfère déléguer le rafraichissement au contrôleur mémoire externe. S'il gère le rafraichissement mémoire, le contrôleur mémoire intègre deux compteurs, un pour gérer l'adresse à rafraichir, l'autre pour gérer l'intervalle de temps entre deux rafraichissements. Le rafraichissement se fait à intervalle régulier, toutes les x microsecondes. Pour déclencher le rafraichissement au bon moment, le contrôleur mémoire contient un ''Refresh Timer'', aussi appelé le '''compteur de rafraichissement'''. Il est initialisé avec le temps entre deux rafraichissements, une adresse est rafraichie quand ce compteur atteint 0. Le rafraichissement mémoire balaye la mémoire adresse par adresse. Pour savoir à quelle adresse il en est rendu, le contrôleur mémoire utilise un '''compteur d'adresse'''. Il contient la prochaine adresse à rafraichir, aussi appelée l'adresse de rafraichissement. Régulièrement, l'adresse dans ce compteur est envoyée à la RAM, pour une lecture. Mais la donnée lue n'est pas envoyée sur le bus de donnée, soit parce que la RAM est prévue pour, soit parce que le contrôleur désactive son bit ''output enable''. Dans le second cas, la RAM fait la lecture en interne, mais se déconnecte du bus de donnée, perdant la donnée lue dans le néant. Pour envoyer l'adresse de rafraichissement sur le bus d'adresse, il faut rajouter un multiplexeur, qui choisit entre l'adresse normale et l'adresse de rafraichissement. [[File:Controleur de DRAM avec rafraichissement mémoire.png|centre|vignette|upright=2|Controleur de DRAM avec rafraichissement mémoire.]] Le multiplexeur ne doit cependant pas être configuré si une adresse est déjà en cours de transfert. Pour cela, un circuit d'arbitrage se débrouille pour éviter qu'un accès mémoire soit interrompu par une demande de rafraichissement et inversement. Il peut être inclus dans le séquenceur mémoire ou séparé de celui-ci. [[File:Controleur mémoire, intérieur simplifié.png|centre|vignette|upright=2.5|Contrôleur mémoire, intérieur simplifié.]] ===Exemple : l'Intel 8202-8203=== L'Intel 8202 et le 8203 étaient des contrôleurs de mémoire DRAM, parmi les plus simples qui soient. Ils avaient une entrée d'adresse de 12 bits, ce qui permettait d'adresser 4 kibioctets de RAM. Ils fournissaient en sortie une adresse multiplexée sur 6 bits, envoyée en deux fois. Ils avaient donc 12 entrées d'adresse, 6 sorties d'adresse, un signal RAS, un signal CAS. Les adresses présentées en entrées n'étaient pas mémorisées dans des registres, ce qui fait qu'elles devaient être maintenues durant toute la durée de l'accès mémoire. Le processeur ne pouvait donc pas se déconnecter du bus d'adresse pendant l'accès mémoire, peu importe sa durée. Le 8202 pouvait être connecté sur 1 à 4 chips mémoire, chacun étant appelé une '''banque'''. Cela permettait de faire passer de 4 kibioctets à 16 kibioctets de RAM maximum. Les 4 chips ne sont pas accédés en parallèle, un seul l'est à chaque fois. Pour cela, le 8202 dispose de deux bits d'entrée BO et B1 pour sélectionner la banque adéquate, ainsi que 4 sorties RAS pour activer la banque adéquate. Lors du transfert d'une adresse haute, seul le signal RAS de la banque sélectionnée est activé, les autres restent à 0. Les deux bits de banque peuvent être vus comme deux bits de poids fort de l'adresse complète, sélection de la banque incluse. Pour commander les lectures et écriture, il recevait en entrée un bit ''Write Request'' et un bit ''Read Request'', qui demandent respectivement une écriture et une lecture. En sortie, on trouvait un unique bit R/W qui valait 0 pour une lecture et 1 pour une écriture. Il avait aussi un bit d'entrée pour forcer le rafraichissement mémoire. S'il est à 1, la mémoire rafraichie l'adresse envoyée par le processeur. Pour communiquer avec le processeur, il disposait de deux bits XACK et SACK. SACK indiquait au processeur que le 8202/8203 est en train de faire un accès mémoire et qu'il est indisponible pour un second accès mémoire. Cela permet de bloquer le processeur tant que le 8202 est indisponible. Il est très utile pour gérer des configurations multiprocesseurs, aussi. Un processeur peut aussi démarrer un accès mémoire, le second processeur saura qu'il doit attendre que l'accès soit terminé pour que ce soit son tour. Le signal XACK indique que l'accès mémoire précédent est terminé et que : soit la donnée lue est présente sur le bus de données, soit que l'écriture s'est terminée. Le 8202 avait une entrée pour un signal d'horloge, ainsi qu'un ''Chip Select'' un peu particulier. Si le signal CS passait à 0 lors d'un accès mémoire, le 8202/8203 ne se désactivait qu'une fois l'accès mémoire terminé. On ne pouvait pas l'interrompre pendant un accès mémoire, même en changeant le bit CS. Le signal d'horloge était utilisé pour commander le ''refresh timer''. ===L'Intel 8207 : ECC et systèmes bi-processeurs=== L'Intel 8207 était un contrôleur mémoire bien plus avancé que les deux précédents. Il avait plusieurs fonctionnalités en plus du 8202/8203. Les adresses d'entrée étaient mémorisées dans des registres pour de meilleures performances. Il pouvait gérer jusqu'à 256 kibioctets de DRAM. La '''gestion de l'ECC''' était partiellement prise en compte dans le contrôleur mémoire. Il avait besoin d'être couplé avec un Intel 8206 pour faire les calculs d'ECC. C'est le 8206 qui détectait/corrigeait les erreurs et générait les bits d'ECC, mais il communiquait avec le contrôleur mémoire pour cela. Précisémment, le 8206 était placé sur le bus de données. Il prenait en entrée : 16 bits de données entrée et 8 bits d'ECC. Ils fournissait en sortie 16 bits de données après correction d'erreur, les 8 bits d'ECC pour indiquer qu'une erreur a été détectée mais pas corrigée, ainsi que des bits de parité. Sur les contrôleurs mémoire modernes, les deux circuits seraient fusionnés, l'ECC serait géré par le contrôleur mémoire lui-même. Un point très important est qu'il avait deux ports séparés, pour fonctionner dans un '''système à deux processeurs'''. L'usage de deux ports séparés permettait de partager une unique mémoire DRAM entre deux processeurs. Le partage se faisait en interfaçant deux processeurs sur le contrôleur mémoire, chacun étant connecté à un port. Lors d'une lecture, il redirigeait la donnée lue vers le bon processeur, en configurant le bus de données correctement. Le contrôleur mémoire recevait des requêtes mémoire de deux processeurs, mais il les exécutait une à la fois. S'il recevait deux requêtes en même temps, l'une d'entre elle était mise en attente. Le contrôleur mémoire doit arbitrer les accès à la mémoire, et faire en sorte que les deux processeurs aient accès à la mémoire à tour de rôle. Et non seulement il doit arbitrer les deux ports, mais il y a aussi un troisième port interne au contrôleur mémoire : le rafraichissement mémoire ! Pour cela, le circuit d'arbitrage qui choisissait entre rafraichissement mémoire et accès mémoire, est amélioré de manière à gérer un second port. Le circuit d'arbitrage donne l'accès au séquenceur mémoire à un port sélectionné. L'arbitrage était configurable, avec deux options : soit le port A est privilégié sur le port B, soit le port le plus récemment accédé a la priorité. Les deux ports pouvaient être configurés pour fonctionner soit de manière asynchrone, soit de manière synchrone. Il était aussi possible de configurer l'ECC, des options liées à la fréquence du processeur et de la RAM, ainsi que de nombreuses options liées au rafraichissement. Pour cela, le 8207 contenait un registre de configuration interne, programmable en fournissant les entrées adéquates.Tout ce qui vient d'être dit se généralise avec plus de deux processeurs. Le 8207 ne permettait pas ça, mais les contrôleurs mémoire des PC modernes en sont capables. Ils peuvent gérer plusieurs dizaines de processeurs facilement. ==Le contrôleur mémoire pour une SDRAM== Comme pour les contrôleurs des DRAM asynchrones, un contrôleur de SDRAM regroupe toujours un '''séquenceur mémoire''' et une '''interface physique'''. Le séquenceur mémoire est souvent combiné avec un circuit pour le rafraichissement mémoire et un circuit d'arbitrage. Parfois, juste avant le séquenceur mémoire, se trouve un circuit pour gérer l'entrelacement. Ce circuit intervertit certains bits de l'adresse lors des accès mémoires. Rappelons qu'avec l'entrelacement, des adresses consécutives sont placées dans des mémoires séparées, ce qui demande de jouer avec les bits d'adresse, chose qui est dévolue à l'étape de traduction d'adresse du contrôleur mémoire. Et on trouve aussi des mémoires FIFOs pour mettre en attente les requêtes mémoire provenant du processeur, dont on expliquera l'utilité plus bas. [[File:Controleur mémoire d'une SDRAM avec entrelacement.png|centre|vignette|upright=2.5|Contrôleur mémoire d'une SDRAM avec entrelacement.]] Contrairement aux mémoires DRAM basiques, les mémoires SDRAM sont cadencées par un signal d'horloge. Et ce signal d'horloge vient bien de quelque part. Pour cela, deux solutions : soit le contrôleur mémoire génère la fréquence qui commande la mémoire, soit il prend en entrée une fréquence de base qu'il multiplie pour obtenir la fréquence désirée. Les deux solutions sont équivalentes, si ce n'est que les circuits impliqués ne sont pas les mêmes. Dans le premier cas, le contrôleur doit embarquer un circuit oscillateur, qui génère la fréquence demandée. Dans l'autre cas, un simple multiplieur/diviseur de fréquence suffit et c'est généralement une PLL qui est utilisée pour cela. : Notez qu'il ne faut pas confondre la fréquence de la SDRAM et celle du contrôleur mémoire. Le contrôleur mémoire fonctionne à une vitesse assez élevée, en interne. Le port relié au processeur fonctionne à haute fréquence, généralement la même que celle du processeur. A vrai dire, de nos jours, il est intégré dans le processeur. ===Le séquenceurs mémoire pour des SDRAM=== Le séquenceur mémoire existe toujours pour les mémoires SDRAM, c'est toujours un circuit séquentiel qui implémente une machine à état. Il traduit une requête du processeur en une séquence de commandes envoyées à des timings bien précis. Simplement, la machine à état est plus complexe. Les commandes mémoires peuvent provenir de l'extérieur, mais aussi d'un circuit de rafraichissement intégré dans le contrôleur mémoire, avec son compteur d'adresse et son ''timer'' de rafraichissement. Pour rappel, une requête de lecture/écriture se fait en trois étapes : une commande PRECHARGE pour précharger le tampon de ligne, une commande ACT qui fixe l'adresse de ligne, et enfin une commande READ/WRITE avec l'adresse de colonne. Et il faut tenir compte des timings mémoire, à savoir le fait que ces commandes sont séparées par des temps d'attentes bien précis. Par exemple, je prends des chiffres arbitraires : il faut attendre 2 cycles entre une commande ACT et une commande READ, 6 cycles avant deux commandes WRITE consécutives, etc. La gestion des ''timings'' rend la conception du séquenceur plus complexe. Le séquenceur mémoire décide s'il faut ajouter ou non des commandes PRECHARGE. Certains accès demandent des commandes PRECHARGE alors que d'autres peuvent s'en passer. Et c'est le séquenceur mémoire qui décide s'il faut ajouter ou non des commandes PRECHARGE. Le cas classiques est celui de deux accès consécutifs, qui atterrissent dans une même ligne : le second accès n'a pas besoin de commande PRECHARGE. D'ailleurs, quand on accède à des données consécutives, on a juste à changer l'adresse de la colonne : pas besoin d'envoyer de commande ACT pour changer de ligne. Mais cela demande que le séquenceur détecte la situation, à savoir que deux accès consécutifs se font dans la même ligne, sans usage du mode rafale. Nous détaillerons cela plus bas, dans une section dédiée. De plus, les SDRAM sont capables d'accepter plusieurs accès mémoire en même temps, à condition qu'elles soient dans des étapes différentes. Par exemple, on peut envoyer une commande ACT pendant que l'accès précédent traite une commande READ. La machine à état est rendue encore plus complexe par cette possibilité, car il faut tenir compte de toutes les possibilités, y compris celles avec deux accès qui se passent en même temps. Mais on peut se poser la question : dans quelles situations on peut se retrouver avec plusieurs accès mémoire simultanés ? ===La mise en attente des accès mémoire=== Avec le 8207, nous avons vu que le contrôleur mémoire pouvait accepter deux accès mémoire simultanés, provenant de deux processeurs. Par contre, il exécute ces accès mémoire un à la fois, sauf si des optimisations comme le ''pipelining'' sont implémentées. Il se trouve que la même chose peut arriver, mais avec un seul processeur. Les processeurs modernes sont beaucoup plus rapides que la mémoire RAM. Et ce n'est pas quelque chose qui est apparu récemment : c'était déjà un problème au temps du 486 et du premier Pentium d'Intel. Quand le processeur envoie une requête de lecture/écriture à la mémoire RAM, celle-ci met plusieurs cycles d'horloge à répondre. Et pendant ce temps, le processeur... attend. Les cycles d'horloge perdus à attendre la mémoire RAM étaient appelés des '''''Wait states'''''. De nos jours, ces ''wait state'' ont cependant disparu, grâce à de nombreuses optimisations. La présence d'un contrôleur mémoire a permet d'éliminer les ''wait state'', dans une certaine mesure. Lors d'un ''wait state'', le processeur doit maintenir l'adresse et la donnée sur le bus mémoire pendant tout l'accès mémoire. Avec un contrôleur mémoire, le processeur envoie l'adresse, et c'est le contrôleur mémoire qui la maintient sur le bus d'adresse. Le processeur peut se déconnecter du bus mémoire et faire du travail dans son coin pendant que le contrôleur mémoire accède à la DRAM. Les ''wait state'' disparaissent alors, du moins du point de vue du processeur. Précisons cependant que si la présence d'un contrôleur mémoire n'est pas nécessaire, le processeur peut faire la même chose sans. Mais ça aide ! Le fait de laisser le processeur faire du travail dans son coin est lié à une optimisation : les '''lectures/écritures non-bloquantes'''. Avec elles, le processeur ne se bloque pas lors d'un accès mémoire, sous certaines conditions. Une instruction de lecture ou d'écriture est toujours suivie par d'autres instructions, généralement des calculs ou des branchements. Et il est fréquent que ces instructions soient indépendantes de la lecture/écriture. Si c'est le cas, le processeur les exécute en avance, pendant que l'accès mémoire est en cours. Pour une écriture, le processeur envoie l'écriture au contrôleur mémoire et continue d'exécuter son programme, sans attendre que l'écriture soit terminée. Il en est de même pour les lectures : les processeurs modernes exécutent les instructions suivant la lecture en attendant que celle-ci fournisse son résultat. Et parmi les instructions suivantes, il peut y avoir d'autres lectures ou écritures. Le résultat est que, pendant un accès mémoire d'une centaine de cycles, le processeur peut envoyer plusieurs lectures/écritures successives au contrôleur mémoire. Le contrôleur mémoire peut alors gérer cela de deux manières : soit il n'exécute qu'un seul accès mémoire à la fois, soit il accepte ces accès mémoire supplémentaires et il les met en attente. Dans le premier cas, le contrôleur mémoire bloque dès qu'on lui demande de faire un second accès mémoire. Le processeur est alors soit bloqué, soit il met en attente cet accès mémoire de lui-même, dans des registres internes. Il doit pour cela incorporer des mécanismes de mise en attente, internes au processeur. Nous décrirons ces mécanismes dans un chapitre dédié, à la fin de ce wikilivre. Dans le second cas, le contrôleur mémoire accepte plusieurs accès mémoire simultanés. Et là, il y a deux mécanismes pour gérer ces accès simultanés. Il peut accepter ces accès simultanés, mais il ne les exécute qu'un seul à la fois. Les autres accès sont mis en attente et seront exécutés dès que l'accès précédent est terminé. Une autre solution exécute plusieurs acc_s mémoire en même temps, à condition qu'ils se fassent soit dans des banques différentes, soit dans la même banque mais à des étapes différentes. Dans les deux cas, on parle de '''''pipelining'' mémoire'''. Dans les deux cas, les accès mémoire sont mis en attente dans une mémoire FIFO, histoire de les exécuter dans leur ordre d'arrivée. Quelques optimisations permettent cependant de changer l'ordre des accès mémoire, pour gagner en performance, comme on le verra plus bas. Évidemment, cette réorganisation ne se voit pas du côté du processeur, car le contrôleur remet les accès dans l'ordre et envoie les données lues au processeur dans l'ordre des requêtes processeur. Il reçoit les données lues depuis la mémoire et les remet dans l'ordre de lecture demandé par le processeur. Mais nous reparlerons de ces capacités d'ordonnancement plus bas. ===La politique de gestion du tampon de ligne=== Le séquenceur mémoire décide quand envoyer les commandes PRECHARGE, qui pré-chargent les bitlines et vident le tampon de ligne. Il peut gérer cet envoi des commandes PRECHARGE de diverses manières nommées respectivement politique de la page fermée, politique de la page ouverte et politique hybride. Dans le cas le plus simple, le contrôleur ferme systématiquement toute ligne ouverte par un accès mémoire : chaque accès mémoire est suivi d'une commande PRECHARGE. Cette méthode est adaptée à des accès aléatoires, mais est peu performante pour les accès à des adresses consécutives. On appelle cette méthode la close ''page autoprecharge'', ou encore '''politique de la page fermée'''. Avec des accès consécutifs, les données ont de fortes chances d'être placées sur la même ligne. Fermer celle-ci pour la réactiver au cycle suivant est évident contreproductif. Il vaut mieux garder la ligne active et ne la fermer que lors d'un accès à une autre ligne. Cette politique porte le nom d'''open page autoprecharge'', ou encore '''politique de la page ouverte'''. Lors d'un accès, la commande à envoyer peut faire face à deux situations : soit la nouvelle requête accède à la ligne ouverte, soit elle accède à une autre ligne. * Dans le premier cas, on doit juste changer de colonne : c'est un '''succès de tampon de ligne'''. Le temps nécessaire pour accéder à la donnée est donc égal au temps nécessaire pour sélectionner une colonne avec une commande READ, WRITE, WRITA, READA. On observe donc un gain signifiant comparé à la politique de la page fermée dans ce cas précis. * Dans le second cas, c'est un '''défaut de tampon de ligne''' et il faut procéder comme avec la politique de la page fermée, à savoir vider le tampon de ligne avec une commande PRECHARGE, sélectionner la ligne avec une commande ACT, avant de sélectionner la colonne avec une commande READ, WRITE, WRITA, READA. Détecter un succès/défaut de tampon de ligne n'est pas très compliqué. Le séquenceur mémoire a juste à se souvenir des lignes et banques actives avec une petite mémoire : la '''table des banques'''. Pour détecter un succès ou un défaut, le contrôleur doit simplement extraire la ligne de l'adresse à lire ou écrire, et vérifier si celle-ci est ouverte : c'est un succès si c'est le cas, un défaut sinon. Pour gagner en performances et diminuer la consommation énergétique de la mémoire, il existe des techniques hybrides qui alternent entre la politique de la page fermée et la politique de la page ouverte en fonction des besoins. Elles décident s'il faut maintenir ouverte la ligne en regardant les accès mémoire en attente, dans la mémoire FIFO avant le séquenceur mémoire. La politique la plus simple laisse la ligne ouverte si au moins un accès en attente y accède. Une autre politique laisse la ligne ouverte, sauf si un accès en attente accède à une ligne différente de la même banque. Avec l'algorithme FR-FCFS (First Ready, First-Come First-Service), les accès mémoires qui accèdent à une ligne ouverte sont exécutés en priorité, et les autres sont mis en attente. Pour implémenter ces techniques, le contrôleur compare la ligne ouverte dans le tampon de ligne et les lignes des accès en attente. Ces techniques demandent de mémoriser la ligne ouverte, pour chaque banque, dans une mémoire RAM : la '''table des banques''', aussi appelée ''bank status memory''. Le contrôleur extrait les numéros de banque et de ligne des accès en attente pour adresser la table des banques, le résultat étant comparé avec le numéro de ligne de l'accès. [[File:Architecture d'un module de gestion des commandes à politique dynamique.jpg|centre|vignette|upright=2.5|Architecture d'un module de gestion des commandes à politique dynamique.]] Pour aller plus loin, les techniques prédictives tentent de prédire s'il faut fermer ou laisser ouvertes les pages ouvertes. Elles peuvent se tromper, mais une erreur de prédiction est corrigée en envoyant des commandes PRECHARGE au bon moment. La méthode la plus simple consiste à laisser ouverte chaque ligne durant un temps prédéterminé avant de la fermer. Une autre solution consiste à effectuer ou non la pré-charge en fonction du type d'accès mémoire effectué par le dernier accès. On peut très bien décider de laisser la ligne ouverte si l'accès mémoire précédent était une rafale, et fermer sinon. Une solution plus complexe mémorise les N derniers accès et en déduire s'il faut fermer ou non la prochaine ligne. On peut mémoriser si l'accès en question a causé la fermeture d'une ligne avec un bit. Mémoriser les N derniers accès demande d'utiliser un simple registre à décalage, un registre couplé à un décaleur par 1. Pour chaque valeur de ce registre, il faut prédire si le prochain accès demandera une ouverture ou une fermeture. * Une première solution consiste à faire la moyenne des bits à 1 dans ce registre : si plus de la moitié des bits est à 1, on laisse la ligne ouverte et on ferme sinon. * Pour améliorer l'algorithme, on peut faire en sorte que les bits des accès mémoires les plus récents aient plus de poids dans le calcul de la moyenne. Mais rien de transcendant. * Une autre technique consiste à détecter les cycles d'ouverture et de fermeture de page potentiels. Pour cela, le contrôleur mémoire associe un compteur pour chaque valeur du registre. En cas de fermeture du tampon de ligne, ce compteur est décrémenté, alors qu'une non-fermeture va l'incrémenter : suivant la valeur de ce compteur, on sait si l'accès a plus de chance de fermer une page ou non. ===Le ré-ordonnancement des commandes mémoires=== Le contrôleur mémoire peut optimiser l'utilisation de la mémoire en changeant l'ordre des requêtes mémoires pour regrouper les accès à la même ligne/banque. Ce ré-ordonnancement marche très bien avec la politique à page ouverte ou les techniques assimilées. Elles ne servent à rien si le séquenceur utilise une politique de la page fermée. L'idée est de profiter du fait qu'une page est restée ouverte pour effectuer un maximum d'accès dans cette ligne avant de la fermer. Les commandes sont réorganisés de manière à regrouper les accès dans la même ligne, afin qu'ils soient consécutifs s'ils ne l'étaient pas avant ré-ordonnancement. Pour réordonnancer les accès mémoire, le séquenceur vérifie si il y a des dépendances entre les accès mémoire. Les dépendances en question n'apparaissent que si les accès se font à une même adresse. Si tous les accès mémoire se font à des adresses différentes, il n'y a pas de dépendances et ont peut, en théorie, faire les accès dans n'importe quel ordre. Le tout est juste que le séquenceur remette les données lues dans l'ordre demandé par le processeur et communique ces données lues dans cet ordre au processeur. Les dépendances apparaissent quand des accès mémoire se font à une même adresse. le cas réellement bloquant, qui empêche toute ré-ordonnancement, est le cas où une lecture lit une donnée écrite par une écriture précédente. Dans ce cas, la lecture doit avoir lieu après l'écriture. Une première solution consiste à regrouper plusieurs accès à des données successives en un seul accès en rafale. Le séquenceur analyse les commandes mises en attente et détecte si plusieurs commandes consécutives se font à des adresses consécutives. Si c'est le cas, il fusionne ces commandes en une lecture/écriture en rafale. Une telle optimisation est appelée la '''combinaison de lecture''' pour les lectures, et la '''combinaison d'écriture''' pour les écritures. Cette méthode d'optimisation ne fait que fusionner des lectures consécutives ou des écritures consécutives, mais ne fait pas de ré-ordonnancement proprement dit. Une variante améliorée combine cette fusion avec du ré-ordonnancement. Une seconde solution consiste à effectuer les lectures en priorité, quitte à mettre en attente les écritures. Il suffit d'utiliser des files d'attente séparées pour les lectures et écritures. Si une lecture accède à une donnée pas encore écrite dans la mémoire (car mise en attente), la donnée est lue directement dans la file d'attente des écritures. Cela demande de comparer toute adresse à lire avec celles des écritures en attente : la file d'attente est donc une mémoire associative. Cette solution a pour avantage de faciliter l'implémentation de la technique précédente. Séparer les lectures et écritures facilite la fusion des lectures en mode rafale, idem pour les écritures. [[File:Double file d'attente pour les lectures et écritures.png|centre|vignette|upright=2.5|Double file d'attente pour les lectures et écritures.]] Une autre solution répartit les accès mémoire sur plusieurs banques en parallèle. Ainsi, on commence par servir la première requête de la banque 0, puis la première requête de la banque 1, et ainsi de suite. Cela demande de trier les requêtes de lecture ou d'écriture suivant la banque de destination, ce qui demande une file d'attente pour chaque banque. [[File:Gestion parallèle des banques.png|centre|vignette|upright=2.5|Gestion parallèle des banques.]] <noinclude> {{NavChapitre | book=Fonctionnement d'un ordinateur | prev=Les mémoires RAM dynamiques (DRAM) | prevText=Les mémoires RAM dynamiques (DRAM) | next=Les mémoires associatives | nextText=Les mémoires associatives }} </noinclude> g2o9pul5kvb1l6u54ymssbfr93tc6ga Affaire Priore/Le P.I.O.M. 0 73588 764214 672504 2026-04-21T10:42:17Z ~2026-24369-39 123573 /* Historique */ 764214 wikitext text/x-wiki {{Affaire Priore - Chapitre|Le P.I.O.M. et l'Affaire Priore}} ==Introduction== Après de décès d'Antoine Priore, le 9 mai 1983, le Pr. Pautrizel a essayé, avec l’aide du Pr [[w:fr:Adolphe Pacault|Adolphe Pacault]] (Faculté des sciences de Bordeaux), de constituer une équipe, mais le Pr. Pacault renonça rapidement. Finalement, sous l’impulsion du Conseil régional d’Aquitaine ([[w:fr:Philippe Madrelle|Philippe Madrelle]], [[w:fr:Alain Rousset|Alain Rousset]], [[w:fr:Gilles Savary|Gilles Savary]]) <ref>{{Archives Priore|id=1lNIJcMLV4NhESNWC3zl0EKXL0MQrvm9R |auteur=A. Rousset|titre=Lettre adressée à P. Chateaureynaud }}<br />{{Archives Priore|id=1050_wwNh5acuRTC_HR0NHj9jmc6KYyv_ |auteur=A. Rousset|titre=Lettre adressée à G. Chavanes }}<br />{{Archives Priore|id=1lHmGn0NPztYQaVV5C2UEsaCl7r2RkzTF |auteur=P. Madrelle|titre=Lettre adressée à J-P. Daulouède }}<br />{{Archives Priore|id=1Tcx7GsS6Fl7Bu-UARd-8nINU2KSrbjpm |auteur=P. Madrelle|titre=Lettre adrssée au Pr. Pautrizel }}</ref> une équipe de la Faculté des sciences de l'université de Bordeaux s’est constituée sous l’égide du Pr. Jacques Joussot-Dubien, à l’époque directeur de l’[[w:fr:École nationale supérieure de chimie, de biologie et de physique|E.N.S.C.B. (École Nationale Supérieure de Chimie de Bordeaux)]]. Cette équipe était formée de : André-Marie Bottreau (physicien), Jacques-Marie Moreau (physicien), Alfred Caristan (chimiste), Bernard Veyret (chimiste), le Raymond Pautrizel (biologiste), Pierrette Chateaureynaud-Duprat (biologiste). Elle s’est donné comme but l’étude « scientifique » de l’appareil Priore. Les biologistes de l'équipe avaient une grande expérience de l'expérimentation animale avec l'appareil de Priore. L'un des deux physiciens, A-M. Bottreau, avait fait des mesures des champs magnétiques et micro-onde du véritable appareil de Priore dans le cadre du contrat avec la D.R.M.E. (voir : [[Affaire Priore/Les appareils d'Antoine Priore|Les appareils d'Antoine Priore]]). Malheureusement, les deux physiciens n'avaient aucune expertise avec les générateurs d'ondes H.H. de puissance utilisés par Antoine Priore. ==Historique== Le laboratoire P.I.O.M. (Physique des Interactions Ondes Matière) fut créé à cette occasion, avec A.-M. Bottreau comme directeur, au sein de l’E.N.S.C.B., qui devint l'E.N.S.C.P.B. (École Nationale Supérieure de Chimie et de Physique de Bordeaux), dont Jacques Joussot-Dubien est Directeur. Le P.I.O.M. était censé avoir deux faces : une face ''officielle'' laissant voir un travail de routine scientifique et une face ''discrète'' consacré à l’étude de l’appareil Priore. La discrétion de ce travail était toute relative : la presse populaire en parla <ref>{{Archives Priore|id=113EYzOdBy_enY2SuPNyDJPM8TNznYWga |auteur=Sud-Ouest |titre=Machine de Priore:une nouvelle étude }}<br />{{Archives Priore|id=1_xI9-NiGOVj2uz97XSuvs5T-HnhqTqiK |auteur=Canard Enchaîné |titre=Priorité à Priore }}</ref>, les membres de l’équipe participèrent à un reportage pour TF1 (qui sera diffusé le 2 août 1986 lors de l’émission ‘Droit de Réponse’ de Michel POLAC.), et le ''Journal Officiel de la République'', en réponse aux questions posées par certains députés en fit mention <ref>{{Archives Priore|id=1sb8d17g8waRAqc0ovZvfiRTzT_UDS9I0|auteur=Journal Officiel|titre=Question 50.516}}<br />{{Archives Priore|id=1HVb9KFEu8tHF2JzQguGrTpDhSrTvVds2 |auteur=Journal Officiel|titre=Question 797 }}<br />{{Archives Priore|id=1W8RkN7UP74rECYlXdcxccUycH9SYd32Y |auteur=Journal Officiel|titre=Question 35.810 }}<br />{{Archives Priore|id=190jVZUKxKt-UbTbXzjIpwSbEQK7-r_bG |auteur=Journal Officiel|titre=Question de P. Favre }}</ref> à plusieurs reprises. Au cours de l’année 1984 le conseil régional d’Aquitaine apporta son soutien à l’équipe universitaire qui déposa un projet <ref>{{Archives Priore|id=1Gx0RwqxAQ1x9MT-gpxT1hveQ4UI-i0wq|auteur=J Joussot-Dubien|titre=Projet de recherche des effets biologiques de champs électromagnétiques}}</ref> de construction d’appareillage, très proche de l’appareil Priore. Ce projet a été élaboré principalement par A.-M. Bottreau. C'est ainsi que l’équipe reçut une subvention d'un million de francs <ref>{{Archives Priore|id=1rtZCF_vOGL-w75P-xzyW-YNLuqHt1TFv |auteur=A. Rousset|titre=Lettre adressée à E. Bidault}}</ref> du Conseil régional, avec en plus quelques dons et fonds privés. Le bon sens et le désir de retrouver l'effet Priore aussi rapidement que possible aurait dû amener l'équipe universitaire et l'équipe de LEROY-SOMER à collaborer étroitement. Hélas, les animosités engendrées au cours des années furent tenaces. Le Conseil régional d’Aquitaine, sous la présidence de Philippe Madrelle, essaya de faire la jonction entre les équipes en proposant un protocole d'accord équitable <ref>{{Archives Priore|id=1Qbcsv2lwIWycfuk6Yl_kTwexXOTU-PeF|auteur=P. Madrelle|titre=Protocole d'accord}}</ref> entre LEROY-SOMER, Mme Priore et l'équipe universitaire. Mais ce fut sans succès, en raison d'une part des exigences financières de [[w:fr:Georges Chavanes|Georges Chavanes]] et d'autre part de l'attitude hargneuse de MM. [[w:fr:Georges Chavanes|Chavanes]] et Ribeau vis-à-vis des universitaires. Selon [[w:fr:Jacques Chaban-Delmas|Jacques Chaban-Delmas]]<ref>{{Archives Priore|id=1UoqJREIGCXoLgb9a_JsIqxPDgYkM6han|auteur=J. Chaban-Delmas|titre=Lettre adressée à P. Chateaureynaud }}</ref>, leur mécontentement était en effet exacerbé par le livre de J-M. Graille qui révélait certains faits historiques peu flatteurs pour eux. Or, Graille avait obtenu, en partie, ces documents par l'intermédiaire du Pr. Pautrizel et de Mme Chateaureynaud, qui étaient membres de l'équipe universitaire... Cette prise de position navrante de MM. Chavanes et Ribeau a aussi été évoquée par Philippe Madrelle<ref>{{Archives Priore|id=1fyQNa5km--YZ6rndPkkHH8SNVLAuZ2qu|auteur=P. Madrelle|titre=Lettre adressée à E. Bidault }}</ref>. Cependant il semble qu’une certaine entente entre l’équipe LEROY-SOMER et l’équipe universitaire fut obtenue par l’intermédiaire de la Mairie de Bordeaux (Gilbert Leroi et [[w:fr:Jacques Valade|Jacques Valade]]) : lors d'un réunion-repas au restaurent ''Le Dubern'' à Bordeaux avec Gilbert Leroi, Jean-Pierre Bader<ref>Auteur du livre : ''Le Cas Priore : Prix Nobel ou imposture ?'', qui semble se ranger avec les industriels et pas avec les chercheurs.</ref>, Georges Chavanes et un certain M. Parienti, le 30 janvier 1985, le Pr Joussot-Dubien accepta de ne pas tenter de construire directement un appareil Priore<ref>{{Archives Priore|id=121Ig1O-YZ3et3X9LNSGJgX_H7E_lBvth |auteur=J. Moreau|titre=Cahier-janvier 1985}}</ref> ! Son équipe se contentera de faire des études plus ''fondamentales''. Elle donnait ainsi une longueur d’avance aux industriels, qui espéraient entre temps avoir une version commerciale d’un « appareil PRIORE ». Le Pr. Joussot-Dubien sembla ne rien obtenir en contrepartie pour s'imposer un frein aux recherches de son équipe. Effectivement, le premier appareil qui fut construit <ref>{{Archives Priore|id=1S3i_bzmviiTKoRmD1n18VipjQBNIWMvg|auteur=J. Joussot-Dubien|titre=Rapport du 21 octobre 1985}}</ref> par l’équipe universitaire n’était pas celui décrit dans la proposition initiale mais une version légèrement modifiée de l’appareil simplifié construit par Berteaud en 1972 et décrit dans son rapport à la D.R.M.E. <ref>{{Archives Priore|id=1OHR2k6FXPUDsvxGaEQH8L_X1Pr5y74Lf |auteur=A-J. Berteaud et A-M. Bottreau|titre=Rapport final : Contrat D.R.M.E}}</ref>. Cet appareil simplifié n’avait donné aucun résultat probant en 1972 et n'en donna pas plus en 1985. Au cours des années, Pautrizel, Bottreau, Mme Chateaureynaud-Duprat et Caristan quittèrent l’équipe du P.I.O.M. pour diverses raisons de désaccord avec la stratégie choisie par MM. Joussot-Bubien et Veyret. L’équipe LEROY-SOMER piétina pendant plusieurs années sans tenter de construire une copie de l’appareil PRIORE ou de faire repartir les appareils existants à Floirac. ==Le groupe de « savoir-faire » == Une ‘fusion’ intervint en mars 1989 entre ceux qui restaient du 'groupe Universitaire' (MM. Joussot-Dubien, Veyret et Moreau) et Paul Ribeau et Hubert Gossot, qui se sont nommés ''groupe de savoir-faire'' <ref>{{Archives Priore|id=1wPQNqer0BTFD5Pv6zAFKLBzq4mcaS8P8|auteur=J. Moreau|titre=Cahier-mars 1989 }}</ref>. Cette fusion ne sembla pas être une mise en commun désintéressée des ressources de chaque groupe avec comme but unique de retrouver "l'effet Priore". Elle avait des aspects mercantiles. Un premier exemple : en septembre 1989 <ref>{{Archives Priore|id=10wGpj2qZpR-qkSg8_FCldNSLD35ycAMN|auteur=J. Moreau|titre=Cahier-septembre 1989 }}</ref>, Ribeau proposa de créer un cabinet d'ingénieurs-conseils et de facturer ses services au groupe universitaire pour un montant d'environ 4 MF. Un deuxième exemple : en décembre 1994, Ribeau proposa aux universitaires un "protocole d'accord" <ref>{{Archives Priore|id=1yeI-e8v8JHYz1AOxDQ15QWmKup-L4KA9 |auteur=P. Ribeau|titre=Protocole d'accords }}</ref> où il était question du partage des bénéfices d'une commercialisation éventuelle de son montage « issu des idées d'Antoine Priore ». Ce texte spécifiait bien que les appareils d'Antoine Priore n'étaient plus couverts par des brevets, mais que leur réalisation et leurs réglages nécessitaient un savoir-faire et que ce savoir-faire était détenu par lui-même et par GOSSOT. Il proposa à nouveau au groupe universitaire un document semblable en 2001 <ref>{{Archives Priore|id=1n-Wo8M_ldT2cG5AGITfKcuXHjexEN-Om |auteur=P. Ribeau|titre=Projet:Accord de collaboration et de développement}}</ref>. Selon ces projets, rédigés par Paul Ribeau, les héritiers d'Antoine Priore ne figuraient pas parmi les éventuels bénéficiaires de la commercialisation d'appareils « issus des idées d'Antoine Priore »... La stratégie adoptée par ce groupe hybride d'universitaires et de ‘privés’ sembla être : * de se contenter de collecter des fonds et d’aménager un local mis à leur disposition sur le domaine universitaire pour abriter un appareil éventuel ; * de ne pas essayer de retracer le cheminement technique et expérimental qui a conduit Antoine Priore, entre 1952 et 1957, vers sa découverte ; * de ne pas produire un relevé détaillé des deux appareils existants à Floirac et de ne pas faire intervenir des spécialistes en H.F., micro-ondes etc. ; * de sous-traiter la construction d’un appareil à Paul Ribeau dès que les sommes allouées au groupe universitaire le permirent : * d'attribuer aux universitaires une seule fonction, celle de vérifier l'efficacité du montage de P. Ribeau en exposant des souris, préalablement infectées avec ''T. equiperdum'', au rayonnement de l'appareil. Une confiance totale fut accordée à Ribeau sur la foi de ses affirmations répétées de « fils spirituel » d'Antoine Priore. En effet, ayant vécu dans l'ombre d'Antoine Priore pendant des années, Ribeau prétendait tout connaître de ses appareils. En utilisant des fonds publics (Conseil régional d’Aquitaine, Ministère de la recherche, C.E.A., etc.) et des fonds privés (Comité de soutien, P. Favre, etc.), pour un montant d’environ 5 MF, un appareil hybride fut finalement construit par Ribeau, avec l'aide de MM. Farago et Genty. Ce montage ressemblait à quelque chose entre le ''P5'', construit avec la subvention de la D.G.R.S.T. et le ''PR1'', construit par la société S.E.R.E.S.O. en 1967. À l’époque, l’appareil ''PR1'' avait été un échec et le ''P5'' une débâcle. Dans un compte rendu daté de novembre 1998 <ref>{{Archives Priore|id=1QSrJQMjLLVCWIvkgQSLtz7G2yUPHYIp9|auteur=B. Veyret|titre=Construction d'un appareillage produisant des champs électromagnétiques pour mener des études biologiques et thérapeutiques }}</ref>, destiné au Ministère de la recherche, pour justifier une partie de la subvention, B. Veyret constata l’absence totale d’effets biologiques du montage de Ribeau. Depuis cette date, malgré certaines modifications du montage, les quelques expérimentations sporadiques faites avec des souris infectées par ''T. equiperdum'', n'ont montré aucun effet biologique probant. ==Conclusion== L’équipe universitaire avait reconstitué une situation analogue à celle qui existait entre Antoine Priore et la société LEROY-SOMER : une seule personne a la main-mise sur la technique du montage et l'accès aux dossier techniques de l'appareil construit par P. Ribeau et la société Leroy-Somer chez Antoine Priore en 1966-1967. (Cet appareil ne fonctionnait pas comme un appareil d'Antoine Priore, mais, sous certains conditions, il y avait de début d'effet noté par le Pr. Rivière. Antoine Priore a signalé<ref>{{Archives Priore|id=1QI65aKmskKDNE_CZfMqwVfDU4klOGKGM |auteur=A. Priore|titre=Lettre adressée au Pr. Maréchal le 2 mars 1967 }}</ref> quelques erreurs de construction et de modifications faites par P. Ribeau). ==Références== {{Colonnes|taille=30| {{Références}} }} [[Catégorie:Affaire Priore (livre)]] i3sr9ywhq0jlrz2v98euxkhuojbxdx9 Le mouvement Wikimédia/Version complète 0 77521 764194 757566 2026-04-21T08:34:40Z Lionel Scheepmans 20012 764194 wikitext text/x-wiki {{DISPLAYTITLE:<span style="color:white;width:0;font-size:0;">{{FULLPAGENAME}}</span>}} __SECTIONNONEDITABLE__ __NOTOC__ {{Centrer|1=<div style="font-size:250%;">'''LE MOUVEMENT WIKIMÉDIA'''</div></br><div style="font-size:250%;">'''Comment rendre la connaissance fiable</br>par le partage, la liberté et l'équité'''</div>}} </br> [[Fichier:Photo de couverture du wikilivre Le mouvement Wikimédia.jpg|centré|sans_cadre|800x800px]] </br> <big><big>{{Centrer|De Lionel Scheepmans<br />Avec l'aide de la communauté Wikimédia}}</big></big> </br> [[Fichier:Wikibooks-logo-fr-noslogan-light.svg|centré|sans_cadre|100x100px]] </br> {{Seulement à l'impression|{{Centrer|Version du {{CURRENTDAY}} {{CURRENTMONTHNAME}} {{CURRENTYEAR}} à {{CURRENTTIME}}}}|div}} {{Nouvelle page imprimée}} == Quatrième de couverture == {{:Le mouvement Wikimédia/Quatrième de couverture}} {{Nouvelle page imprimée}} == Sommaire == {{:Le mouvement Wikimédia/Sommaire1}} {{Nouvelle page imprimée}} == Avant-propos == {{:Le mouvement Wikimédia/Avant-propos}} {{Nouvelle page imprimée}} == Introduction : Wikimédia n’est pas Wikipédia == {{:Le mouvement Wikimédia/Introduction : Wikimédia n'est pas Wikipédia}} {{Nouvelle page imprimée}} == Première partie : La naissance du mouvement Wikimédia == {{:Le mouvement Wikimédia/La naissance du mouvement Wikimédia}} === L'utopie Wikimédia === {{:Le mouvement Wikimédia/L'utopie Wikimédia}} === Le mouvement du logiciel libre === {{:Le mouvement Wikimédia/Le mouvement du logiciel libre}} === Les licences et la culture libres === {{:Le mouvement Wikimédia/Les licences et la culture libres}} === Le réseau Internet === {{:Le mouvement Wikimédia/Le réseau Internet}} == Le World Wide Web === {{:Le mouvement Wikimédia/Le World Wide Web}} === Les platesformes Wiki === {{:Le mouvement Wikimédia/Les platesformes Wiki}} === L’encyclopédie libre et universelle === {{:Le mouvement Wikimédia/L'encyclopédie libre et universelle}} === L'arrivée des projets frères === {{:Le mouvement Wikimédia/L'arrivée des projets frères}} === La conscientisation du mouvement === {{:Le mouvement Wikimédia/La conscientisation du mouvement}} === La création des organismes affiliés === {{:Le mouvement Wikimédia/La création des organismes affiliés}} === L'héritage d'une contre-culture === {{:Le mouvement Wikimédia/L'héritage d'une contre-culture}} {{Nouvelle page imprimée}} == Deuxième partie : Cosmographie du mouvement Wikimédia == {{:Le mouvement Wikimédia/Cosmographie du mouvement Wikimédia}} === La constellation des projets en ligne === {{:Le mouvement Wikimédia/La constellation des projets en ligne}} === Les projets de partage de la connaissance === {{:Le mouvement Wikimédia/Les projets de partage de la connaissance}} === Les projets de gouvernance, de gestion et de sensibilisation === {{:Le mouvement Wikimédia/Les projets de gouvernance, de gestion et de sensibilisation}} === Les projets de gestion technique === {{:Le mouvement Wikimédia/Les projets de gestion technique}} === Les espaces de communication et d’information === {{:Le mouvement Wikimédia/Les espaces de communication et d’information}} {{Nouvelle page imprimée}} === La constellation de la Fondation et de ses affiliés === {{:Le mouvement Wikimédia/La constellation de la Fondation et de ses affiliés}} === La Fondation Wikimédia === {{:Le mouvement Wikimédia/La Fondation Wikimédia}} === Le conseil d’administration de la Fondation === {{:Le mouvement Wikimédia/Le conseil d’administration}} === Les comités, groupes de travail et conseils === {{:Le mouvement Wikimédia/Les comités, groupes de travail et conseils}} === Les associations locales === {{:Le mouvement Wikimédia/Les associations locales}} === Les organisations thématiques, centrales et linguistiques === {{:Le mouvement Wikimédia/Les organisations thématiques, centrales et linguistiques }} === Les groupes d’usagers === {{:Le mouvement Wikimédia/Les groupes d’usagers}} === Les projets d’assistances === {{:Le mouvement Wikimédia/Les projets d’assistances}} === Les cycles de conférences et espaces de rencontres === {{:Le mouvement Wikimédia/Les cycles de conférences et espaces de rencontres}} === Les partenariats avec des entités externes au mouvement === {{:Le mouvement Wikimédia/Les partenariats externes}} {{Nouvelle page imprimée}} == Conclusion : Un mouvement culturel inspirant == {{:Le mouvement Wikimédia/Conclusion : Un mouvement culturel inspirant}} {{Nouvelle page imprimée}} == Remerciements == {{:Le mouvement Wikimédia/Remerciements}} {{Nouvelle page imprimée}} == Notes et références == [[Fichier:Qr code références livre Wikimédia.svg|alt=centrer|droite|sans_cadre|65x65px]] <small>{{Cacher à l'impression|<references />}}</small> == Bibliographie == {{:Le mouvement Wikimédia/Bibliographie}} [[Catégorie:Livres]] [[Catégorie:Livres]] [[Catégorie:Étude du cyber-mouvement du logiciel libre (livre)]] [[Catégorie:Anthropologie]] [[Catégorie:Sciences humaines]] [[Catégorie:Livres terminés]] [[Catégorie:Le mouvement Wikimédia]] [[Catégorie:Le mouvement Wikimédia (livre)]] [[Catégorie:Livres en vitrine]] {{AutoCat}} 7vz3q6ob7w3yfsphjt01fvj2ryx5ya9 764197 764194 2026-04-21T08:36:53Z Lionel Scheepmans 20012 764197 wikitext text/x-wiki {{DISPLAYTITLE:<span style="color:white;width:0;font-size:0;">{{FULLPAGENAME}}</span>}} __SECTIONNONEDITABLE__ __NOTOC__ {{Centrer|1=<div style="font-size:250%;">'''LE MOUVEMENT WIKIMÉDIA'''</div></br><div style="font-size:250%;">'''Comment rendre la connaissance fiable</br>par le partage, la liberté et l'équité ?'''</div>}} </br> [[Fichier:Photo de couverture du wikilivre Le mouvement Wikimédia.jpg|centré|sans_cadre|800x800px]] </br> <big><big>{{Centrer|De Lionel Scheepmans<br />Avec l'aide de la communauté Wikimédia}}</big></big> </br> [[Fichier:Wikibooks-logo-fr-noslogan-light.svg|centré|sans_cadre|100x100px]] </br> {{Seulement à l'impression|{{Centrer|Version du {{CURRENTDAY}} {{CURRENTMONTHNAME}} {{CURRENTYEAR}} à {{CURRENTTIME}}}}|div}} {{Nouvelle page imprimée}} == Quatrième de couverture == {{:Le mouvement Wikimédia/Quatrième de couverture}} {{Nouvelle page imprimée}} == Sommaire == {{:Le mouvement Wikimédia/Sommaire1}} {{Nouvelle page imprimée}} == Avant-propos == {{:Le mouvement Wikimédia/Avant-propos}} {{Nouvelle page imprimée}} == Introduction : Wikimédia n’est pas Wikipédia == {{:Le mouvement Wikimédia/Introduction : Wikimédia n'est pas Wikipédia}} {{Nouvelle page imprimée}} == Première partie : La naissance du mouvement Wikimédia == {{:Le mouvement Wikimédia/La naissance du mouvement Wikimédia}} === L'utopie Wikimédia === {{:Le mouvement Wikimédia/L'utopie Wikimédia}} === Le mouvement du logiciel libre === {{:Le mouvement Wikimédia/Le mouvement du logiciel libre}} === Les licences et la culture libres === {{:Le mouvement Wikimédia/Les licences et la culture libres}} === Le réseau Internet === {{:Le mouvement Wikimédia/Le réseau Internet}} == Le World Wide Web === {{:Le mouvement Wikimédia/Le World Wide Web}} === Les platesformes Wiki === {{:Le mouvement Wikimédia/Les platesformes Wiki}} === L’encyclopédie libre et universelle === {{:Le mouvement Wikimédia/L'encyclopédie libre et universelle}} === L'arrivée des projets frères === {{:Le mouvement Wikimédia/L'arrivée des projets frères}} === La conscientisation du mouvement === {{:Le mouvement Wikimédia/La conscientisation du mouvement}} === La création des organismes affiliés === {{:Le mouvement Wikimédia/La création des organismes affiliés}} === L'héritage d'une contre-culture === {{:Le mouvement Wikimédia/L'héritage d'une contre-culture}} {{Nouvelle page imprimée}} == Deuxième partie : Cosmographie du mouvement Wikimédia == {{:Le mouvement Wikimédia/Cosmographie du mouvement Wikimédia}} === La constellation des projets en ligne === {{:Le mouvement Wikimédia/La constellation des projets en ligne}} === Les projets de partage de la connaissance === {{:Le mouvement Wikimédia/Les projets de partage de la connaissance}} === Les projets de gouvernance, de gestion et de sensibilisation === {{:Le mouvement Wikimédia/Les projets de gouvernance, de gestion et de sensibilisation}} === Les projets de gestion technique === {{:Le mouvement Wikimédia/Les projets de gestion technique}} === Les espaces de communication et d’information === {{:Le mouvement Wikimédia/Les espaces de communication et d’information}} {{Nouvelle page imprimée}} === La constellation de la Fondation et de ses affiliés === {{:Le mouvement Wikimédia/La constellation de la Fondation et de ses affiliés}} === La Fondation Wikimédia === {{:Le mouvement Wikimédia/La Fondation Wikimédia}} === Le conseil d’administration de la Fondation === {{:Le mouvement Wikimédia/Le conseil d’administration}} === Les comités, groupes de travail et conseils === {{:Le mouvement Wikimédia/Les comités, groupes de travail et conseils}} === Les associations locales === {{:Le mouvement Wikimédia/Les associations locales}} === Les organisations thématiques, centrales et linguistiques === {{:Le mouvement Wikimédia/Les organisations thématiques, centrales et linguistiques }} === Les groupes d’usagers === {{:Le mouvement Wikimédia/Les groupes d’usagers}} === Les projets d’assistances === {{:Le mouvement Wikimédia/Les projets d’assistances}} === Les cycles de conférences et espaces de rencontres === {{:Le mouvement Wikimédia/Les cycles de conférences et espaces de rencontres}} === Les partenariats avec des entités externes au mouvement === {{:Le mouvement Wikimédia/Les partenariats externes}} {{Nouvelle page imprimée}} == Conclusion : Un mouvement culturel inspirant == {{:Le mouvement Wikimédia/Conclusion : Un mouvement culturel inspirant}} {{Nouvelle page imprimée}} == Remerciements == {{:Le mouvement Wikimédia/Remerciements}} {{Nouvelle page imprimée}} == Notes et références == [[Fichier:Qr code références livre Wikimédia.svg|alt=centrer|droite|sans_cadre|65x65px]] <small>{{Cacher à l'impression|<references />}}</small> == Bibliographie == {{:Le mouvement Wikimédia/Bibliographie}} [[Catégorie:Livres]] [[Catégorie:Livres]] [[Catégorie:Étude du cyber-mouvement du logiciel libre (livre)]] [[Catégorie:Anthropologie]] [[Catégorie:Sciences humaines]] [[Catégorie:Livres terminés]] [[Catégorie:Le mouvement Wikimédia]] [[Catégorie:Le mouvement Wikimédia (livre)]] [[Catégorie:Livres en vitrine]] {{AutoCat}} 5b05qf1woggb539afusd8ixh0cjrr7p Le mouvement Wikimédia/Introduction : Wikimédia n'est pas Wikipédia 0 78999 764183 763849 2026-04-21T06:30:22Z Lionel Scheepmans 20012 764183 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. En quelques mois et dans le cadre d'un mémoire de master réalisé, on peut ainsi fournir une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Cependant, pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref name=":0">{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues, dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Ethnographie fr Wikipédia</small> |<small>Thèse ''Imagine un monde''</small> |{{Centrer|<small>Wikiscan</small>}} |<small>Statistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} 6pjr0rhu4zzcxjir8jgx2k2rl98bwoa 764184 764183 2026-04-21T06:33:35Z Lionel Scheepmans 20012 764184 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. En quelques mois et dans le cadre d'un mémoire de master réalisé, on peut ainsi fournir une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Cependant, pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref name=":0">{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Ethnographie fr Wikipédia</small> |<small>Thèse ''Imagine un monde''</small> |{{Centrer|<small>Wikiscan</small>}} |<small>Statistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} boca99yx1v9cadbbb0woukhoo14x8b4 764185 764184 2026-04-21T06:45:34Z Lionel Scheepmans 20012 764185 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. En quelques mois et dans le cadre d'un mémoire de master réalisé, on peut ainsi fournir une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Cependant, pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref name=":0">{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Ethnographie fr Wikipédia</small> |<small>Thèse ''Imagine un monde''</small> |{{Centrer|<small>Wikiscan</small>}} |<small>Statistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} 1l4w1u0pqqa1q5edg66xddeawc0yrtf 764186 764185 2026-04-21T06:52:08Z Lionel Scheepmans 20012 764186 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. En quelques mois et dans le cadre d'un mémoire de master réalisé, on peut ainsi fournir une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Cependant, pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref name=":0">{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} cds78us7bjckuy9l1bn6zcxojhfx11j 764203 764186 2026-04-21T08:51:24Z Lionel Scheepmans 20012 764203 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. En quelques mois et dans le cadre d'un mémoire de master réalisé, on peut ainsi fournir une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Cependant, pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref>{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} ilb8x24qd3q0ldtg4lgebsq9iauffyd 764205 764203 2026-04-21T09:02:30Z Lionel Scheepmans 20012 764205 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. Dans le cadre d'un mémoire de master, on peut ainsi fournir en quelques mois une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Alors que pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, pas moins de cinq années de recul supplémentaires dans le cadre d'une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref>{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> furent nécessaires pour finaliser le projet. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} msqbg5tyq51n219zjpohp4zqnybq0tb 764206 764205 2026-04-21T09:04:36Z Lionel Scheepmans 20012 764206 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. Dans le cadre d'un mémoire de master, on peut ainsi fournir en quelques mois une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Alors que pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref>{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires pour finaliser le projet. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358, seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} 3cpcsvatu1dcfgalr6b93j6adkamfxp 764207 764206 2026-04-21T09:05:44Z Lionel Scheepmans 20012 764207 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. Dans le cadre d'un mémoire de master, on peut ainsi fournir en quelques mois une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Alors que pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref>{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires pour finaliser le projet. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358 seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} 4b0k013nawly66cw7ahbmpmhzbh5fal 764209 764207 2026-04-21T09:10:42Z Lionel Scheepmans 20012 764209 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}} </noinclude> Depuis le succès initial de Wikipédia, une myriade de projets de partage des connaissances, d’organisations et de groupes de soutien ont émergé pour former ce qu’on appelle aujourd’hui le mouvement Wikimédia. Même si, à ce jour, l’encyclopédie libre reste le projet phare du mouvement, il serait regrettable de réduire l’ensemble du mouvement à cet unique projet pédagogique. Malheureusement, il arrive bien trop souvent qu'une seule version linguistique de Wikipédia suffise pour cacher l’étendue de la forêt Wikimédia. En réalité, Wikimédia représente un mouvement social, international et interculturel complexe, au sein duquel Wikipédia n’est qu’une composante parmi d’autres. Dans le cadre d'un mémoire de master, on peut ainsi fournir en quelques mois une [[v:recherche:Culture_fr_Wikipédia|ethnographie du projet Wikipédia en français]]<ref>{{Lien web|titre=Culture fr Wikipédia, ethnographie du projet Wikipédia en français|url=https://web.archive.org/web/20250905132014/https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|auteur=Lionel Scheepmans|site=Wikiversité|année=2011}}.</ref>. Alors que pour synthétiser les origines, l’organisation et les dynamiques globales du mouvement Wikimédia, une [[v:fr:Recherche:Imagine_un_monde|thèse de doctorat]]<ref>{{Ouvrage|langue=fr|prénom1=Lionel|nom1=Scheepmans|lien auteur1=user:Lionel Scheepmans|titre=Imagine un monde : quand le mouvement Wikimédia nous aide à penser de manière prospective la société globale et numérique de demain|éditeur=UCL - Université Catholique de Louvain|année=2022|date=17/06/2022|lire en ligne=https://dial.uclouvain.be/pr/boreal/object/boreal:264603|consulté le=2024-03-10|nature article=Thèse de doctorat}}</ref> et cinq années de recul supplémentaires furent nécessaires pour finaliser le projet. [[Fichier:Wikimedia project stickers.jpg|vignette|<small>Figure 1. Série d’autocollants reprenant les logos des principaux projets collaboratifs actifs au sein du mouvement Wikimédia.</small>]] À la fin de l'année 2025, l’ampleur numérique du mouvement est effectivement impressionnante. Chaque mois, des millions de modifications bénévoles sont effectuées sur plus de 500 millions de pages<ref>{{Lien web|auteur=Stat.wikimedia.org|titre=Statistiques de Wikimédia|url=https://web.archive.org/web/20251209230902/https://stats.wikimedia.org/#/all-projects}}.</ref>, réparties sur plus d’un millier de sites web<ref>{{Lien web|url=https://web.archive.org/web/20251217134333/https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|titre=All Wikimedia Projects by Size|auteur=Wikistats wmcloud}}.</ref>, dont 358 seulement, correspondent aux [[m:List_of_Wikipedias|versions linguistiques de Wikipédia]]<ref>{{Lien web|url=https://web.archive.org/web/20251208041814/https://meta.wikimedia.org/wiki/List_of_Wikipedias|titre=List_of_Wikipedias|auteur=Méta-Wiki}}.</ref>. Ce qui prouve donc clairement que les activités en ligne portées par l'ensemble du mouvement Wikimédia dépassent largement ce qui se passe au sein de l’encyclopédie. Il existe ainsi huit autres projets pédagogiques susceptibles d'atteindre un jour l'envergure et la notoriété de Wikipédia, avec un objectif et un fonctionnement spécifiques à chacun. De manière détaillée, Wikilivres crée des livres pédagogiques, Wikiversité rassemble des supports d'enseignement et des travaux de recherche, Wikinews fait du journalisme collaboratif, Wikivoyage développe un guide touristique, pendant que Wiktionnaire apporte des définitions des mots de toutes les langues et dans toutes les langues. Contrairement à Wikipédia, tous ces projets ne sont pas soumis à une neutralité de point de vue, ni limités à l'usage de sources secondaires reconnues, au niveau de la rédaction des articles. La plupart d'entre eux acceptent aussi la publication de travaux de recherche ou de productions personnelles, alors que cela est tout à fait interdit dans Wikipédia. Selon l'étymologie du mot encyclopédie, le but de Wikipédia est en effet de synthétiser ou, plus précisément, d'encercler le savoir humain déjà préexistant. Cette contrainte éditoriale limite donc les contributeurs et contributrices à l'usage de sources secondaires et tertiaires présentes dans des publications externes au projet. De ce fait, Wikipédia reproduit fatalement les biais systémiques, tels que les déséquilibres et les surreprésentations de genre et de culture, présents dans un monde de l'édition majoritairement occidental. Or, cette impasse éditoriale propre à Wikipédia n'existe pas dans les autres projets pédagogiques. Comme ces projets frères, Wikipédia n'est pas non plus un projet complètement autonome des autres projets Wikimédia. L'encyclopédie compte en effet sur le projet Wikimedia Commons pour héberger l'ensemble de sa médiathèque. Elle utilise ensuite le contenu du projet Wikidata comme base de données structurée. Quant aux personnes qui produisent l'encyclopédie, elles peuvent aussi puiser leurs sources dans la bibliothèque Wikisource, ou se référer à des citations d'auteurs collectées dans le projet Wikiquote. Tout cela sans oublier que des dizaines de sites web traitent l'archivage permanent de Wikipédia et des autres projets Wikimédia, dans le but de fournir des analyses précieuses et totalement libres d’accès. Enfin, il faut aussi garder à l'esprit qu'au-delà de tous ces sites web, le mouvement Wikimédia, c'est aussi de nombreuses institutions et organisations affiliées dispersées dans le monde. Autour de la [[w:Fondation_Wikimédia|Fondation Wikimédia]] chargée de la gestion et de l’organisation internationales, avec près de 650 salariés de nationalités diverses<ref>{{Lien web|langue=|auteur=Wikimedia Foundation|titre=Les personnes derrière notre connaissance|url=https://web.archive.org/web/20250904032058/https://wikimediafoundation.org/fr/who-we-are/people/|site=|date=|consulté le=}}</ref>, se regroupent des centaines d'organisations satellites. Parmi celles-ci, on retrouve 2 [[m:Wikimedia_thematic_organizations/fr|associations thématiques]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia thematic organisations|url=https://web.archive.org/web/20250926235310/https://meta.wikimedia.org/wiki/Wikimedia_thematic_organizations|site=|date=|consulté le=}}.</ref>, 40 [[m:Wikimedia_chapters/fr|associations locales]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia chapters|url=https://web.archive.org/web/20251006092129/https://meta.wikimedia.org/wiki/Wikimedia_chapters}}</ref>, dont ''Wikimedia Deutschland'' qui regroupe plus de 170 emplyés<ref>{{Lien web|langue=|auteur=RocketReach|titre=Wikimedia Deutschlande. V. Information|url=https://web.archive.org/web/20251218034616/https://rocketreach.co/wikimedia-deutschland-e-v-profile_b5caf600f42e140f|site=|date=|consulté le=}}.</ref>, et finalement 141 [[metawiki:Wikimedia_user_groups/fr|groupes d’utilisateurs et utilisatrices]]<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Wikimedia user groups|url=https://web.archive.org/web/20251008041452/https://meta.wikimedia.org/wiki/Wikimedia_User_Groups|site=|date=|consulté le=}}</ref>. Tout ce qui vient d'être exposé dans cette introduction justifie donc la nécessité de distinguer le mouvement Wikimédia du projet Wikipédia. Imaginons seulement que l’on se limite à citer Paris pour décrire et comprendre un pays aussi vaste que la France. Certes, Paris est une ville mondialement connue et qui compte plus de deux millions d’habitants et un patrimoine culturel impressionnant. Mais est-ce pour autant qu'il faudrait oublier les autres villes, villages et métropoles françaises ? Sans compter que la France regroupe aussi des départements et des territoires d’outre-mer et qu'elle entretient des relations et des partenariats internationaux qui dépassent de loin ce qui se passe entre Paris et le reste du monde. Ne pas confondre le mouvement Wikimédia avec le projet Wikipédia relève donc du bon sens. En 2019 cependant, la Fondation Wikimédia a envisagé de se renommer en Fondation Wikipédia et de remplacer le terme « Wikimédia » par celui de « Wikipédia », partout où ce terme est utilisé dans la sphère hors ligne du mouvement. Le but était d’acquérir une plus grande visibilité et d’attirer des milliards de personnes, grâce au nom de marque Wikipédia, considéré comme l’un des plus connus au monde<ref>{{Lien web|langue=|auteur=Zack McCune|titre=Leading with Wikipedia: A brand proposal for 2030|url=https://web.archive.org/web/20210117025153/https://wikimediafoundation.org/news/2019/02/26/leading-with-wikipedia-a-brand-proposal-for-2030/|site=Wikimedia Foundation News|éditeur=|date=26 February 2019|consulté le=}}.</ref>. Ce changement n’a toutefois pas été accepté par de nombreuses personnes actives au sein du mouvement Wikimédia. En janvier 2020, ces opposants ont ainsi créé une page d’[[m:Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|appel à commentaires]], qui fut le siège d’un long débat<ref name="Requests for comment">{{Lien web|langue=|auteur=Méta-Wiki|titre=Requests for comment/Should the Foundation call itself Wikipedia|url=https://web.archive.org/web/20210905054842/https://meta.wikimedia.org/wiki/Requests_for_comment/Should_the_Foundation_call_itself_Wikipedia|consulté le=}}.</ref>. À l’issue de ce dernier, 73 représentants d’organisations affiliées et 984 personnes ont signé une [[m:Community_open_letter_on_renaming/fr|lettre ouverte]] adressée à la Fondation qui comprenait le paragraphe suivant<ref>{{Lien web|langue=|auteur=Méta-Wiki|titre=Lettre ouverte de la Communauté sur le changement de nom|url=https://web.archive.org/web/20210122162652/https://meta.wikimedia.org/wiki/Community_open_letter_on_renaming/fr|consulté le=}}.</ref> : <blockquote> Depuis 20 ans, les bénévoles ont bâti la réputation de Wikipédia en tant que ressource indépendante et communautaire. Les projets du mouvement Wikimédia, dont Wikipédia, se développent autour de la décentralisation et du consensus. Il est essentiel d’établir des distinctions claires entre la Fondation Wikimédia, les affiliés et les contributeurs individuels. Tout changement qui affecte cet équilibre exige le consentement éclairé et la collaboration des communautés. Il est donc très préoccupant de voir « Wikipédia » présenté pour le nom de l’organisation et du mouvement malgré le mécontentement général de la communauté. </blockquote> En s’opposant aux idées de la Fondation, ces membres de la communauté Wikimédia ont ainsi fait preuve de sagesse. De plus, ils ont signalé dans de nombreux commentaires que beaucoup de personnes connaissent le mouvement Wikimédia uniquement au travers de son encyclopédie. Il est même étonnant d'observer que la méconnaissance du mouvement existe aussi en interne. L'[[w:en:Wikimedia_movement|article du projet Wikipédia en anglais consacré au mouvement Wikimédia]], par exemple, ne s’est développé qu’à partir de 2016<ref>{{Lien web|auteur=Wikipedia|titre=Wikimedia mouvement - old revision|url=https://en.wikipedia.org/w/index.php?title=Wikimedia_movement&oldid=716240586|consulté le=}}.</ref>, tandis que ce même article dans la [[w:fr:Mouvement_Wikimédia|version francophone de l'encyclopédie]] n’est apparu qu’en 2019<ref>{{Lien web|auteur=Wikipédia|titre=Mouvement Wikimédia - version archivée|url=https://fr.wikipedia.org/w/index.php?title=Mouvement_Wikim%C3%A9dia&oldid=158268859|consulté le=}}.</ref>. Quant aux autres versions linguistiques, il est tout aussi étonnant de constater qu'en octobre 2025, seulement [[wikidata:Q3568028|39 d'entre elles sur un total de 358]] possédaient un article dédié au mouvement Wikimédia<ref>{{Lien web|auteur=Wikidata|titre=Wikimedia Movement|url=https://web.archive.org/web/20251004091239/https://www.wikidata.org/wiki/Q3568028}}.</ref>. Tous ces éléments justifient donc la nécessité d’offrir au monde une meilleure connaissance du mouvement Wikimédia et des nombreux projets et organisations qui soutiennent leurs missions de partage du savoir. En ce sens, ce livre est une contribution importante aux défis stratégiques que doit relever le mouvement Wikimédia à l’approche de 2030. Car au-delà des [[wmf:Resolution:Next_Steps_for_Brand_Work,_2021|résolutions]] prises pour développer de nouveaux processus participatifs et délibératifs concernant les questions de marque<ref>{{Lien web|auteur=Wikimedia Foundation Wiki|titre=Resolution:Next Steps for Brand Work, 2021|url=https://web.archive.org/web/20211020232912/https://foundation.wikimedia.org/wiki/Resolution:Next_Steps_for_Brand_Work,_2021|date=|consulté le=}}.</ref>, c’est avant tout un travail d’information et de sensibilisation à destination du grand public qu'il reste à faire. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Qrcode Culture fr Wikipédia.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Culture_fr_Wikip%C3%A9dia|100x100px|centré|sans_cadre]] |[[Fichier:Qrcode Imagine un monde.svg|lien=https://fr.wikiversity.org/wiki/Recherche:Imagine_un_monde|centré|sans_cadre|100x100px]] |[[Fichier:Code qr Wikiscan.svg|lien=http://wikiscan.org|100x100px|centré|sans_cadre]] |[[Fichier:QR code Statistiques Wikimédia.png|lien=https://stats.wikimedia.org|centré|sans_cadre|100x100px]] |[[Fichier:QR-code Wikistats wmcloud.png|lien=https://wikistats.wmcloud.org/wikimedias_html.php?s=users_asc&th=0&lines=2000|centré|sans cadre|100x100px]] |- |<small>Q 5 : Ethnographie fr Wikipédia</small> |<small>Q 2 : Thèse ''Imagine un monde''</small> |{{Centrer|<small>Q 2 : Wikiscan</small>}} |<small>QStatistiques de Wikimédia</small> |<small>Wikistats wmcloud</small> |} ‎<includeonly></includeonly> {{AutoCat}} s3w8mssbwui72rylq6mhi3yqv9nh5jp Le mouvement Wikimédia/La naissance du mouvement Wikimédia 0 79002 764211 763850 2026-04-21T09:27:11Z Lionel Scheepmans 20012 764211 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Il existe dans l'espace web une multitude d’archives permettant de retracer les événements qui ont conduit à la naissance du mouvement Wikimédia. Cette « préhistoire » du mouvement peut notamment être explorée grâce au réseau d’éducation populaire [[w:Framasoft|Framasoft]], dont le site est apparu environ un an avant la création de la version francophone de Wikipédia. On trouve sur cette plateforme une mine d’informations concernant les [[logiciels libres]] et la [[w:Culture_libre|culture libre]]. Deux épisodes majeurs de l’histoire de l’informatique et d’Internet, malheureusement méconnus du grand public. [[Fichier:Wikipedia Michelangelo.JPG|alt=Le tableau La création d'Adam de Michel-Ange retouché par un Wikimédien de telle sorte à faire apparaitre le logo de Wikipédia entre le doigt de Dieu et celui d'Adam|gauche|vignette|<small>Figure 2. [[w:La_Création_d'Adam_(Michel-Ange)|''La création d’Adam'']] de [[w:Michel-Ange|Michel-Ange]] revisitée par un contributeur de Wikipédia.</small>|300x300px]] Grâce à Framasoft et bien d’[[w:Catégorie:Association_ou_organisme_lié_au_logiciel_libre_en_France|autres associations]], il est possible de découvrir l’organisation et les motivations des millions de personnes qui participent au [[w:fr:mouvement du logiciel libre|mouvement du logiciel libre]]. On y apprend que ce mouvement politique et social a été initié en 1983 par [[w: fr: Richard Stallman|Richard Stallman]], un programmeur du Massachusetts Institute of Technology ([[w:Massachusetts_Institute_of_Technology|MIT]]), qui a eu l’idée d’offrir à chacun une alternative à la marchandisation du secteur informatique. Cette philosophie de libre partage, concrétisée par le projet de Stallman, permit l’essor d’une organisation et d’une éthique de travail originale, développée au sein d’une [[w:Sous-culture|sous-culture]] en vogue dans le milieu informatique depuis les années 1950. Celle-ci fut documentée dans de nombreux ouvrages, dont « ''[[w:L'Éthique_hacker|L’éthique hacker]]'' »<ref>{{Ouvrage|prénom1=Pekka|nom1=Himanen|titre=The Hacker Ethic and the Spirit of the Information Age|éditeur=Vintage|date=2001|isbn=978-0-09-942692-9|consulté le=}}.</ref>, un livre remarquable, dans lequel le philosophe finlandais, [[w:Pekka_Himanen|Pekka Himanen]], analyse en détail les origines de la [[w:Hacker_(sous-culture)|culture hacker]]. Un simple extrait de sa quatrième de couverture<ref>{{Ouvrage|prénom1=Pekka|nom1=Himanen|titre=L'éthique hacker et l'esprit de l'ère de l'information|éditeur=Exils|date=2001|isbn=2-912969-29-8|isbn2=978-2-912969-29-3|oclc=51085264|lire en ligne=|consulté le=}}.</ref>, repris ci-dessous, permet d’appréhender la manière de penser de ces informaticiens, rejoints par Richard Stallman durant ses études universitaires, avant d'en devenir l’une des figures les plus charismatiques. <blockquote> On considérait jusqu’à présent le « hacker » comme un voyou d’Internet, responsable d’actes de piratage et de vols de numéros de cartes bancaires. Le philosophe Pekka Himanen voit au contraire les hackers comme des citoyens modèles de l’ère de l’information. Il les considère comme les véritables moteurs d’une profonde mutation sociale. Leur éthique, leur rapport au travail, au temps ou à l’argent, sont fondés sur la passion, le plaisir ou le partage. Cette éthique est radicalement opposée à l’[[w:Éthique_protestante_du_travail|éthique protestante]], telle qu’elle est définie par [[w:Max_Weber|Max Weber]], du travail comme devoir, comme valeur en soi, une morale qui domine encore le monde aujourd’hui. </blockquote> En introduisant cette première partie d'ouvrage de la sorte, nous pouvons déjà comprendre que le mouvement Wikimédia plonge ses racines dans une transition culturelle remplie d’utopie<ref>{{Article|langue=fr|prénom1=Anne|nom1=Bellon|titre=Qu’est devenue l’utopie d’Internet ?|périodique=Revue Projet|volume=371|numéro=4|date=2019-08-27|issn=0033-0884|doi=10.3917/pro.371.0006|lire en ligne=https://web.archive.org/web/20241209072859/https://shs.cairn.info/revue-projet-2019-4-page-6?lang=fr|consulté le=2025-12-21|pages=6–11}}</ref>. Une utopie qui s’oppose notamment à ce que l’historien et anthropologue [[w:Karl_Polanyi|Karl Polanyi]]<ref>{{Ouvrage|langue=|prénom1=Karl|nom1=Polanyi|prénom2=Fred|nom2=Block|prénom3=Joseph E|nom3=Stiglitz|titre=The great transformation: the political and economic origins of our time|éditeur=Beacon press|date=2001|isbn=978-0-8070-5643-1|oclc=1277370048}}.</ref> désignait, en 1944 déjà, comme un [[w:Libéralisme_économique|libéralisme économique]] qui « subordonne les objectifs humains à la logique d’un mécanisme de marché impersonnel »<ref>Texte original avant sa traduction par www.deepl.com/translator : « ''subordinates human purposes to the logic of an impersonal market mechanism ».''</ref>. Étape par étape et en commençant par analyser cette utopie spécifiquement au niveau du mouvement Wikimédia, voyons maintenant ce qui s'est passé tout au long de cette révolution culturelle numérique. {{AutoCat}} 660zg3nabrdwvsyt6ezj66yxl70izvf Le mouvement Wikimédia/Quatrième de couverture 0 79251 764199 758513 2026-04-21T08:42:28Z Lionel Scheepmans 20012 764199 wikitext text/x-wiki '''Le mouvement Wikimédia, une audacieuse aventure collective mondiale au service du savoir libre.''' Quel est ce seul acteur à but non lucratif présent dans le top 100 des sites les plus visités sur le Web ? Comment incarne-t-il l’expression la plus visible des valeurs de liberté, d’équité et de partage, héritées de la révolution numérique et des mouvements sociaux des années 1960 ? Comment, à partir de Wikipédia et suite à la création d’une quinzaine de projets frères distribués en centaines de versions linguistiques, le mouvement social Wikimédia a imaginé un monde dans lequel le savoir se produit et se partage librement ? Et comment, en toute autonomie, des dizaines de projets pédagogiques, édités par des millions de bénévoles, soutenus par une fondation et près de 200 associations et groupes locaux, produisent-ils la plus grande intelligence collective au monde ? Avec de nombreux codes QR, cet ouvrage répond à ces questions, tout en permettant de mieux comprendre le monde global et numérique qui nous entoure. ---- [[Utilisateur:Lionel Scheepmans|Lionel Scheepmans]] est docteur en sciences politiques et sociales, militant de la culture libre et professeur d’anthropologie numérique. Il occupe plusieurs postes d’administrateur au sein du mouvement Wikimédia qu’il observe de manière participative depuis 2011. Ses travaux universitaires, du master à la thèse de doctorat, furent consacrés à l’organisation et aux enjeux de Wikipédia et du mouvement Wikimédia. {{AutoCat}}<br /><br /> {{Centrer|'''Accès aux formats de publications'''}} <br /> {| width="100%" style="margin: auto;" ![[Fichier:Code qr version complète Le mouvement Wikimédia.svg|lien=https://fr.wikibooks.org/wiki/Le_mouvement_Wikim%C3%A9dia|alt=|centré|sans_cadre|100x100px]] ![[Fichier:Code QR pdf Le mouvement Wikimédia.svg|lien=https://upload.wikimedia.org/wikipedia/commons/8/88/Le_mouvement_Wikim%C3%A9dia_%E2%80%94_Wikilivres.pdf|alt=|centré|sans_cadre|100x100px]] ![[Fichier:Code QR audio Le mouvement Wikimédia.svg|lien=https://upload.wikimedia.org/wikipedia/commons/1/15/Le_mouvement_Wikim%C3%A9dia.oga|alt=Audio|centré|sans_cadre|100x100px]] |- !Page web !PDF !Livre audio |} {{Autocat}} 3bnb4qxsovvz09gravtbet30h8h4p2q Le mouvement Wikimédia/Avant-propos 0 79252 764182 758514 2026-04-21T05:04:22Z Lionel Scheepmans 20012 764182 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sans perdre entièrement la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long des versions imprimées de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible d’imprimer.[[Fichier:Code qr version complète Le mouvement Wikimédia.svg|droite|sans_cadre|100x100px]] Par exemple, ce premier code QR, placé à côté de ce paragraphe, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les vidéos qui s’y trouvent et consulter leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. [[Fichier:Qr code références livre Wikimédia.svg|droite|sans_cadre|100x100px]] Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible avec ce nouveau code QR ci-joint. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs propres hyperliens, afin de consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. [[Fichier:Qr code page discussion livre Le mouvement Wikimédia.svg|droite|sans_cadre|100x100px]] Une page de discussion générale, accessible par le code QR ci-contre, permet aussi de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. [[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|sans_cadre|100x100px|droite]] Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, ce dernier code QR donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {{AutoCat}} pztziz01odulr0x4fghhp8aroxlgbgd 764187 764182 2026-04-21T07:02:32Z Lionel Scheepmans 20012 764187 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sans perdre entièrement la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long des versions imprimées de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible d’imprimer. Par exemple, le code QR 1, placé ci-dessous, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les vidéos qui s’y trouvent et consulter leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible avec le nouveau code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs propres hyperliens, afin de consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Une page de discussion générale, accessible par le code QR ci-contre, permet aussi de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, ce dernier code QR donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code qr version complète Le mouvement Wikimédia.svg|sans_cadre|100x100px]] |[[Fichier:Qr code références livre Wikimédia.svg|sans_cadre|100x100px]] |[[Fichier:Qr code page discussion livre Le mouvement Wikimédia.svg|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} jow79a5ens44iu7q2auasxc082wbvgb 764188 764187 2026-04-21T07:03:43Z Lionel Scheepmans 20012 764188 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sans perdre entièrement la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long des versions imprimées de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible d’imprimer. Par exemple, le code QR 1, placé ci-dessous, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les vidéos qui s’y trouvent et consulter leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible avec le nouveau code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs propres hyperliens, afin de consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Une page de discussion générale, accessible par le code QR ci-contre, permet aussi de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, ce dernier code QR donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} tfhy91qjnya71rezmztctp225wl2qvd 764189 764188 2026-04-21T07:05:29Z Lionel Scheepmans 20012 764189 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sans perdre entièrement la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long des versions imprimées de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible d’imprimer. Par exemple, le code QR 1, placé ci-dessous, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les vidéos qui s’y trouvent et consulter leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible avec le nouveau code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs propres hyperliens, afin de consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Une page de discussion générale, accessible par le code QR 3, permet aussi de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} 5zsh1j245p2z62cjjsdv7lx40so7xz4 764190 764189 2026-04-21T07:54:46Z Lionel Scheepmans 20012 764190 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sur papier sans perdre la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible à imprimer. Par exemple, le code QR 1, affiché en fin de page, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les enregistrements qui s’y trouvent et consulter ensuite leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible via le code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien pointant vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve repris, pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs hyperliens originels, pour consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Une page de discussion générale est aussi accessible grâce au code QR 3. Elle permet quant à elle de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} mytf9mdqrg24b4ktgdymashcx08sx1d 764191 764190 2026-04-21T08:04:59Z Lionel Scheepmans 20012 764191 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sur papier sans perdre la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible à imprimer. Par exemple, le code QR 1, affiché en fin de page, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les enregistrements qui s’y trouvent et consulter ensuite leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible via le code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien pointant vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve repris, pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs hyperliens originels, pour consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, chacun est invité à améliorer sa prochaine version. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Cela peut se faire très simplement en cliquant sur « Modifier » au niveau des pages des pages de contenu et « Ajouter un sujet » lorsque vous êtes sur une des pages de discussion accessibles en cliquant sur « Discussion » . Une page de discussion générale est aussi accessible grâce au code QR 3. Elle permet quant à elle de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} tjv47xvykua25k54455rk2ybcre4qja 764192 764191 2026-04-21T08:11:00Z Lionel Scheepmans 20012 764192 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sur papier sans perdre la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible à imprimer. Par exemple, le code QR 1, affiché en fin de page, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les enregistrements qui s’y trouvent et consulter ensuite leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible via le code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien pointant vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve repris, pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs hyperliens originels, pour consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, tout le monde est invité à améliorer les prochaines versions. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Cela peut se faire très simplement en cliquant sur « Modifier » , quand on est sur une des pages de chapitre et sur « Ajouter un sujet » , après avoir cliqué sur « Discussion » . Une page de discussion générale est aussi accessible grâce au code QR 3. Elle permet quant à elle de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} srsswjz067gkfza3nnw7u1qv3gu3olr 764193 764192 2026-04-21T08:29:37Z Lionel Scheepmans 20012 764193 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sur papier sans perdre la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible à imprimer. Par exemple, le code QR 1, affiché en fin de page, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les enregistrements qui s’y trouvent et consulter ensuite leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible via le code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien pointant vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve repris, pour garantir un accès aux archives des pages citées dans l’ouvrage, mais qui auraient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs hyperliens originels, pour consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, tout le monde est invité à améliorer les prochaines versions. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Cela peut se faire très simplement en cliquant sur « Modifier » , quand on est sur une des pages de chapitre et sur « Ajouter un sujet » , après avoir cliqué sur « Discussion » . Une page de discussion générale est aussi accessible grâce au code QR 3. Elle permet quant à elle de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Le_mouvement_Wikim%C3%A9dia/Version_compl%C3%A8te]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Le_mouvement_Wikim%C3%A9dia/Version_compl%C3%A8te#Notes_et_r%C3%A9f%C3%A9rences]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Discussion:Le_mouvement_Wikim%C3%A9dia]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px|lien=https://listen.hatnote.com]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} d3caxson9uongdd9jgdg4gm5z6680ly 764201 764193 2026-04-21T08:48:36Z Lionel Scheepmans 20012 764201 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Pour offrir un confort de lecture sur papier sans perdre la puissance du numérique, des [[w:Codes_QR|codes QR]] sont affichés tout au long de cet ouvrage. À l’aide d’une tablette ou d’un smartphone, ils offrent un accès direct à ce qui serait coûteux ou impossible à imprimer. Par exemple, le code QR 1, affiché en fin de page, donne accès directement à la page web qui reprend l’intégralité de l’ouvrage. Une fois sur celle-ci, on peut alors visionner les illustrations en couleur ou les enregistrements qui s’y trouvent et consulter ensuite leurs pages de descriptions en cas de besoin. Cette version numérique comprend aussi de nombreux hyperliens pointant vers Wikipédia et d’autres sites du mouvement Wikimédia, où se trouvent des compléments d’informations et leurs mises à jour. Pour économiser du papier lors de l’impression, la section regroupant les notes et les références de l’ouvrage n’est disponible qu’au format numérique, mais est directement accessible via le code QR 2 repris ci-dessous. Grâce aux indices de renvoi chiffrés et placés en exposant dans le texte imprimé, il est alors possible, au départ d'un smartphone ou d'une tablette, de retrouver les notes et les références en fonction de leur numérotation. Lorsque la référence correspond à une page web, un lien pointant vers le projet [[w:Internet_Archive|Internet Archive]] s’y trouve repris, pour garantir un accès aux archives des pages citées dans l’ouvrage, si jamais elles avaient disparu du web. Quant aux pages toujours existantes, elles restent accessibles via leurs hyperliens originels, pour consulter leurs éventuelles évolutions. Étant donné que ce livre est produit sur une plateforme collaborative, tout le monde est invité à améliorer les prochaines versions. On peut le faire en corrigeant des fautes d’orthographe ou de syntaxe sur les pages web qui constituent les différents chapitres de l’ouvrage, ou encore en apportant des commentaires sur les pages de discussion qui leur sont associées. Cela peut se faire très simplement en cliquant sur « Modifier » , quand on est sur une des pages de chapitre et sur « Ajouter un sujet » , après avoir cliqué sur « Discussion » . Une page de discussion générale est aussi accessible grâce au code QR 3. Elle permet de commenter le livre dans son ensemble, ou de poser une question à son sujet. Il suffit pour cela d’indiquer un titre dans le champ « Démarrer un nouveau sujet », d’écrire le contenu du message dans l’encadré situé juste en dessous, puis de cliquer sur le bouton « Ajouter un sujet de manière anonyme » pour publier son message. Enfin, pour ceux qui voudraient agrémenter leur lecture d’un fond sonore relaxant et original, le code QR 4 donne accès à une page web qui diffuse une musique mélodieuse. Celle-ci est composée de sons spécifiquement produits chaque fois qu’une modification est apportée sur un projet Wikimédia, ou qu’un nouveau compte y est créé. Ce dispositif ingénieux offre ainsi aux lecteurs qui le souhaitent une ambiance sonore particulièrement confortable, ainsi qu’une nouvelle expérience immersive au sein du mouvement Wikimédia. {| class="wikitable"style="margin: auto;" "text-align:center;" |+ |[[Fichier:Code_qr_version_complète_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Le_mouvement_Wikim%C3%A9dia/Version_compl%C3%A8te]] |[[Fichier:Qr_code_références_livre_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Le_mouvement_Wikim%C3%A9dia/Version_compl%C3%A8te#Notes_et_r%C3%A9f%C3%A9rences]] |[[Fichier:Qr_code_page_discussion_livre_Le_mouvement_Wikimédia.svg|centré|sans_cadre|100x100px|lien=https://fr.wikibooks.org/wiki/Discussion:Le_mouvement_Wikim%C3%A9dia]] |[[Fichier:Qr_code_Listen_to_Wikipedia.svg|lien=https://listen.hatnote.com/|centré|sans_cadre|100x100px]] |- |<small>QR 1 : Livre complet</small> |<small>QR 2 : Notes et références</small> |<small>QR 3 : Page de discussion générale</small> |<small>QR 4 : Ambiance sonore</small> |} {{AutoCat}} 58qo5rccc70b91v5mgq1huq3fwel3pj Le mouvement Wikimédia/L'utopie Wikimédia 0 79253 764087 764086 2026-04-20T12:00:37Z Lionel Scheepmans 20012 764087 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref> ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref> et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aidez à visualiser ce qui s'y passe dans sa dimenssion numérique, voici une métaphore dans laquelle le mouvement Wikimédia apparait tel un quartier au sein d"une ville que serait l'espace web. Dans cette ville, Internet serait le réseau routier, les serveurs informatiques, les batiments, et les pages web, les différentes pièces présentes au sein de ces édifices. Le quartier Wikimédia rassemblerait ainsi plus d’un millier d’édifices. Au sein de ceux-ci, chaque pièce peut être visitée gratuitement et même, à l’exception de quelques pièces situées dans des bâtiments administratifs, il est possible d'en modifier le contenu. On peut ajouter de nouvelles choses, tels que du texte, des photos, des vidéos ou des documents sonores, mais on peut aussi changer ou supprimer ce qui a été modifié par d’autres, dans le but de rendre les choses plus esthétiques ou plus autentique. Et lorsque plusieurs personnes ont des idéés différentes concernant l'aménagement d'une pière, pas de problème. Chaque pièce possède un espace annexe dédié au débats et à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Sauf que dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectées par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillantes et contacter la personne responsable. En cas de multirécidive, le ou la vandal se verra privé de sa capacité de modifier les pièces, soit, dans le bâtiment vandalisé, soit, dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des batiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais aussi surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte et de profiter, entre autres, d'un système de notification qui permet de reçevoir un message d'avertissement à chaque modification d'une pièce que l'on veut surveiller. Pour la création de ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors des visites des bâtiments Wikimédia n’est collectée pour être vendue à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires en cas de non-connexion. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes pouvant faire suite aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia est ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de encyclopédie. Juste à côté et toujours séparés en versions linguistiques, se trouvent ensuite les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], puis, les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas se situe [[commons:main page|Wikimedia Commons]], un musée médiatique, et enuite [[wikidata:wikidata:main_page|Wikidata]], la plus grande banque d’informations structurées au monde, dont l'une des fonctions, au même titre que Wikimedi Commons, est d’enrichir les pièces situées des les autres buildings du quartier. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribuer à l'organisation des projets. Une organisation qui reçois le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieu entièrement dédiés à la maintenance technique sur l'ensemble du quartier. Quand aux aspects administratifs, on retrouve le siège de la gouvernance dans le bâtiment [[metawiki:main page|Méta-Wiki]], traitement des courriers dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] et des initiatives de sensibilisations et de recrutements de nouveaux bénévoles dans le bâtiment ''[[outreach:main page|Wikimedia outreach]]''. Le plus utopique dans tout cela est finalement le fait que, en dehors de certains aspects techniques, tous ces bâtiments sont excusivement gérés par des communautés bénévoles, entièrement ouvertes à l'accueil de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quand au conseil d'administration de la fondation, il possède aussi son propre bâtiment dont la modification des pièces est réservée aux élus et certains employés, pour une officialisation de leurs contenus évidente. Au finale et face à tant d'utopie, il devient tentant de se demander comme tout cela a-t-il été rendu possible ? Pour y répondre, cela demande de parcourir toute une période de l'histoire allant de l'apparition de la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jour, tout en passant par toutes les étapes de la révolution numérique. On y découvre alors que les chercheurs et étudiants en informatique, pionniers des réseaux et de leurs applications, étaient fortement influencés par le mouvement hippie et autres changements idéologiques symbolisé en France par les événements de [[w:mai_68|mai 68]]. Car c'est en effet au départ de ces impulsions que naîtra cette philosophie du partage décentralisé et ce mode d’organisation tout à fait spécifiques, hérité par le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui simplifie les interactions humaines à l’échelle planétaire, jusqu'à l'avènement des logiciels qui ont rendu possible la modification de sites web à l'aide d’un simple navigateur, pour former ce que l'on appelle aujourd’hui le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia, devenue par ce fait actrice au sein du [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]]. Voyons donc de quoi il s'agit.{{AutoCat}} 0xc7i9dbvh7c7iikahgxhti9579sfzu 764212 764087 2026-04-21T09:50:01Z Lionel Scheepmans 20012 764212 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville espace web. Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure de bâtiments, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables de ces édifices. Le quartier Wikimédia rassemblerait ainsi plus d’un millier d’édifices. Au sein de ceux-ci, chaque pièce peut être visitée gratuitement et même, à l’exception de quelques pièces situées dans des bâtiments administratifs, il est possible d'en modifier le contenu. On peut ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores. On peut même changer ou supprimer ce qui a été modifié par d’autres, dans le but de rendre les choses plus esthétiques ou plus authentiques. Ensuite, lorsque plusieurs personnes ont des idées différentes concernant l'aménagement d'une pièce ? Pas de problème. Chaque pièce possède un espace annexe dédié aux débats et à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment, un système qui envoi des notifications à chaque fois qu'une pièce que l'on veut surveiller est modifiée. Pour la création de ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors des visites des bâtiments Wikimédia n’est collectée pour être vendue à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour le modifications faites par des gens non connectés. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent ensuite les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], puis, les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas se situe [[commons:main page|Wikimedia Commons]], un musée médiatique, et ensuite [[wikidata:wikidata:main_page|Wikidata]], la plus grande banque d’informations structurées au monde, dont l'une des fonctions, au même titre que Wikimedia Commons, est d’enrichir les pièces situées des les autres buildings du quartier. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribuer à l'organisation des projets. Une organisation qui reçois le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieu entièrement dédiés à la maintenance technique sur l'ensemble du quartier. Quand aux aspects administratifs, on retrouve le siège de la gouvernance dans le bâtiment [[metawiki:main page|Méta-Wiki]], traitement des courriers dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] et des initiatives de sensibilisations et de recrutements de nouveaux bénévoles dans le bâtiment ''[[outreach:main page|Wikimedia outreach]]''. Le plus utopique dans tout cela est finalement le fait que, en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement gérés par des communautés bénévoles, entièrement ouvertes à l'accueil de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quand au conseil d'administration de la fondation, il possède aussi son propre bâtiment dont la modification des pièces est réservée aux élus et certains employés, pour une officialisation de leurs contenus évidente. Au finale et face à tant d'utopie, il devient tentant de se demander comme tout cela a-t-il été rendu possible ? Pour y répondre, cela demande de parcourir toute une période de l'histoire allant de l'apparition de la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jour, tout en passant par toutes les étapes de la révolution numérique. On y découvre alors que les chercheurs et étudiants en informatique, pionniers des réseaux et de leurs applications, étaient fortement influencés par le mouvement hippie et autres changements idéologiques symbolisé en France par les événements de [[w:mai_68|mai 68]]. Car c'est en effet au départ de ces impulsions que naîtra cette philosophie du partage décentralisé et ce mode d’organisation tout à fait spécifiques, hérité par le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui simplifie les interactions humaines à l’échelle planétaire, jusqu'à l'avènement des logiciels qui ont rendu possible la modification de sites web à l'aide d’un simple navigateur, pour former ce que l'on appelle aujourd’hui le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia, devenue par ce fait actrice au sein du [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]]. Voyons donc de quoi il s'agit.{{AutoCat}} 41wem8o1k19oux1vg8e0a7n62s3gv4k 764213 764212 2026-04-21T10:09:41Z Lionel Scheepmans 20012 764213 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment, un système qui envoi des notifications à chaque fois qu'une pièce que l'on veut surveiller est modifiée. Pour la création de ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors des visites des bâtiments Wikimédia n’est collectée pour être vendue à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour le modifications faites par des gens non connectés. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent ensuite les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], puis, les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas se situe [[commons:main page|Wikimedia Commons]], un musée médiatique, et ensuite [[wikidata:wikidata:main_page|Wikidata]], la plus grande banque d’informations structurées au monde, dont l'une des fonctions, au même titre que Wikimedia Commons, est d’enrichir les pièces situées des les autres buildings du quartier. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribuer à l'organisation des projets. Une organisation qui reçois le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieu entièrement dédiés à la maintenance technique sur l'ensemble du quartier. Quand aux aspects administratifs, on retrouve le siège de la gouvernance dans le bâtiment [[metawiki:main page|Méta-Wiki]], traitement des courriers dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] et des initiatives de sensibilisations et de recrutements de nouveaux bénévoles dans le bâtiment ''[[outreach:main page|Wikimedia outreach]]''. Le plus utopique dans tout cela est finalement le fait que, en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement gérés par des communautés bénévoles, entièrement ouvertes à l'accueil de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quand au conseil d'administration de la fondation, il possède aussi son propre bâtiment dont la modification des pièces est réservée aux élus et certains employés, pour une officialisation de leurs contenus évidente. Au finale et face à tant d'utopie, il devient tentant de se demander comme tout cela a-t-il été rendu possible ? Pour y répondre, cela demande de parcourir toute une période de l'histoire allant de l'apparition de la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jour, tout en passant par toutes les étapes de la révolution numérique. On y découvre alors que les chercheurs et étudiants en informatique, pionniers des réseaux et de leurs applications, étaient fortement influencés par le mouvement hippie et autres changements idéologiques symbolisé en France par les événements de [[w:mai_68|mai 68]]. Car c'est en effet au départ de ces impulsions que naîtra cette philosophie du partage décentralisé et ce mode d’organisation tout à fait spécifiques, hérité par le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui simplifie les interactions humaines à l’échelle planétaire, jusqu'à l'avènement des logiciels qui ont rendu possible la modification de sites web à l'aide d’un simple navigateur, pour former ce que l'on appelle aujourd’hui le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia, devenue par ce fait actrice au sein du [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]]. Voyons donc de quoi il s'agit.{{AutoCat}} detjzfdivbo4atb05q6ijyeepkwrylo 764215 764213 2026-04-21T11:33:50Z Lionel Scheepmans 20012 764215 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, voire « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications à chaque fois qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour le modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} blcnmas7oz95sfmr3gf3axwpn353ize 764216 764215 2026-04-21T11:39:32Z Lionel Scheepmans 20012 764216 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, voire « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications dès qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour les modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} nfzwg8eh1ok2zd9h1nr1bt1giqm0n9k 764217 764216 2026-04-21T11:41:30Z Lionel Scheepmans 20012 764217 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Wikipédia est parfois perçus comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, voire « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même par certains, comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Certains perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, ou même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications dès qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour les modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} 4easnr37wf2h1h5koloeyomg9fdmzoe 764218 764217 2026-04-21T11:42:41Z Lionel Scheepmans 20012 764218 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Certains auteurs perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « une utopie réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Certains perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, ou même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications dès qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour les modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} 18xfqjjdrr51xm4ok7s2r0g3h1ocjnw 764219 764218 2026-04-21T11:43:40Z Lionel Scheepmans 20012 764219 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Certains auteurs perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « une utopie réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville numérique que constituerait l'espace web. Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Certains perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, ou même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications dès qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour les modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} 2d5dginsdwiit4jxtlvrwmfgmnnf2tn 764220 764219 2026-04-21T11:46:13Z Lionel Scheepmans 20012 764220 wikitext text/x-wiki <noinclude>{{Le mouvement Wikimédia}}</noinclude> Au fil du temps, Wikipédia fut perçu comme une utopie en marche<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, puis comme une utopie réalisée<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, et finalement comme la dernière utopie collective du Web<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville numérique que constituerait l'espace web. Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Certains perçoivent Wikipédia comme « une utopie en marche »<ref>{{Article|langue=|prénom1=Christian|nom1=Vandendorpe|titre=Le phénomène Wikipédia: une utopie en marche|périodique=Le Débat|volume=148|numéro=1|éditeur=Gallimard|date=2008|issn=0246-2346|pages=17}}.</ref>, ou « réalisée »<ref>{{Ouvrage|prénom1=Théo|nom1=Henri|directeur1=|titre=Wikipédia : une utopie réalisée ?|lieu=Université de Poitier|date=juillet 2013|pages totales=98|lire en ligne=https://web.archive.org/web/20211103122912/https://www.seies.net/sites/theo/doc/HENRI_theo_-_master_1_-_memoire.pdf}}.</ref>, ou même comme « la dernière utopie collective du Web »<ref>{{Lien web|langue=fr-FR|nom1=Dupont-Besnard|prénom1=Marcus|titre=Wikipédia, la dernière utopie collective du web ?|url=https://web.archive.org/web/20250516050814/https://www.numerama.com/tech/805447-wikipedia-la-derniere-utopie-collective-du-web.html|site=Numerama|date=2021-12-29|consulté le=2025-12-21}}</ref>. Mais qu'en est-il de l'ensemble du mouvement Wikimédia ? Pour nous aider à comprendre ce qui se passe dans la dimension numérique de ce mouvement, voici une métaphore décrivant un quartier établi au sein d'une ville « espace web ». Dans cette ville, Internet constitue le réseau routier, des serveurs informatiques font figure d'édifices, tandis que les pages web qu'ils contiennent représentent les différentes pièces habitables. Le quartier Wikimédia rassemblerait ainsi plus d’un millier de bâtiments. Au sein de ceux-ci et à l’exception de quelques lieux administratifs, chaque pièce peut être visitée gratuitement et même modifiée au niveau de son contenu. On peut ainsi y ajouter de nouvelles choses, telles que du texte, des photos, des vidéos ou des documents sonores, et changer ou supprimer ce qui a été créé ou modifié par d’autres. Tout cela, bien sûr, dans le but de rendre ces endroits plus esthétiques et plus authentiques et en tenant compte des différentes idées et des éventuelles oppositions de point de vue concernant les aménagements. Pour faciliter l'entente entre les personnes qui s'investissent dans ces aménagements, chaque pièce des bâtiments Wikimédia possède un espace annexe dédié à la discussion. Le quartier Wikimédia est tellement libre qu'une personne mal intentionnée peut faire disparaitre tout le contenu d'une pièce. Néanmoins, dans la seconde qui suit, un robot aura remis tout en place, avant de transmettre un message concernant le traitement du vandalisme. Lorsqu'une action plus discrète n'est pas détectée par un robot, c'est alors une des personnes qui ont enrichi la pièce qui prendra le relais pour annuler les changements malveillants et contacter la personne responsable. En cas de multirécidive, la personne vandale se verra privée de sa capacité de modifier les pièces, soit dans le bâtiment vandalisé, soit dans tout le quartier quand cela se justifie. La sanction est toujours mise en application après discussion et par un administrateur ou une administratrice bénévole, choisi ou choisie par l'ensemble des autres bénévoles qui prennent soin des bâtiments. [[Fichier:The Digital City, Riyadh 191957.jpg|vignette|<small>Figure 3. Photo de la ''Digital City'' de [[w:Riyad|Riyadh]] et son aspect visuel en lien avec la métaphore du quartier Wikimédia.</small>|300x300px]] On comprend donc que tout le monde peut enrichir, mais également surveiller et protéger les richesses partagées dans le quartier Wikimédia. Il suffit pour cela de rejoindre le mouvement en se créant un compte. Cela permet de profiter de nombreux outils, dont notamment un système qui envoie des notifications dès qu'une pièce que l'on veut surveiller est modifiée. Pour créer ce compte, pas besoin de fournir une adresse ou un numéro de téléphone. Les seules informations personnelles indispensables au bon fonctionnement du quartier Wikimédia sont les [[w:Adresses_IP|adresses IP]] des ordinateurs connectés. Car contrairement à ce qui se passe dans les quartiers commerciaux de la grande ville numérique, tels que les [[w:GAFAM|GAFAM]], [[w:NATU_(Netflix,_Airbnb,_Tesla_et_Uber)|NATU]], [[w:BATX|BATX]] ou autres, aucune des informations récoltées lors de la visite des bâtiments. Wikimédia ne collecte effectivement aucune donnée dans le but de les vendre à des personnes qui en feront l'exploitation. Même les adresses IP enregistrées par le système ne sont pas visibles par les autres visiteurs. Elles sont remplacées par les noms et les pseudonymes fournis lors de la création des comptes, ou masquées par des comptes temporaires pour les modifications faites par des personnes non connectées. Seules quelques personnes accréditées par la communauté pour effectuer des contrôles d’usurpation d’identité ont accès à ces informations<ref>{{Lien web|auteur=MédiaWiki|titre=Produit de confiance et de sécurité/Comptes temporaires|url=https://web.archive.org/web/20250813140004/https://www.mediawiki.org/wiki/Trust_and_Safety_Product/Temporary_Accounts/fr}}.</ref>. C’est là une précaution nécessaire au bon déroulement des votes qui succèdent parfois aux recherches de [[w:Consensus|consensus]] concernant l'aménagement du quartier Wikimédia. Dans cette ville numérique que constituerait l'espace web, Wikimédia apparait ainsi comme le plus grand quartier dédié au partage de la connaissance. Tout d'abord, il y a les plus de 350 bâtiments [[w:Wikipédia:Accueil_principal|Wikipédia]], chacun dédié à une version linguistique de l'encyclopédie. Ensuite, juste à côté et toujours séparés en versions linguistiques, se trouvent les bibliothèques [[:en:fr:accueil|Wikilivres]] et [[s:fr:Wikisource:Accueil|Wikisource]], les bâtiments lexicaux multilingues [[wikt:fr:Wiktionnaire:Page_d’accueil|Wiktionnaire]], le centre journalistique [[n:fr:accueil|Wikinews]], le centre pédagogique et de recherche [[v:fr:accueil|Wikiversité]], le centre d'informations touristique [[voy:fr:accueil|Wikivoyage]], le répertoire des êtres vivants [[species:main page|Wikispecies]] et enfin l'institut des citations d’auteurs [[q:fr:accueil|Wikiquote]]. Cela sans oublier qu'à deux pas de là se situent le musée médiatique [[commons:main page|Wikimedia Commons]] et [[wikidata:wikidata:main_page|Wikidata]] qui constitue la plus grande banque d’informations structurées au monde. Deux bâtiments dont l'une des fonctions principales communes est d’enrichir les pièces situées dans les autres buildings du quartier Wikimédia. Dans tous ces immeubles, il arrive souvent que plus de la moitié des étages soient uniquement attribués à l'organisation des activités qui s'y déroulent. Chaque bâtiment peut aussi compter sur le soutien d'autres édifices tels que [[mw:main page|MediaWiki]], [[wikitech:Main_Page|Wikitech]], [[w:fr:phabricator|Phabricator]], qui sont trois lieux entièrement dédiés aux maintenances techniques sur l'ensemble du quartier. Quant aux aspects administratifs, c'est dans le bâtiment [[metawiki:main page|Méta-Wiki]] que s'opère la gouvernance générale du quartier et dans le bâtiment [[otrswiki:Main page|Wikimedia VRT]] que le traitement des courriers est effectué. À la suite de quoi, il ne reste plus qu'à citer le bâtiment ''[[outreach:main page|Wikimedia outreach]],'' pour des initiatives de sensibilisation au mouvement, et le bâtiment [https://diff.wikimedia.org Diff Wikimedia], pour des publications d'articles à son sujet. Le plus utopique dans tout cela, c'est qu'en dehors de certains aspects techniques, tous ces bâtiments sont exclusivement régis par des communautés bénévoles et toujours prêtes à accueillir de nouveaux membres. Les seuls immeubles du quartier qui diffèrent de ce principe sont les bâtiments vitrines de la Fondation Wikimédia et des autres associations Wikimédia qui engagent du personnel. Quant au conseil d'administration de la Fondation, il possède, lui aussi, son propre bâtiment, dont la modification des pièces est réservée à ces élus et aux employés qui les aident dans leurs tâches. Cela pour garantir l'officialité de ce qui s'y passe. Finalement et face à tant d'utopies, il est tentant de se demander comment tout cela fut rendu possible. La réponse à cette question n'est pas courte. Elle demande de parcourir tout un pan de l'histoire de la révolution numérique, depuis la [[w:Contre-culture_des_années_1960|contre-culture des années 1960]] jusqu'à nos jours. On y découvre alors que les pionniers du réseau Internet et de ses applications étaient des chercheurs et étudiants en informatique fortement influencés par les mouvements idéologiques mondiaux. Ceux qui, entre autres, ont contribué à l'avènement de [[w:mai_68|mai 68]] en France. De toutes ces impulsions naîtra en effet la philosophie de partage, de liberté, de décentralisation et ce mode d’organisation tout à fait spécifique, dont a hérité le mouvement Wikimédia. Cela commence par [[w:Internet|Internet]], un réseau mondial de communication en libre accès, puis par le développement du ''[[w:World_Wide_Web|World Wide Web]]'', qui a grandement simplifié les interactions humaines à l’échelle planétaire. Cela se poursuit ensuite par l'arrivée des sites web que l'on peut modifier à l'aide d’un simple navigateur et qui furent à l'origine de ce que l'on a appelé le [[w:Web_2.0|Web 2.0]]. Or, parmi ces logiciels se trouvent les [[w:fr:Moteur de Wiki|moteurs de Wiki]], dont le plus puissant d’entre eux, [[w:MediaWiki|MediaWiki]], est un [[Logiciels libres|logiciel libre]] développé par la Fondation Wikimédia. Le moment est donc venu d'en savoir un peu plus sur ces logiciels et sur le [[w:Mouvement_du_logiciel_libre|mouvement du logiciel libre]] qui s'est constitué tout autour.{{AutoCat}} irgjxlqdomsz9b4grvt4a37o1m8m9e2 Le mouvement Wikimédia 0 80088 764195 756985 2026-04-21T08:35:37Z Lionel Scheepmans 20012 764195 wikitext text/x-wiki <!--<noinclude>{{NavDébut|book={{PAGENAME}}|page=Avant-propos|pageText=Démarrer}}</noinclude>--> <noinclude>{{NavDébut|book=Le mouvement Wikimédia|page=Avant-propos|pageText=Démarrer}}</noinclude> {{Page de garde |image=Photo de couverture du wikilivre Le mouvement Wikimédia.jpg |description=<big>'''{{Centrer|Comment rendre la connaissance fiable par le partage, la liberté et l'équité}}'''</big><br/> En lien avec la révolution numérique et la [[W:Contre-culture des années 1960|contre-culture des années 1960]], ce livre retrace les origines du [[W:Mouvement Wikimédia|mouvement Wikimédia]], avant d'en présenter l'organisation. Issu de la première partie d'une [[v:fr:recherche:Imagine_un_monde|thèse de doctorat rédigée sur Wikiversité]], il est accessible sur Wikilivres, chapitre par chapitre, ou [[Le mouvement Wikimédia/Version complète| en version complète sur une seule page]] que l'on peut imprimer avec son navigateur web. Cet ouvrage est également disponible au format [https://upload.wikimedia.org/wikipedia/commons/8/88/Le_mouvement_Wikim%C3%A9dia_%E2%80%94_Wikilivres.pdf PDF] et bientôt aux formats [https://upload.wikimedia.org/wikipedia/commons/1/15/Le_mouvement_Wikim%C3%A9dia.oga audio], EPUB et livre de poche. Dans le but d'améliorer son contenu, les questions et les commentaires sont les bienvenus sur [[discussion:Le mouvement Wikimédia|cette page de discussion]]. |avancement=Terminé |cdu= * {{CDU item|3/31/316|316.3/316.35}} {{Moteur}} {{Version complète}} {{Statistiques}} }} == Quatrième de couverture == {{/Quatrième de couverture}} == Sommaire == {{/Sommaire}} [[Catégorie:Livres]] [[Catégorie:Étude du cyber-mouvement du logiciel libre (livre)]] [[Catégorie:Anthropologie]] [[Catégorie:Sciences humaines]] [[Catégorie:Livres terminés]] [[Catégorie:Le mouvement Wikimédia (livre)]] [[Catégorie:Livres en vitrine]] [[Catégorie:Le mouvement Wikimédia]] sqqb05m50laeevh9a7umffyogptq14w 764196 764195 2026-04-21T08:36:17Z Lionel Scheepmans 20012 764196 wikitext text/x-wiki <!--<noinclude>{{NavDébut|book={{PAGENAME}}|page=Avant-propos|pageText=Démarrer}}</noinclude>--> <noinclude>{{NavDébut|book=Le mouvement Wikimédia|page=Avant-propos|pageText=Démarrer}}</noinclude> {{Page de garde |image=Photo de couverture du wikilivre Le mouvement Wikimédia.jpg |description=<big>'''{{Centrer|Comment rendre la connaissance fiable par le partage, la liberté et l'équité ?}}'''</big><br/> En lien avec la révolution numérique et la [[W:Contre-culture des années 1960|contre-culture des années 1960]], ce livre retrace les origines du [[W:Mouvement Wikimédia|mouvement Wikimédia]], avant d'en présenter l'organisation. Issu de la première partie d'une [[v:fr:recherche:Imagine_un_monde|thèse de doctorat rédigée sur Wikiversité]], il est accessible sur Wikilivres, chapitre par chapitre, ou [[Le mouvement Wikimédia/Version complète| en version complète sur une seule page]] que l'on peut imprimer avec son navigateur web. Cet ouvrage est également disponible au format [https://upload.wikimedia.org/wikipedia/commons/8/88/Le_mouvement_Wikim%C3%A9dia_%E2%80%94_Wikilivres.pdf PDF] et bientôt aux formats [https://upload.wikimedia.org/wikipedia/commons/1/15/Le_mouvement_Wikim%C3%A9dia.oga audio], EPUB et livre de poche. Dans le but d'améliorer son contenu, les questions et les commentaires sont les bienvenus sur [[discussion:Le mouvement Wikimédia|cette page de discussion]]. |avancement=Terminé |cdu= * {{CDU item|3/31/316|316.3/316.35}} {{Moteur}} {{Version complète}} {{Statistiques}} }} == Quatrième de couverture == {{/Quatrième de couverture}} == Sommaire == {{/Sommaire}} [[Catégorie:Livres]] [[Catégorie:Étude du cyber-mouvement du logiciel libre (livre)]] [[Catégorie:Anthropologie]] [[Catégorie:Sciences humaines]] [[Catégorie:Livres terminés]] [[Catégorie:Le mouvement Wikimédia (livre)]] [[Catégorie:Livres en vitrine]] [[Catégorie:Le mouvement Wikimédia]] bfaj0e9fl13cg6fsnx68f94d93y2g19 Discussion Wikilivres:Le Bistro/2026 5 83406 764088 763589 2026-04-20T15:00:25Z MediaWiki message delivery 36013 /* Actualités techniques n° 2026-17 */ nouvelle section 764088 wikitext text/x-wiki == Actualités techniques n° 2026-03 == <section begin="technews-2026-W03"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/03|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * La Fondation Wikimedia a publié des questions directrices pour son plan annuel de juillet 2026 à juin 2027 sur les plateformes [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] et ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. Celles-ci portent sur les tendances mondiales, une expérimentation plus rapide et plus constructive, un meilleur accompagnement des nouveaux contributeurs, le renforcement du rôle des éditeurs et des utilisateurs avancés, l'amélioration de la collaboration entre les projets, ainsi que le développement et la fidélisation du lectorat. Des commentaires et suggestions sont les bienvenus sur la [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|page de discussion]]. '''Actualités pour la contribution''' * Dans le cadre des travaux en cours de l'équipe technique communautaire sur le projet [[m:Special:MyLanguage/Community Wishlist/W372|Listes de surveillance multiples]], l'affichage de [[Special:EditWatchlist|Modifier la liste de surveillance]] sera mis à jour entant que qu'une première étape vers la prise en charge de plusieurs listes de surveillance. De plus, la pagination de [[Special:Search|Recherche]] sera également mise à jour, dans le cadre du travail sur le souhait [[m:Special:MyLanguage/Community Wishlist/W186|Refonte de la pagination / navigation des pages]]. [https://phabricator.wikimedia.org/T411596] * [[m:Special:GlobalWatchlist|La Liste de Surveillance Globale]] est une [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] de MediaWiki qui vous permet de voir vos listes de surveillance provenant de différents wikis sur la même page. Il a récemment été mis à jour pour ressembler davantage à la [[Special:Watchlist|Liste de surveillance]] régulière, par exemple en le préparant pour les comptes temporaires dans le masquage IP (y compris le réacheminement des liens des utilisateurs vers les pages de contributions), en mettant les titres de page en gras et en ouvrant les liens dans les résumés d'édition et les balises dans de nouveaux onglets du navigateur. [https://phabricator.wikimedia.org/T398361][https://phabricator.wikimedia.org/T298919][https://phabricator.wikimedia.org/T273526][https://phabricator.wikimedia.org/T286309] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:28|la tâche soumise|les {{formatnum:28}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:28||s}} la semaine dernière]]. Par exemple, le problème selon lequel les blocs globaux ne disposaient pas de l'option permettant de désactiver l'envoi d'e-mails a maintenant été résolu et sera disponible à l'utilisation à partir de la semaine du 13 janvier. [https://phabricator.wikimedia.org/T401293] '''Actualités pour la contribution technique''' * L'[[mw:Special:MyLanguage/VisualEditor/Citation tool|outil de citation VisualEditor]] et les [[mw:Special:MyLanguage/Help:Reference Previews|Aperçus de référence]] prennent désormais en charge "carte" comme type de référence. [https://phabricator.wikimedia.org/T411083] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.10|MediaWiki]]/[[mw:MediaWiki 1.46/wmf.11|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/03|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W03"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 12 janvier 2026 à 20:33 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29907192 --> == Thank You for Last Year – Join Wiki Loves Ramadan 2026 == Dear Wikimedia communities, We hope you are doing well, and we wish you a happy New Year. ''Last year, we captured light. This year, we’ll capture legacy.'' In 2025, communities around the world shared the glow of Ramadan nights and the warmth of collective iftars. In 2026, ''Wiki Loves Ramadan'' is expanding, bringing more stories, more cultures, and deeper global connections across Wikimedia projects. We invite you to explore the ''Wiki Loves Ramadan 2026'' [[m:Special:MyLanguage/Wiki Loves Ramadan 2026|Meta page]] to learn how you can participate and [[m:Special:MyLanguage/Wiki Loves Ramadan 2026/Participating communities|sign up]] your community. 📷 ''Photo campaign on '' [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan 2026|Wikimedia Commons]] If you have questions about the project, please refer to the FAQs: * [[m:Special:MyLanguage/Wiki Loves Ramadan/FAQ/|Meta-Wiki]] * [[c:Special:MyLanguage/Commons:Wiki Loves Ramadan/FAQ|Wikimedia Commons]] ''Early registration for updates is now open via the '''[[m:Special:RegisterForEvent/2710|Event page]]''''' ''Stay connected and receive updates:'' * [https://t.me/WikiLovesRamadan Telegram channel] * [https://lists.wikimedia.org/postorius/lists/wikilovesramadan.lists.wikimedia.org/ Mailing list] We look forward to collaborating with you and your community. '''The Wiki Loves Ramadan 2026 Organizing Team''' 16 janvier 2026 à 20:44 (CET) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29879549 --> == <span lang="en" dir="ltr">Tech News: 2026-04</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W04"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/04|Translations]] are available. '''Updates for editors''' * The tray shown on [[Special:Diff|Special:Diff]] in mobile view has been redesigned. It is now collapsed by default, and incorporates a link to undo the edit being viewed, making it easier for mobile editors and reviewers to take action while keeping the interface uncluttered. [https://phabricator.wikimedia.org/T402297] * [[m:Special:GlobalWatchlist|The Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continues to improve — it now automatically determines the text direction (ensuring correct display of sites with unusual domain names) and shows detailed descriptions for log actions. Later this week, a new permanent link for page creations and CSS classes for each entry element will be added. [https://phabricator.wikimedia.org/T412505][https://phabricator.wikimedia.org/T287929][https://phabricator.wikimedia.org/T262768][https://phabricator.wikimedia.org/T414135] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:32}} community-submitted {{PLURAL:32|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the previously observed issue in Vector 2022, where anchor link targets were obscured by the sticky header, has now been addressed. [https://phabricator.wikimedia.org/T406114] '''Updates for technical contributors''' * As mentioned in the [[m:Special:MyLanguage/Tech/News/2025/44|October 2025 deprecation announcement]], MediaWiki Interfaces team will begin sunsetting all transform endpoints containing a trailing slash from the MediaWiki REST API the week of January 26. Changes are expected to roll out to all wikis on or before January 30th. All API users currently calling them are encouraged to transition to the non-trailing slash versions. Both endpoint variations can be found, compared, and tested using the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox]. If you have questions or encounter any problems, please file a ticket in Phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * Interactive reference documentation for the [[mw:Special:MyLanguage/Wikimedia REST API|Wikimedia REST API]] has moved. Requests to API docs previously hosted through [[mw:Special:MyLanguage/RESTBase|RESTBase]] (e.g.: <code dir=ltr>https://en.wikipedia.org/api/rest_v1/</code>) are now redirected to the [[w:en:Special:RestSandbox|REST Sandbox]]. * The [[mw:Special:MyLanguage/Wikidata Platform|WMF Wikidata Platform team]] (WDP) has published its [[d:Special:MyLanguage/Wikidata:Wikidata Platform team/Newsletter|January 2026 newsletter]]. It includes updates on the legacy full-graph endpoint decommissioning, the User-Agent policy change, the monthly Blazegraph migration office hours, and efforts to reduce regressions caused by the legacy endpoint shutdown. As a reminder, you can [[m:Special:MyLanguage/Global message delivery/Targets/WDP team updates|subscribe to the WDP newsletter]]! * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.12|MediaWiki]] '''Meetings and events''' * The [[mw:Wikimedia Hackathon Northwestern Europe 2026|Wikimedia Hackathon Northwestern Europe 2026]] will take place on 13-14 March 2026 in Arnhem, the Netherlands. Applications opened mid-December and will close soon or when capacity is reached. It's a two-day, technically oriented hackathon bringing together Wikimedians from the region. Hope to see you there! '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/04|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W04"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 19 janvier 2026 à 21:29 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29943403 --> == Révision annuelle du code universel de conduite et des lignes directrices de l'application == <section begin="announcement-content" /> Nous vous informons que la période de relecture annuelle du Code de conduite universel et des règles d'applications est actuellement ouverte. Vous pouvez faire vos commentaires sur les modifications que vous souhaitez apporter jusqu'au 9 février 2026. C'est la première d'une série d'étapes nécessaires pour la révision annuelle. Vous trouverez [[m:Special:MyLanguage/Universal Code of Conduct/Annual review/2026|d'autres informations et les discussions auxquelles participer sur la page UCoC de Meta]]. Le [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee|Comité de coordination du code universel de conduite]] (U4C &mdash; Universal Code of Conduct Coordinating Committee) est un groupe global dont le rôle est de fournir une implémentation équitable et cohérente de l'UCoC. Cette relecture annuelle a été envisagée et mise en place par l'U4C. Pour plus d'informations et les responsabilités de l'U4C, veuillez lire la [[m:Special:MyLanguage/Universal Code of Conduct/Coordinating Committee/Charter|Charte de l'U4C]]. Veuillez partager ces informations avec les autres membres concernés de votre communauté. -- En coopération avec l'U4C, [[m:User:Keegan (WMF)|Keegan (WMF)]] ([[m:User talk:Keegan (WMF)|discussion]])<section end="announcement-content" /> 19 janvier 2026 à 22:01 (CET) <!-- Message envoyé par User:Keegan (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Global_message_delivery&oldid=29905753 --> == Actualités techniques n° 2026-05 == <section begin="technews-2026-W05"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/05|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * La Fondation Wikimedia invite à donner des commentaires sur [[m:Special:MyLanguage/Product and Technology Advisory Council/Year1 Reflections and Proposed Way Forward 2026 Update|l’avenir proposé]] du [[:m:Special:MyLanguage/Product and Technology Advisory Council|Conseil consultatif des produits et technologies]] jusqu’au 28 février. * Tous les utilisateurs disposant d'un compte enregistré peuvent désormais utiliser des clés d'accès pour la [[m:Special:MyLanguage/Help:Two-factor authentication|double authentification]] (2FA). Les clés d'accès sont un moyen simple de se connecter sans utiliser un second appareil. Elles vérifient l'identité de l'utilisateur à l'aide d'une empreinte digitale, d'une reconnaissance faciale ou d'un code PIN. Pour configurer une clé d'accès, configurez d'abord une méthode 2FA classique. Actuellement, pour se connecter avec une clé d'accès, les utilisateurs doivent également utiliser un mot de passe. Plus tard ce trimestre, la connexion sans mot de passe permettra aux utilisateurs de se connecter d'un simple clic avec une clé d'accès. Les utilisateurs disposant de droits avancés devront également avoir la 2FA activée. Cela fait partie du projet [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security|Sécurité du compte]]. * Les contributeurs non enregistrés sur des IP bloquées ou des plages d'IP bloquées peuvent désormais interagir sur le wiki pour faire appel d'un blocage en créant un compte temporaire afin de contester un blocage sur la page de discussion de l'utilisateur, sauf si l'option « empêcher cet utilisateur de modifier sa propre page de discussion » est activée. Cela résout le problème des utilisateurs déconnectés incapables d'utiliser le processus de déblocage par défaut via la page de discussion de l'utilisateur. [https://phabricator.wikimedia.org/T398673] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:20|la tâche soumise|les {{formatnum:20}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:20||s}} la semaine dernière]]. Par exemple, la description des méthodes d'authentification à deux facteurs (2FA) sur la page de gestion a été mise à jour. Il est désormais plus clair et plus facile pour les utilisateurs à comprendre et à utiliser. [https://phabricator.wikimedia.org/T332385] '''Actualités pour la contribution technique''' * Une nouvelle variable AbuseFilter, <code>account_type</code>, a été ajoutée pour fournir un moyen fiable de déterminer le type de compte créé dans les actions <code>createaccount</code> et <code>autocreateaccount</code>. Dans le cadre de ce changement, la variable <code>accountname</code> a été renommée en <code>account_name</code>, et <code>accountname</code> est désormais obsolète. Les gestionnaires de filtres doivent mettre à jour tous les filtres qui utilisent des vérifications de type de compte codées en dur ou la variable obsolète. [https://phabricator.wikimedia.org/T414049] * Les vignettes d'images demandées dans des tailles non standard, et en utilisant des méthodes non standard telles que les requêtes directes à <code dir=ltr><nowiki>upload.wikimedia.org/…</nowiki></code>, cesseront de fonctionner dans un proche avenir. Ce changement vise à prévenir les abus externes continus par des robots et des aspirateurs web. Certains utilisateurs ayant des CSS/JS personnalisés, les administrateurs d'interface qui peuvent corriger les gadgets et les thèmes locaux, ainsi que les auteurs d'outils, devront mettre à jour leur code pour utiliser des tailles de vignettes standard. [[phab:T414805|Des détails, des liens de recherche et des exemples de correction sont disponibles dans la tâche]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.13|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/05|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W05"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 26 janvier 2026 à 22:17 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=29969530 --> == <span lang="en" dir="ltr">Tech News: 2026-06</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W06"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/06|Translations]] are available. '''Updates for editors''' * The "{{int:pageinfo-toolboxlink}}" feature, which gives validating information about a page ([{{fullurl:{{FULLPAGENAME}}|action=info}} example]), now automatically includes a table of contents. If there is a local [[{{ns:8}}:Pageinfo-header]] page created by individual users, it can now be removed. [https://phabricator.wikimedia.org/T363726] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, VisualEditor previously added bold or italic formatting inside link descriptions, making the wikicode complex. This has now been fixed. [https://phabricator.wikimedia.org/T409669] '''Updates for technical contributors''' * There was no XML dump on 20 January. Additionally, from now on, dumps will be generated once per month only. [https://phabricator.wikimedia.org/T414389] * The MediaWiki Interfaces team removed support for all transform endpoints containing a trailing slash from the [https://www.mediawiki.org/wiki/Special:MyLanguage/API:REST%20API MediaWiki REST API]. All API users currently calling those endpoints are encouraged to transition to the non-trailing slash versions. If you have questions or encounter any problems, please file a ticket in phabricator to the [https://phabricator.wikimedia.org/project/view/6931/ #MW-Interfaces-Team board]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.14|MediaWiki]] '''Weekly highlight''' * Users are reminded that the Wikimedia Foundation has shared some guiding questions for the July 2026–June 2027 Annual Plan on [[m:Special:MyLanguage/Wikimedia Foundation Annual Plan/2026-2027/Product & Technology OKRs|Meta]] and ''[[diffblog:2025/12/10/shaping-wikimedia-foundations-2026-2027-annual-goals-key-questions-for-the-wikimedia-movement/|Diff]]''. These focus on global trends, faster and healthier experimentation, better support for newcomers, strengthening editors and advanced users, improving collaboration across projects, and growing and retaining readership. Feedback and ideas are welcome on the [[m:Talk:Wikimedia Foundation Annual Plan/2026-2027|talk page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/06|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W06"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 février 2026 à 18:43 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30000986 --> == Actualités techniques n° 2026-07 == <section begin="technews-2026-W07"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/07|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] Les contributeurs connectés qui gèrent de grandes ou complexes listes de suivi peuvent désormais organiser et filtrer les pages surveillées de manière à améliorer leurs flux de travail grâce à la nouvelle fonctionnalité [[mw:Special:MyLanguage/Help:Watchlist labels|Étiquettes de liste de suivi]]. En ajoutant des étiquettes personnalisées (par exemple : pages que vous avez créées, pages surveillées pour vandalisme, ou pages de discussion), les utilisateurs peuvent identifier plus rapidement ce qui nécessite une attention, réduire la charge cognitive et répondre plus efficacement. Cela améliore l'utilisabilité de la liste de suivi, en particulier pour les éditeurs très actifs. * Une nouvelle fonctionnalité disponible sur [[Special:Contributions|Special:Contributions]] montre [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts|des comptes temporaires]] qui sont probablement utilisés par la même personne, et rend ainsi le patrouillage moins chronophage. En vérifiant les contributions d'un compte temporaire, les utilisateurs ayant accès aux adresses IP des comptes temporaires peuvent désormais avoir une vue des contributions des comptes temporaires associés. La fonctionnalité recherche toutes les adresses IP associées à un compte temporaire donné pendant la période de conservation des données et affiche toutes les contributions de tous les comptes temporaires ayant utilisé ces adresses IP. [[mw:Special:MyLanguage/Trust and Safety Product/Temporary Accounts#February 2026: Improvements to the patroller tooling|Plus...]] [https://phabricator.wikimedia.org/T415674] * Lorsque les éditeurs prévisualisent une modification de wikitexte, la boîte de rappel indiquant qu'ils ne voient qu'une prévisualisation (qui est affichée en haut) a désormais un fond gris/neutre au lieu d'un fond jaune/d'avertissement. Cela facilite la distinction entre les notes de prévisualisation et les avertissements réels (par exemple, les conflits de modification ou les cibles de redirection problématiques), qui seront désormais affichés dans des boîtes d'avertissement ou d'erreur séparées. [https://phabricator.wikimedia.org/T414742] * La [[m:Special:GlobalWatchlist|Liste de suivi globale]] vous permet de consulter vos listes de suivi provenant de plusieurs wikis sur une seule page. L' [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] continue de s'améliorer — elle prend désormais en charge correctement plus d'un site Wikibase, par exemple à la fois [[d:|Wikidata]] et [[testwikidata:|testwikidata]]. De plus, des problèmes concernant la direction du texte ont été résolus pour les utilisateurs qui préfèrent Wikidata ou d'autres sites Wikibase dans des langues de droite à gauche (RTL). [https://phabricator.wikimedia.org/T415440][https://phabricator.wikimedia.org/T415458] * <span lang="en" dir="ltr" class="mw-content-ltr">The automatic "magic links" for ISBN, RFC, and PMID numbers have been [[mw:Special:MyLanguage/Help:Magic links|deprecated in wikitext since 2021]] due to inflexibility and difficulties with localization. Several wikis have successfully replaced RFC and PMID magic links with equivalent external links, but a template was often required to replace the functionality of the ISBN magic link. There is now a new [[mw:Special:MyLanguage/Help:Magic words#isbn|built-in parser function]] <code dir=ltr><nowiki>{{#isbn}}</nowiki></code> available to replace the basic functionality of the ISBN magic link. This makes it easier for wikis who wish to migrate off of the deprecated magic link functionality to do so.</span> [https://phabricator.wikimedia.org/T145604] * Deux nouveaux wikis ont été créés : ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q35401|Jju]] ([[w:kaj:|<code>w:kaj:</code>]]) [https://phabricator.wikimedia.org/T413283] ** un {{int:project-localized-name-group-wikipedia}} dans [[d:Q1186896|Nawat]] ([[w:ppl:|<code>w:ppl:</code>]]) [https://phabricator.wikimedia.org/T413273] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. '''Actualités pour la contribution technique''' * Un nouveau groupe d'utilisateurs global a été créé : [[{{int:grouppage-local-bot}}|{{int:group-local-bot}}]]. Il sera utilisé en interne par le logiciel pour permettre aux robots communautaires de contourner les limites de débit appliquées aux [[w:en:Web_scraping|web scrapers]] abusifs. Les comptes approuvés en tant que robots sur au moins un wiki Wikimedia seront automatiquement ajoutés à ce groupe. Cela ne changera pas les autorisations dont dispose le robot. [https://phabricator.wikimedia.org/T415588] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.15|MediaWiki]] '''Rencontres et évènements''' * La [[mw:Special:MyLanguage/MediaWiki Users and Developers Conference Spring 2026|Conférence des utilisateurs et des développeurs de MediaWiki, Printemps 2026]] se tiendra du 25 au 27 mars à Salt Lake City, États-Unis. Cet événement est organisé par et pour la communauté MediaWiki de tiers. Vous pouvez proposer des sessions et vous inscrire pour y assister. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/AZBWVI46SDEB65PGR5J6E4TYOQQEZXM7/] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/07|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W07"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 10 février 2026 à 00:30 (CET) <!-- Message envoyé par User:Quiddity (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30026671 --> == Actualités techniques n° 2026-08 == <section begin="technews-2026-W08"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/08|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * <span class="mw-translate-fuzzy">L'[[mw:Special:MyLanguage/Wikimedia Site Reliability Engineering|équipe SRE]] va procéder au nettoyage d'[[m:Special:MyLanguage/Etherpad|Etherpad]], l'éditeur web open source de documents collaboratifs en temps réel. Tous les blocs-notes seront définitivement supprimés après le 30 avril 2026 – si des projets de migration sont encore en cours à cette date, l'équipe pourra réexaminer la date au cas par cas. Veuillez effectuer des sauvegardes locales de tout contenu que vous souhaitez conserver, car les données supprimées ne pourront pas être récupérées. Ce nettoyage permet de réduire la taille de la base de données et l'empreinte de l'infrastructure. Etherpad continuera de prendre en charge la collaboration en temps réel, mais le stockage à long terme n'est plus assuré. D'autres nettoyages pourront avoir lieu ultérieurement sans préavis.</span> [https://phabricator.wikimedia.org/T415237] '''Actualités pour la contribution''' * L'équipe de Recherche d'Informations lancera une [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|expérimentation sur l'application mobile Android]], afin de tester des fonctionnalités de recherche hybrides capables de gérer à la fois les requêtes sémantiques et par mots-clés. L'amélioration de la recherche sur la plateforme permettra aux lecteurs de trouver plus facilement ce qu'ils cherchent, directement sur Wikipédia. L'expérimentation sera d'abord lancée sur Wikipédia en grec fin février, puis sur les versions anglaise, française et portugaise en mars. [https://diff.wikimedia.org/2026/01/08/semantic-search-making-it-easier-to-find-the-information-readers-want/ En savoir plus] sur le blog ''Diff''. [https://www.mediawiki.org/wiki/Readers/Information_Retrieval] * L'équipe « Croissance des lecteurs » mènera [[mw:Special:MyLanguage/Readers/Reader Growth/WE3.10.2 Mobile Table of Contents|une expérience]] auprès des utilisateurs de la version mobile du site web qui ajoute une table des matières et développe automatiquement toutes les sections des articles, afin de mieux comprendre les problèmes de navigation qu'ils rencontrent. Le test sera disponible sur les versions arabe, chinoise, anglaise, française, indonésienne et vietnamienne de Wikipedia. * Auparavant, les notifications ([[{{ns:8}}:Sitenotice]] et [[{{ns:8}}:Anonnotice]]) du site ne s'affichaient que sur la version ordinateur. Maintenant, elles s'afficheront désormais sur toutes les plateformes. Les utilisateurs mobiles verront ces notifications. Les administrateurs du site doivent être prêts à tester et à corriger les notifications sur les appareils mobiles afin d'éviter toute interférence avec les articles. Pour désactiver ces notifications, les administrateurs d'interface peuvent ajouter <code dir="ltr">#siteNotice { display: none; }</code> à [[{{ns:8}}:Minerva.css]]. [https://phabricator.wikimedia.org/T138572][https://phabricator.wikimedia.org/T416644] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:19|la tâche soumise|les {{formatnum:19}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:19||s}} la semaine dernière]]. Par exemple, un problème concernant la section ''[[Special:RecentChanges|Spécial:Modifications récentes]]'' a été résolu. Auparavant, cliquer sur « Masquer » dans les filtres actifs entraînait la disparition du bouton « Afficher les nouvelles modifications depuis… », alors qu'il aurait dû rester visible. Ce bouton fonctionne désormais correctement. [https://phabricator.wikimedia.org/T406339] '''Actualités pour la contribution technique''' * Une nouvelle documentation est désormais disponible pour aider les rédacteurs à déboguer les fonctionnalités de recherche interne. Elle facilite le dépannage lorsque des pages n'apparaissent pas dans les résultats, lorsque le classement semble inattendu et lorsqu'il est nécessaire d'inspecter le contenu indexé, ce qui permet de mieux comprendre et d'analyser le comportement de la recherche. [[mw:Help:CirrusSearch/Debug|En savoir plus]]. [https://phabricator.wikimedia.org/T411169] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.16|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/08|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W08"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 février 2026 à 20:17 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30086330 --> == <span lang="en" dir="ltr">Tech News: 2026-09</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W09"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/09|Translations]] are available. '''Weekly highlight''' * [[mw:Special:MyLanguage/Edit check/Reference Check|Reference Check]] has been deployed to English Wikipedia, completing its rollout across all Wikipedias. The feature prompts newcomers to add a citation before publishing new content, helping reduce common citation-related reverts and improve verifiability. In A/B testing, the impact was substantial: newcomers shown Reference Check were approximately 2.2 times more likely to include a reference on desktop and about 17.5 times more likely on mobile web. [https://analytics.wikimedia.org/published/reports/editing/reference_check_ab_test_report_final_2025.html] '''Updates for editors''' * The [[mw:Special:MyLanguage/Extension:InterwikiSorting|InterwikiSorting extension]], which allowed for the [[m:Special:MyLanguage/Interwiki sorting order|sorting of interwiki links]], has been undeployed from Wikipedia. As a result, editors who had enabled interwiki link sorting in non-compact mode (full list format) will now see links reordered. The links moving forward will be listed in the alphabetical order of language code. [https://phabricator.wikimedia.org/T253764] * Later this week, people who are editing a page-section using the mobile visual editor, will notice a new "Edit full page" button. When tapped, you will be able to edit the entire article. This helps when the change you want to make is outside the section you initially opened. [https://phabricator.wikimedia.org/T387175][https://phabricator.wikimedia.org/T409112] * [[mw:Special:MyLanguage/Readers/Reader Experience|The Reader Experience team]] is inviting editors to assess whether dark mode should still be considered "beta" on their wiki, based on their experience of how well it functions on desktop and mobile. If the feature is deemed mature, editors can update the interface messages in <code dir=ltr>MediaWiki:skin-theme-description</code> and <code dir=ltr>MediaWiki:Vector-night-mode-beta-tag</code> to indicate that dark mode is ready and no longer considered beta. * The improved [[mw:Wikimedia_Apps/Team/iOS/Activity_Tab|Activity tab]] which displays user-insights is now available to all users of the Wikipedia iOS app (version 7.9.0 and later). Following earlier A/B testing that showed higher account creation among users with access to the feature, it has been rolled out to 100% of users along with some updates. The Activity tab now shows your edited articles in the timeline, offers editing impact insights like contribution counts and article view trends, and customization options to improve in-app experience for users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:21}} community-submitted {{PLURAL:21|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, a bug that prevented [[mw:Special:MyLanguage/Extension:DiscussionTools|DiscussionTools]] from working on mobile has now been fixed, restoring full functionality. [https://phabricator.wikimedia.org/T415303] '''Updates for technical contributors''' * The [[m:Special:GlobalWatchlist|Global Watchlist]] lets you view your watchlists from multiple wikis on one page. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] that makes this possible continues to improve. The latest upgrade is the inclusion of a [[mw:Extension:GlobalWatchlist#hook|new hook]], <code dir=ltr>ext.globalwatchlist.rebuild</code>, which fires after each watchlist rebuild. This allows you to run gadgets and user scripts for the Special page. [https://phabricator.wikimedia.org/T275159] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.17|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/09|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W09"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 février 2026 à 20:03 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30119102 --> == Actualités techniques n° 2026-10 == <section begin="technews-2026-W10"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/10|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments|mode Anniversaire]] Wikipedia 25 est maintenant disponible sur Wikipédia en français, anglais, betawi, breton, chinois, espagnol, gorontalo, indonésien, italien, luxembourgeois, madurais, néerlandais, sicilien, tchèque, thaï et vietnamien ! Cette campagne à temps limitée célèbre 25 ans de Wikipédia avec une mascotte : « Baby Globe », disponible sous la forme d'un réglage. Lorsque ce réglage est activé, Baby Globe est montrée sur [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments/article configuration|environ 2 500 articles]], attendant d'être découverte par des lecteurs. Chaque communauté peut choisir d'activer le mode Anniversaire par consensus et en demandant à un administrateur de le rendre disponible et de le personaliser via une [[m:Special:MyLanguage/Wikipedia 25/Easter egg experiments#Community Configuration Demo|configuration]] sur le wiki local. '''Actualités pour la contribution''' * Le [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|sous-référencement]], une nouvelle fonctionalité pour réutiliser des références avec des détails différents est maintenant disponible sur Wikipédia en suédois, polonais et [[:phab:T418209|quelques autres]]. Vous pouvez [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing#test|essayer la fonctionalité]] sur ces projets ou sur testwiki et [https://en.wikipedia.beta.wmcloud.org/wiki/Sub-referencing betawiki]. Les retours des premiers essais sur Wikipédia en allemand ont été [[:m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing/Learnings|publiés dans un rapport]]. Contactez l'équipe de Wikimédia Allemagne si vous êtes [[:m:Talk:WMDE Technical Wishes/Sub-referencing#Pilot wikis|intéressés pour devenir un wiki pilote]]. * La [[mw:Special:MyLanguage/Help:Edit check#Paste check|vérification du collage clavier]] sera disponible sur tous les Wikipédias cette semaine. Cette fonctionalité avertit les nouveaux contributeurs qui collent du texte qu'ils n'ont probablement pas écrit de vérifier si laisser celui-ci risque de causer une violation du droit d'auteur. La vérification du collage clavier [[mw:Special:MyLanguage/Edit check/Tags|marque]] toutes les modifications où l'avertissement a été montré pour permettre leur vérification. Les administrateurs locaux peuvent configurer les différents aspects de cette fonctionalité à travers [[{{#special:EditChecks}}]]. Des [[mw:Special:MyLanguage/Edit check/Paste Check#A/B Experiment|études]] sur 22 wikis ont montré que cette vérification permet une réduction de 18% des annulations comparé au groupe de contrôle. Les traducteurs peuvent [https://translatewiki.net/w/i.php?title=Special%3ATranslate&group=ext-visualeditor-ve-mw-editcheck&filter=&optional=1&action=translate aider à traduire] cette fonctionalité. * <span lang="en" dir="ltr" class="mw-content-ltr">The [[mw:Special:MyLanguage/Readers/Reader Experience|Reader Experience team]] will be standardizing the user menu in the top right for all mobile users so that it is closer to the desktop experience. Currently this user menu is only visible to users with Advanced Mobile Controls (AMC) turned on. The only change is that a couple buttons previously in the left-side menu will move to the top right for users who do not have AMC turned on. This change is expected to go out March 9 and seeks to improve the user interface.</span> [https://phabricator.wikimedia.org/T413912] * À partir de la semaine du 2 mars, les emails envoyés lorsqu'une adresse email a été ajoutée, supprimée ou changée pour un compte changera pour adopter un formattage HTML beaucoup plus agréable et plus clair que le texte brut précédent. [https://phabricator.wikimedia.org/T410807] * Les notifications sont actuellement limitées à 2 000 entrées historiques par utilisateur et remontent à 2013 lorsque la fonctionnalité a été publiée. Le système va être modifié pour ne stocker que les notifications des 5 dernières années, mais jusqu'à 10 000 d'entre elles. Cela contribuera à la santé à long terme des infrastructures et à empêcher que les notifications plus récentes disparaissent trop tôt. [https://phabricator.wikimedia.org/T383948] * <span lang="en" dir="ltr" class="mw-content-ltr">The [[m:Special:GlobalWatchlist|Global Watchlist]] which lets you view your watchlists from multiple wikis on a single page continues to see improvements. The latest update improves label usage experience. The [[mw:Special:MyLanguage/Extension:GlobalWatchlist|extension]] now allows activating the [[mw:Special:MyLanguage/Manual:Language#Fallback languages|language fallback system]] for Wikidata items without labels in the viewed language, and showing those labels in the user’s preferred Wikidata language if no <code dir=ltr>uselang=</code> URL parameter is provided.</span> [https://phabricator.wikimedia.org/T373686][https://phabricator.wikimedia.org/T416111] * L'équipe Wikipédia Android a commencé un test beta de la [[mw:Special:MyLanguage/Readers/Information Retrieval/Phase 1|recherche hybride]] sur Wikipédia en grec. Cette recherche hybride supporte les requêtes sémantique et par mot clés, permettant aux utilisateurs de trouver ce qu'ils cherchent plus facilement. * Pour des raisons de sécurité, les membres de certains groupes sont [[m:Special:MyLanguage/Mandatory two-factor authentication for users with some extended rights|forcés d'avoir la double authentification]] (A2F) d'activée. Actuellement, l'A2F n'est nécessaire que pour utiliser les droits du groupe, et non pour en faire partie. Vu que ce système admet certaines failles, il sera [[phab:T418580|changé graduellement en mars]]. Les membres de ces groupes ne pourront plus désactiver la dernière méthose d'A2F sur leur compte, et il sera impossible d'ajouter des utilisateurs sans A2F à ces groupes. Il sera toujours possible de rajouter d'autres méthodes d'authentification et d'en enlever, tant qu'une est toujours activée. Dans la seconde moitié de mars, les utilisateurs sans A2F seront retirés de ces groupes. Cela s'applique aux administrateurs CentralNotice, aux vérificateurs d'utilisateurs, aux administrateurs d'interface, aux masqueurs, aux staff de Wikidata et Wikifonctions ainsi qu'aux bureaux IT et Confiance et sécurité de la WMF. Rien ne changera pour les autres utilisateurs. Voir la tâche liée pour le calendrier de déploiement. [https://phabricator.wikimedia.org/T418580] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:27|la tâche soumise|les {{formatnum:27}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:27||s}} la semaine dernière]]. Par exemple, le problème empêchant les utilisateurs de créer une instance dans [https://www.wikibase.cloud/ Wikibase.cloud] a maintenant été résolu. [https://phabricator.wikimedia.org/T416807] '''Actualités pour la contribution technique''' * <span lang="en" dir="ltr" class="mw-content-ltr">To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], over the next month the Wikimedia Foundation will implement global API rate limits across our APIs. In early March, stricter limits will be applied to unidentified requests from outside Toolforge/WMCS and API requests that are made from web browsers. In April, higher limits will be applied to identified traffic. These limits are intentionally set as high as possible to minimise impact on the community. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]].</span> * <span lang="en" dir="ltr" class="mw-content-ltr">The Wikidata Query Service Linked Data Fragment (LDF) endpoint will be decommissioned in February. This endpoint served limited traffic, which was successfully migrated to other data access methods that were better suited to support existing use cases. The hardware used to support the LDF endpoint will be reallocated to support the ongoing backend migration efforts.</span> [https://phabricator.wikimedia.org/T415696] * Le nouvel analyseur syntaxique Parsoid [[mw:Special:MyLanguage/Parsoid/Parser Unification/Updates|continue d'être déployés sur plus de wikis]], améliorant la pérennité de la platforme et rendant plus facile l'ajout de nouvelles fonctionalités de lecture et de modification. Parsoid est maintenant l'analyseur par défaut sur 488 wikis de la WMF (268 Wikipédias), couvrant plus de 10% de toutes les lectures de pages Wikipédia. * Le processus et les critères pour [[Special:MyLanguage/Wikimedia Enterprise#Access|demander un accès exceptionnel]] au flux à fort volume de l'API ''Wikimédia Entreprise'' (sans coût pour des utilisations en rapport à notre mission) [[m:Talk:Wikimedia Enterprise#Exceptional access criteria|ont maintenant été publiés]]. Notre but est de donner une documentation plus claire et plus complète aux utilisateurs. * [https://techblog.wikimedia.org/ Le blog Tech], dédié à la communité technique de Wikimédia [https://techblog.wikimedia.org/2026/02/24/a-tech-blog-diff/ va migrer] vers [[diffblog:|Diff]], le blog pour les nouvelles et événements de la communauté. La migration devrait être terminée en Avril 2026, après quoi les nouveaux posts seront acceptés pour être publiés. Les lecteurs pourront lire les posts - anciens ou nouveaux - sur https://diff.wikimedia.org/. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.18|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/10|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W10"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 2 mars 2026 à 18:51 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30137798 --> == <span lang="en" dir="ltr">Tech News: 2026-11</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W11"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/11|Translations]] are available. '''Weekly highlight''' * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. * Last week, all wikis had 2 hours of read-only time, and extended unavailability for user-scripts and gadgets. This was due to a security incident which has since been resolved. Work is ongoing to prevent re-occurrences. For current information please see the [[m:Steward's noticeboard#Statement on Meta about today's user script security incident|post on the Stewards' noticeboard]] ([[m:Special:MyLanguage/Wikimedia Foundation/Product and Technology/Product Safety and Integrity/March 2026 User Script Incident|translations]]). '''Updates for editors''' * Users facing multiple blocks on mobile will now see the reasons for each block separately, instead of a generic message. This helps them understand why they are blocked and what steps they can take to resolve the issue. For example, users affected for using common VPNs (such as [[Special:MyLanguage/Apple iCloud Private Relay|iCloud Private Relay]]) will receive clearer guidance on what they need to do to start editing again. [https://phabricator.wikimedia.org/T357118] * Later this week, [[mw:Special:MyLanguage/VisualEditor/Suggestion Mode|Suggestion Mode]] will become available as a beta feature within the visual editor at all Wikipedias. This feature proactively suggests various types of actions that people can consider taking to improve Wikipedia articles, and learn about related guidelines. The feature is locally configurable, and can also be locally expanded with custom Suggestions. Current settings can be seen at [[Special:EditChecks]] and there are [[mw:Special:MyLanguage/Help:Suggestion mode#For administrators %E2%80%93 local customization|instructions for how administrators can customize]] the links to point to local guidelines. The feature is connected to [[mw:Special:MyLanguage/Help:Edit check|Edit check]] which suggests improvements while someone is writing new content. In the future, the Editing team plans to evaluate the feature's impact with newcomers through a controlled experiment. [https://phabricator.wikimedia.org/T404600] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:23}} community-submitted {{PLURAL:23|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the issue where the cursor became misaligned during the use of CodeMirror’s syntax highlighting, which makes wikitext and code easier to read, has now been fixed. This problem specifically affected users who defined a font rule in a custom stylesheet while creating a new topic with DiscussionTools. [https://phabricator.wikimedia.org/T418793] '''Updates for technical contributors''' * API rate limiting update: To help ensure [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|fair use of infrastructure]], global API rate limits will be applied this week to requests without a compliant User-Agent that originate from outside Toolforge/WMCS and to unauthenticated requests made from web browsers. Higher limits will be applied to identified traffic in April. Bots running in Toolforge/WMCS or with the bot user right on any wiki should not be affected for now. However, all developers are advised to follow updated best practices. For more information, see [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|Wikimedia APIs/Rate limits]]. * The new GraphQL API has been released. The API was developed as a flexible alternative to select features of the Wikidata Query Service (WDQS), to improve developer experience and foster adaptability, and efficient data access. Try it out and [[d:Wikidata:Wikibase GraphQL#Feedback and development|give feedback]]. You can also [https://greatquestion.co/wikimediadeutschland/GraphQLAPI/apply sign up for usability tests]. * The [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group|PTAC Unsupported Tools Working Group]] continued improvements to [[commons:Special:MyLanguage/Commons:Video2commons#|Video2Commons]] in February, with fixes addressing authentication errors, large-file handling, task queue visibility, and clearer upload behavior. Work is still ongoing in some areas, including changes related to deprecated server-side uploads. Read [[m:Special:MyLanguage/Product and Technology Advisory Council/Unsupported Tools Working Group#February 2026|this update]] to learn more. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.19|MediaWiki]] '''In depth''' * The Article Guidance team invites experienced Wikipedia editors from selected [[mw:Special:MyLanguage/Article guidance/Pilot wikis and collaborators#Collaborators|pilot wikis]] and interested contributors from other Wikipedias to fill out this questionnaire which is available in [https://docs.google.com/forms/d/e/1FAIpQLSfmLeVWnxmsCbPoI_UF2jyRcn73WRGWCVPHzerXb4Cz97X_Ag/viewform English], [https://docs.google.com/forms/d/e/1FAIpQLSd6rzr4XXQw8r4024fE3geTPFe13M_6w7Mitj-YJi0sOlWTAw/viewform?usp=header Arabic], [https://docs.google.com/forms/d/e/1FAIpQLSdok3-RfB18lcugYTUMGkpwmqG_8p760Wv4dCXitOXOszjUDw/viewform?usp=header Bengali], [https://docs.google.com/forms/d/e/1FAIpQLSfjTfYp4jEo0akA4B1e-Nfg3QZPCudUjhJzHzzDi6AHyAaMGA/viewform?usp=header Japanese], [https://docs.google.com/forms/d/e/1FAIpQLScteVoI29Aue4xc72dekk-6RYtvmMgQxzMI900UOawrFrSTWg/viewform?usp=header Portuguese], [https://docs.google.com/forms/d/e/1FAIpQLSetdxnYwL3ub2vqA7awCg5hJZPMIYcDPaiTe12rY9h0GYnVlw/viewform?usp=header Persian], and [https://docs.google.com/forms/d/e/1FAIpQLScNvfJF-Ot-4pzA4qAN771_0QDJ4Li19YcUsaTgSKW8Nc7U_Q/viewform?usp=header Turkish]. Your answers will help the team customize guidance for less experienced editors and help them learn community policies and practices while creating an article. Learn more [[mw:Special:MyLanguage/Article guidance|on the project page]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/11|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W11"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 9 mars 2026 à 19:52 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30213008 --> == <span lang="en" dir="ltr">Tech News: 2026-12</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W12"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/12|Translations]] are available. '''Updates for editors''' * The [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature, also known as [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], has been used for wikitext syntax highlighting since November 2024. It will be promoted out of beta by May 2026 in order to bring improvements and new [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Features|features]] to all editors who use the standard syntax highlighter. If you have any questions or concerns about promoting the feature out of beta, [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|please share]]. [https://phabricator.wikimedia.org/T259059] * Some changes to local user groups are performed by stewards on Meta-Wiki and logged there only. Now, interwiki rights changes will be logged both on Meta-Wiki and the wiki of the target user to make it easier to access a full record of user's rights changes on a local wiki. Past log entries for such changes will be backfilled in the coming weeks. [https://phabricator.wikimedia.org/T6055] * On wikis using [[m:Special:MyLanguage/Flagged Revisions|Flagged Revisions]], the number of pending changes shown on [[{{#Special:PendingChanges}}]] previously counted pages which were no longer pending review, because they have been removed from the system without being reviewed, e.g. due to being deleted, moved to a different namespace, or due to wiki configuration changes. The count will be correct now. On some wikis the number shown will be much smaller than before. There should be no change to the list of pages itself. [https://phabricator.wikimedia.org/T413016] * Wikifunctions composition language has been rewritten, resulting in a new version of the language. This change aims to increase service stability by reducing the orchestrator's memory consumption. This rewrite also enables substantial latency reduction, code simplification, and better abstractions, which will open the door to later feature additions. Read more about [[f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-11|the changes]]. * Users can now sort search results alphabetically by page title. The update gives an additional option to finding pages more easily and quickly. Previously, results could be sorted by Edit date, Creation date, or Relevance. To use the new option, open 'Advanced Search' on the search results page and select 'Alphabetically' under 'Sorting Order'. [https://phabricator.wikimedia.org/T403775] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:28}} community-submitted {{PLURAL:28|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented UploadWizard on Wikimedia Commons from importing files from Flickr has now been fixed. [https://phabricator.wikimedia.org/T419263] '''Updates for technical contributors''' * A new special page, [[{{#special:LintTemplateErrors}}]], has been created to list transcluded pages that are flagged as containing lint errors to help users discover them easily. The list is sorted by the number of transclusions with errors. For example: [[{{#special:LintTemplateErrors}}/night-mode-unaware-background-color]]. [https://phabricator.wikimedia.org/T170874] * Users of the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature have been using [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] for syntax highlighting when editing JavaScript, CSS, JSON, Vue and Lua content pages, for some time now. Along with promoting CodeMirror 6 out of beta, the plan is to replace CodeEditor as the standard editor for these content models by May 2026. [[mw:Special:MyLanguage/Help talk:Extension:CodeMirror|Feedback or concerns are welcome]]. [https://phabricator.wikimedia.org/T419332] * The [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] JavaScript modules will soon be upgraded to CodeMirror 6. Leading up to the upgrade, loading the <code dir=ltr>ext.CodeMirror</code> or <code dir=ltr>ext.CodeMirror.lib</code> modules from gadgets and user scripts was deprecated in July 2025. The use of the <code dir=ltr>ext.CodeMirror.switch</code> hook was also deprecated in March 2025. Contributors can now make their scripts or gadgets compatible with CodeMirror 6. See the [[mw:Special:MyLanguage/Extension:CodeMirror#Gadgets and user scripts|migration guide]] for more information. [https://phabricator.wikimedia.org/T373720] * The MediaWiki Interfaces team is expanding coverage of REST API module definitions to include [[mw:Special:MyLanguage/API:REST API/Extensions|extension APIs]]. REST API modules are groups of related endpoints that can be independently managed and versioned. Modules now exist for [https://phabricator.wikimedia.org/T414470 GrowthExperiments] and [https://phabricator.wikimedia.org/T419053 Wikifunctions] APIs. As we migrate extension APIs to this structure, documentation will move out of the main MediaWiki OpenAPI spec and REST Sandbox view, and will instead be accessible via module-specific options in the dropdown on the [https://test.wikipedia.org/wiki/Special:RestSandbox REST Sandbox] (i.e., [[{{#Special:RestSandbox}}]], available on all wiki projects). * The [[mw:Special:MyLanguage/Extension:Scribunto|Scribunto]] extension provides different pieces of information about the wiki where the module is being used via the [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual|mw.site]] library. Starting last week, the library also provides a [[mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#mw.site.wikiId|way]] of accessing the [[mw:Special:MyLanguage/Manual:Wiki ID|wiki ID]] that can be used to facilitate cross-wiki module maintenance. [https://phabricator.wikimedia.org/T146616] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.20|MediaWiki]] '''In depth''' * The [[m:Special:MyLanguage/Coolest Tool Award|2026 Coolest Tool Award]] celebrating outstanding community tools, is now open for nominations! Nominate your favorite tool using the [https://wikimediafoundation.limesurvey.net/435684?lang=en nomination survey] form by 23 March 2026. For more information on privacy and data handling, please see the [[foundation:Special:MyLanguage/Legal:Coolest_Tool_Award_2026_Survey_Privacy_Statement|survey privacy statement]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/12|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W12"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 16 mars 2026 à 20:35 (CET) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30260505 --> == <span lang="en" dir="ltr">Upcoming deployment of CampaignEvents extension to Wikibooks</span> == <div lang="en" dir="ltr"> <section begin="message"/> Hello everyone, We are writing to inform you that the [[mw:Help:Extension:CampaignEvents|CampaignEvents extension]] will be deployed to all Wikibooks projects during the week of '''23 March 2026'''. This follows last year’s broader rollout across Wikimedia projects. We realized that Wikibooks was not included at the time, and we’re now addressing that to ensure consistency across all communities. The CampaignEvents extension provides tools to support event and campaign organization on-wiki, including features like on-wiki event registration and collaboration lists(global event list). We welcome any questions, feedback, or concerns you may have. We are also happy to support anyone interested in trying out the tools. ''Apologies if this message is not in your preferred language. If you’re able to help translate it for your community, please feel free to do so.'' <section end="message"/> </div> <bdi lang="en" dir="ltr">[[User:Udehb-WMF|Udehb-WMF]] ([[User talk:Udehb-WMF|discussion]]) 19 mars 2026 à 19:22 (CET)</bdi> <!-- Message envoyé par User:Udehb-WMF@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=User:Udehb-WMF/sandbox/MM_target&oldid=30284073 --> == <span lang="en" dir="ltr">Tech News: 2026-13</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W13"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/13|Translations]] are available. '''Weekly highlight''' * Wikimedia site users can now log in without a password using passkeys. This is a secure method supported by fingerprint, facial recognition, or PIN. With this change, all users who opt for passwordless login will find it easier, faster, and more secure to log in to their accounts using any device. The new passkey login option currently appears as an autofill suggestion in the username field. An additional [[phab:T417120|"Log in with passkey" button]] will soon be available for users who have already registered a passkey. This update will improve security and user experience. The [[c:File:Passwordless_login_screencast.webm|screen recording]] demonstrates the passwordless login process step by step. * [[m:Special:MyLanguage/Tech/Server switch|All wikis will be read-only]] for a few minutes on Wednesday, 25 March 2026 at [https://zonestamp.toolforge.org/1774450800 15:00 UTC]. This is for the datacenter server switchover backup tests, [[wikitech:Deployments/Yearly calendar|which happen twice a year]]. During the switchover, all Wikimedia website traffic is shifted from one primary data center to the backup data center to test availability and prevent service disruption even in emergencies. '''Updates for editors''' * Wikimedia site users can now export their notifications older than 5 years using a [[toolforge:echo-chamber|new Toolforge tool]]. This will ensure that users retain their important notifications and avoid them being lost based on the planned change to delete notifications older than 5 years, as previously announced. [https://phabricator.wikimedia.org/T383948] * Wikipedia editors in Indonesian, Thai, Turkish, and Simple English now have access to Special:PersonalDashboard. This is an [[mw:Special:MyLanguage/Moderator Tools/Dashboard|early version of an experience]] that introduces newer editors to patrolling workflows, making it easier for them to move from making edits to participating in more advanced moderation work on their project. [https://phabricator.wikimedia.org/T402647] * The [[Special:Block]] now has two minor interface changes. Administrators can now easily perform indefinite blocks through a dedicated radio button in the expiry section. Also, choosing an indefinite expiry provides a different set of common reasons to select from, which can be changed at: [[MediaWiki:Ipbreason-indef-dropdown]]. [https://phabricator.wikimedia.org/T401823] * Mobile editors [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#Logged-out|at several wikis]] can now see an improved logged-out edit warning, thanks to the recent updates from the Growth team. These changes released last week are part of ongoing efforts and tests to enhance [[mw:Special:MyLanguage/Contributors/Account Creation Experiments|account creation experience on mobile]] and then increase participation. [https://phabricator.wikimedia.org/T408484] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:36}} community-submitted {{PLURAL:36|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, the bug that prevented mobile web users from seeing the block information when affected by multiple blocks has been fixed. They can now see messages of all the blocks currently affecting them when they access Wikipedia. '''Updates for technical contributors''' * Images built using Toolforge will soon get the upgraded buildpacks version, bringing support for newer language versions and other upstream improvements and fixes. If you use Toolforge Build Service, review the recent [https://lists.wikimedia.org/hyperkitty/list/cloud-announce@lists.wikimedia.org/thread/EMYTA32EV2V5SQ2JIEOD2CL66YFIZEKV/ cloud-announce email] and update your build configuration as necessary to ensure your tools are compatible. [https://wikitech.wikimedia.org/w/index.php?title=Help:Toolforge/Building_container_images&oldid=2392097#Buildpack_environment_upgrade_process][https://phabricator.wikimedia.org/T380127] * The [https://api.wikimedia.org/wiki/Main_Page API Portal] documentation wiki will shut down in June 2026. API keys created on the API Portal will continue to work normally. api.wikimedia.org endpoints will be deprecated gradually starting in July 2026. Documentation on the API Portal is moving to [[mw:Wikimedia APIs|mediawiki.org]]. Learn more on the [[wikitech:API Portal/Deprecation|project page]]. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.21|MediaWiki]] '''In depth''' * [[m:Special:MyLanguage/WMDE Technical Wishes|WMDE Technical Wishes]] is considering improvements to [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names|automatically generated reference names in VisualEditor]]. Please check out the [[m:WMDE Technical Wishes/References/VisualEditor automatic reference names#Proposed solutions|proposed solutions]] and participate in the [[m:Talk:WMDE Technical Wishes/References/VisualEditor automatic reference names#Request for comment|request for comment]]. '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/13|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W13"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 23 mars 2026 à 17:51 (CET) <!-- Message envoyé par User:UOzurumba (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30268305 --> == Actualités techniques n° 2026-14 == <section begin="technews-2026-W14"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/14|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Le version Beta de [[abstract:|Abstract Wikipedia]], un nouveau projet Wikimédia indépendant du langage, a été lancée la semaine dernière. Ce projet permet aux communautés de construire des articles Wikipédia dans leur langue natale, qui peuvent directement être lus par les autres utilisateurs et utilisatrices dans leur propre langage. Le wiki fonctionne grâce à des instructions de Wikifunctions et au contenu structuré issu de Wikidata. [[:f:Special:MyLanguage/Wikifunctions:Status updates/2026-03-26|En savoir plus]]. '''Actualités pour la contribution''' * L'équipe Croissance mène un test A/B afin d'évaluer l'effet d'un message plus clair et plus convivial encourageant à la création de comptes sur les wikis. Actuellement, lorsqu'un utilisateur mobile non connecté lance la modification, un message d'avertissement s'affiche, pouvant paraître abrupt et décourageant. Il présente également la modification par compte temporaire comme option par défaut, au lieu d'inciter à la création d'un compte. Le test est mené sur dix Wikipédia, dont les versions en arabe, français, espagnol et allemand. [[mw:Special:MyLanguage/Contributors/Account Creation Experiments#2. Improve logged-out warning message (T415160)|En savoir plus]]. * L'équipe des applications Wikimédia sollicite vos commentaires sur [[mw:Special:MyLanguage/Wikimedia Apps/Team/Future of Editing on the Mobile Apps|comment devrait fonctionner l'édition dans les applications mobiles Wikipédia]]. La discussion porte sur l'amélioration de l'accès aux outils d'édition lorsque les utilisateurs appuient sur « Modifier ». Cette initiative s'inscrit dans un effort plus large visant à offrir aux lecteurs intéressés par la contribution une expérience utilisateur plus intuitive. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:45|la tâche soumise|les {{formatnum:45}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:45||s}} la semaine dernière]]. Par exemple, un problème avec la récupération de citations à partir du site d'archive de journaux [https://www.newspapers.com Newspapers.com], qui ne fonctionnait plus en raison d'un blocage des requêtes [[mw:Special:MyLanguage/Citoid|Citoid]], a maintenant été résolu. [https://phabricator.wikimedia.org/T419903] '''Actualités pour la contribution technique''' * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.22|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/14|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W14"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 30 mars 2026 à 21:25 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30329462 --> == Action Required: Update templates/modules for electoral maps (Migrating from P1846 to P14226) == Hello everyone, This is a notice regarding an ongoing data migration on Wikidata that may affect your election-related templates and Lua modules (such as <code>Module:Itemgroup/list</code>). '''The Change:'''<br /> Currently, many templates pull electoral maps from Wikidata using the property [[:d:Property:P1846|P1846]], combined with the qualifier [[:d:Property:P180|P180]]: [[:d:Q19571328|Q19571328]]. We are migrating this data (across roughly 4,000 items) to a newly created, dedicated property: '''[[:d:Property:P14226|P14226]]'''. '''What You Need To Do:'''<br /> To ensure your templates and infoboxes do not break or lose their maps, please update your local code to fetch data from [[:d:Property:P14226|P14226]] instead of the old [[:d:Property:P1846|P1846]] + [[:d:Property:P180|P180]] structure. A [[m:Wikidata/Property Migration: P1846 to P14226/List|list of pages]] was generated using Wikimedia Global Search. '''Deadline:'''<br /> We are temporarily retaining the old data on [[:d:Property:P1846|P1846]] to allow for a smooth transition. However, to complete the data cleanup on Wikidata, the old [[:d:Property:P1846|P1846]] statements will be removed after '''May 1, 2026'''. Please update your modules and templates before this date to prevent any disruption to your wiki's election articles. Let us know if you have any questions or need assistance with the query logic. Thank you for your help! [[User:ZI Jony|ZI Jony]] using [[Utilisateur:MediaWiki message delivery|MediaWiki message delivery]] ([[Discussion utilisateur:MediaWiki message delivery|discussion]]) 3 avril 2026 à 19:11 (CEST) <!-- Message envoyé par User:ZI Jony@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Distribution_list/Non-Technical_Village_Pumps_distribution_list&oldid=29941252 --> == Actualités techniques n° 2026-15 == <section begin="technews-2026-W15"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/15|D’autres traductions]] sont disponibles. '''Actualités pour la contribution''' * L’[[mw:Special:MyLanguage/Help:Extension:CampaignEvents|extension CampaignEvents]] comprend désormais une nouvelle fonctionnalité de définition d’objectifs de groupe, permettant aux organisateurs de définir et de suivre les objectifs de l’événement, tels que le nombre d’articles créés et de contributeurs participants en temps réel. De même, les participants peuvent travailler vers des cibles communes et voir leur impact collectif au fur et à mesure que l’événement se déroule. Cette fonctionnalité est désormais disponible sur tous les wikis Wikimedia. Pour en savoir plus, consultez [[mw:Special:MyLanguage/Help:Extension:CampaignEvents/Registration/Collaborative contributions#Goal setting|la documentation]]. * [[File:Maki-gift-15.svg|12px|link=|class=skin-invert|Concerne un souhait]] La nouvelle fonctionnalité d'[[mw:Special:MyLanguage/Help:Watchlist labels|étiquettes de liste de suivi]] (annoncée dans les [[m:Special:MyLanguage/Tech/News/2026/07|Actualités techniques 2026-07 ]]) est désormais disponible via l'ÉditeurVisuel, l'éditeur de code et l'«étoile de suivi»(ou le lien de suivi, pour les habillages qui n'ont pas d'icône d'étoile). Auparavant, il n'était possible d'attribuer des étiquettes que via [[Special:EditWatchlist|Modifier la liste de suivi]]. Dans ces trois emplacements, il s'agit d'un nouveau champ situé après le champ d'expiration. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:23|la tâche soumise|les {{formatnum:23}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:23||s}} la semaine dernière]]. Par exemple, le problème où les pages de discussion sur mobile avec Parsoid sont inutilisables après les en-têtes de section vides, a maintenant été résolu. [https://phabricator.wikimedia.org/T419171] '''Actualités pour la contribution technique''' * La [[m:Special:MyLanguage/WMDE Technical Wishes/Sub-referencing|fonctionnalité de sous-référencement]], qui permet aux contributeurs d'ajouter des détails à une référence existante sans la dupliquer, sera progressivement déployée sur [[phab:T414094|davantage de wikis]] plus tard cette année. Les wikis utilisant le gadget [[mw:Special:MyLanguage/Reference Tooltips|Reference Tooltips]] sont encouragés à mettre à jour leur version (généralement sur [[m:MediaWiki:Gadget-ReferenceTooltips.js|MediaWiki:Gadget-ReferenceTooltips.js]] comme indiqué [https://en.wikipedia.org/w/index.php?diff=1344408362 ici]) pour assurer la compatibilité. D'autres gadgets liés aux références pourraient également être affectés. [https://phabricator.wikimedia.org/T416304] * Toutes les éditions de Wikinews seront fermées et passeront en mode lecture seule le 4 mai 2026. Le contenu restera accessible, mais aucune nouvelle modification ni aucun nouvel article ne pourra être ajouté. Cette fermeture a été approuvée par le Conseil d'administration de la Fondation Wikimedia à la suite de discussions prolongées. [[m:Wikimedia Foundation Board noticeboard#Board of Trustees Approves Closure of Wikinews|En savoir plus]]. * L'[[:mw:Special:MyLanguage/API:Action API|API d'action]] a proposé plusieurs formats pour les résultats demandés. L'un d'entre eux, <bdi lang="zxx" dir="ltr"><code><nowiki>format=php</nowiki></code></bdi>, sera bientôt supprimé. Veuillez vous assurer que vos scripts ou robots utilisent le [[mw:Special:MyLanguage/API:Data formats#Output|format JSON]]. Cette suppression devrait affecter très peu de scripts et de robots. [https://phabricator.wikimedia.org/T118538] * La page [[Special:NamespaceInfo|Special:NamespaceInfo]] inclut désormais les alias d'espace de noms. Par exemple «WP» pour l'espace de noms ''Projet'' (''Wikipédia'') sur la Wikipédia en allemand. [https://phabricator.wikimedia.org/T381455] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Détail des mises-à-jour à venir cette semaine : [[mw:MediaWiki 1.46/wmf.23|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/15|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W15"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 6 avril 2026 à 18:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30362761 --> == <span lang="en" dir="ltr">Tech News: 2026-16</span> == <div lang="en" dir="ltr"> <section begin="technews-2026-W16"/><div class="plainlinks"> Latest '''[[m:Special:MyLanguage/Tech/News|tech news]]''' from the Wikimedia technical community. Please tell other users about these changes. Not all changes will affect you. [[m:Special:MyLanguage/Tech/News/2026/16|Translations]] are available. '''Weekly highlight''' * Experienced editors are invited to [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Main_Page test] the [[mw:Special:MyLanguage/Article guidance|Article guidance]] feature, designed to help less-experienced editors create well-structured, policy-compliant Wikipedia articles. Testing instructions are [[mw:Special:MyLanguage/Article guidance/Test feature guide|available]]. Also, after reviewing [https://b24e11a4f1.catalyst.wmcloud.org/wiki/Category:Pages_using_article_guidance the outlines], please provide feedback on the [[mw:Talk:Article guidance|project talk page]]. Based on your input, the feature will be refined and transferred to the pilot Wikipedias to translate and adapt. Check out [[c:File:Article Guidance workflow demo - April 2026.webm|the video]] explaining the feature. '''Updates for editors''' * On most wikis, all autoconfirmed users can now use [[Special:ChangeContentModel|Special:ChangeContentModel]] page to [[mw:Special:MyLanguage/Help:ChangeContentModel|create new pages with custom content models]], such as mass message lists, making custom page formats more accessible. Check [[Special:ListGroupRights|Special:ListGroupRights]] for the status of your wiki. [https://phabricator.wikimedia.org/T248294] * The Growth team has launched an [[mw:Special:MyLanguage/Contributors/Account_Creation_Experiments|account creation experiment]] to evaluate whether adding an account creation button to the mobile web header increases new account registrations and encourages more mobile users to contribute to the wikis. The experiment is currently live on Hindi, Indonesian, Bengali, Thai, and Hebrew Wikipedia, and targets 10% of logged-out mobile web users. * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] View all {{formatnum:30}} community-submitted {{PLURAL:30|task|tasks}} that were [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|resolved last week]]. For example, an issue where VisualEditor could get stuck loading on Windows devices with animations turned off, has now been fixed. [https://phabricator.wikimedia.org/T382856] '''Updates for technical contributors''' * Starting later this week, {{int:group-abusefilter}} who have the [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]] beta feature enabled will have [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] instead of [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] as the editor at [[Special:AbuseFilter|Special:AbuseFilter]]. This is part of the broader effort to make the user experience more consistent across all editors. [https://phabricator.wikimedia.org/T399673][https://phabricator.wikimedia.org/T419332] * Tools and bots that access the [[mw:Special:MyLanguage/Notifications/API|Notifications API]] (<bdi lang="zxx" dir="ltr"><code><nowiki>action=query&meta=notifications</nowiki></code></bdi>) will need to update their OAuth or BotPassword grants to also include access to private notifications. [https://phabricator.wikimedia.org/T421991] * Due to a library upgrade, listings on category pages may be displayed out of order starting on Monday, 20th April. A migration script will be run to correct this, and will take hours to days depending on the size of the wiki (up to a week for English Wikipedia). [https://phabricator.wikimedia.org/T422544] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Recurrent item]] Detailed code updates later this week: [[mw:MediaWiki 1.46/wmf.24|MediaWiki]] '''''[[m:Special:MyLanguage/Tech/News|Tech news]]''' prepared by [[m:Special:MyLanguage/Tech/News/Writers|Tech News writers]] and posted by [[m:Special:MyLanguage/User:MediaWiki message delivery|bot]]&nbsp;• [[m:Special:MyLanguage/Tech/News#contribute|Contribute]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/16|Translate]]&nbsp;• [[m:Tech|Get help]]&nbsp;• [[m:Talk:Tech/News|Give feedback]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|Subscribe or unsubscribe]].'' </div><section end="technews-2026-W16"/> </div> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 13 avril 2026 à 17:19 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30380527 --> == Actualités techniques n° 2026-17 == <section begin="technews-2026-W17"/><div class="plainlinks"> Dernières '''[[m:Special:MyLanguage/Tech/News|actualités techniques]]''' de la communauté technique de Wikimedia. N’hésitez pas à informer les autres utilisateurs de ces changements. Certains changements ne vous concernent pas. [[m:Special:MyLanguage/Tech/News/2026/17|D’autres traductions]] sont disponibles. '''En lumière cette semaine''' * Après deux ans de développement, la version [[mw:Special:MyLanguage/Help:Extension:CodeMirror|{{int:codemirror-beta-feature-title}}]], également connue sous le nom de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror 6]], sortira de sa phase bêta le mardi 21 avril. Elle offrira une meilleure lisibilité du code et du wikitext, une réduction des fautes de frappe et d'autres [[mw:Special:MyLanguage/Help:Extension:CodeMirror|avantages]] à tous les utilisateurs du surligneur de syntaxe standard. Un grand merci au bénévole [https://phabricator.wikimedia.org/p/Bhsd/ Bhsd] qui a développé de nombreuses nouvelles fonctionnalités, notamment [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Code folding|le repliement de code]], [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Autocompletion|la saisie semi-automatique]] et [[mw:Special:MyLanguage/Help:Extension:CodeMirror#Linting|l'analyse statique du code]]. [https://phabricator.wikimedia.org/T259059] * Une mise à jour majeure de l'application Wikipédia pour iOS est en cours de déploiement, en restructurant l'interface pour s'harmoniser avec le tout nouveau design visuel "Liquid Glass" d'Apple. [https://apps.apple.com/us/app/wikipedia/id324715238 Télécharger la dernière version] et découvrez les nouveautés. '''Actualités pour la contribution''' * [[mw:Special:MyLanguage/Readers/Reader Experience/WE3.3.4 Reading lists|Les listes de lecture]] est une fonctionnalité qui permet aux lecteurs d'enregistrer des articles dans une liste pour les lire ultérieurement. Cette fonctionnalité est actuellement en version bêta sur les Wikipédias en arabe, français, indonésien, vietnamien et chinois, et activée par défaut pour tous les nouveaux comptes sur toutes les Wikipédias. * Une expérimentation visant à étendre [[mw:Special:MyLanguage/Readers/Reader Growth/Mobile page previews|les aperçus de page au web mobile]] sera lancée la semaine du 20 avril sur les versions arabe, anglaise, française, italienne, polonaise et vietnamienne de Wikipédia. Les aperçus de page sont des fenêtres contextuelles affichant une miniature, un premier paragraphe et un lien bleu permettant d'ouvrir l'article complet, facilitant ainsi la découverte de contenu. Cette fonctionnalité est déjà disponible sur ordinateur et dans les applications. [[m:Special:MyLanguage/List of experiments in Product and Technology#Template|En savoir plus sur cette expérimentation et d'autres]]. * Sur plusieurs wikis, les contributeurs connectés qui n'ont pas [[mw:Special:MyLanguage/Help:Email confirmation|confirmé leur adresse électronique]] peuvent désormais voir une bannière les invitant à le faire. La confirmation de l'adresse électronique permet à un utilisateur de récupérer l'accès à son compte en cas de perte. [[mw:Special:MyLanguage/Product Safety and Integrity/Account Security#Encouraging users to confirm their email addresses|En savoir plus]]. [https://phabricator.wikimedia.org/T421366] * [[File:Reload icon with two arrows.svg|12px|link=|class=skin-invert|Sujet récurrent]] Voir {{PLURAL:15|la tâche soumise|les {{formatnum:15}} tâches soumises}} par la communauté [[m:Special:MyLanguage/Tech/News/Recently resolved community tasks|résolue{{PLURAL:15||s}} la semaine dernière]]. Par exemple, un problème qui entraînait des ralentissements lors de la modification de très grandes pages wiki dans l'éditeur wikitext de 2017, des problèmes de chargement, de prévisualisation et de défilement, ainsi que des problèmes de performance lors de la sélection, de la découpe ou du collage de contenu, a maintenant été résolu. [https://phabricator.wikimedia.org/T184857] '''Actualités pour la contribution technique''' * Dans le cadre de la promotion de [[mw:Special:MyLanguage/Help:Extension:CodeMirror|CodeMirror]] à partir d'une fonctionnalité bêta, tous les utilisateurs se serviront de [[mw:Special:MyLanguage/Extension:CodeMirror|CodeMirror]] au lieu de [[mw:Special:MyLanguage/Extension:CodeEditor|CodeEditor]] pour la coloration syntaxique lors de l'édition de pages de contenu JavaScript, CSS, JSON, Vue et Lua. [https://phabricator.wikimedia.org/T419332] * <span class="mw-translate-fuzzy">Le service <code>mirrors.wikimedia.org</code> pour les utilisateurs de Debian et Ubuntu sera définitivement arrêté le 15 mai. Le matériel du serveur sera remplacé par des solutions plus performantes. Certains utilisateurs devront peut-être migrer vers un autre serveur qui ne devra prendre qu'une minute. [https://lists.wikimedia.org/hyperkitty/list/wikitech-l@lists.wikimedia.org/thread/LJYRIS4WB66HIRCAO4GIDTXCMDVZRBMA/ Vous pouvez en savoir plus].</span> [https://phabricator.wikimedia.org/T416707] * Les tables <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi> seront supprimées de [[wikitech:Help:Wiki Replicas|wikireplicas]]. Si vos outils ou requêtes accèdent directement à <bdi lang="zxx" dir="ltr"><code><nowiki>image</nowiki></code></bdi> ou <bdi lang="zxx" dir="ltr"><code><nowiki>oldimage</nowiki></code></bdi>, veuillez les mettre à jour pour utiliser les tables <bdi lang="zxx" dir="ltr"><code><nowiki>file</nowiki></code></bdi> et <bdi lang="zxx" dir="ltr"><code><nowiki>filerevision</nowiki></code></bdi> avant le 28 mai. [https://phabricator.wikimedia.org/T28741] * Suite à la récente mise en place de limites de débit globales pour les API non identifiées, la Fondation Wikimedia poursuit ses efforts pour garantir [[mw:Special:MyLanguage/MediaWiki Product Insights/Responsible Reuse|une utilisation équitable de l'infrastructure]] en appliquant des limites globales au trafic des API identifiées à partir de la dernière semaine d'avril. Ces limites sont volontairement fixées au niveau le plus élevé possible afin de minimiser l'impact sur la communauté. Les bots exécutés dans Toolforge/WMCS ou disposant des droits d'utilisateur de bot sur un wiki ne devraient pas être affectés pour le moment. Toutefois, il est conseillé à tous les développeurs de suivre les bonnes pratiques mises à jour. Pour plus d'informations, consultez la page [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits|API Wikimedia/Limites de débit]] et la [[mw:Special:MyLanguage/Wikimedia APIs/Rate limits/FAQ|Foire aux questions]]. * L'[[mw:Special:MyLanguage/Attribution API|API d'attribution]] est désormais disponible en [[mw:Special:MyLanguage/Wikimedia APIs/Stability policy|version bêta]]. Elle récupère les informations nécessaires pour créditer les articles et les fichiers multimédias de Wikimedia, quel que soit leur lieu d'utilisation. La documentation de référence est disponible sur la page dédiée au Sandbox REST, accessible sur tous les wikis Wikimedia (comme [https://en.wikipedia.org/w/index.php?api=attribution.v0-beta&title=Special%3ARestSandbox le sandbox REST de Wikipédia en anglais]). N'hésitez pas à partager vos commentaires sur la [[mw:Talk:Attribution API|page de discussion du projet]]. * Il n'y aura pas de nouvelle version de MediaWiki cette semaine. '''''[[m:Special:MyLanguage/Tech/News|Actualités techniques]]''' préparées par les [[m:Special:MyLanguage/Tech/News/Writers|rédacteurs des actualités techniques]] et postées par [[m:Special:MyLanguage/User:MediaWiki message delivery|robot]]. [[m:Special:MyLanguage/Tech/News#contribute|Contribuer]]&nbsp;• [[m:Special:MyLanguage/Tech/News/2026/17|Traduire]]&nbsp;• [[m:Tech|Obtenir de l’aide]]&nbsp;• [[m:Talk:Tech/News|Donner son avis]]&nbsp;• [[m:Global message delivery/Targets/Tech ambassadors|S’abonner ou se désabonner]].'' </div><section end="technews-2026-W17"/> <bdi lang="en" dir="ltr">[[User:MediaWiki message delivery|MediaWiki message delivery]]</bdi> 20 avril 2026 à 17:00 (CEST) <!-- Message envoyé par User:STei (WMF)@metawiki en utilisant la liste sur https://meta.wikimedia.org/w/index.php?title=Global_message_delivery/Targets/Tech_ambassadors&oldid=30432763 --> 80jacylyz4yq5bn34rizta84e4gzh28 Discussion:ConTeXt/Installation 1 83826 764181 2026-04-21T00:42:23Z ~2026-24363-83 123569 /* TeXLive */ nouvelle section 764181 wikitext text/x-wiki == TeXLive == Les informations concernant TeXlive sont obsolètes et incorrectes. [[Spécial:Contributions/&#126;2026-24363-83|&#126;2026-24363-83]] ([[Discussion utilisateur:&#126;2026-24363-83|discussion]]) 21 avril 2026 à 02:42 (CEST) 45p4yrfvdjnyi2ocb54k2sf1stwzxnz