Архитектура

Теперь будет большой пост про разработку и оптимизацию моей 4-битной архитектуры. Вот спойлер к тому, что уже удалось запустить на моей архитектуре через эмулятор. А в следующем посте будет змейка)

В моем компьютере будет 3 регистра: 4-битный X – основной регистр: в нем будут инструкции для арифметики, данные из оперативы будут подгружаться в него и другие небольшие операции. Второй 4-битный регистр T – счетчик в циклах и на нем проверка в условных прыжках. И наконец 16-битный MAR (Memory Address Register) – регистр адреса памяти, который в том числе позволяет мне делать длинные вычисления (об этом чуть позже).

Immediate operands

Создание набора инструкций – интересная задача: выбрать оптимальный базис из 16 инструкций, на котором я смогу писать все нужные алгоритмы и делать это достаточно удобно. Первое улучшение качества жизни – добавление констант в код. Допустим, я хочу написать X = 5 в коде, чтобы потом сделать какую-то операцию. Для этого я могу хранить сначала один ниббл самой инструкции SET, а потом уже ее параметр: 5 в следующем ниббле. В архитектуре X86 так и работает (immediate operands). Такая модификация очень сильно упрощает написание кода. Например, теперь можно делать прыжки на конкретные строки, а не только относительные. То есть цикл на моей архитктуре будет выглядеть вот так:

MARK LOOP // Сохранение номера строчки на который прыгать под названием LOOP

// Логика цикла

INC // T += 1

TJMP LOOP // If (T != 0) JMP LOOP

А еще, так как оперативную память найти на 4 бита очень трудно, то у меня будут 8 битные RAM и ROM. Это на самом деле очень приятно, так как это значит, что инструкция и ее параметр будут занимать одну ячейку памяти. Это сильно упростит устройство компьютера.

Работа с RAM/ROM/матрицей

У моего компьютера будет Гарвардская архитектура, то есть отдельно ROM для программы и каких-то нужных файлов и отдельно RAM для промежуточных вычислений и переменных. Плюс ROM — данные в нём не теряются при потере питания, а плюс RAM — высокая скорость доступа.. В мою архитектуру нужно было добавить инструкции для работы с обоими. А еще есть матрица и кнопки для ввода/вывода информации, для которых я тоже изначально думал сделать свои инструкции. Но тут я немного подсмотрел архитектуры у других компьютеров: Вместо того, чтобы поддерживать инструкции для RAM, ROM и матрицы, можно работать с ними как с одной сущностью. Например, часто бывает индекс памяти MAR (Memory Address Register) – 16 бит, но при этом сами чипы памяти – 15 бит. Это сделано, чтобы первый бит в MAR отвечал за то – это будет RAM или ROM. Тем самым получается нужно поддерживать только один набор инструкции для работы с обоими типами памяти. У меня еще добавляется матрица и генератор псевдо-рандомных чисел. Поэтому первые 2 бита MAR отвечают за тип обращения, а оставшиеся 14 – за сам адрес.

Длинная арифметика

Так, как у меня всего 16 чисел в регистрах, то сразу возникла пробема длинной арифметики: если мне не хватает регистров, чтобы проитерироваться по моей матрице 16×16, то как вообще мне с ней работать? Изначально я думал сделать матрице свой небольшой контроллер, который бы делал flush пикселя и сдвигал текущий пиксель на следующий. Тем самым можно было бы все обновлять. Но это не сильно удобнее и требует свой контроллер для матрицы.

Поэтому я сделал MAR 16-битным регистром с поддержкой своих простых операций сложения и вычитания – то есть длинная арифметика. Поскольку по нему нужно лишь последовательно передвигаться по нему, то мне достаточно только эти 2 операции. Кроме того, я переоформил их как прибавление 1 к конкретному биту MAR (то есть +/- 2^d). А чтобы прочитать этот регистр в мой 4-битный X есть команда, которая принимает какой ниббл MAR я хочу прочитать и записать в X. Тем самым, чтобы вывести пиксель в матрицу мне достаточно записать значение в MAR, где первые 2 бита отвечают за матрицу, а последние 8 – кодируют конкретный пиксель. Очень удобно и просто реализовать.

И если вы считаете, что я считерил сделав MAR 16 битным в своем 4-битном компьютере, то взгляните например на микропроцессор 6502: в нем регистры 8 бит, но для работы с памятью тоже выделено 16 бит)

Instruction set

Вот как выглядит моя архитектура в текущий момент:

CategoryCommandDescriptionComments
MiscNOPDo nothing for one cycle
MiscSET kX = kSet constants in code
MiscSWPX, T = T, X
JumpsJMP kPC = kUnconditional jump
JumpsTJMP kif (T == 0) PC += 2 else PC = kConditional jump
ArithmeticADDI kX = (X + k) mod 16
ArithmeticINCT = T + 1
ArithmeticAND kX = X & kBit and (if k = 0 => AND with T)
ArithmeticXOR kX = X | kBit xor (if k = 0 => XOR with T)
ArithmeticSFTX = X >> 1Bit shift right (div by 2)
MemoryLDX = RAM[MAR]
MemoryWTRAM[MAR] = X
MemorySMAR dMAR = X with shift d
MemoryIMAR dMAR = (MAR + (1 << d)) mod 16384Decrease MAR
MemoryDMAR dMAR = (MAR – (1 << d)) mod 16384Increase MAR
MemoryGMAR dX = (MAR >> d) & 0xFGet the specified nibble from MAR to X

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *