Выбор архитектуры процессора для LLVM / CLANG - PullRequest
15 голосов
/ 20 сентября 2011

Я проектирую последовательный компьютер TTL и изо всех сил стараюсь выбрать архитектуру, более подходящую для бэкэнда компилятора LLVM (я хочу иметь возможность запускать там любое программное обеспечение C ++).Не будет никакого MMU, никакого умножения / деления, никакого аппаратного стека, никаких прерываний.

У меня есть 2 основных варианта:

1) 8-битная память, 8-битный ALU, 8-битовые регистры (~ 12-16).Ширина адреса памяти 24 бита.Поэтому мне нужно будет использовать 3 регистра в качестве IP и 3 регистра для любой области памяти.

Нет необходимости говорить, что любые вычисления адресов были бы чистой болью для реализации в компиляторе.

2) 24-битовая память, 24-битный ALU, 24-битные регистры (~ 6-8).Плоская память, приятно.Недостатки в том, что из-за серийного характера дизайна каждая операция будет занимать в 3 раза больше тактов, даже если мы работаем с некоторыми логическими значениями.Ширина данных в 24-битной памяти дорогая.И это сложнее реализовать на аппаратном уровне в целом.


Вопрос в следующем: считаете ли вы возможным реализацию всех функций c ++ на этом 8-разрядном оборудовании без стеков, или мне нужно иметь большесложное оборудование для генерации кода приемлемого качества и скорости?

Ответы [ 5 ]

18 голосов
/ 26 сентября 2011

Второе предложение использовать LCC. Я использовал его в этом 16-битном проекте RISC: http://fpgacpu.org/xsoc/cc.html.

Я не думаю, что будет иметь большое значение, собираете ли вы 8-битный вариант и используете 3 add-with-carry для увеличения IP, или 24-битный вариант и делаете все это аппаратно. Вы можете скрыть разницу в вашем ассемблере.

Если вы посмотрите мою статью выше или еще более простой процессор здесь: http://fpgacpu.org/papers/soc-gr0040-paper.pdf, вы увидите, что вам действительно не нужно так много операторов / инструкций, чтобы охватить целое число C. Фактически, существует утилита lcc (ops), которая печатает набор операторов min для данного компьютера.

Для получения дополнительной информации см. Мою статью о переносе lcc на новую машину здесь: http://www.fpgacpu.org/usenet/lcc.html

Как только я портировал lcc, я написал ассемблер, и он синтезировал больший набор инструкций из основных. Например, у моей машины был load-byte-unsigned, но не load-byte-signed, поэтому я выпустил следующую последовательность:

lbs rd,imm(rs) ->
  lbu rd,imm(rs)
  lea r1,0x80
  xor rd,r1
  sub rd,r1

Так что я думаю, что вы можете обойтись этим минимальным прикрытием операций:

  registers
  load register with constant
  load rd = *rs
  store *rs1 = rs2
  + - (w/ w/o carry)    // actually can to + with - and ^
  >> 1                  // << 1 is just +
  & ^                   // (synthesize ~ from ^, | from & and ^)
  jump-and-link rd,rs   // rd = pc, pc = rs
  skip-z/nz/n/nn rs     // skip next insn on rs==0, !=0, <0, >=0

Еще проще - не иметь регистров (или эквивалентно размывать регистры с памятью - все регистры имеют адрес памяти).

Отложите регистр для SP и напишите в компиляторе обработчик функции prolog / epilog, и вам не придется беспокоиться о командах стека. Есть только код для хранения каждого из регистров сохранения вызываемого абонента, настройки SP в соответствии с размером кадра и т. Д.

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

Интересный проект. Я вижу, что в настоящее время проводится конкурс TTL / 7400, и я сам думал о том, как легко можно обойтись без машины, и будет ли обманом добавить асинхронную SRAM 32 КБ или 128 КБ на машину для хранения кода и данных.

В любом случае, счастливого взлома!

приписка

1) Вы захотите решить, насколько велик каждый целочисленный тип. Вы, конечно, можете сделать char, short, int, long, long long и т. Д. Одного размера, если хотите, одним 24-битным словом, хотя это не будет соответствовать минимальным диапазонам представления.

2) И хотя я сосредоточился здесь на lcc, вы спрашивали о C ++. Я рекомендую убедить C сначала. Как только вы разберетесь с C, включая операторы *, /,% в программном обеспечении и т. Д., Вам будет удобнее перейти на полноценный C ++, будь то в LLVM или GCC. Разница между C и C ++ заключается в том, что «только» лишние таблицы vtables и RTTI и кодовые последовательности (полностью построенные из повторения целочисленного оператора примитива C) необходимы для обработки вызовов виртуальных функций, указателя на разыменование члена, динамического приведения, статического конструктора, исключения обработка и т. д.

3 голосов
/ 25 сентября 2011

ИМХО, это возможно для c компилятора. Я не уверен в C ++, хотя.

LLVM / CLang может быть трудным выбором для 8-битного компьютера,

Вместо этого сначала попробуйте lcc , затем второй llvm / etc, HTH.

Биллу Бузби удалось изменить настройки компилятора lcc для своего Magic-1 (известного как homebrewcpu ).

Несмотря на то, что аппаратное проектирование и конструкция Magic-1 обычно привлекают наибольшее внимание, большая часть проекта (безусловно) занималась разработкой / портированием программного обеспечения. Для этого мне пришлось написать ассемблер и компоновщик с нуля, перенастроить компилятор C, написать и перенести стандартные библиотеки C, написать упрощенную операционную систему, а затем портировать более сложную. Это был вызов, но веселый. Полагаю, я немного извращен, но мне нравится отлаживать сложные проблемы. И, когда ошибка, которую вы пытаетесь отследить, может включать один или несколько из следующих недостатков: аппаратный недостаток конструкции, плохой или сломанный провод, плохой или плохой чип TTL, ошибка ассемблера, ошибка компоновщика, ошибка компилятора, ошибка библиотеки времени выполнения C или, наконец, ошибка в рассматриваемой программе, есть много возможностей для развлечения. О, и я также не могу позволить себе роскошь обвинять в ошибках кого-либо еще.

