Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Предисловие
Это вторая часть попытки создания TTA процессора в программе Logisim. В процессе создания появилась нужда в дополнительной памяти, в которой могли бы храниться некоторые промежуточные значения, а для этой памяти появилась нужда в изменении управляющего устройства.
Часть 1.
Часть 2.
Дополнительная память
Так как команды и константы сложно хранить в памяти, сложно будет сделать полностью адресуемую память, значит нужно что-то попроще, для этого хорошо подойдет стек или очередь.
Очередь не выглядит очень удобно, да и для стека придуман язык Forth, компилятор которого мне хотелось бы и написать. Реализуем стек как функциональное устройство:
Выглядит запутанно, но на самом деле это устройство выполняет простые функции: счетчик указывает на следующую ячейку, при поступлении данных, они записываются в ячейку, на которую указывает счетчик и он увеличивается, при взятии данных, они отдаются из ячейки, стоящей предыдущей за той, на которую указывает счетчик и счетчик уменьшается. Тут возникает другая проблема, как узнать что из стека взяли данные, для этого нужен флаг, тогда управляющее устройство(УУ) будет выглядеть так:
Для удобства соединения выходы будут располагаться слева, а входы справа, тогда блок УУ и другие функциональные устройства(стек, сумматор, AND, OR, регистор и т.д.):
Соберем простую схему с памятью команд, двумя стеками, двумя регистрами, сумматором, негатором, And, Or и некоторой константой(пусть будет 5):
Осталось создать память для констант и можно писать компилятор Forth, но пока попробуем написать некоторые слова из него прямо в памяти.
Dup
Слово dup делает простую вещь: дублирует данные верхней ячейки стека обратно в стек. Для начала нужно что в стек загрузить, например нашу константу (in6 -> o1), теперь у нас есть данные в первой ячейке стека, но при взятии данных, они как-бы исчезают из стека, как быть? Для этого есть регистры, загрузим ячейку стека в регистр и она там сохраниться, после чего два раза загрузим её в стек, тем самым дублировав ее, псевдокод выглядит так:
1. in6 -> o1 // Загрузка в стек константы
2. in1 -> o3 // Загрузка ячейки из стека в регистра
3. in3 -> o1
4. in3 -> o1 // Два раза загружаем содержимое регистра в стек
Вот и всё, в памяти это выглядит так:
А после исполнения стек выглядит так:
Что и ожидалось увидеть, наши две константы. Вот и всё, похожим образом можно сделать drop, swap, rot и т.д.
Спасибо за внимание, надеюсь, было нескучно!
Ссылка на гитхаб: GitHub