Механизм рестартов
Поскольку наш проект с самодельным
АЛУ на NAND близок к успешному завершению, я продумываю и другие вопросы, связанные с нашим
4-битым ЦПУ.
И один из вопросов, аппаратно затратных - это
механизм прерываний, а мы сошлись во мнении, что прерывания необходимы. С этим вопросом тесно связан другой -
вызовы подпрограмм и возвраты из них.
В оригинале схемы, которую я выбрал из-за её простоты, но, тем не менее, и некоторой функциональности, данный вопрос решен примитивно просто, хотя и вполне работоспособно.
В этой конструкции
JMP ADDR ничем не отличается от
CALL ADDR и приводит к переключению страниц (или сегментов). То есть,
JMP ADDR происходит на смещение
0 указанного в
ADDR сегмента.
Ещё "
смелее" решен вопрос с возвратом из подпрограмм - это просто сброс программного счётчика в
0, то есть переход на ячейку с адресом
000H.
Прерывания не реализованы вовсе.
Это, конечно, всё работает, и даже можно счесть решение оригинальным для простой, но работающей модели ЦПУ, только в практической конструкции вряд ли применимо.
Мы привыкли, что адреса возвратов заносятся в стек, откуда и извлекаются по разным командам возврата. Но вот со стеком в этом проекте пока проблемы.
Поскольку для простоты мы склонились к Гарвардской архитектуре, оставив себе послабление, что в память программ возможна запись, то я пока простого механизма записи в ОЗУ, содержащее
12 бит КОП и 4 бита непосредственно данных, не вижу.
Даже табличные данные, похоже, придётся сделать как в
PIC: через
RET с загрузкой аккумулятора.
И основная проблема, что нужно бы задействовать двунаправленные шинные формирователи, а их в конструкции просто пока совершенно нет - что я, в общем-то, записываю в плюс простоте схемотехники.
Так вот, я предлагаю реализовать механизм прерываний и вызовов-возвратов через рестарты - то есть короткие переходы на фиксированный адрес, как
RST N в
i8080.
Под адреса рестартов выделить нулевой сегмент ОЗУ программ, размером в 256 байт.
Первые 3-4 этих адресов - выделить под
аппаратные прерывания, а остальные - по сути - будут
фиксированные точки возвратов из
CALL ADDR, или просто
переходы на фиксированный адрес в нулевом сегменте.
Работать всё это должно так.
Code: Select all
JMP START; переход за границу 0-го сегмента.
... ; вектора переходов
ARET5: ; фиксированный адрес перехода по RET5
JMP ADDR_RET_SUB10; возврат к вызову SUB10
... ; вектора переходов
START:
... ; что-то тут делаем в программе
CALL SUB10
ADDR_RET_SUB10: ; адрес возврата из SUB10
SUB10:
... ; что-то тут делаем в программе
RET5 ; возврат по фиксированному адресу -> ARET5
Да, возможно механизм очень непривычный, но аппаратно реализуется довольно просто и всё ж более гибкий, нежели в оригинальной конструкции.
Это же избавляет от необходимости иметь где-то стек, но, похоже, накладывает ограничение, характерное для Фортрана - подпрограмму нельзя вызвать из самой себя, или что-то похожее связанное с вызовом в цикле.
В Фортране ранних машин стек также не использовался, а адрес возврата помещался в первые ячейки вызываемой подпрограммы, откуда и вызывался по
RET.
В ЦПУ Гарвардской архитектуры необходим значительный набор
регистров общего назначения (
РОН) в роли памяти данных.
Как я упоминал уже - с этим есть проблема: на роль
РОН у меня пока претендуют регистры
К155ТМ8, по их
4-битности и доступности, но много таких корпусов в ЦПУ напихивать не хотелось бы, чтобы не раздувать простую конструкцию аппаратно.
Но, возможно, кто-либо знает другое - простое и оригинальное решение?