2024-11-12

vak: (Default)
Прибавление в моей коллекции: компьютер Aquarius+ Mini. Фактически реплика древнего Mattel Aquarius, но с современной периферией. Процессор установлен родной Zilog Z80 на частоте 3.5 МГц. Память 512 килобайт, переключаемая страницами по 16к. Стандартный монитор VGA, клавиатура USB, карточка SD, звук стерео. Есть выход на WiFi и Bluetooth через встроенный микроконтроллер ESP32. Имеется на Ebay за $150.

Есть бейсик с кучей игрушек, Си-компилятор SDCC, операционная система CP/M. Под CP/M тоже есть игрушки, к примеру классический Zork. Все материалы на Гитхабе. Имеется развитый симулятор.

Есть подробное техническое описание для программистов: TRM Overview



Обзор:



Ещё фотки )

Симпатичный девайс получился. В юности я мечтал про подобный компьютер, медитируя на схему Радио-86РК. 😀 Подумалось: не предложить ли [personal profile] spamsink портонуть сюда LSX Unix? Вроде ресурсов достаточно. Если юникс поместился на БК-0010, то сюда и подавно влезет.
vak: (Default)
Представьте, что вам в программе нужно сложить два целых числа. Получили некий ответ, скажем 42. Верный ли это результат? А вдруг произошло переполнение, и на самом деле вышло огромное число, но не поместилось в размер переменной? Большинство языков программирования помочь не могут.

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

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

Не так давно в компиляторы GCC и CLANG ввели встроенные функции, чтобы отлавливать переполнение. Посмотрим, как эта штука работает.

Сложение

int64_t a, b, c;
if (__builtin_add_overflow(a, b, &c)) {
// переполнение
}
Компилируем для riscv64. Конструкция превращается в машинные команды:
add     a4, a2, a3          # a4 = a + b
slti a1, a3, 0 # a1 = (b < 0)
slt a5, a4, a2 # a5 = (a + b < a)
bne a1, a5, overflow # (b < 0) != (a + b < a) ? overflow
Это эквивалентно Си-шному коду:
int64_t a, b, c;
c = a + b;
if ((b < 0) != (c < a)) {
// переполнение
}
Вполне эффективное решение.

Умножение

Интересно, как компилятор сделает проверку переполнения при умножении.
int64_t a, b, c;
if (__builtin_mul_overflow(a, b, &c)) {
// переполнение
}
Смотрим машинный код для riscv64.
mul     a4, a2, a3          # a4 = (a * b) bits 63:0
mulh a1, a2, a3 # a1 = (a * b) >> 64
srai a5, a4, 63 # a5 = (int64_t) (a * b) >> 63
bne a1, a5, overflow # (a * b) >> 64 != (int64_t) (a * b) >> 63 ? overflow
На Си это выглядело бы:
int64_t a, b, c;
c = a * b;
if (((int128_t)a * b) >> 64 != c >> 63) {
// переполнение
}
Неплохо придумано. К счастью, на RISC-V имеется хитрая команда MULH, которая умножает два 64-битных целых и выдаёт старшие 64 бита результата.
vak: (Default)
Последние версии компилятора умеют порождать код для архитектуры VE:
clang --target=ve -O -S hello.c
Это векторный процессор фирмы NEC, судя по всему нечто наподобие Cray-1.

"The VE architecture provides 64 scalar 64-bit registers (%s0 - %s63). In addition, the architecture provides 64 vector registers (%v0 - %v63), each 64-bit wide 256 elements, and 16 vector mask registers (%vm0 - %vm15), each 256-bit wide."

Про эту архитектуру мне удалось нагуглить документы:
vak: (Default)
Я тут подумал. Если взглянуть на взаимодействие юзерского кода с ядром юникса, можно заметить, что системы команд не обязаны совпадать. Программа юзера может иметь одну систему команд, а ядро - совсем другую. Параметры системного вызова передаются через регистры. Если форматы данных и указателей более-менее совместимы, то и нет проблем.

Мы имеем мэсм6, то есть реализацию системы команд БЭСМ-6 на Верилоге. А Микрочип имеет PolarFire: микропроцессор RISC-V с Линуксом и FPGA в одном чипе. Платка стоит $132 на microchipdirect.com.
Что если скрестить ежа с ужом? Добавить к имеющимся ядрам RISC-V еще и ядро БЭСМ-6. Благо FPGA вроде немаленького размера (95K логических элементов). Научить Линукс запускать и обслуживать процесс БЭСМ-6. Задействовать имеющийся у нас компилятор Паскаля, и можно будет кодить для БЭСМ-6 под Линуксом!

А если ещё маленько поднапрячься, можно и мониторную систему "Дубна" подтащить. Получим весь спектр языков программирования и ассемблеров. Опыт мы наработали на симуляторе dubna.

Мне кажется, вполне реальная идея.