Я постоянно удивляюсь, что эта чертова штука работает вообще, а тем более бежит так же хорошо, как и она.

1 голос
/ 23 сентября 2011

Реализация, безусловно, возможна, но я сомневаюсь, что она будет полезна (по крайней мере, для кода C ++). Как уже было отмечено, первая проблема - отсутствие стека. Далее, связка C ++ сильно зависит от динамического выделения памяти, также «большие» структуры C ++ довольно велики.

Так что, как мне кажется, будет лучше, если вы:

  1. Избавиться от требования C ++ (или, по крайней мере, ограничить себя некоторым подмножеством)
  2. Используйте 24 бита, а не 8 бит для всего (также для регистров)
  3. Добавить аппаратный стек
1 голос
/ 22 сентября 2011

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

Когда вы идете по маршруту без стека, вы, вероятно, выделите большинство своих переменных как «статические»,и не имеют входных функций.В этом случае режимы адресации в стиле 6502 могут быть эффективными.Например, вы можете использовать следующие режимы адресации:

  1. Немедленный адрес (24 бита) как часть кода операции
  2. Немедленный адрес (24 бита) плюс индексный регистр (8 бит)
  3. Непрямой доступ: непосредственный 24-битный адрес в памяти, который содержит фактический адрес
  4. Косвенный доступ: 24-битный адрес в памяти, 8-битный индексный регистр, добавленный к значению из памяти.

АдресРежимы, описанные выше, позволят эффективный доступ к массивам, структурам и объектам, размещенным по постоянному адресу (статическое распределение).Они были бы менее эффективными (но все же применимыми) для динамически распределяемых по стеку объектов.

Вы также получили бы некоторую выгоду от вашего последовательного проекта: обычно добавление 24 бита + 8 бит не занимает 24 цикла, новместо этого вы можете закорачивать добавление, когда значение переноса равно 0.

Вместо непосредственного сопоставления IP-адреса как регистра, вы можете разрешить изменять его только с помощью инструкций перехода / перехода, используя те же режимы адреса, что и выше.Переходы к динамически вычисляемым адресам встречаются довольно редко, поэтому более целесообразно указывать весь 24-битный адрес непосредственно в коде операции.

Я думаю, что если вы тщательно спроектируете ЦП, вы сможете довольно эффективно использовать многие функции C ++.,Однако не ожидайте, что любой случайный код C ++ будет работать быстро на таком ограниченном процессоре.

0 голосов
/ 27 сентября 2011

Вы не сможете запускать там «любой» код C ++.Например, fork (), system () и т. Д. Все, что явно зависит от прерываний, например.Вы можете пройти долгий путь, конечно.Теперь вы имеете в виду какие-либо программы, которые могут / были написаны на C ++, или вы ограничиваете себя только языком, а не библиотеками, которые обычно связаны с C / C ++?Сам язык - гораздо более легкое правило.

Я думаю, что более простой вопрос / ответ: почему бы просто не попробовать?что ты уже испробовал?Можно утверждать, что x86 - это 8-битный компьютер, без учета выравнивания и множества 8-битных инструкций.msp430 был портирован на llvm, чтобы показать, насколько легко и быстро это можно сделать. Я хотел бы видеть эту платформу с лучшей поддержкой (не там, где мои сильные стороны, в противном случае я бы это делал) - 16-битная платформа.нет мму.есть стек и прерывания, конечно, не нужно их использовать, и если вы удаляете библиотечные правила, то что осталось, что требует прерывания?

Я бы посмотрел на llvm, но учтите, что подготовленная документация показывает, насколько легко это сделатьэто портировать, устарел и ошибочен, и вы в основном должны выяснить это самостоятельно из источников компилятора.У ООО есть книга, известная тем, что не оптимизирована.Источники плохо компилируются на современных компьютерах, всегда приходится возвращаться назад во времени, чтобы использовать его, каждый раз, когда я подхожу к нему после вечера, просто пытаясь собрать его, как я сдаюсь.vbcc, простой, чистый, документированный, не недружелюбный к меньшим процессорам.Это C ++, не помню.Из всех них проще всего запустить и запустить компилятор.Из всех них LLVM является наиболее привлекательным и наиболее полезным, когда все сказано и сделано.не подходите близко к gcc или даже не думайте об этом, скотч и проволочная сетка внутри удерживают его вместе.

Вы уже изобрели свой набор инструкций?у вас еще есть симулятор и ассемблер?Посмотрите на lsasim на github, чтобы найти мой набор инструкций.Вы можете написать для меня бэкэнд llvm как практику для вашего ... ухмылка ... (мой бэкэнд vbcc ужасен, мне нужно начать все сначала) ...

Вы должны иметь представление о том, какбудет реализован высокий уровень, но вам действительно нужно начать с набора команд, симулятора набора команд и какого-либо ассемблера.Затем начните вручную преобразовывать код C / C ++ в ассемблер для вашего набора инструкций, который должен довольно быстро объяснить вам «могу ли я сделать это без стека» и т. Д. В этом процессе определите соглашение о вызовах, реализуйте больше кода на C / C ++ вручнуюиспользуя ваше соглашение о вызовах.Затем копаться в компиляторе и сделать бэкэндЯ думаю, что вы должны рассматривать vbcc как ступеньку, а затем идти к LLVM, если кажется, что он (isa) будет работать.

...