Comments 46
А поддержки llvm хоть в каком-то виде там нет?
0
«Очень хороший вопрос! Я ждал этого вопроса. Пожалуйста, следующий вопрос!» ©
Я не разбираюсь в теме, но мне кажется, что разработку / поддержку двух сильно разных компиляторов МЦСТ не потянет — хорошо бы хоть LCC пилить, не отставая от нововведений C++XX.
Я не разбираюсь в теме, но мне кажется, что разработку / поддержку двух сильно разных компиляторов МЦСТ не потянет — хорошо бы хоть LCC пилить, не отставая от нововведений C++XX.
+5
Так реализация llvm как раз позволит не пилить свой компилятор, а воспользоваться clang, а может быть и gcc (не знаю, на сколько его llvm backend стабилен).
Да и другие языки можно было бы использовать, скажем, Rust.
Да и другие языки можно было бы использовать, скажем, Rust.
+5
> для высокоуровневого разбора исходных кодов используется фронтэнд от Edison Design Group
Они не пилят.
Кроме того, видимо, биткод не очень хорош для влива, и используются другие структуры данных, более подходящие.
Они не пилят.
Кроме того, видимо, биткод не очень хорош для влива, и используются другие структуры данных, более подходящие.
+1
Для VLIW нельзя не пилить свой компилятор, одна из главных черт этого класса архитектур — упрощение структуры за счет того, что значительная часть работы перекладывается на компилятор, который в принципе является неотъемлемой частью процессора.
+1
Нужно поддерживать только backend. В представлении LLVM достаточно информации для оптимизации.
+1
А что я то? Я точно не гуру. :) Ну а так, конечно LLVM можно хотя и очевидно, что сложнее чем не VLIW.
С другой стороны в LLVM уже есть несколько VLIW архитектур и в последнее время была проделана работа в этом направлении.
Ошибочное утверждение. Хотя конечно с LLVM не всё будет просто.
Меня бесит больше то, что они юзают GPL ный GCC, а исходники не открывают.
С другой стороны в LLVM уже есть несколько VLIW архитектур и в последнее время была проделана работа в этом направлении.
Для VLIW нельзя не пилить свой компилятор
Ошибочное утверждение. Хотя конечно с LLVM не всё будет просто.
Меня бесит больше то, что они юзают GPL ный GCC, а исходники не открывают.
0
Если я не ошибаюсь, то можно тот же rust скомпилить в C, с помощью соответствующего бэкенда к llvm, а получившийся код потом уже, например, в этот LCC засунуть.
0
Я слышал о том что некие коллективы делали что то на базе LLVM для МЦСТ. Вполне вероятно, что речь была о бакенде для Эльбруса.
P.S.: По поводу инструкции return в середине. Могу предположить, что здесь происходит что-то аналогичное delay slot из мира MIPS (обратите там внимание на примеры). Если инструкция упала в конвейер в общем кортеже, то она будет ждать выполнения хвоста. А потом управление будет передано в соответствии с return.
P.S.: По поводу инструкции return в середине. Могу предположить, что здесь происходит что-то аналогичное delay slot из мира MIPS (обратите там внимание на примеры). Если инструкция упала в конвейер в общем кортеже, то она будет ждать выполнения хвоста. А потом управление будет передано в соответствии с return.
+1
nop 5 — скорее всего, действительно ожидание результата. Но вот return %ctp — это гораздо хуже — это подготовка перехода, который можно выполнить когда угодно. Если бы там была только игра с задержками, им бы пришлось ставить return за фиксированное число тактов конвейера до актуального момента перехода (решение более элегантное, хотя и менее гибкое).
+1
Насчет операции return, — погуглите «split branch sh5», это нечто похожее. Общий смысл такой: процессоре есть три так называемых «станка подготовки перехода», для можно запустить подготовку перехода заранее, а затем инструкцией «ct» выполнить переход на один такт (если он будет подготовлен к этому моменту).
+3
а если проще: он крут или нет?
+1
Если исполнение команд процессора хоть чем-то похоже на процессоры TI C6xxxx (а на первый взгляд, сходства очень много), то разобраться в ассемблерных программах без очень подробного описания будет совершенно нереально. Одно только отложенное получение результата чего стоит (это когда в конвейере устройства находится сразу несколько команд на разных стадиях выполнения). И куча команд nop 5 указывает, что ждать результатов действительно приходится.
Надо книжку почитать.
Надо книжку почитать.
0
И куча команд nop 5 указывает, что ждать результатов действительно приходится.Это могут быть delay slot-ы, о которых я выше уже отписался.
0
Почитал… Ну они и наворотили. Команды для явного управления памятью L2… надо же такое придумать.
А почему команда return стоит в начале — это отложенная команда перехода. Она заносит в %ctpr3 (не знаю, что это такое) информацию о переходе и начинает загружать и обрабатывать команды, которые будут выполняться после перехода. И по команде ct %ctpr3 выполняется уже сам переход — конвейер уже полностью подготовлен.
А почему команда return стоит в начале — это отложенная команда перехода. Она заносит в %ctpr3 (не знаю, что это такое) информацию о переходе и начинает загружать и обрабатывать команды, которые будут выполняться после перехода. И по команде ct %ctpr3 выполняется уже сам переход — конвейер уже полностью подготовлен.
+2
Даааа, вспоминаются лабораторные ВУЗовские по TMS, где чтение из памяти на 4 такта отложено, и эти 4 такта можно оперировать старым значением регистра.
0
Плюс 5 тактов на выполнение перехода. И при этом цикл из 8 команд при большой удаче можно упаковать в один такт.
0
Про переход за 5 тактов не помню, почему-то кажется, что в 1 делалось. По крайней мере, на том процессоре.
Да, упаковка хороша. Помню, была задача обработать массив с количеством тактов меньше кол-ва элементов в массиве. Ох, сидели мы, строили графики «лесенкой», паковали инструкции и в итоге-таки добились того, что с точки зрения программиста на x86 просто невозможно.
Да, упаковка хороша. Помню, была задача обработать массив с количеством тактов меньше кол-ва элементов в массиве. Ох, сидели мы, строили графики «лесенкой», паковали инструкции и в итоге-таки добились того, что с точки зрения программиста на x86 просто невозможно.
0
Выполняется переход, конечно, за 1 такт. Но заказывать его надо за 5 тактов до перехода. На процессорах TMS320C6xxx.
А обработать массив быстрее, чем за такт на элемент — тут сильно зависит от наличия команды загрузки двойного регистра (LDDW) — кажется, она появилась только в C64xx. Без неё удастся в лучшем случае посчитать сумму элементов.
А обработать массив быстрее, чем за такт на элемент — тут сильно зависит от наличия команды загрузки двойного регистра (LDDW) — кажется, она появилась только в C64xx. Без неё удастся в лучшем случае посчитать сумму элементов.
0
Не помню такого, вроде за 1 такт и непосредственно по «заказу». Но модель не помню, допускаю, что есть различия.
А там какой-то примитив навроде суммы и был. Все равно, по сравнению с х86 удивительно было.
А там какой-то примитив навроде суммы и был. Все равно, по сравнению с х86 удивительно было.
0
Давненько я не брал в руки шашек…
Можно даже сказать, никогда.
Можно даже сказать, никогда.
Тем не менее, код работает.
sum:
CMPGT .L2 B4,0,B0
|| ZERO .L1 A5
|| ZERO .S2 B5
|| ZERO .S1 A3
[!B0] B .S2 _END
NOP 5
MVC CSR,B6
AND B6,-2,B0
MVC B0,CSR
AND .L2 B4,1,B1
|| ADD .S2X 4,A4,B2
|| SHR .S1X B4,1,A2
[B1] LDW .D1 *A4++[2],A3
|| [!A2] B .S2 _END
|| [A2] SUB .L1 A2,1,A2
LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
_LOOP:
ADD .L1 A5,A0,A5
|| ADD .L2 B5,B0,B5
|| LDW .D1 *A4++[2],A0
|| LDW .D2 *B2++[2],B0
|| [A2] SUB .S1 A2,1,A2
|| [A2] B .S2 _LOOP
_END:
B .S2 B3
MVC B6,CSR
ADD .L1 A5,A3,A4
ADD .L1X A4,B5,A4
NOP 2
0
Что-то типа такого. Кстати, судя по всему вы правы — переход через 5 тактов:
Не уверен, что это хороший код, но рабочий. У меня лежит примерно 30 вариантов, в каждом по несколько циклов ужимается, а вот какой финальный — не помню. Интересный был предмет.
.ref _c_int00 ;точка входа
_c_int00:
;///////////////////////////////////////
.data ;секция данных
array1: .ushort 1,2,3,1,2,6,7,8,1,1,1,1,1,2,1,2,3,4,5,6,7,8,1,2,6 ;создаем массив 32 разрядных чисел
size .set 23 ;размер массива(>1)(препроцессорная константа)
;///////////////////////////////////////
.text ;секция кода
;Инициализация:
MVKL .S1 array1,A7 ;загружаем адрес массива1 в A3
MVKH .S1 array1,A7
; ADD .S1 A3, 2, A7
MVK .S2 size,B2 ;загружаем колво элементов массива в A2
; SUB .L2 B2,1,B2
MVK .S1 1,A5 ;ПРОИЗВЕДЕНИЕ ТЕКУЩИХ элементов массива
MVK .S1 2,A6 ;сумма произведений
MVKL .S1 0X20001, A12
MVKH .S1 0X20001, A12
MVK .S1 0,A1
MVK .S1 0,A4 ;GGGG
MVK .S1 0,A8
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
NOP 4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
NOP 4
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
NOP 4
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
NOP 4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||ADD .S1 A7,2,A7
LOOP:
[B2] B .S2 LOOP
||SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
SUB .D2 B2,1,B2
||LDW .D1 *A7, A0
||CMPEQ .L1 A0,A12,A2
||ADD .S1 A7,2,A7
||[A2] ADD .L2 B4,1,B4
THEEND:
NOP
Не уверен, что это хороший код, но рабочий. У меня лежит примерно 30 вариантов, в каждом по несколько циклов ужимается, а вот какой финальный — не помню. Интересный был предмет.
0
Непонятно, как он может быть рабочим. Ведь в этих процессорах нельзя читать память по невыровненному адресу (точнее, можно — но только начиная с C64, и используя команду невыровненного чтения — LDNW, а не LDW).
0
Серьёзная задача. Похоже, что можно упаковать обработку 8 элементов в 6 тактов. Но это будет очень непросто.
0
Примерно так.
.global find12
find12:
AND .L2 B4,3,B2
|| SHR .S1X B4,2,A2
|| ADD .D2XA4,4,B4
|| ZERO .L1 A0
|| ZERO .S2 B0
|| MV .D1 A6,A8
ZERO .L2 B2
|| SUB .L1 A2,2,A2
|| MV .D2XA6,B8
|| MVC CSR,B9
AND B9,-2,B1
MVC B1,CSR
|| LDW .D1 *A4++[2],A5 ;; [0@0]
|| LDW .D2 *B4++[2],B5 ;; [0@0]
NOP 2
LDW .D1 *A4++[2],A5 ;; [0@3]
|| LDW .D2 *B4++[2],B5 ;; [0@3]
NOP
CMPEQ .L1 A5,A8,A1 ;; [5@0]
|| SHR .S1 A5,16,A7 ;; [5@0]
LDW .D1 *A4++[2],A5 ;; [0@6]
|| LDW .D2 *B4++[2],B5 ;; [0@6]
|| ADD .S1 A0,A1,A0 ;; [6@0]
|| B .S2 _F12LOOP
SUB .D2 B5,B8,B1 ;; [7@0]
|| SHL .S1X B5,16,A6 ;; [7@0]
|| SHR .S2 B5,16,B7 ;; [7@0]
|| ZERO .L2 B6 ;; [7@0]
|| [A2] SUB .D1 A2,1,A2 ;; [7@0]
CMPEQ .L1 A5,A8,A1 ;; [5]
|| SHL .S2X A5,16,B6 ;; [5]
|| SHR .S1 A5,16,A7 ;; [5]
|| [!B1] ADD .L2 B0,1,B0 ;; [8]
|| ADD .D1 A6,A7,A6 ;; [8]
|| ADD .D2 B2,B6,B2 ;; [8]
_F12LOOP:
LDW .D1 *A4++[2],A5 ;; [0]
|| LDW .D2 *B4++[2],B5 ;; [0]
|| ADD .S1 A0,A1,A0 ;; [6]
|| ADD .L2 B6,B7,B6 ;; [6]
|| CMPEQ .L1 A6,A8,A1 ;; [9]
|| [A2] B .S2 _F12LOOP ;; [9]
SUB .D2 B5,B8,B1 ;; [7]
|| SHL .S1X B5,16,A6 ;; [7]
|| SHR .S2 B5,16,B7 ;; [7]
|| CMPEQ .L2 B6,B8,B6 ;; [7]
|| [A2] SUB .D1 A2,1,A2 ;; [7]
|| ADD .L1 A0,A1,A0 ;; [10]
CMPEQ .L1 A5,A8,A1 ;; [5]
|| SHL .S2X A5,16,B6 ;; [5]
|| SHR .S1 A5,16,A7 ;; [5]
|| [!B1] ADD .L2 B0,1,B0 ;; [8]
|| ADD .D1 A6,A7,A6 ;; [8]
|| ADD .D2 B2,B6,B2 ;; [8]
;; end loop
B .S2 B3
CMPEQ .L1 A6,A8,A1 ;; [9]
ADD .L2 B0,B2,B0
ADD .L1 A0,A1,A0 ;; [10]
ADD .L1X A0,B0,A4
MVC .S2 B9,CSR
3 такта на 4 полуслова.
Правда, этот код работает только для массивов длиной, кратной 4 и не меньше 12, но добавить дополнительную обработку для коротких массивов — дело техники.
0
А уж как в этих процах (TI) тормозит кастрированный C++ код… Интересно как тут оптмизатор с плюсами справляется.
0
А как с ними вообще можно справиться? Для вызова виртуальной функции нужно, как минимум, двойное обращение к памяти (плюс какой-нибудь анализ на случай множественного наследования), а потом — сам вызов. Тоже весьма долгий, так как адрес заранее неизвестен. Хорошо, если параллельно с подготовкой вызова можно ещё что-нибудь поделать. А если нет — остаётся только ждать.
+1
Очень круто вы все описываете — тема сложная, но изложено все грамотно и системно, в отличие от многих подобных статей на хабре. Спасибо!
Сколько же этот Эльбрус был у вас «проездом», что так детально удалось покопаться? :)
Сколько же этот Эльбрус был у вас «проездом», что так детально удалось покопаться? :)
+4
(книгу не смотрел)
Вангую, что расположение инструкции return явно учитывает наличие конвейера. return начинает загружать инструкции из точки возврата в конвейер, а пока до них дойдёт управление, выполняются идущие перед ними инструкции текущей функции.
Вангую, что расположение инструкции return явно учитывает наличие конвейера. return начинает загружать инструкции из точки возврата в конвейер, а пока до них дойдёт управление, выполняются идущие перед ними инструкции текущей функции.
0
Есть ли возможность скачать где-то LCC от МЦСТ, в виде кросс компилятора с x86/amd64 или в виде исходников?
0
А в чём выражется совместимость с GCC? Можно ли Аду открутить от GCC и поставить на LCC?
0
Имеется в виду способность выглядеть как GCC, плавать как GCC (но не крякать как GCC, правда) — с точки зрения языков C, C++, Fortran. То есть поддерживаются все те же ключи запуска и дополнения к языковым стандартам. Компилируемая программа думает, что ею занимается GCC; хотя, если она в курсе про существование LCС, то, конечно, может детектировать его по соответствующим define'ам.
+1
Мда. Очень печально, что адскими проверками нельзя насладиться на архитектуре, которая реализует их аппаратно.
Интересно было бы сравнить Эльбрус+LCC и CHERI+BERI. CHERI поизвестнее LCC будет, однако внезапно Эльбрус у нас оказался более массовым, а я думаю, Эльбрусов выпущено гораздо больше, чем BERI.
Интересно было бы сравнить Эльбрус+LCC и CHERI+BERI. CHERI поизвестнее LCC будет, однако внезапно Эльбрус у нас оказался более массовым, а я думаю, Эльбрусов выпущено гораздо больше, чем BERI.
0
Only those users with full accounts are able to leave comments. Log in, please.
Обзор и сравнительное тестирование ПЭВМ «Эльбрус 401‑PC». Часть третья — средства разработки