Исследование процессора и его функциональная симуляция

от автора

Наверное каждый программист ASM / C / C++ когда-то задумывался о написании своей собственной операционной системы.

И наверное каждый разработчик Verilog / VHDL для ПЛИС когда нибудь задумывался о создании своего процессора.

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

Я решил поизучать ARM совместимый процессор AMBER. Его исходники есть на http://opencores.org.

Прежде всего, нужно заметить, что исходники проекта AMBER из opencores описывают не самый новый процессор. Это всего лишь ARM v2a. Это все из-за того, что более старшие процессоры и их система команд запатентованы, а вот v2a нет. Тем не менее, я решил выбрать для своих экспериментов именно этот процессор потому, что:

  • все таки это ARM – один из самых популярных процессоров в телефонах, планшетах и всяких embedded системах. Изучение системы команд ARM не пройдет зря.
  • исходный код процессора написан на Verilog – мне этот язык знаком.
  • разработчиком системы на кристалле AMBER предоставляются патчи ядра Linux для его сборки и вроде бы инструкции вполне подробные.

Мне кажется, что создание «нового» процессора само по себе возможно, но не имеет ценности без компилятора и ОС. Каждый разработчик, желающий начать создание своего процессора должен задумываться об этом. Система на кристалле AMBER вроде бы дает пищу для ума – есть и процессор ARM v2a, и компилятор GCC и есть Linux.

Несмотря на то, что исходники системы открыты, работу предстояло сделать большую. Оригинальный проект AMBER запускался на отладочной плате с ПЛИС Xilinx. Я же собирался портировать проект на совсем другую плату с ПЛИС Altera.

Я портирую проект AMBER на плату Марсоход2:

На этой плате установлена ПЛИС Cyclone III EP3C10E144C8 (10 тысяч логических элементов), микросхема памяти SDRAM 8Mb, встроенный программатор на базе FTDI FT2232H, микросхема АЦП, кнопочки, светодиодики, разъем VGA. Вполне бюджетная плата.

Микросхема FTDI дает плате USB интерфейс. Чип FT2232H имеет два канала, которые могут программироваться в разные режимы работы. В данной плате предполагается, что канал A микросхемы FTDI будет использоваться для программирования ПЛИС через JTAG, а канал B будет как скоростной последовательный порт (921600 бит/сек). Оба канала работают независимо друг от друга. Таким образом, ПЛИС может принимать или передавать данные через последовательный порт, а тем временем внутренние сигналы ПЛИС можно изучать инструментом Altera SignalTap через JTAG. Это довольно удобно – все через один кабель USB – и питание платы, и передача данных и загрузка/отладка проекта.

К сожалению, портирование проекта AMBER в плату Марсоход2 было не очень гладким и потребовало довольно много усилий. Некоторые проблемы были предсказуемыми и понятными, вроде того, что в проекте нужно было заменить Xilinx компоненты DLL и блоки памяти для кеша или bootram на аналогичные компоненты Altera. Или вот еще понятная задача – вместо компоненты DDR контроллера использовать модуль SDRAM. Я использовал Wishbone BUS совместимый SDRAM контроллер с открытыми исходниками с того же opencores. Еще нужно было сделать новые назначения входных/выходных сигналов пинам ПЛИС согласно схемы платы Марсоход2.

Другие проблемы, которые пришлось решать, оказались совсем не тривиальными.

Например, оказалось, что некоторые конструкции языка Verilog трактуются компилятором Altera Quartus II несколько не так, как у компилятора Xilinx. Более того, для функциональной симуляции проекта я использовал Icarus Verilog и похоже он трактует Verilog так же, как и Xilinx, а не так, как Altera. Это несколько расстраивает, но в конце концов, мне удалось выявить и исправить проблемные места в исходном коде Verilog процессора AMBER после симуляции икарусом и внутрисхемной отладки с Altera SignalTap.

Следующая трудность была связана с ядром Linux, которое я компилировал для запуска на плате. Здесь я совсем не ожидал проблем, ведь автор системы на кристалле AMBER Santifort Conor описал в своей инструкции как собирать ядро и как его запускать. Не знаю почему, но его инструкция не сработала. Я встретил и проблему наложения патчей и ошибки компиляции ядра, которые пришлось решать по ходу дела. Так же пришлось вносить изменения в конфигурационные файлы ядра, вносить изменения в само ядро.

Тем не менее, результат уже есть. Как это работает в железе:

Программой терминала TeraTerm открываю COM порт принадлежащий плате и из другой программы программатора Altera Quartus II загружаю образ HW системы в ПЛИС. Процессор стартует из bootram ПЛИС и в консоли терминала появляется интерактивный «монитор». С его помощью можно читать или писать в ячейки памяти, а так же загрузить любой файл из компьютера в ОЗУ платы через тот же последовательный порт протоколом XMODEM.

Так, я загружаю initrd по адресу 0x700000 и загружаю само ядро Linux по адресу 0x80000. Команда “j 80000” из консоли монитора запускает ядро и видно, как оно стартует:

