Форум программистов, компьютерный форум, киберфорум
R71MT
Войти
Регистрация
Восстановить пароль
Рейтинг: 5.00. Голосов: 1.

Контроллёр памяти (заметки на полях)

Запись от R71MT размещена 21.08.2018 в 23:03
Обновил(-а) R71MT 27.08.2018 в 07:19

Сабж по типу "заметок на полях", поэтому очевидные для себя вещи не затрагиваю. Если кому интересно, можно углубится в технические детали. Рассматривается устройство и принцип работы контроллёра памяти современных процессоров в том виде, в котором он представляется мне. В качестве источников, использовался Google и даташиты Intel.

Каждый виток эволюции DDR,2,3,4 несёт с собой не только повышение производительности, но и кучу архитектурных решений, в результате чего возникает путаница - новые типы памяти требуют новых контроллёров, поскольку работа памяти основывается уже на иных принципах, неизменной остаётся только DRAM-матрица ячеек памяти. Рассмотрим подноготную..

Chip Select - управляющие линии активации модуля

Модуль памяти (Rank) представляет из себя параллельно-последовательную сборку из 8-ми чипов памяти. Разрядность шины-данных одного чипа - 8 бит, последовательное соединение 8-ми чипов модуля образуют его внешнюю 64-битную шину-данных. Шина-адреса и линии управления разводятся по всем чипам параллельно, т.е. адрес(0) будет физическим адресом(0) во-всех 8-ми чипах модуля памяти, а вот логическим - 0:7. Другими словами, при обмене с памятью за единицу измерения берётся не байт, а 8-байтное (64-битное) DRAM-слово с последовательными адресами.

Для активации ранка, контроллёр имеет линию CS#, активным уровнем которой считается нуль(#). На каждый слот памяти приходит пара дорожек CS#[1:0], для поддержки 2-ранковых модулей - CS#0 активирует одну сторону, а CS#1 - вторую сторону модуля. Если ранк один, то второй CS# не задействуется. В большинстве случаях на один канал контроллёра производители мат.плат устанавливают 2 слота памяти, так-что линий CS# получается всего четыре - CS#[3:0].

Нажмите на изображение для увеличения
Название: mch.png
Просмотров: 822
Размер:	31.4 Кб
ID:	5004

Механизм конфигурации DIMM

Во всех модулях DDR предусмотрена м/схема SPD 'Serial-Presence-Detect', которая висит на шине i2С и находится под контролем системного менеджера SMM. В ней хранится паспорт модуля, но основной её функцией является обнаружение факта присутствия модулей DIMM в системе. По наличию SPD биос делает вывод, что слот не пустой и в нём имеется модуль. На одной шине i2C благополучно уживаются до 8-ми устройств, для чего слоты памяти и м/схемы SPD имеют 3-линии SA[2:0] Serial Address. Благодаря управляющим линиям SA модули DIMM получают порядковый номер в системе:

Рисунок 2.

Нажмите на изображение для увеличения
Название: spd.png
Просмотров: 360
Размер:	15.0 Кб
ID:	5005

По умолчанию, выводы SA на модулях DIMM висят в воздухе и тупо выходят проводниками наружу. Когда модуль вставляется в слот, то исходя из разводки слота, пины SPD-SA оказываются подключёнными в указанном выше порядке. Другими словами, номера слотам (а значит и модулям) задаёт производитель мат.платы, который 3-контакта слота соединяет одним из 8-ми приведённым способом - у каждого слота своя схема подключения линий SA. Если на мат.плате всего 4 слота DIMM, производитель может использовать только 2-линии SA[1:0].

Перед тем как взаимодействовать с памятью, BIOS должен настроить соответствующие регистры чипсета. Данные считываются с выводов SCL и SDA м/схемы SPD и по шине SMB непосредственно идут на чипсет. Биос общается с SPD по стандартному протоколу i2c, метод передачи информации – старт/стоповый. Пакет состоит из 8-бит, после чего контроллёр освобождает линию для получения подтверждения ACK от чипа SPD - Acknowledgement.

