Вы когда-нибудь задумывались, «как работает процессорЭ» Да-да, именно тот, который стоит в вашем ПК/ноутбуке/смартфоне.
В этой статье я хочу привести пример процессора собственного изобретения, спроектированного на языке Verilog. Verilog — это не совсем тот язык программирования, на который он похож.
Это язык описания оборудования.
Написанный код ничем не исполняется (если, конечно, вы не запускаете его в симуляторе), а превращается в физическую схемотехнику или в форму, воспринимаемую FPGA (программируемой пользователем вентильной матрицей).
Отказ от ответственности: эта статья является результатом университетского проекта, поэтому время было ограничено, и многие части проекта все еще находятся на ранних стадиях разработки.
Обратите внимание, что процессор, созданный в этой статье, имеет мало общего с современными широко распространенными процессорами, но создавая его, я пытался достичь несколько иной цели.
Чтобы по-настоящему понять процесс программирования, вам необходимо понять, как работает каждый из используемых инструментов: компилятор/интерпретатор языка, виртуальная машина, если она у вас есть, промежуточный код и, конечно же, сам процессор.
Очень часто люди, изучающие программирование, на первом этапе проводят много времени — они думают только о том, как работает язык и его компилятор.
Это часто приводит к ошибкам, пути решения которых начинающему программисту неизвестны, поскольку он понятия не имеет, откуда берутся корни этих проблем.
Я сам видел несколько живых примеров, где ситуация была примерно такой же, как в описании выше, поэтому я решил попробовать исправить эту ситуацию и создать набор вещей, которые помогут начинающим программистам понять все этапы.
Этот набор состоит из:
- Фактически изобретенный язык
- Плагин подсветки для VS Code
- Компилятор для этого
- Набор инструкций
- Простой процессор, способный выполнять этот набор инструкций (написанный на Verilog).
Вещи, которые вам понадобятся, если вы хотите запустить его самостоятельно: Для запуска моделирования ЦП вам понадобится ModelSim, который можно загрузить с веб-сайта Intel. Для запуска компилятора OurLang требуется версия Java > = 8. Ссылки на проекты: https://github.com/IamMaxim/OurCPU https://github.com/IamMaxim/OurLang Расширение: https://github.com/IamMaxim/ourlang-vscode Для сборки части Verilog я обычно использую bash-скрипт:
Но это можно повторить через графический интерфейс.#/bin/bash vlib work vlog *.
v vsim -c testbench_1 -do "run; exit"
Для работы с компилятором удобно использовать Intellij IDEA. Главное — следить за тем, от каких модулей у нужного вам модуля есть зависимости.
Я не сделал готовый .
jar общедоступным, поскольку ожидаю, что читатель прочтет исходный код компилятора.
Запущенные модули — Компилятор и Интерпретатор.
С компилятором все понятно, Interpreter — это всего лишь симулятор OurCPU на Java, но в этой статье мы его рассматривать не будем.
Набор инструкций
Я думаю, лучше начать с набора инструкций.Существует несколько архитектур набора команд:
- На основе стека — это то, что описано в статье.
Отличительной особенностью является то, что все операнды помещаются в стек и берутся из стека, что сразу исключает возможность распараллеливания выполнения, но в то же время является одним из самых простых подходов к работе с данными.
- Аккумуляторный — суть в том, что существует только один регистр, хранящий значение, модифицируемое инструкциями.
- Регистрация на основе регистров — это то, что используется в современных процессорах, поскольку позволяет добиться максимальной производительности за счет использования различных оптимизаций, включая распараллеливание выполнения, конвейерную обработку и т. д.
Далее предлагаю взглянуть на реализацию процессора: Код состоит из нескольких модулей:
- Процессор
- БАРАН
- Модули для каждой инструкции
ЦП — модуль, который непосредственно управляет выполнением программы: читает инструкции, передает управление нужной инструкции, сохраняет необходимые регистры (указатель на текущую инструкцию и т. д.).
Почти все инструкции работают только в стеке, поэтому вам нужно их просто выполнить.
Некоторые (например, putw, putb, jmp и jif) имеют дополнительный аргумент в самом операторе.
Им нужно дать всю инструкцию, чтобы они смогли прочитать необходимые данные.
Вот диаграмма, которая в общих чертах описывает ход работы процессора:
Общие принципы проектирования программ на уровне инструкций Думаю, пришло время познакомиться со структурой самих программ.
Как видно из диаграммы выше, после выполнения каждой инструкции адрес переходит к следующей.
Это дает линейную прогрессию программы.
Когда возникает необходимость нарушить эту линейность (условие, цикл и т.п.
), используются инструкции ветвления (в нашем наборе инструкций это jmp и jif).
При вызове функций нам необходимо сохранять текущее состояние всего, и для этого существуют записи активации — записи, хранящие эту информацию.
Они никоим образом не привязаны к самому процессору или инструкциям, это просто концепция, которая используется компилятором при генерации кода.
Запись активации в OurLang имеет следующую структуру:
Как видно из этой диаграммы, локальные переменные также хранятся в записи активации, что позволяет вычислять адрес переменной в памяти во время компиляции, а не во время выполнения, и тем самым ускоряет выполнение программы.
Для вызовов функций наш набор инструкций предоставляет способы работы с двумя регистрами, содержащимися в модуле ЦП (указатель операции и указатель адреса активации) — putopa/popopa, putara/popara.
Компилятор
Теперь посмотрим на часть, наиболее близкую к конечному программисту — компилятор.В целом компилятор как программа состоит из 3 частей:
- Лексер
- Парсер
- Компилятор
Анализатор строит абстрактное синтаксическое дерево из этих лексических единиц.
Компилятор просматривает это дерево и генерирует некоторый код, состоящий из инструкций низкого уровня.
Это может быть как байт-код, так и двоичный код, готовый к исполнению процессором.
В компиляторе OurLang эти части представлены классами соответственно.
- Лексер.
java
- Парсер.
java
- Компилятор.
java
Язык
OurLang находится в зачаточном состоянии, то есть работает, но многого в нем еще нет и даже Core часть языка не доделана.Но для понимания сути работы компилятора уже достаточно текущего состояния.
В качестве примера программы для понимания синтаксиса предлагается такой фрагмент кода (он также используется для тестирования функционала): // single-line comments
/*
* Multi-line comments
*/
function print(int arg) {
instr(putara, 0);
instr(putw, 4);
instr(add, 0);
instr(lw, 0);
instr(printword, 0);
}
function func1(int arg1, int arg2): int {
print(arg1);
print(arg2);
if (arg1 == 0) {
return arg2;
} else {
return func1(arg1 - 1, arg2);
};
}
function main() {
var i: int;
i = func1(1, 10);
if (i == 0) {
i = 1;
} else {
i = 2;
};
print(i);
}
Я не буду зацикливаться на языке, оставлю его для вашего изучения.
Конечно же, через код компилятора ;).
При его написании я старался сделать понятный и понятный без комментариев код, поэтому проблем с пониманием кода компилятора возникнуть не должно.
Ну, конечно, самое интересное — написать код и потом посмотреть, во что он превратится.
К счастью, компилятор OurLang генерирует ассемблерный код с комментариями.
что поможет вам не запутаться в том, что происходит внутри.
Также рекомендую установить расширение для Visual Studio Code, оно облегчит работу с языком.
Удачи в изучении проекта! Теги: #программирование #java #FPGA #verilog #свой язык
-
Спиннинг
19 Oct, 24 -
«Яндекс» Приобрел Spb Software
19 Oct, 24 -
Как Провести Трехбалльную Оценку?
19 Oct, 24 -
Сто Миллиардов Бесплатных Минут
19 Oct, 24