электроника сәнгате
644 subscribers
643 photos
71 videos
56 files
319 links
сәлам дуслар! здесь схемотехника, pcb дизайн, микроконтроллеры, линукс встроенный и десктопный
Download Telegram
⚡️alignment

В большинстве современных систем минимальный адресуемый объём информации — один байт. Как удобно было работать с восьмиразрядками, у которых машинное слово — тоже один байт! Можно было безболезненно и просто обращаться к любой ячейке памяти.

С ростом разрядности процессора появляется проблема. Процессор обязан уметь читать и записывать объём информации, равный машинному слову, за одну инструкцию, иначе профит от увеличения разрядности во многом теряется. Но при этом нужно уметь читать и записывать байтную информацию, это удобно для многих приложений, скажем, для работы с ascii-строками. Если процессор 32-разрядный, то хорошо бы ещё уметь адресовать 16-битные полуслова, так как некоторые переменные целесообразно делать именно 16-битными. Итого имеем множество способов обращения в память, и сделать устройство управления, которое допускало бы все сценарии обращений, очень тяжело.

Выход: сделать систему чтения памяти, которая всегда читала бы 32-разрядное слово, чей адрес описывается битами A31-A2. При команде lw (чтение 32 бит) слово сразу бы передавалось в регистр. При команде lb (чтение 8 бит) конкретный байт выбирался бы битами A1 и A0 и передавался бы в младший значащий байт регистра. При команде lh (чтение 16 бит) нужное полуслово выбиралось бы битом A1 и следовало бы в младшее значащее полуслово регистра.

Собственно, так и сделано в RISC-V.

Из минусов: команда lw применима только к двоичным адресам, которые оканчиваются на 2 нуля. То есть, обратиться в ячейку 0x1234 можно, а 0x1235 — нет, процессор выкинет исключение "load address misaligned", "адрес загрузки не выровнен". Аналогичная ситуация с командой lh, она неприменима к нечетным адресам.

Компилятор, зная данную особенность процессора, размещает переменные в памяти как надо, чтобы не вызывать конфликтов выравнивания при обращении и использовать статическую память оптимально.

Однако есть 2 вещи, где порядок переменных пользователь определяет сам: структуры и аргументы функций. Аргументы функций сейчас трогать не будем, а вот структуры рассмотрим подробнее.

Я создал тип данных-структуру:
typedef struct
{
uint32_t dummy1; //4
uint8_t dummy2; //1
uint32_t dummy3; //4
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

И вроде бы она должна занимать в памяти 4+1+4+1+1=11 байт, но если посмотреть размер через sizeof, получим:
Size of struct: 16
Object address: 02003FE0

На поле dummy1 компилятор выделяет 4 байта. Адрес начала объекта-структуры делится на 4 нацело. Если бы на dummy2 был выделен 1 байт, то абсолютный адрес dummy3 уже не был бы кратен 4, и процессор не смог бы быстро читать поле dummy3. Поэтому на dummy2 выделяется аж 4 байта, где 3 байта никак не используются, это пустышки. Чтобы адреса переменных за структурой были так же выровнены, после полей dummy4 и dummy5 идут еще 2 байта-пустышки. Итого получаем 16.

5 байт драгоценной ОЗУ улетели в трубу. Ужас!
Иногда экономия памяти важнее производительности, и на этот случай в компиляторах GCC существует атрибут packed:
typedef struct __attribute__((packed))
{
uint32_t dummy1; //4
uint8_t dummy2; //1
uint32_t dummy3; //4
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

В этом случае структура будет плотно "сжата", и пустышек не будет:
Size of struct: 11
Object address: 02003FE4

Но в то же время обращение к полю dummy3 очень сильно усложнится. Для простого чтения поля процессору придется дважды читать 32-разрядные ячейки, дважды применять инструкцию сдвига и еще применить инструкцию логического ИЛИ. Атрибут packed — это очень радикальная вещь, и лучше его не использовать. Вместо этого предлагается оптимальнее расставлять переменные в структуре.
typedef struct
{
uint32_t dummy1; //4
uint32_t dummy3; //4
uint8_t dummy2; //1
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

Здесь компилятору приходится вводить лишь одну пустышку, и память удается сэкономить.
Size of struct: 12
Object address: 02003FE4
🔥5
⚡️alignment-2

Собственно, слово "alignment" означает "выравнивание". В 16-разрядных машинах адреса переменных выравниваются по 2 байта, в 32-разрядных — по 4 байта. Но иногда нам нужно выровнять переменные так, чтобы их адреса были кратны какой-то большей степени двойки. Для этого в GCC существует атрибут aligned.

Рассмотрим на примере.
typedef struct __attribute__((aligned(8)))
{
uint32_t dummy1; //4
uint32_t dummy3; //4
uint8_t dummy2; //1
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

Size of struct: 16
Object address: 02003FE0

Структура начала занимать 16 байт, хотя поля расположены в правильном порядке. Обращаем внимание на адрес: он кратен 8. Для наглядности попробуем выровнять по большему значению.
typedef struct __attribute__((aligned(128)))
{
uint32_t dummy1; //4
uint32_t dummy3; //4
uint8_t dummy2; //1
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

Size of struct: 128
Object address: 02003F00

Адрес действительно выравнивается, теперь он стал кратен 128.
Кстати, интересно, что абсолютное значение адреса уменьшилось. Это потому что я создаю объект в теле функции main, не помечая его ключевыми словами volatile или static, и этот объект лоцируется в область стека, которая растет сверху вниз. То, что адрес стал меньше, значит, что под объект было выделено больше памяти в стеке.

P.S. Кстати, атрибут aligned сильнее, чем атрибут packed. Если написать так:
typedef struct __attribute__((aligned(128), packed))
{
uint32_t dummy1; //4
uint32_t dummy3; //4
uint8_t dummy2; //1
uint8_t dummy4; //1
uint8_t dummy5; //1
} my_struct_t;

Результат будет тот же, что и раньше.
Size of struct: 128
Object address: 02003F00
🔥6
⚡️restrict-указатели

Появились в Си не сразу, в 1999 году, оттого почему-то малораспространены.

Сообщают компилятору, что к области памяти, на которую указывает указатель, имеет доступ только одна подпрограмма. Это позволяет компилятору удобно кешировать необходимые элементы области в регистрах без боязни нарушить работу других участков кода.

Можно сравнить 3 вида указателей:
volatile-указатели;
• обычные указатели;
restrict-указатели.

Рассмотрим случай, когда имеем дело с указателем на структуру, внутри которой есть поле "счетчик". Каждое обращение через volatile-указатель неизбежно ведет к обращению в память. При использовании restrict-указателя при частых обращениях к счетчику поле будет скопировано в регистр, и при обращении к нему будет применяться регистровая адресация, гораздо более быстрая, нежели обращение в память. При использовании обычного указателя будет что-то среднее — в одних случаях то, в других это. В целом надо учиться по-максимуму использовать restrict-указатели там, где можно, особенно в однозадачных приложениях.
int mik32fat_wheels_single_read(void *__restrict cookie, uint32_t sector_addr, uint8_t *dst);
🔥7
«Кошечка» — советский мультфильм, созданный в 1968 году с помощью машины БЭСМ-4. Один из первых примеров компьютерной анимации.

Кадры фильма формировались путём печати символов БЭСМ-4 на бумаге с помощью алфавитно-цифрового печатающего устройства АЦПУ-128, затем их готовил к «плёнке» профессиональный художник-мультипликатор. Именно ему принадлежат кадры (следующие за титрами), когда кошка строит рожицы и выгибает спину.

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

Другим важным техническим нововведением мультфильма было представление трёхмерного анимируемого объекта в виде иерархической структуры данных, напоминающей октодерево. На западе подобные техники анимации были переоткрыты только в 1980-х годах, хотя в биомеханике такие расчёты движения велись и раньше — с начала 1970-х годов.

Уравнения мультфильма не выводились исходя из физических моделей мышц и суставов животного, они составлены «на глазок», чтобы воспроизводить типичную походку кошки. Тем не менее, авторам удалось достигнуть реализма движений, который отметил, к примеру, профессор Университета Огайо Рик Парент, автор фундаментальной книги «Компьютерная анимация: алгоритмы и технология».

В комментариях будет полная статья по данной научной работе.
19👍311
Сегодня на канале опубликован обзор на BUSY Bar - девайс, помогающий сконцентрироваться на важных задачах.
В обзоре вас ждут:
- фишки и особенности
- создание интеграции с девайсом с помощью chatGPT и HTTP API
- бесплатное приложение BUSY
- разборка девайса
- средства отладки
- железячная эстетика

Приятного просмотра!

BUSY Bar. Большой обзор
https://youtu.be/rHnStTAFY_c
🔥5🥰2🤔1
Forwarded from Lemora Electronics⚡️
Чип-арт — это крошечные изображения, наносимые непосредственно на кристалл интегральных схем. Явление было популярно в 1970-80-е. Чип-арт являлся не только способом самовыражения, но и позволял доказать факт копирования чипа конкурентом, поскольку в то время использовалось копирование методом изготовления фотошаблонов, то есть копировали всё, что было на чипе
🔥62