На этапе процедуры POST, биос генерит цикл чтения из SPD начиная с устройства 000, для опроса всех слотов памяти. Получив команду Read, SPD сначала возвращает бит подтверждения запроса после чего посылает и сам байт данных. Если в течении трёх тактов биос не получает сигнала ACK от SPD, слот считается пустым и биос переходит к проверке следующего слота DIMM. Прокрутив цикл чтения всех слотов один раз, биос получает полную карту устройств памяти.

Если на запрос чтения биос получает ответ от SPD, то с этой м/схемы считывается весь паспорт данных, среди которых: производитель, тип, объём, тайминги, рабочее напряжение и прочие характеристики модуля памяти. Исчерпывающую таблицу содержимого SPD можно найти на сайте JEDEC, где для каждого типа памяти DDR2,3,4 имеется свой лист. Полученную из SPD информацию биос использует для настройки регистров чипсета и контроллёра памяти, после чего сохраняет её в системных SMBIOS/ACPI-таблицах.

Адресация модулей памяти

Чтобы понять как адресуется глобальное пространство ОЗУ, достаточно разобраться с устройством одного чипа памяти, поскольку внутри модуля, адресные линии всех чипов соединены параллельно. Мало того, параллельно они разводятся и по всем слотам DIMM, а конкретный слот (модуль) уже активируется управляющими линиями CS#. Напомню, что при этом 8-битные шины-данных всех чипов, соединяются плечом-к-плечу последовательно. На первый взгляд это мутная тема, но если вникнуть в детали, то всё оказывается просто.

Для процессора - вся память линейна (в диапазоне адресов от 0 до N), поэтому он и выставляет на шину-адреса линейный адрес. Но внутри DRAM-модуля запоминающие ячейки выстроены в виде прямоугольной матрицы и чтобы подобраться к ним, нужно указать двумерные координаты: т.е. адрес-строки и адрес-столбца. На их пересечении и будет находится адресуемая ячейка размером всего 1-бит.

Значит линейный адрес процессора нужно разбить на две составляющие, которые назвали Row и Column Address (стробируются линиями RAS# и CAS# соответственно). Эти два адреса передаются по адресным линиям по очереди: сначала адрес-строки, затем адрес-столбца (мультиплексная шина). Такой подход позволил (!) в 4-раз сократить общее кол-во адресных линий модуля - теперь их не 64, а всего 15.

Давайте посчитаем, матрицу какого объёма можно адресовать 15-битной шиной?
Значит 215 = 32768 строк, и столько-же столбцов - итого: 327682 = 1.073.741.824 всего бит в матрице одного чипа.

Но 1-бит ничего из себя не представляет, и запрашивать процедуру чтения из памяти ради 1-бита это глупо. Поэтому производители чипов ещё на заводе объединяют несколько столбцов в один столбец матрицы. Как-правило между собой соединяются каждые 8-столбцов = 1 байт, которые отзываются теперь на один адрес столбца. В зависисмости от геометрии чипа, производитель может организовать его столбцы разными способами, например: х4, х8, х16, но в десктопном сегменте рынка это х8:

Рисунок 3.
Нажмите на изображение для увеличения
Название: x4.png
Просмотров: 234
Размер:	8.0 Кб
ID:	5008

При геометрии х8, общее кол-во адресуемых столбцов сокращается в 8-раз (32768/8=4096-столбцов), и соответственно бит для их адресации требуется меньше - всего 12 (212=4096), т.е. для строк выделяем как и прежде 15-бит, а для столбцов 12.

В результате простых манипуляций получили матрицу размером 32768-строк и 4096-столбцов, которая адресуется теперь по-байтно. Объём её составляет 32768*4096=134.217.728 байт, или 128 Mбайт. Условимся считать эту матрицу - одной плоскостью, и добавим сверху ещё 7 таких слоёв, наложив их друг-на-друга. Итого 8 самостоятельных матриц. Каждый слой назовём 'Банком памяти' и выделим для их активации 3-бита BA[2:0] - Bank Activate (Bank Select). На заключительном этапе соберём всё/это хозяйство под одну крышу, и получим 1 чип памяти, который имеет в свой тушке 8 банков, и объём: 128*8=1024 байт, или 1Gb.

Чтобы увеличить объёи памяти, соберём на одном модуле кластер из 8-ми таких чипов, соединив их адресные линии параллельно, а шины данных - последовательно. Теперь объём памяти разбух с одного до 8Gb. После всех телодвижений получаем законченный модуль DIMM, который можем вставлять в слот мат.платы:

Рисунок 4.
Нажмите на изображение для увеличения
Название: dimm0.png
Просмотров: 254
Размер:	13.6 Кб
ID:	5009

Посмотрим ещё раз на рисунки 3 и 4..
При подаче контроллёром 15-битного адреса строки, эта строка открывается сразу для всех 4096 столбцов матрицы, и в буферы SenseAMP активного банка за-раз сливаются 4096*8 чипов = 32Kb данных. Строку в буфере SenseAMP называют 'Открытой DRAM-страницей'. Затем подаётся 12-битный адрес-столбца, который выбирает 8-байт уже из буфера SenseAMP. При этом активная строка в матрице сразу не закрывается, т.к. после чтения ячеек, запоминающие конденсаторы этой строки разряжаются и их нужно восстановить из SenseAMP опять в матрицу - регенерация строки памяти.

Проблема открытых DRAM-страниц перед инженерами стоит жёстко. Пик потребляемой мощности памяти DDR приходится как-раз на момент открытия строки, именно в этот момент память греется потребляя энергию. Если одновременно открывать не одну, а сразу несколько страниц в разных банках, то мощность (и соответственно тепловыделение) увеличивается в разы, вынуждая применять внешний радиатор.

С другой стороны, чем больше открытых страниц, тем ниже латентность памяти - т.е. время между подачей адреса-строки и момента, когда страница уже становится доступна для чтения. Эту задержку называют RAS-to-CAS Latency, и она отнимает больше всего времени. После того как страница открыта, из неё можно сливать данные в пакетном режиме без каких-либо задержек, а если страницы в разных банках открываются параллельно, то это значительно экономит время.

Поэтому контроллёр должен обладать не хилым интеллектом, чтобы правильно распределять нагрузку на память - или держать открытыми несколько страниц и переключать банки по-требованию (чередовать их), или разумно распределять данные внутри одного банка. Практика доказала, что первый вариант выигрывает в производительности, хотя нельзя сбрасывать со счетов и альтернативу. Различные политики работы контроллёра рассматриваются ниже.

Пакетный режим чтения/записи


Ещё со-времён Pentium, минимальной порцией обмена с ОЗУ является 64-байтная кэш-строка. Процессор не станет записывать в память байт или слово, а сбросит целиком всю Cache-Line. То-же и с чтением.. ведь какой смысл читать 8-байт, когда в буфере SenseAMP лежит уже готовая 32Kb DRAM-страница? Процессор с радостью забрал-бы хоть всю её (хотя есть и такой/страничный обмен), только проблема - как быстро перекачать эту страницу из памяти в свой кэш, шина-то всего 8-байтная? Поэтому приходится искать золотую середину, ограничившись 64-байтными пакетами.

Для организации пакетного обмена, контроллёр имеет счётчик повторов Burst-Length, который может принимать значения BL=4,8,16,Page (хранится в SPD). В большинстве случаях BL=8, а остальные режимы для DDR2,3 скорее исключение, чем правило. Вычислив начальный адрес DRAM-столбца, контроллёр повторяет цикл чтения BL=8 раз, каждый раз увеличивая адрес столбца на 1. На выходе получаем пакет из 8*8=64 байт данных, которые помеcтив по обоим фронтам синхроимпульса DDR, можно передать по 8-байтной (64-битной) внешней шине, всего за 4 такта.

Рисунок 5.

Нажмите на изображение для увеличения
Название: bl8.png
Просмотров: 353
Размер:	6.7 Кб
ID:	5010

Нумерация байт начинается с разноцветных маркеров переднего плана - это 8-байт коричневого цвета 0:7. Теперь контроллёр сам увеличивает адрес столбца и повторяет операцию чтения - получаем следующее 8-байтное слово заднего плана голубого цвета, дальше - зелёного цвета, жёлтого, синего и т.д, вплоть до последнего DRAM-слова чёрного цвета. Как упоминалось выше, весь 64-байтный пакет отправляется из ОЗУ прямиком в линейку кэш, от куда и читается процессором.

Когда процессору приспичит не считать, а записать что-нибудь в ОЗУ, то он выгрузит в память опять всю 64-байтную линейку, а не отдельный её байт. Таким образом, запрашиваемый процессором адрес всегда выравнивается на 64-байтную границу. Если адрес не кратен 64 (и он прописан в тэгах кэш-памяти), значит данные уже находятся в кэш, и не нужно обращаться к тормознутой ОЗУ.


Регистры контроллёра DDR2-SDRAM

На моей экспериментальной машине контроллёр памяти внешний, поэтому практиковаться вынужден на нём. А вообще без разницы какие координаты в системе он имеет (встроенный в CPU или нет), методы его программирования остаются те же - через конфигурационное пространство шины PCI. Чипсет у меня 2-хабовый MCH-945G/ICH7, с двуканальным DRAM-контроллёром. Установлено памяти 1+1=2Gb, слотов на плате 2 и оба заполнены. Из инструментов буду использовать даташит на свой MCH945G и программу для просмотра памяти Read&Write Utility.

Нажмите на изображение для увеличения
Название: i945g.png
Просмотров: 155
Размер:	17.5 Кб
ID:	5013

В архитектуре компьютера, шина PCI объединяет всю/системную братию и DRAM-контроллёр не исключение. Регистры отображаются на память, и BIOS общается с ними посредством MMIO - Memory Mapped I/O. Подобраться к контроллёру памяти можно только через корневой HUB с координатами на шине PCI: Bus(0), Dev(0), Func(0). В PCI-регистрах хаба имеется 32-битное поле MCHBAR - Memory Controller Base Address Register, содержимое которого послужит мне базой для доступа к регистрам МС.

Системная поддержка памяти невероятно обширна, кол-во управляющих регистров уже давно перевалило за сотню и не каждому профи они по зубам. Одни регистры мапируют память (затеняют отдельные её участки от юзера), другие - задают кэшируемые области и т.д. Но в данном контексте нас интересует другая категория регистров, а именно регистры-управления самими модулями DIMM на физ.уровне. Армия их не так многочисленна, зато эти регистры индивидуальны не то-что для каждого модуля DIMM, но и для каждого из 2-х его ранков. Каждый канал имеет своё войско регистров, которые похожи как братья-близнецы - т.е. регистры канала(А) являются точной копией регистров канала(В). Откроем утилиту RW и посмотрим на конфиг.пространство HOST-контроллёра..

Нажмите на изображение для увеличения
Название: mbar1.png
Просмотров: 320
Размер:	21.9 Кб
ID:	5014

Для доступа к любому из корневых контроллёров нужен его BAR, младший бит в котором является 'битом достоверности адреса' и не учитывается. Здесь видно, что BAR моего DRAM-контроллёра лежит в 32-битном регистре(44h) хоста, и указывает на адрес FED1_4000 (в терминологии конфиг.пространства PCI все смещения называют регистрами). Листаю даташит дальше и вижу, что DRAM-регистры начинаются со-смещения 100h относительно базы, значит я должен указать адрес FED1_4100. Рассмотрим эти регистры подробней..

Нажмите на изображение для увеличения
Название: mbar3.png
Просмотров: 359
Размер:	51.3 Кб
ID:	5015
  1. 00-03h: Rank Boundary - верхняя граница адреса для ранков 0-3 канала А.
    В среднем, на каждый канал производитель вешает по 2 слота DIMM, и каждый DIMM имеет право быть 2-ранковым. У контроллёра есть 4 регистра 00:03h для каждого из ранков двуслотовой конфигурации, причём для канала В предусмотрены свои DRB-регистры. Они задают потолок адреса для каждого из ранков в 32-МБ единицах. Используются для определения того, какую из линий CS# нужно активировать для текущего адреса.

    Например у меня, во-всех этих регистрах лежит значение 20h (см.рис.выше). Соответственно, перевожу его в DEC=32 и умножаю на гранулярность 32 МБ. Угу.. значит мои слоты поддерживают планки с макс.ёмкостью ранка в 32*32=1024 МБ - если модуль 2-ранковый, то 2048 МБ. Другими словами, линии CS# на моём чипсете будут переключаться всякий раз, на пересечении 1-Гбайтной границы адреса, и я не смогу заставить его работать с DDR-SDRAM, ёмкость ранка которого превышает 1 ГБ.

  2. 08h: Rank 0-1 Attribute - регистр ранковых атрибутов определяет размеры DRAM-страниц.
    Если модуль 1-ранковый, то соответствующие поля регистра забиваются нулями. В этом 8-битном регистре кодируются оба ранка одного модуля DIMM, а моё значение DRA=03h, что эквивалентно 00000011. От мл.бита к старшему расшифровывается оно так - страница ранка(0) размером 8 КБ, а ранк(1) пустой:

    биты[2:0] - размер DRAM-страницы ранка 0:
    000 = ранк отсутствует;
    010 = 4 КБ;
    011 = 8 КБ.

    биты[6:4] - размер DRAM-страницы ранка 1 (см.биты 2:0).

  3. 09h: Rank 2-3 Attribute - см.описание регистра 08h.
    Поскольку у меня всего 1 слот на каждом из каналов, то этот регистр имеет значение 0 и не используется.

  4. 0Ch: Clock Disable - отключение тактовой частоты на неиспользуемых слотах DIMM.
    8-битный регистр решает проблему электромагнитных помех от линии Clock. Если слот пустой, то клок на нём отключается (сброшенный бит в регистре). Внутри байта, слоты нумеруются от мл.бита к старшему.

  5. 0E-0Fh: Bank Architecture - 16-битный регистр хранит кол-во банков в модулях DIMM.
    Хотя регистр размером в слово, старший его байт отправлен в резерв. В младшем байте на каждый ранк выделяется по 2-бита, значит в 8-битах можно закодировать все 4 ранка одного канала памяти (два слота на канал): 00=4-банка, 01=8-банков. У меня регистр DBA=0005h=00.00.01.01 (без ст.байта), что означает поддержку моим контроллёром 8-банковых модулей DDR2-SDRAM.

  6. 14-17h: Timing Register - 32-битный регистр текущих таймингов канала памяти.
    Мои значения: 03618922h, в каждых/трёх битах кодируются 4 тайминга. Поскольку портянка там большая, есть повод ознакомится с даташитом на свой чипсет.

  7. 20-23h: Controller Mode 0 - 32-битный режим работы самого DRAM-контроллёра.
    Толмут с описанием потянет на отдельную статью, поэтому детали - в даташите:

    бит[29] - BIOS выставляет этот бит после настройки DRAM-контроллёра;
    бит[10:8] - авто или ручная регенерация ..и если ручная, то с какой скоростью;
    бит[6:4] - один из 7-ми спец.режимов работы интерфейса DRAM при включении питания;
    бит[1:0] - 4 типа интерфейса DDR1,2,3,4.

  8. 24-27h: Controller Mode 1 - ещё одно определение режима, в котором фигурирует только старший бит(31). Разрешает расширенное распределение участков памяти, взамен стандартной карты адресов.

Большинство перечисленных регистров заполняется биосом на этапе процедуры POST. Инфа запрашивается из м/схем SPD модулей памяти и заносится в соответствующие регистры DRAM-контроллёра. Нужно отметить, что данные регистры доступны на чтение и запись, поэтому загрузчик ОС может без труда изменить конфигурацию контроллёра под свои требования.


Синхронная и асинхронная работа контроллёра

DRAM-контроллёр может функционировать как в синхронном, так и в асинхронном режиме передачи данных. В чём разница и какой режим выигрывает в производительности? Давайте разбираться..

Передача данных по каналу связи осуществляется либо байтами, либо массивом байт, называемым 'кадром данных'. Кадры могут содержать сотни байт, однако в обоих случаях передача осуществляется только последовательно, бит-за-битом. Если наименьшей единицей является всё-таки бит, то синхронизировать передачу нужно тоже по-битно. Тогда получается, что чем больше частота следования тактовых импульсов, тем выше скорость передачи данных.

• В синхронном режиме, CPU по управляющей линии посылает DRAM-контроллёру запрос, и не ждёт от него ответа. Он просто даёт пару-тактов на обдумывание, после которых контроллёр должен начать передачу данных, предварив эти данные командным байтом 'Start'. Процессор судит об окончании передачи по флагу 'Stop!' и даже не информирует контроллёр о том, успешно или нет прошёл обмен - он тупо освобождает шину памяти и продолжает заниматься своими делами. Одним словом - полное доверие и взаимопонимание, в результате чего экономится драгоценное время.

Такая картина предъявляет жёсткие требования к синхронной работе всех участников обмена, иначе получим винегрет. Значит и CPU и DRAM-контроллёр и сама память обязательно должны работать на одной частоте - никаких множителей и прочих виртуальных обманок быть не должно! К сожалению, в наше время частота работы процессора давно обогнала частоту памяти, поэтому о синхронном режиме DRAM-контроллёра остаётся только вспоминать.

Вообще-то и сейчас можно встретить синхронный обмен, но только в серверных архитектурах, где применяется память типа 'Rambus' (со-своим RDRAM-контроллёром). Этот тип памяти способен работать на более высоких частотах, чем обычная память, и если правильно подобрать конфигурацию серверного железа, то можно загнать контроллёр в синхронный режим. Это тема для отдельного разговора, и мы не будем в неё вникать. Лучше посмотрим на отличительные особенности двух режимов:

Нажмите на изображение для увеличения
Название: async.png
Просмотров: 340
Размер:	13.6 Кб
ID:	5016

В синхронном режиме, передатчик и приёмник устанавливают начальную синхронизацию, затем непрерывно передают данные на протяжении всей транзакации. Это позволяет эффективно доставлять большие пакеты данных на больших скоростях, зато никто не несёт ответственности за достоверность переданной информации. Сей факт считается слабым местом синхронных контроллёров памяти.

• Асинхронный режим уступает синхронному тем, что из-за несоответствия рабочих частот участников обмена, DRAM-контроллёру приходится сначала накопить в буфере считанные из DDR данные, и только потом передать их в синхронном режиме процессору. Ясно, что где буфер - там и тормоза, которые умножают на ноль все достоинства асинхронного режима. Но как-бы то нибыло, на наш век выпала участь сидеть именно на асинхронных контроллёрах, без возможности перехода в синхронный режим по указанным выше причинам.

Здесь, процессор выставляет на шину запрос и ждёт от контроллёра ответа ACK#. Плюс такой политики в том, что до получения ответа на запрос, процессор может переключится на другую задачу, а не томиться в ожидании его прихода (в это время, в режиме DMA память может читать кто-то другой). Как-только от контроллёра поступит ответ, процессор опять переключится на DRAM-контроллёр и начнёт шинную транзакацию.

Согласно асинхронному протоколу, байты здесь не передаются непрерывным потоком, а собираются в кадры. Помимо самих данных, каждый кадр должен иметь маркеры своего начала и конца. То-есть синхронизировать приходится уже не только пакет, но и отдельные его кадры. На данный момент размер кадра составляет 64-байт, что как-раз вписывается в одну CacheLine пакетного режима с BL=8. По окончанию обмена, приёмник отвечает передатчику подтверждением приёма, что гарантирует доставку данных.
Размещено в Без категории
Просмотров 2837 Комментарии 0
Всего комментариев 0
Комментарии
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.