Полный вывод консоли выглядит вот так:

Linux version 2.4.27-vrs1 (nick@ubuntu) (gcc version 4.5.2 (Sourcery G++ Lite 2011.03-46) ) #1 Tue Jan 22 23:48:37 PST 2013 CPU: Amber 2 revision 0 Machine: Amber-FPGA-System On node 0 totalpages: 256 zone(0): 256 pages. zone(1): 0 pages. zone(2): 0 pages. Kernel command line: console=ttyAM0 mem=8M root=/dev/ram 19.91 BogoMIPS (preset value used) Memory: 8MB = 8MB total Memory: 6304KB available (783K code, 222K data, 64K init) Dentry cache hash table entries: 4096 (order: 0, 32768 bytes) Inode cache hash table entries: 4096 (order: 0, 32768 bytes) Mount cache hash table entries: 4096 (order: 0, 32768 bytes) Buffer cache hash table entries: 8192 (order: 0, 32768 bytes) Page-cache hash table entries: 8192 (order: 0, 32768 bytes) POSIX conformance testing by UNIFIX Linux NET4.0 for Linux 2.4 Based upon Swansea University Computer Society NET3.039 Initializing RT netlink socket Starting kswapd ttyAM0 at MMIO 0x16000000 (irq = 1) is a WSBN pty: 256 Unix98 ptys configured Serial driver version 5.05c (2001-07-08) with no serial options enabled ttyS00 at 0x03f8 (irq = 10) is a 16450 ttyS01 at 0x02f8 (irq = 10) is a 16450 RAMDISK driver initialized: 16 RAM disks of 208K size 1024 blocksize NET4: Linux TCP/IP 1.0 for NET4.0 IP Protocols: ICMP, UDP, TCP IP: routing cache hash table of 4096 buckets, 32Kbytes TCP: Hash tables configured (established 4096 bind 8192) NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. RAMDISK: ext2 filesystem found at block 0 RAMDISK: Loading 200 blocks [1 disk] into ram disk... done. Freeing initrd memory: 208K VFS: Mounted root (ext2 filesystem) readonly. Freeing init memory: 64K BINFMT_FLAT: Loading file: /sbin/init Mapping is 2b0000, Entry point is 8068, data_start is 8e4c Load /sbin/init: TEXT=2b0040-2b8e4c DATA=2b8e50-2b8e83 BSS=2b8e83-2b8e88 start_thread(regs=0x21f9fa4, entry=0x2b8068, start_stack=0x2affb4) Hello, World! Hello, Marsohod! 

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

Симуляция производится с помощью тестбенча. Тестбенч – это такая же программа на Verilog, только она описывает уже всю систему целиком.

Например, есть система AMBER, портированная для платы Марсоход2. Это тот проект, который я компилирую с помощью Altera Quartus II и потом получившийся образ загружаю в ПЛИС. У модуля самого верхнего уровня SOC AMBER есть входной сигнал тактовой частоты 100Мгц, вход и выход последовательного порта TX/RX, а так же сигналы к микросхеме памяти SDRAM.

Если написать к этой системе тестбенч, то у него уже не должно быть ни входов ни выходов – теперь это будет уже модуль самого верхнего уровня – иммитатор печатной платы с ее компонентами. Тестбенч должен имитировать кварцевый генератор платы, внешний приемопередатчик последовательного порта (возможно посылающий команды через порт), а так же иммитировать микросхему SDRAM. Модели микросхем памяти можно получить у их производителей. По крайней мере Micron выкладывает Verilog модели своих микросхем памяти в свободный доступ, где я ее (модель микросхемы MT48LC4M16A2) и взял.

Запуск тестбенча в симуляторе Verilog дает возможность полностью проследить все сигналы системы. Это может быть не просто и может быть довольно долго. Но это очень мощный инструмент.

Например, в симуляторе можно видеть циклы исполнения команд процессора, содержимое регистров, служебные сигналы:

Еще можно рассмотреть pipeline процессора, увидеть циклы обращения к кэшу или к внешней памяти, можно реально измерить и увидеть реакцию на прерывания процессора.

Вообще, можно полностью симулировать в тестбенче запуск и исполнения ядра Linux.
Я это делал, в консоли командной строки с помощью Icarus Verilog:

Правда на этом скриншоте прервал симуляцию в самом начале – полная симуляция длится около часа или даже больше и то, если не делать полный дамп всех сигналов в VCD файл. А так да, все возможно.

Я вот тоже мечтаю сделать свой процессор. Думаю этот опыт мне пригодится…

Полезные ссылки:
1) Исходный проект системы на кристалле AMBER на сайте http://opencores.org
2) Исходники проекта AMBER для ПЛИС Altera Cyclone III на GitHub (мое портирование). В исходниках весь код системы на кристалле, а так же тестбенчи и патчи для ядра Linux. Все что требуется для полного воспроизведения полученного результата.
3) Вся история портирования описана подробно здесь.
4) Описание и схема платы Марсоход2.

ссылка на оригинал статьи http://habrahabr.ru/post/167987/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *