Практикум «Оптимизирующие компиляторы» (на примере GCC) (1157417), страница 11
Текст из файла (страница 11)
Длина таблицы для инструкции непревышаетвременивыполненияинструкции.Примертаблицырезервирования приведен ниже.Реализация распознавателя конфликтов основывается на использованииконечных автоматов, построенных на базе таблиц резервирования. Каждоесостояниеавтоматафункциональныхотражаетустройствивсесуществующеерезервированиевозможностибесконфликтногоисполнения инструкций в этом состоянии в виде переходов в иныесостояния автомата. Если два состояния соединены дугой (маркировкадуги соответствует выполняемой инструкции), то эта инструкция можетбыть выполнена в текущем состоянии автомата и её выполнение невызовет конфликтов по ресурсам с инструкциями, которые в данныймомент выполняются в конвейере.
Из каждого состояния автоматаПрактикум «оптимизирующие компиляторы»проведена дуга, маркированная ’следующий такт’ – она используется вслучае, если нет возможности в этом такте выполнить какую-либоинструкцию.Рассмотрим гипотетический процессор, состоящий из трёх устройств:целочисленного арифметико-логического устройства (АЛУ), АЛУ длячисел с плавающей запятой и функционального устройства (ФУ) доступа кпамяти (Рисунок 17).intfloatmemРисунок 17. Структурная схема гипотетического процессораПроцессор может выполнять следующие инструкции:a) целочисленная арифметико-логическая операция занимает на 1 тактцелочисленное АЛУb) арифметико-логическая с плавающей точкой занимает на 1 такт АЛУдля чисел с плавающей запятойc) загрузка значения из памяти или сохранение в памяти в течениепервого такта занимает целочисленное АЛУ и устройство доступа кпамяти, в течение второго такта только устройство доступа к памяти.Соответствующая схема резервирования представлена в таблице 7.Практикум «оптимизирующие компиляторы»Таблица 7.
Таблица резервирования для гипотетического процессора.ЗанятыеустройстваКласс инструкции1такт2 тактЦелочисленная (i)int-с плавающей запятой (f)float-Загрузка из памяти (ls)mem+ intmemКонечный автомат для описанного процессора представлен на Рисунке 18(0 – означает,что устройство “доступно”, x – “не доступно”).Подробности о составление автомата на базе таблиц резервированияпредставлены в [24].fx000x0сл. тактx0x0x0iсл. такт000000сл. тактfiсл.
тактls00x000x0x0xx00x0x0flsсл. тактсл. тактx000xxсл. такт0000x0Рисунок 18. Автомат для определения конфликтов приисполнении инструкцийПрактикум «оптимизирующие компиляторы»Длятогочтобыопределитьресурсныезадержкипланировщикуинструкций достаточно пройти из начального состояния по дугам,соответствующим инструкциям или дугам, маркированным ‘сл. такт’, еслиневозможновыполнитьинструкцию.Фактическиформировательрасписания инструкций прямо использует автомат при генерациирасписания инструкций.Модель описания конвейера в GCCВ GCC описание процессора производится с помощью Lisp-подобногоязыка. Синтаксис основных конструкций, необходимых для описанияпроцессора, приведен в Таблице 8.Таблица 8. Синтаксис описания модели конвейера.КонструкцияОписаниеконструкцииПараметры конструкции(define_automatonAUTOMATON-NAME)определениеавтомата —распознавателяконфликтовAUTOMATON-NAME – строка,название автомата(define_cpu_unit UNITNAMESAUTOMATON-NAME)определениефункциональныхустройствпроцессораUNIT-NAMES – строка, названиефункционального устройстваAUTOMATON-NAME – названиеавтомата, куда помещаетсяописываемое устройство(define_insn_reservationINSN-NAMEDEFAULT-LATENCYCONDITION REGEXP)определениерезервированияфункциональныхустройств дляинструкцийDEFAULT-LATENCY – число,определяющее латентность(время исполнения) инструкцииINSN-NAME – строка,внутреннее имя инструкцииCONDITION – определяет какиеRTL инструкции описываются(класс инструкций)REGEXP – описывает, какиефункциональные устройствапроцессора будутзарезервированы инструкцией(define_reservationопределениеRESERVATION-NAME резервированияREGEXP)функциональныхустройствклассоминструкцийRESERVATION-NAME – строка,имя резервированияREGEXP – описывает, какиефункциональные устройствапроцессора будутзарезервированы инструкциейПрактикум «оптимизирующие компиляторы»(exclusion_setUNIT-NAMESUNIT-NAMES)(presence_setUNIT-NAMESPATTERNS)(absence_setUNIT-NAMESPATTERNS)определениедополнительныхограничений,налагаемых наресурсы приисполненииинструкцийUNIT-NAMES – строка,перечисление функциональныхустройствPATTERNS – строка, шаблоныфункциональных устройств,перечисленных через запятую.Шаблон – одно устройство илигруппа устройств, перечисленныхчерез пробелПри описании конвейера сначала определяется автомат с помощьюdefine_automaton.Файлописанияможетсодержатьнесколькоавтоматов, но все они должны иметь уникальные имена.
На практикеразличные автоматы применяются для описания различных процессороводной архитектуры. Иногда несколько автоматов применяются дляописания одного процессора.Таблица 9. Синтаксис описания резервирования устройств.regexp = regexp “,” oneof| one ofСимвол “,” используется дляразделения резервирования по тактамalloff = allof “+” repeat| repeatСимвол “+” используется для описаниятого, что резервирование определяетсяи первым регулярным выражением, ивторым регулярным выражением и т.д.oneof = oneof “|” allof| allofСимвол “|” используется для описаниятого, что резервирование определяетсяили первым регулярным выражениемили вторым регулярным выражением ит.д.repeat = element “*” number| elementСимвол “*” – указывает на то, чтоelement будет зарезервирован numberтактовelement = cpu_unit_name| reservation_name| result_name| “nothing”| “(“ regexp “)”“nothing” – функциональные устройстване резервируютсяcpu_unit_name – резервируетсясоответствующее функциональноеустройствоДля описания характеристик занятия конвейера классом инструкцийприменяется конструкция define_insn_reservation.
Для описаниярезервирования используются регулярные выражения, в Таблице 9приведен их синтаксис.Практикум «оптимизирующие компиляторы»Рассмотрим описание конвейера на примере гипотетического процессора.Пример описанияВ качестве примера рассмотрим фрагмент описания суперскалярногоRISC-процессора, который может выбирать на исполнение три инструкции(две целочисленных и одну с плавающей запятой) за один такт, но можетзавершить выполнение только двух инструкций. Схематически такойпроцессор представлен на Рисунке 19. Фрагмент описания конвейераприведен ниже.inti0_pipelinefloatmemport0i1_pipelinei2_pipelinedivport1Рисунок 19. Структурная схема гипотетического процессора.Рассмотрим описания функциональных устройств и инструкций.Порты декодирования инструкций:1: (define_cpu_unit “i0_pipeline, i1_pipeline”)Целочисленное АЛУ не описывается.АЛУ с плавающей запятой и выходные порты:2: (define_cpu_unit “f_pipeline, port0, port1”)Устройство “деление”3: (define_cpu_unit “div”)Простая целочисленная инструкция, исполняющаяся 2 такта:4: (define_insn_reservation “simple” 2Практикум «оптимизирующие компиляторы»(eq_attr “cpu” “int”)“(i0_pipeline|i1_pipeline),(port0|port1)”)Инструкция умножения (полностью конвейеризирована, потому неиспользуется выделенное устройство-умножитель):5: (define_insn_reservation “mult” 4(eq_attr “cpu” “mult”)“i1_pipeline, nothing*2,(port0|port1)”)Инструкция деления, (не конвейеризирована):6: (define_insn_reservation “div” 9(eq_attr “cpu” “div”)“i1_pipeline, div * 7, div + (port0|port1)”)Инструкции обработки чисел с плавающей запятой:7: (define_insn_reservation “float” 3(eq_attr “cpu” “float”)“f_pipeline, nothing, (port0|port1)”)Все простые целочисленные инструкции могут запускаться через декодер вцелочисленных конвейерах, результат выполнения будет доступен черездва такта (определение 4).
Сначала целочисленная инструкция пытаетсязанять функциональное устройство i0_pipeline, если оно занято делаетсяпопытка занять функциональное устройство i1_pipeline. Целочисленноеумножение и деление могут исполняться только во втором целочисленномконвейере, их результат выполнения будет получен через 4 и 9 тактовсоответственно (определения 5 и 6). Инструкция умножения (определение5) полностью конвейеризирована – т.е. новая инструкция умноженияможет быть подана на исполнение в каждом такте. Целочисленное делениене конвейеризировано (т.е.
невозможно запустить инструкцию деления,пока не отработала предыдущая аналогичная инструкция). Операции сплавающей запятой полностью конвейеризированы, результат их доступенчерез 3 такта (определение 7).Практикум «оптимизирующие компиляторы»Описание целевой машины в GCC на примере микроконтроллерасемейства AVR.AVR – это новое семейство 8-разрядных RISC-микроконтроллеров фирмыAtmel.
Они отличаются сравнительно большой скоростью работы и большейуниверсальностью. Очень быстрая гарвардская RISC-архитектура загрузки ивыполнения большинства инструкций в течение одного цикла тактовогогенератора. Смысл её состоит в том, что память программ и данныхрасполагается в разных областях памяти. Так во время выполнения однойкоманды следующая выбирается из памяти.
Отсутствует внутреннее делениечастоты (если использован кварцевый резонатор 16 МГц, то быстродействиебудетпочти16MIPS).Программысодержатсявэлектрическиперепрограммируемой постоянной памяти FLASH ROM. Система командмикроконтроллеров AVR изначально проектировалась с учетом языкапрограммирования высокого уровня C. Микроконтроллер имеет 32 регистра,каждый из которых напрямую работает с АЛУ. Имеются относительныекоманды переходов и ветвлений, что позволяет получать перемещаемый код.Отсутствует необходимость переключать страницы памяти.Кроме регистровых операций, для работы с регистровым файлом могутиспользоваться доступные режимы адресации, так как регистровый файлзанимает адреса $00-$1F в области данных, обращаться к ним можно и как кячейкам памяти.Пространство ввода/вывода состоит из 64 адресов для периферийныхфункций процессора, таких, как управляющие регистры, таймеры/счетчики идр.Доступкпространствуввода/выводаможетосуществлятьсянепосредственно как к ячейкам памяти, расположенным после регистровогофайла ($20-$5F).Практикум «оптимизирующие компиляторы»Большинство команд, использующих регистры, могут использовать любыерегистрыобщегоназначения.Исключениесоставляютпятькомандоперирующих с константами: SBCI, SUBI, CPI, ANDI, ORI и команда LDI.Эти команды работают только со второй половиной регистрового файла –R16…R31.Шесть из 32 регистров – R26…R31 – можно использовать как три 16разрядных адресных указателя в адресном пространстве данных.
Этирегистры обозначаются как X, Y, Z. Регистр Z можно использовать дляадресации таблиц в памяти программы.Регистр X:Регистр Y:157R27($18)157R26($1A)000 7R29($1D)Регистр Z:000 7157R28($1C)000 7R31($1F)R30($1E)Эти регистры могут использоваться как фиксированный адрес для адресациис автоинкрементном или с автодекрементном.Большая часть команд имеет размер 16 разрядов. Каждый адрес в памятипрограммы содержит одну 16 или 32-разрядную команду.При обработке прерываний и вызове подпрограмм адрес возвратазапоминается в стеке, размещаемом в оперативный памяти SRAM, или вреализуемом аппаратно стеке глубиной 3, для микроконтроллеров без SRAM.Минимальное время реакции на любое из предусмотренных в процессорепрерываний – 4 такта.Практикум «оптимизирующие компиляторы»Детальную информацию о микроконтроллерах AVR можно получить насайте производителя www.atmel.com.Теперьперейдёмктому,какрассмотреннаяархитектураAVRпредставляется в GCC.tm.htm.ctm.mdRTLCodeRTLAssemblerРисунок 20В GCC описание процессора (класса процессоров) выделено в несколькоотдельных от основной реализации back end’а файлов, а именно: tm.h,tm.c, tm.md (см.