Могу предложить следующую структуру обработки данных.
Преимущество такого построения - уменьшается на один такт
конвейер процессора.
Вид для печати
Могу предложить следующую структуру обработки данных.
Преимущество такого построения - уменьшается на один такт
конвейер процессора.
Стандартный конвейер процессора имеет регистры после мультиплексоров регистрового файла,
т.е. на входах АЛУ. В состав АЛУ входит выходной мультиплексор, оканчивающийся своим
регистром. Тут мы видим 3 такта конвейера: декодирование команды, собственно операция АЛУ
и запись в регистровый файл.
У меня немного по другому. На стадии декодирования мы вычисляем операции АЛУ,
заканчивающиеся регистрами на каждую операцию, а затем на шаге записи в регистровый файл
мультиплексируем результаты каждой операции. На самом деле количество регистров можно
сократить, например, объединив несколько быстрых логических операций, суммирование и
вычитание имеют свои регистры.
Сигналы bypassRA и bypassRB нужны, если RD предыдущей команды совпал с RA или RB текущей,
т.е. когда результат предыдущей команды еще не попал в регистровый файл.
Типичный заголовок алу может быть следующим:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.my_arith.all;
entity alu32pe is
port (
opa : in std_logic_vector(31 downto 0);
opb : in std_logic_vector(31 downto 0);
opalu : in std_logic_vector(4 downto 0);
reset : in std_logic;
sclk : in std_logic;
cealu : in std_logic;
cb_in : in std_logic;
result: out std_logic_vector(31 downto 0);
cc : out std_logic_vector(3 downto 0)
);
end;
Что касается самих операций АЛУ, то их лучше оформить в отдельном файле библиотеки (package, у меня это my_arith.vhd),
и вызывать их в файле описания АЛУ.
Если надо, могу дать свой.
P.S.
Сигнал cealu - разрешение записи в регистры АЛУ (может быть использован для остановки
конвейера при извлечении операнда из синхронной памяти данных за 2 такта).
cb_in - (carry/borrow) вход переноса/заема от предыдущего вычисления.
Выходные флаги сс лучше хранить в одном из регистров регистрового файла (сделать его
специализированным, например, регистром флагов).
Если этот регистр делать отдельно - это увеличит аппаратуру.
Единый файл у Вас будет оооооочень большой.
У Вас же есть книжка Паттерсона, со стр.388.
Только там регистровый файл выполнен в виде ОЗУ.
И вычисление адреса памяти данных выполняется в АЛУ. У меня не так.
Вычисление адреса происходит на том же такте, что и операции АЛУ.
Это я не могу посчитать, но потребуются свои дешифраторы, отдельный код операции и что-нибудь еще.
Нет, это я просто вычленил схему вычисления данных из общей архитектуры своего процессора.
Честно говоря я не пойму, какова цель тогда тут что то спрашивать?, тебе говорят, ты же в ответ, извиняюсь за выражение "херню городишь".
Выбор вечно не по прямому простому пути, а через непонятные дали.
Это как на гитаре по книжке учиться играть, не беря в руки гитару.
АЛУ не самое сложное. ИМХО не с него надо начинать.Цитата:
А пока ещё и нечего брать, код даже для АЛУ ещё не написан, самой гитары нет.
Мой совет - не закладываться вообще на конкретный ПЛИС. Делать чтобы работало на чем угодно. Это вполне возможно. Я в качестве изучения переделывал Forth процессор J1 под себя (переписал с Verilog на VHDL, сделал его 32 битным, дописал байтовый доступ к памяти, инструкции ускорений циклов итд итп) все делал на чистом VHDL под эмулятором ghdl. Планирую делать из них 2D сеть на LX25 или LX75 (есть 2 платы от ztex)Цитата:
Не пойму, это к чему. Здесь и сейчас изучается и будет применяться микросхема ПЛИС фирмы Xilinx семейства Spartan-6.
Берем 1 и сдвигаем на 1 бит - это умножение на 2. Получается 2 бита. Сдвигаем еще на 1 бит - это умножение на 4. Получается 3 бита. Все логично. Если не понятно как делается умножение - делайте его в столбик как с десятичными числами - там получается сдвиг и суммирование с переносом.
В этом конечно что-то есть. Но например fetch и decode намного проще alu но их реализация уже создает иллюзию работы (; Да и потом к ним alu цеплять и проверять проще, чем один alu "в воздухе"Цитата:
Ну пока это единственное, что мне кажется стало более менее понятным, по крайней как будет выглядеть код, и как вообще этот блок работает, поэтому начинаю с него. Хотя как мне видится, не важно с чего начинать.
Мой 32 битный процессор занимает четверть от LX25, а уж я там себя не сдерживал (; Кстати он получился даже меньше чем "самый маленький 32 битный с поддержкой gcc toolchain" (ZPU)Цитата:
Но тут выбор уже сделан, так как смысл написать код, который влезет только в LX16
Мне было интересно смогу ли я. Смог. Заодно разобрался как он работает просто досконально.Цитата:
Интересно, и это оправдано?
Я оригинальную частоту не знаю. У меня на LX25 получилось 106Мгц. Меня соотношение размер/fmax устроил.Цитата:
снизилась частота дизайна.
Вся эпопея здесь - http://strijar.livejournal.com/tag/k32
Экономия RAM - можно иметь быстрый доступ (за один такт) к байтовым массивам. У меня в качестве теста реализована игра LifeЦитата:
И смысл тогда в байтовом доступе к памяти, если он уже может оперировать 4-мя?
---------- Post added at 15:06 ---------- Previous post was at 14:48 ----------
Посмотрел ваш код. У вас получился "подстрочный перевод". Я сделал по честному - логично связанные сигналы упаковывал в record (;
А циклические сдвиги делал через srl и sllКод:entity k32 is
port (
clk : in std_logic;
rst : in std_logic;
en : in std_logic;
ibus_in : in ibus_in_type;
ibus_out : out ibus_out_type;
data_in : in dbus_in_type;
data_out : out dbus_out_type;
io_in : in dbus_in_type;
io_out : out dbus_out_type;
exception : out exception_type
);
end k32;
Код:when x"8" =>
ds_top <= alu_a srl to_integer(unsigned(alu_b(4 downto 0)));
when x"9" =>
ds_top <= alu_a sll to_integer(unsigned(alu_b(4 downto 0)));
Какой в нем практический смысл?Цитата:
P - (parity) бит чётности (1)
Тоже самое. Ноль он и есть ноль - зачем дополнительный флаг?Цитата:
Z - (zero) бит нуля (2)
Флаг Z - необходим для ветвлений по =0.
А вот для каких вычислений бит четности - не понятно.
Четность показывает сколько единиц в слове. При этом четность результата зависит от младшего бита. Это разные вещи.Цитата:
Чтобы понять чётный результат или нет. Можно использовать в условных переходах.
Так может просто сравнивать с нулем и все? Сама инструкция перехода пусть это делает, отдельный бит не нужен.Цитата:
То же самое, чтобы понять равен результат нулю или нет.
Недалее как, был разговор как бы сделать так чтобы все влезло ;)Цитата:
Хоть он и не часто используется, но пусть будет, пригодится
вообще в проце достаточно 1 флага алу, можно его стек вместе с PC ложить, если инструкции с выравниванием по 32бит в памяти, то там есть целых 2 бита свободных
А команда сравнения, ставит флаг если условие истина
сравнения банальные a<b a<=b a==b, если сильно хочется можно еще четность, parity, a==0, a<0
в командах сложения вычитания, флаг работает как перенос/заем работает
в командах сдвига, вытесненный добавочный бит
команд ветвления парочку хватати, if (flag) jump и if (!flag)
но это из темы процессоров с минимальным набором инструкций
К сожалению, если только ЭТО надо было бы использовать в командах ветвления,
то да, отдельный флаг не нужен. В том же MIPS-е для остальных условных переходов (кроме !=) приходится использовать регистр и дополнительную команду для вычислений условий, что не намного лучше команды CMP.
В том же J1 был условный переход если равно 0 (true). И добавочно две инструкции сравнения на == и < результатом которой -1 (false) или 0 (true). Через это можно сделать все остальное
Странный подход. Сначала бы обдумать общую архитектуру, а АЛУ это уже частности.
Когда я пробовал писать процессор - я посмотрел все имеющиеся в наличии. Гарвардские, фон-неймовские, регистровые, стековые итд итп. Оценил что мне нравиться, а что нет. Потом уже начал что-то делать. И то в конце концов получилось что мне запал один так как подходил почти полностью - то что не подходило и переделал.
Хорошо. Буду ждать конкретных вопросов. Чем смогу - помогу. Сам только учусь.
кстати, что бы не рыскать по всему интернету в поисках инструкций ALU
есть замечательный ресурс, где все собрано в одном месте, есть разнообразные фильтры
https://software.intel.com/sites/lan...trinsicsGuide/
К сожалению только на английском, но там есть простой псевдокод, объясняющий что инструкции делают
Думаю 8 бит для кода операции алу будет недостаточно, сейчас разумно 12-16 бит
---------- Post added at 01:23 ---------- Previous post was at 00:59 ----------
И выход алу должен быть 64бит, умножение 2х 32 битных дает 64бит
причем должно быть организовано как 2выхода по 32бит, так как то же, целочисленное деление, возвращает частное и остаток по 32бит
>> Оставлю пока так, увеличить всегда можно, изменив одну цифру.
Если бы одну, придется поправлять все паттерны сравнения, к тому же необходимо сразу в коды операции зарезервировать биты, гораздо проще, неиспользуемые биты не подключать, синтезатор оптимизирует и ни одного лишнего логического вентиля не будет
а что читать, умножение десятичных 100х100 (по 2 нуля) = 10000 (4 нуля) тоже самое и с числами с основанием 2
---------- Post added at 02:05 ---------- Previous post was at 01:49 ----------
Еще не хватает в алу сигналов от флагов
по флагам тоже могу кое какие вспомнить, которые можно в 32битный регистр флагов добавить
1. антипереполнение - это когда результат деления настолько мал оказался, что из за ограничений разрядной стеки стал равен = 0
2. для математики с фиксированной точкой, надо флаг Z для старших 24 и 16 бит, а так же для младших 8 и 16 бит, что бы можно было определять что целая часть 0 и дробная часть 9
3. опять же для математики с фиксированной точкой, надо флаги переноса из 7 в 8 разряд и из 15 в 16
4. надо флаги которые показываю, дробная часть больше .5 или меньше, опять же для форматов fixed point 24:8 и 16:16, нужно для работы с округлениями
5. нужен флаг, который показывает что было деление на 0
6. очень полезен флаг, который говорит что число в регистре является степенью 2, для быстрых делений
7. опять же нужен флаг четности, именно тот что копирует младший бит числа
8. не обязательно, но плезно, флаг который показывает что число делится на 3, глобально ускоряет троичную логику.
9. для работы с двоично десятичным числами можно добавить пару флагов, однин что в регистре корректное двоично десятично число, второй, флаг переноса/заема для двоично десятично арифметики
10. иногда полезен флаг, что число в регистре акроним, то есть младшая часть и старшая часть регистра, зеркально одинаковы
на память больше вспомнить не могу, можно по документации на процессоры покопаться, посмотреть какие еще флаги забыл
там еще куча флагов с тригонометрией есть, но они были мне скучны, я даже не читал особо про них
Дело было вечером, делать было нечего.
Предлагаю разработать процессорный элемент, пока Viktor2312 ищет какие флаги добавить в регистр флагов
Процессор будет называться 5-РИМВ
Технические требования:
0. стеково/регистровый, ну что бы как стековый мог работать и как регистровый
1. 8 регистров общего назначения, ширина 64бит
2. фиксированная ширина кода операции 16бит!
4. регулируемая ширина слова стека данных
5. команд алу 32, кодировать 12 битами
6. указатель инструкций 12 битный
7. только относительные переходы
8. процессор без флагового регистра
9. возможность при синтезе задать максимальную разрядность процессора, но так что бы на коды инструкций не влияло
И да, писать придется на Verilog, думаю Viktor2312 поможет на VHDL перевести
У кого какие мнения по поводу ТЗ? реально?
---------- Post added at 21:17 ---------- Previous post was at 21:11 ----------
Команда ALU
команды будут 4 видов 3х адресные, 2х адресные, 1н адресные, безадресныеКод:15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
1 1 [siz] [ aluop ][ dst ][ left ][ right ]
3х адресные, код операции задается в 3х битном поле aluop
0 - add dst, left, right // dst = left + right
1 - adc dst, left, right // dst = left + right + flag
2 - sub dst, left, right // dst = left - right
3 - sbc dst, left, right // dst = left - right - flag
4 - and dst, left, right // dst = left & right
5 - or dst, left, right // dst = left | right
6 - xor dst, left, right // dst = left ^ right
7 - 2х адресные команды, код операции 2х адресных команд задает поле left
2х адресные команды:
0 - shr dst, right // dst = right >> 1, младший бит в флаг, старший 0
1 - ror dst, right // dst = right >> 1, младший бит в флаг, старший из флага
2 - add dst, right // dst = right + left left, используется как непосредственный параметр, только не от 0до7 а от 1 до 8
3 - sub dst, right // dst = right - left, left опять же imm
4 - == // flag = (dst == right)
5 - < // flag = (dst < right)
6 - > // flag = (dst > right)
7 - 1 адресная команда, код одноадресных команд в поле right
1но адресные команды
0 - neg // dst = 0-dst
1 - inv // dst = fffffffff^dst
2 - not // dst = !dst
3 - ==0 // dst==0
4 - <0 // dst < 0
5 - parity
6 - четность
7 - безадресные команды алу, код команды задает поле dst
безадресные команды
0 - set flag // flag = 1
1 - reset flag // flag = 0
2 - invert flag // flag = !flag
3..7 резерв
Команда условного перехода
И команда вызова процедуры
b[15:13] == 3'b010 JR
b[15:13] == 3'b011 CALL
b[12] - F, срабатывает при равном значении F=flag
b[11:0] для jr относительный адрес в словах, ширина слова задается максимально разрядностью процедуры, то есть если продура maxsize = 64бит, то прыгать будет кратно 8 байт, если адрес == 0 то это команда halt
для call - номер процедуры в каталоге процедур, если номер процедуры 0, то это команда ret
Каталог процедур это табличка, на табличку процедур указывает указатель из дескриптора задачи.
В каталоге задается физический адрес процедуры (Физический адрес инструкции это PROC_BASE + PC), максимальная ширина слова, ну там можно, длина процедуры, к примеру для защиты, можно максимальную глубину стека, что бы защита от переполнения была, итд, пусть пока будет табличка из элементов скажем по 8 байт, аля дескрипторы 80386
отсюда и PC = 12 битам, нефик делать процедуру больше 4к слов, для 64бит процедур это аж 32кб
Команда const, загружает в регистр константу
b[15:12] == 4'b0000
b[11] - imm, если 1 то 8бит констранта непосредственно в команде, если 0, то указатель на таблицу констант процедуры
b[10:9] - imm8 старшие 2 бита для непосредственно заданной 8 бит константы
b[8:6] - dst, номер регистра куда загружать константу
b[5:0] - если imm ==0 то тут номер констатны в таблице констант, если imm==1 то тут младшие 6 бит непосредственной 8 бит константы
константы в коде будут храниться перед телом процедуры, адресация будет как в стеке в сторону уменьшения адресов, то есть если процедура юзает 2 константы, то перед текло процедуры будет пару слов с константами, ширина слова константы, равна разрядности процедуры из дескриптора
Команды обмена с памятью
команд 6
b[15:11] = 5'b10010 // select var, выставляет для чтения адрес переменной в стеке
b[15:11] = 5'b10011 // select [base + index*mul + offs], выставляет адрес для чтения из памяти
эти 2 команды игнорируют прерывания
b[15:11] = 5'b10000 // ld чтение с шины данных
b[15:11] = 5'b10100 // st var, сохраняет регистр в переменную в стеке
b[15:11] = 5'b10101 // st [base+offs], сохраняет регистр в памяти
b[15:11] = 5'b10111 // st [base+index], сохраняет регистр в памяти
для чтения, получилось более гибкая адресация, но это не все, команды еще стараются быть полезными
форматы команд:
команда select var
b[10:9] - mode, определяет доп действия, 00-если следующая команда ALU, то данные с шины будут левым аргументом алу, 01-если следующая команда ALU, то данные с шины будут правым аргументом, 10-11 на поведение АЛУ не влияет, 10-декремент регистра dst, 11-инкремент регистра dst
b[8:6] - dst регистр, который инкрементируется/декрементируется если заданно параметром mode
b[5:0] - номер переменной в стеке
команда select [base + index*mul + offset]
b[10:9] - mul 00-x0, 01-x1, 10-x2, 11-x4, то есть mul=00 регистр index не используется (на 0 умножил)
b[8:6] - base
b[5:3] - offset
b[2:0] - index
команда ld, читает данные с шины в регистр, применима после команд select и const с чтением константы из памяти
b[10:9] - sz, размер читаемого аргумента
b[8:6] - dst, регистр для записи результата
b[5:3] - aluop - команды алу, пока придумал следующие
000-nop
001-знаковое расширение
команда st var
b[10:9] - size
b[8:6] - src, сохраняемый регистр
b[5:0] - номер переменной
команда st [base + offset]
b[10:9] - size
b[8:6] - base
b[5:3] - offset
b[2:0] - right - записываемый регистр
команда st [base + index], аналогично предыдущей, только b[5:3] номер регистра index
Z80 - CISC, поэтому его не просто улучшать. RISC в этом плане значительно проще
---------- Post added at 21:52 ---------- Previous post was at 21:50 ----------
Нет там ошибок. Это известный Forth процессор из статьи на Хабре. Он чисто стэковый, без регистрового доступа.
---------- Post added at 21:55 ---------- Previous post was at 21:52 ----------
Что имеется ввиду? Стек но с возможностью адресации к любому элементу? Не только в TOS и NOS как обычно?Цитата:
0. стеково/регистровый, ну что бы как стековый мог работать и как регистровый
Какой практический смысл иметь разную ширину слова в стэке и в регистре?Цитата:
1. 8 регистров общего назначения, ширина 64бит
4. регулируемая ширина слова стека данных
Предложение - может отделить темы? А то получается уже каша на 60 страницах
Продолжаем, комада ALU это команда для АЛУ :)
команды будут 4 видов 3х адресные, 2х адресные, 1н адресные, безадресные
3х адресные, код операции задается в 3х битном поле aluop
0 - add dst, left, right // dst = left + right
1 - adc dst, left, right // dst = left + right + flag
2 - sub dst, left, right // dst = left - right
3 - sbc dst, left, right // dst = left - right - flag
4 - and dst, left, right // dst = left & right
5 - or dst, left, right // dst = left | right
6 - xor dst, left, right // dst = left ^ right
7 - 2х адресные команды, код операции 2х адресных команд задает поле left
2х адресные команды:
0 - shr dst, right // dst = right >> 1, младший бит в флаг, старший 0
1 - ror dst, right // dst = right >> 1, младший бит в флаг, старший из флага
2 - add dst, right // dst = right + left left, используется как непосредственный параметр, только не от 0до7 а от 1 до 8
3 - sub dst, right // dst = right - left, left опять же imm
4 - == // flag = (dst == right)
5 - < // flag = (dst < right)
6 - > // flag = (dst > right)
7 - 1 адресная команда, код одноадресных команд в поле right
1но адресные команды
0 - neg // dst = 0-dst
1 - inv // dst = fffffffff^dst
2 - not // dst = !dst
3 - ==0 // dst==0
4 - <0 // dst < 0
5 - parity
6 - четность
7 - безадресные команды алу, код команды задает поле dst
безадресные команды
0 - set flag // flag = 1
1 - reset flag // flag = 0
2 - invert flag // flag = !flag
3..7 резерв
---------- Post added at 22:07 ---------- Previous post was at 22:06 ----------
да, 8 верхних элементов в регистрах, дальше уже к стеку идет оращение, добавление на вершину, выталкивает 8 регистр в стек
---------- Post added at 22:07 ---------- Previous post was at 22:07 ----------
а можно просто как с регистрами работать
а не надо разделять, в заголовке процедурины сказать что максимум 32бит, все, стек 32бит, регистры могут быть максимум 32бит в этой процедуре, попытка 64бит доступа игнорируется
---------- Post added at 22:15 ---------- Previous post was at 22:12 ----------
MVV товарищ какой то странный, по удалял сообщения, даже ответить не успел
Так, дальше, команда условного отностительного перехода
И команда вызова процедуры
b[15:13] == 3'b010 JR
b[15:13] == 3'b011 CALL
b[12] - F, срабатывает при равном значении F=flag
b[11:0] для jr относительный адрес в словах, ширина слова задается максимально разрядностью процедуры, то есть если продура maxsize = 64бит, то прыгать будет кратно 8 байт, если адрес == 0 то это команда halt
для call - номер процедуры в каталоге процедур, если номер процедуры 0, то это команда ret
Каталог процедур это табличка
где задается физический адрес процедуры, максимальная ширина слова, ну там можно, длина процедуры, к примеру для защиты, можно максимальную глубину стека, что бы защита от переполнения была, итд, пусть пока будет табличка из элементов скажем по 8 байт, аля дескрипторы 80386
отсюда и PC = 12 битам, нефик делать процедуру больше 4к слов, для 64бит процедур это аж 32кб
Указатель на табличку процедур может быть в дескрипторе задачи к примеру, сейчас получается что проц может адресовать максимум 32к * 4к = 128мб кода на задачу, как бы с головой
---------- Post added at 22:37 ---------- Previous post was at 22:29 ----------
обновил пост http://zx-pk.ru/showpost.php?p=806353&postcount=588
---------- Post added at 22:48 ---------- Previous post was at 22:37 ----------
Так, команда чтения мне вообще не нравится, комада записи может быть однотактная, чтение же нет, в общем разделим их на 2 команды, первая будет адресацией заниматься, может что еще полезного влезет, к код инструкции, вторая команда будет непосредственно чтение, можно её немного команд алушных добавить например, причем команда инициализации чтения, будет конфигурировать муксы, для чтения, они будут сохраняться в этом состоянии пока не перенастроят, в код инструкции надо вставить битик, что следующая инструкция будет инструкцией чтения, что бы оно заранее сработало :) как то так, странно, но вроде интересно
---------- Post added at 22:57 ---------- Previous post was at 22:48 ----------
о! как же без констант, нужно же в регистры что то записывать, так как в ТЗ фиксированная длина инструкции 16 бит и нини, будем делать команду загрузки констант, в конце концов 64бит регистр загрузить при 16бит коде операций - сложно
Команда const, загружает в регистра константу
b[15:12] == 4'b000
b[11] - imm, если 1 то 8бит констранта непосредственно в команде, если 0, то указатель на таблицу констант процедуры
b[10:9] - imm8 старшие 2 бита для непосредственно заданной 8 бит константы
b[8:6] - dst, номер регистра куда загружать константу
b[5:0] - если imm ==0 то тут номер констатны в таблице констант, если imm==1 то тут младшие 6 бит непосредственной 8 бит константы
константы в коде будут храниться перед телом процедуры, адресация будет как в стеке в сторону уменьшения адресов, то есть если процедура юзает 2 константы, то перед текло процедуры будет пару слов с константами, ширина слова константы, равна разрядности процедуры из дескриптора
---------- Post added at 23:08 ---------- Previous post was at 22:57 ----------
Непосредственно заданная константа, будет знаково расширятся до ширины слова, ну там что бы -1 можно было задать
Вот, странны команды обмена с памятью
команд 6
b[15:11] = 5'b10010 // select var, выставляет для чтения адрес переменной в стеке
b[15:11] = 5'b10011 // select [base + index*mul + offs], выставляет адрес для чтения из памяти
эти 2 команды игнорируют прерывания
b[15:11] = 5'b10000 // ld чтение с шины данных
b[15:11] = 5'b10100 // st var, сохраняет регистр в переменную в стеке
b[15:11] = 5'b10101 // st [base+offs], сохраняет регистр в памяти
b[15:11] = 5'b10111 // st [base+index], сохраняет регистр в памяти
для чтения, получилось более гибкая адресация, но это не все, команды еще стараются быть полезными
форматы команд:
команда select var
b[10:9] - mode, определяет доп действия, 00-если следующая команда ALU, то данные с шины будут левым аргументом алу, 01-если следующая команда ALU, то данные с шины будут правым аргументом, 10-11 на поведение АЛУ не влияет, 10-декремент регистра dst, 11-инкремент регистра dst
b[8:6] - dst регистр, который инкрементируется/декрементируется если заданно параметром mode
b[5:0] - номер переменной в стеке
команда select [base + index*mul + offset]
b[10:9] - mul 00-x0, 01-x1, 10-x2, 11-x4, то есть mul=00 регистр index не используется (на 0 умножил)
b[8:6] - base
b[5:3] - offset
b[2:0] - index
команда ld, читает данные с шины в регистр, применима после команд select и const с чтением константы из памяти
b[10:9] - sz, размер читаемого аргумента
b[8:6] - dst, регистр для записи результата
b[5:3] - aluop - команды алу, пока придумал следующие
000-nop
001-знаковое расширение
команда st var
b[10:9] - size
b[8:6] - src, сохраняемый регистр
b[5:0] - номер переменной
команда st [base + offset]
b[10:9] - size
b[8:6] - base
b[5:3] - offset
b[2:0] - right - записываемый регистр
команда st [base + index], аналогично предыдущей, только b[5:3] номер регистра index
Ухххх, все, у проца есть весь базовый набор, добавить только разных системных управляющих и готово
---------- Post added at 01:25 ---------- Previous post was at 01:08 ----------
void memcpy(void* dst, void* src, uint16_t cnt)
{
while (cnt--) *dst++ = *src++;
}
как бы выглядела на псевдоасме псевдопроца
proc: memcpy (dword dst, dword src, word cnt)
size: 32
stack: 4 // dst+src+cnt+tmp
byte tmp;
m1: if.16 (cnt ==0) m2 // 16bit aluop "=="; jr m2
sub cnt,1
select [src]
add src,1
ld.8 tmp
st.8 [dst]
add dst,1
fres // flag=0
jrn m1
m2:
ret
много инструкций конечно, не pdp11
но тут стек до 8 переменных, особо не видно преимуществ от команд, может их вообще нет :)
надо с флагом придумать политику, что бы были безусловные преходы
Viktor2312 теперь дело за тобой
Открой для себя github ну или хотя бы pastebin
так и набирай в браузере
ну да, постить сюда полотно, вида "вот немого добавил", гораздо удобнее, особенно для тек, кому ты хотел показать это полотно, все сразу кинулись сравнивать 2 версии, искать 10 отличий. Да и вообще, http://pastebin.com/BVWbXsFZ гораздо приятней, чем полотно по тексту
Хех, вот и я стал счастливым обладателем платки Nexys 4 на базе Artix-7 XC7A100T :) Так что скоро тоже присоединюсь к изучению :)
Запустил демо-проект.
http://cs625629.vk.me/v625629117/31fa6/WVHRf1iZBiQ.jpg
http://www.xilinx.com/support/answers/35548.html
Только зачем вам это? Вы уже все написали, отладили и занимаетесь оптимизацией?
А зачем вам 3 клока?
Т.е. когда вы учились кататься на велосипеде вы тоже изучали процесс вулканизирования резины, только потому что она используется в шинах?Цитата:
Я изучаю досконально, поэтому мне это нужно для более глубокого въезда.
Задаете констрейнами ваш входной клок (частоту) - это достаточно, на вашем этапе, на 99.9%. На этапе синтеза если роутинг не уложится в какие либо тайминги - будет ошибка или предупреждение (в зависимости от параметров синтеза).Цитата:
Есть параметр, его можно оставить по умолчанию, а можно задать такой, какой он есть на самом деле
Чаще всего на этапе отладки частоту оставляют заведомо меньше чем позволяет роутинг. Например мой K32 синтезируется на 106мгц, но отлаживаю я его без DCM или PLL на входных 48мгц и не забиваю себе голову. Когда все работает как надо - тогда уже можно играться с констрейнами и "затягивать гайки". Это уже "полировка". Но вначале нужно сделать что полировать (;
Но дело конечно хозяйское :v2_dizzy_tired2:
Временные ограничения - http://www.xilinx.com/support/docume...linx11/cgd.pdfЦитата:
Я пока не настолько знаком с аббревиатурами, что значит констрейнами? Можно об этом чуть поподробнее, чтобы я понял о чём идёт речь.
Размещение прошивки на кристалле - http://www.xilinx.com/support/docume...pga_design.htmЦитата:
Так же интересует, что такое роутинг?
Ну так вот я и намекаю - что немного не с того конца вы начинаете (; Освойте синтаксис VHDL или Verilog на хорошем уровне. Доведите понимание что делает каждая конструкция и как это можно использовать. Что бы можно было писать самому и понимать что написано другими.Цитата:
Понятно, до этого ещё далеко, пока изучаю имеющуюся информацию