* 2009 *

Макарченко И.П. (Ivan Mak aka WingLion)

Описание soft-процессоров серии EQUINOX:
Е16, Е32, Е64, 3Е16, 3Е32, 3Е64

версия документа 1.04 от 4 декабря 2009г
Внимание! документ предназначен для просмотра на дисплеях от 1024 точек по горизонали.


Изменения в документе:
05.12.09: мелкие стилистические правки
--------- 1.04
04.12.09: проведены некоторые несущественные для содержания правки
04.12.09: дополнения в описании адресного интерпретатора
04.12.09: дополнения в системе команд
03.12.09: исправлена таблица системы команд (приведена в соответствие с реальным VHDL кодом процессора)
--------- 1.03
31.10.09: изменена система обозначений процессора E16 -> 1E16, Е32 -> 1E32, E64 -> 3E64
31.10.09: добавлена информация о многоядерных вариантах процессора 3Е16, 3Е32, 3Е64
31.10.09: введены изменения в описание системы команд в соответствии с текущим состоянием проекта
--------- 1.02
04.07.09: добавлено содержание со ссылками на разные части документа и простейшей навигацией
04.07.09: изменен формат данного документа для просмотра на менее широких мониторах
--------- 1.01
03.07.09: исправлено описание команды ONE
03.07.09: изменена таблица результатов разводки
03.07.09: расширено описание адресного интерпретатора
03.07.09: добавлены ссылки на код процессора и его обсуждение на форуме
--------- 1.00
02.07.09: первая версия этого описания

Содержание

Введение
Архитектура процессора
Адресный интерпретатор
Результаты разводки процессора в Quartus II
Система команд процессора
Многоядерный вариант процессора EQUINOX

к содержанию

Введение

Название процессора EQUINOX происходит от дня, в который он был задуман − день равноденствия. Разработка полностью российская. Автор - Макарченко И.П. (Ivan Mak aka WingLion). Исходный код процессора на языке AHDL (ALTERA Hardware Design Language) свободен для доступа и обсуждается здесь: http://fforum.winglion.ru/viewtopic.php?t=1517 Ссылка на зип-файл с исходным кодом последней версии: http://winglion.ru/equinox/fcpu7.zip

Кодовые названия (1E16, 1E32, 1E64) содержaт в себе указание на варианты ширины шины данных и адреса − 16, 32 и 64. В AHDL описании ширина шин задается как параметр и должна быть кратна четырем, т.к. система команд процессора является четырехбитной.

к содержанию

Архитектура процессора

Процессор основан на стековой архитектуре. EQUINOX имеет два аппаратных стека: стек данных и стек возвратов, глубина которых задается параметром AHDL-описания. В начальной конфигурации она составляет 8 элементов стека данных и 8 элементов стека возвратов. Стек данных предназначен для хранения обрабатываемых данных, а стек возвратов используется для адресов возврата из подпрограмм и временного хранения данных.

Два внутренних регистра процессора по сути являются вершинами соответствующих стеков: PC - вершина стека возвратов, TR - вершина стека данных.



Рис.1 Архитектура процессора EQUINOX.




Рис.2 Обобщенный базовый формат команды процессора EQUINOX. Для вариантов E16, E32 и E64, соответственно, 4, 8 и 16 опкодов в слове.


Команды загружаются в процессор группами, упакованными в машинное слово, и исполняются последовательно от младшей тетрады бит к старшей.

Если среди загруженных команд появляются литеральные команды, требующие непосредственных операндов, они загружаются в процессе исполнения группы команд в тот момент, когда приходит время исполнения литеральной команды. Данные для нее берутся из следующих адресов кода программы. Если в группе несколько литеральных команд, данные для них следуют за кодовой группой последовательно в соответствии с положением литеральных команд в группе.

Так, группа команд   LIT LIT ! NOP   будет закодирована в слово 0A11 вслед за которым в коде будут находиться два литерала, которые будут взяты командами LIT и положены в стек данных, после чего произойдет исполнение команды !. Затем по команде NOP произойдет загрузка следующей группы команд из адреса кода, следующего за последним операндом. Таким образом одной группой команд в стек могут быть загружены до 4 операндов для 16-битного варианта процессора, до 8 операндов для 32-битного и до 16 операндов для 64-битного.

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

Команды с префиксами состоят из двух четверок бит (нибблов) - префикса и модификатора. Если префикс попадает в старшую тетраду командного слова, его модификатор оказывается равным нулю(!). В данный момент модификаторы используются не все. Те модификаторы, которые не описаны в таблице системы команд, остаются зарезервированными.

Исполнение команд с префиксами сдвигает регистр команд сразу на две четверки бит, и на следующем такте, после появления префикса, исполняется команда, следующая за префиксом и его модификатором.

к содержанию

Адресный интерпретатор

Процессор разработан таким образом, чтобы Адресный интерпретатор не требовал для своей работы дополнительных манипуляций. Использование адресного интерпретатора обусловлено в первую очередь уменьшением объема кода и увеличением скорости исполнения последовательности вызовов подпрограмм в подобном режиме. Объем кода уменьшается за счет отсутствия кодов команды CALL перед каждым адресом в последовательности вызовов. Увеличение скорости исполнения обеспечивается аппаратной реализацией команды NEXT, которая по сути исполняет за один такт команды RET и CALL. Адрес перехода для последней берется из кода программы верхнего уровня, адрес которого сохранен в стеке возвратов в момент исполнения первого CALL.

Вызов адресного интерпретатора производится командой CALL, вслед за которой следуют адреса исполняемых программ. Каждое слово, исполняемое адресным интерпретатором должно заканчиваться командой NEXT. В этом случае по окончании выполнения программы производится немедленный вызов следующей программы. Если программа закончится командой RET, то произойдет выход из адресного интерпретатора и возврат к командному режиму исполнения программы.

Вложенная адресная интерпретация допустима и возникает, если в выполняемой программе появляется новый вызов CALL.


Комментарии к схеме работы адресного интерпретатора:
1. Вызов адресного интерпретатора производится командой CALL за которой следует список адресов, по которым производится вызовы функций. Каждая функция заканчивается командой NEXT, которая выбирает следующий адрес из списка адресов верхнего уровня и передает его на исполнение.
2. В режиме обычного подпрограммного механизма подпрограммы завершаются командой RET. Возврат происходит на код, следующий после адреса вызова. Все команды, которые находятся после CALL в том же слове, где и код CALL - игнорируются. Адрес четверки, определяющий текущую команду в слове - отсутствует, а четверки выделяются путем сдвига командного слова в регистре команд.
3. Если команда RET встречается в слове из списка адресной интерпретации, то она работает подобно команде CODE которая переключает исполнение из режима адресного интерпретатора в нормальный режим, в котором исполняется непосредственно процессорный код.
4. Aдрес подпрограммы с единственной командой RET играет роль команды выхода из режиме адресного интерпретатора.
5. Если надо оформить некую подпрограмму, как слово, вызываемое через адресный интерпретатор, ее надо заключить в "оболочку", вызыващую эту подпрограмму отдельно и заканчивающуюся командой NEXT.
MyWORD: код подпрограммы 
	RET \ стандартное завершение подпрограммы 

	CALL MyWORD вызов подпрограммы из обычного кода
	-- \ сюда происходит возврат

MyWORD_A: \ слово MyWORD оформленное для исполнения через адресный интерпретатор
	CALL MyWORD вызов слова 
	NEXT \ сюда происходит возврат из MyWORD после чего 
	\ происходит переход на следующее слово из списка адресной интерпретации

	\ список адресной интерпретации с использованием вызова подпрограммы MyWORD
	WORDxx
	MyWORD_A
	WORDyy


к содержанию

Результаты разводки процессора в Quartus II

Результаты разводки процессора на Quartus II 9.0 Web Edition в различных режимах для разных ПЛИС.
РежимЧипОбъем, LE-/-EMB (% объема чипа)частота, MHzглубина стеков
.1E12EP2C20F484C7597-/-0 (3%)164.12 8
.1E12EP2C20F484C7501-/-0 (3%)164.12 4
.1E16EP2C20F484C7794-/-0 (4%)159.08 8
.1E16EP2C20F484C7667-/-0 (4%)162.26 4
.1E16EP1K30QC208-1997-/-0 (58%)78.74 8
.1E16mul*EP2C20F484C7794-/-2 (4%)97.21 8
.1E16Stratix II GX413ALUT263.30 8
.1E16Stratix III407ALUT411.18 8
.1E16EP3C40Q240C8811178.16 8
.1Е32EP2C20F484C71517-/-0 (8%)129.37 8
.1Е32EP2C20F484C71261-/-0 (7%)131.58 4
.1Е32mul*EP2C20F484C71608-/-6 (9%)70.88 8
.1E32Stratix II GX785ALUT230.89 8
.1E32Stratix III779ALUT345.78 8
.1E32EP3C40Q240C81553148.96 8
.1Е64EP2C20F484C73010-/-0(16%)98.74 8
.1Е64EP2C20F484C72566-/-0(16%)100.39 4
.1Е64mul*EP2C20F484C73342-/-20(18%)56.24 8
* Суффикс mul в режиме означает, что в системе команд присутствует команда умножения (при ее отключении увеличивается предельная рабочая частота, что может быть важно в ряде случаев)



к содержанию

Система команд процессора

Таблица 1. Команды процессоров Е16(E32,E64)
кодМнемоникакраткое описаниестек данныхстек возвратов
0,NOPнет операцииDS: ( −− )RS: ( −− )
1,LITзагрузка литерала DS: ( −− lit )RS: ( −− )
2,CALLвызов подпрограммы (адресного интерпретатора)( −− )( −− PC+1 )
3,RETвозврат из подпрограммы( −− )( Adr −− )
4,IFусловный переход, если вершина стека данных равна 0( Cond −− )( −− )
5,DUP#префикс операции типа DUP (глубина использования стека увеличивается)( −− Xxx )( −− )
5,0,DUPдублировать вершину стека данных( Data −− Data Data )( −− )
5,1,OVERкопировать подвершину стека данных( Data2 Data1 −− Data2 Data1 Data2 )( −− )
5,2,TRUEположить на вершину стека данных число 0( −− 0 )( −− )
5,3,FALSEположить на вершину стека данных число −1( −− −1 )( −− )
5,4,ONEположить на вершину стека данных число 1( −− 1 )( −− )
5,x,DUPRESERVED - дублировать вершину стека данных( Data −− Data Data )( −− )
6SWAP#префикс операции типа SWAP (глубина использования стека не меняется)(−− )( −− )
6,0,SWAPпоменять местами два верхних элемента стека( Data2 Data1 −− Data1 Data2 )( −− )
6,1,INCувеличить верхний элемент на единицу( Data1 −− Data1+1 )( −− )
6,2,DECуменьшить верхний элемент на единицу( Data1 −− Data1−1 )( −− )
6,3,MULперемножить два верхних элемента стека( Data2 Data1 −− Data2 × Data1 )( −− )
6,4,BSWAPпоменять местами старшую и младшую половины в верхнем элементе стека( Data1 −− Data1* )( −− )
6,5,LCONVлогическое конвертирование( Data1 −−
0 если Data1<>0 |
−1 иначе )
( −− )
6,x,SWAPRESERVED - поменять местами два верхних элемента стека( Data2 Data1 −− Data1 Data2 )( −− )
7DROP#префикс операции типа DROP (глубина использования стека уменьшается)( −− )( −− )
7,0,DROPудалить верхний элемент стека( Data2 Data1 −− Data2 )( −− )
7,1,ADDсложить два верхних элемента стека
( Data2 Data1 −− Data2+Data1 )( −− )
7,2,SUBВычесть верхний элемент из нижнего( Data2 Data1 −− Data2−Data1 )( −− )
7,3,ANDпоразрядное AND верхнего и нижнего элементов стека( Data2 Data1 −− Data2 and Data1 )( −− )
7,4,ORпоразрядное OR верхнего и нижнего элементов стека( Data2 Data1 −− Data2 or Data1 )( −− )
7,5,XORпоразрядное XOR верхнего и нижнего элементов стека( Data2 Data1 −− Data2 xor Data1 )( −− )
7,x,DROPRESERVED - удалить верхний элемент стека( Data2 Data1 −− Data2 )( −− )
8,@разыменовать - прочитать данное из памяти по адресу с вершины стека( Addr −− Mem[Addr] )( −− )
9,!присвоить - записать в память по адресу с вершины стека данное из подвершины стека( Data Addr −− )( −− )
А,>Rпереместить вершину стека данных на стек возвратов( Data −− )( −− Data )
B,R>переместить вершину стека возвратов на стек данных( −− Data )( Data −− )
C,MOVEкопировать блок данных**( −− )( −− )
D,NEXTзакончить исполнение слова и перейти на следующее (операция эквивалентная RET+CALL)( −− )(AdInt −− AdInt+1)
E,NOP*RESERVED ( −− )( −− )
F,NOP*RESERVED ( −− )( −− )

к содержанию

Многоядерный вариант процессора EQUINOX

Доступ к внутренней памяти ПЛИС требует временных затрат. В синхроном режиме данные из ячейки по выставленному адресу появляются на выходе памяти только через два такта. Один такт на защелкивание адреса и один на защелкивание выходных данных. Такова реальность ПЛИС фирмы ALTERA. В связи с этим при построении встроенной системы на основе форт-процессора оказывается, что невозможно получить процессор, исполняющий одну команду за один такт, если длительность этого такта равна пределу, на котором работает внутреннее ОЗУ. Время доступа к ОЗУ составляет 2 такта плюс один такт на выполнение операций с полученными из памяти данными, и получается, что минимальный цикл процессора составляет 3 такта, что не так уж плохо при условии, что тактовая частота, на которой работает память в ПЛИС довольно высока - сотни мегагерц.
Тем не менее, для получения более высоких показателей скорости обработки информации имеет смысл конвееризовать процессор таким образом, чтобы за один такт исполнялась одна команда. Для этого был разработан трехъядерный фортпроцессор, у которого каждый такт исполняется команда одного из трех ядер. Остальные при этом ждут поступления данных из ОЗУ для того чтобы в свой рабочий такт выполнить свою команду.
Для получения такого эффекта все регистры процессора были утроены, а логика оставлена без изменений. Регистры соединены в конвеерное кольцо и данные в них каждый такт смещаются на одну позицию. В первой позиции при смещении данных по конвееру происходит их обработка логической схемой процессора. Таким образом одна логическая схема "обслуживает" столько ядер, сколько имеется позиций конвеера. Перемещение данных происходит синхронно, поэтому на каждой ступени каждый такт находятся данные одного из ядер.
Скорость работы каждого ядра такого многоядерного процессора составляет 1/N от частоты синхронизации конвеера, т.е. при трех ступенях - она составляет 1/3 общей частоты. Суммарная же скорость работы равна ровно тактовой частоте, что существенно выше, чем при одноядерном построении процессора.
Варианты многоядерных процессоров обозначаются кодами xE16,xE32,xE64, где x - количество ядер. В данный момент реально в ПЛИС существует вариант 3E16, а варианты 3Е32 и 3E64 только компилировались для проверки, но не были использованы в работе.
В данный момент (декабрь 2009г) проверка работы процессора EQUINOX ведется на варианте 3E16 с одним включенным ядром.