Forth http://fforum.winglion.ru/ |
|
4 битный процессор http://fforum.winglion.ru/viewtopic.php?f=3&t=150 |
Страница 1 из 5 |
Автор: | mOleg [ Вт авг 01, 2006 03:37 ] |
Заголовок сообщения: | 4 битный процессор |
Предлагаю продолжить здесть. in4 писал(а): oleg писал(а): Вообще можно и адресовать половинку байта. Просто сокращается все-тот же 1 бит в старшем разряде. Тогда выравнивать ничего ненадо! Так-то оно так, но при этом выборка команд будет сложнее, нужна дополнительная проверка. Это усложняет систему(что хуже) и снижает быстродействие(не так критично). Щедрый Мур адресует группу команд, забивая остаток группы nop-ами Я так понимаю, что нопы тоже выполняются какое-то время - например 1 такт на исполнение и, вероятно, 1/2 такта обращения к памяти!? Насчет дополнительного условия я не понял: зачем? Делаем внешнюю шину данных, например, 8битной. Тогда команды будут грузиться парами ( за исключением литералов) Грузим эти команды в двойной 4 битный регистр. 1 такт выполняем загрузку команд+дешифрацию первого полубайта, второй такт - дешифрация второго полубайта + загрузка следующей пары. Если был совершен переход на второй полубайт, то нужно выполнять вторую часть байта. in4 писал(а): Щедрый Мур адресует группу команд, забивая остаток группы nop-ами Мур оптимизирует процессоры. У него несколько команд за такт исполняется. Я хочу проще. Я хочу максимально простой проц. Простой как лапоть!) in4 писал(а): Туда же Хотя должна присутствовать возможность записать адрес с помощью литерала. Так как и call & if в предложенном варианте адрес перехода получают на стеке данных. С этим уж ничего не поделаешь... Обойти, конечно, можно, но это лишняя сложность... Я бы сейчас не возился. Потом посмотрим... А ничего с этим делать и не надо. Слишком большое адресное пространство такому процу нафиг не нужно, я думаю, что даже для cell = 8 больше 64 кб памяти не будет нужно. К тому же уменьшение адресного пространства осовобождает как ноги в\в так и уменьшает кол-во вентилей на кристале (немного, но все же%) in4 писал(а): oleg писал(а): Нет, обязательное -так как в случае data_stack_width = 32 а return_stack_width = 16 бит можно реализовать >R и R> а если они не кратны - то уже нельзя 8( Зя! Пусть d:32 и r:14, одна ячейка данных в стеке возвратов займет 3-4 ячейки. В реализации R> маскируем лишние биты. Или просто пакуем по-другому. Например, байт в ячейке возвратов. Лишние биты просто не используем при восстановлении! Будет быстро, но много ячеек возвратов... Это усложнение, но только в реализации и только для некратных размеров стеков, а не везде. Программы будут работать в обоих случаях одинаково! Мы абстрагировались от некратности... И наш машинно-независимый код опирается на стандартные(!) слова, просто с машинно-зависимой реализацией. Насчет маскирования и пр по-моему не стоит. Да и вообще разрядность стеков таки должна быть одинакова - иначе нельзя будет делать такие вещи: lit('of_something) >r ret ну и всякое тому подобное. Мы не много потеряем если разрядность стека возвратов будет в два раза шире, чем необходимо, но от проблем избавимся. in4 писал(а): Идею о том, что можно делать машинно-независимые вещи на основе машинно-зависимых, я впервые встретил в статье Михаила Гассаненко в 93 или 94 году. Это очень важная идея и она должна быть основой стандарта!
Странно. Для меня это было как бы подразумевающимся всегда. Впрочем может просто не зафиксировалось, когда мое сознание вобрало в себя это. |
Автор: | mOleg [ Вт авг 01, 2006 03:51 ] |
Заголовок сообщения: | |
in4 писал(а): oleg писал(а): Ну а я предлагаю в память все лишнее проекцировать! Кстати для хохмы можно и алу в память спроекцировать и оставить лишь одну команду запуска алу а результат получать по необходимому смещению!!! Хотя изврат конечно страшный, но он ничем не хуже использования префикса для арифметических команд! Хуже. У тебя идет загрузка, м.б. логическая операция(можно обойти, по-разному отобразив флажки в память), а только потом сравнение. И так каждый раз! Для частых команд это не хорошо. if0 или аналог я буду отстаивать в основном наборе, очень желательно проверку на отрицательное, но ее я пока(пока нет аргументов ) готов уступить... Ну есть всего 16 команд! Одного условия с головой! А флаги можно получать иначе. Можно сделать shift арифметический, тогда сдвиг вправо на все биты кроме знакового даст нам наш знак. А логический сдвиг можно сделать со сбросом старшего бита уже в коде. in4 писал(а): IMHO, реализация с префиксом отработает быстрее и будет меньше, чем альтернатива Зато в алу можно и деление и умножение запихнуть и, представляешь, пока ты к нужному результату обратишься все варианты для двух чисел уже готовы Кстати по-моему получается, что самыми неудобными командами будут if и store - обе выгребают из стека два параметра. Нужно полностью перегрузить оба верхних регистра стека - то есть в любом случае два такта получится. in4 писал(а): Смотри, что получается! Префикс может играть роль короткой записи или короткого чтения твоих замапленых регистров! 4 бита(префикс) +4(операция) вместо 4(lit)+CELL(адрес флага)+4(load?)... да можно-то можно. Но хочется без префиксов, ну хотя бы с самого начала. in4 писал(а): oleg писал(а):
in4 писал(а): И желательно */ к арифметике добавить или умножение с делением на нем делать... ага, и больше всего на кристале места будет занимать умножитель и делитель Или сделать умножение многотактным? то есть за один такт - одна итерация умножения? как у Чака Если ВМ, то команда, для кристалла если не получится команда, сделать многотактное... Программы разницы не заметят... Да как сказать. Смотря что делать. Хотя в любом случае можно отрабатывать в эмуляторе задержки на исполнение той или иной команды. |
Автор: | mOleg [ Вт авг 01, 2006 04:00 ] |
Заголовок сообщения: | |
WingLion писал(а): oleg писал(а): Туда жеCool Хотя должна присутствовать возможность записать адрес с помощью литерала. Так как и call & if в предложенном варианте адрес перехода получают на стеке данных. Команда "Литерал" в этом случае может быть и скрытой, т.е. железяка, получив команду if или call автоматом считает, что ей сначала надо lit исполнить и вытащить адрес... Хотя, явный литерал может быть в каких-то случаях и удобнее. Явный удобнее, так как гибче. К тому же if с адресом перехода в коде после команды - это ведь обычная практика. WingLion писал(а): oleg писал(а): Нет, обязательное -так как в случае data_stack_width = 32 а return_stack_width = 16 бит можно реализовать >R и R> а если они не кратны - то уже нельзя 8( Вообще-то, даже в кратном случае возникнут проблемы. Откуда командам >R и R> знать, с чем они в данный момент работают? С данными или с адресом возврата? За этим программисту следить придется, и использовать либо по одной, либо по несколько R> и >R подряд, в зависимости от того, что делается. А универсальными эти команды могут быть только при равенстве ширины стеков. Абсолютно согласен. Сам к этому выводу пришел. Можно делать различные разрядности стеков только если проц имеет много больше команд (нежели 16 в четырех битах). WingLion писал(а): Это ж какие тормоза получатся! Тут же вытаскивание результата АЛУ потребует литерала с адресом! Зато какая идея! Процессор лишается АЛУ - то есть того, что всегда сичталось чуть ли не его основой... Опять же вполне оправдано, если хочется больше, чем 3 команды иметь арифметико-логические, а набор команд всего в 4 бита влазит. А вот если будет префикс, то уже нельзя говорить о 16 командах - нужно говорить о 31-оЙ!( WingLion писал(а): oleg писал(а):
ага, и больше всего на кристале места будет занимать умножитель и делитель Sad Или сделать умножение многотактным? то есть за один такт - одна итерация умножения? как у Чака Smile Совсем не факт, что много. В новых ПЛИС-ах умножители отдельные есть по несколько десятков на кристалле. А делитель можно и многотактным сделать, если совсем невмоготу без него. У меня EPF10K10... Умножителей на кристале нет. |
Автор: | WingLion [ Вт авг 01, 2006 04:21 ] |
Заголовок сообщения: | |
oleg писал(а): У меня EPF10K10... Умножителей на кристале нет.
Ну, тогда, однозначно, умножитель/делитель последовательный. Можно извернуться и 16x16 умножение за 8 тактов успеть. (Мне чуть полегче, у меня 2 шт. EP1K50 на одном устройстве есть) P.S. Имхо, спор о командах можно уже прекращать. В принципе и так ясны варианты. Пора переходить и к более интересному делу - запихиванию сего набора в железяку. |
Автор: | mOleg [ Вт авг 01, 2006 05:10 ] |
Заголовок сообщения: | |
WingLion писал(а): P.S. Имхо, спор о командах можно уже прекращать. В принципе и так ясны варианты. Пора переходить и к более интересному делу - запихиванию сего набора в железяку.
Я пока что в оркаде разрисовал основные устройства и пути передачи данных между ними. Получилось _ исполнительных устройств(без учета дешифратора команд) TOP - верхний элемент стека данных - регистр - вход - выход SUBTOP - подвершина стека данных - регистр - вход - выход RTOP - вершина стека возвратов - регистр - вход - выход ADDR - защелка адреса (используется при обращении в память командами fetch & store ) - вход DS - стек данных - скорее всего во встроенной памяти - вход - выход RS - стек возвратов - то же - вход - выход IP - указатель на следующую команду - регистр - вход - выход INTRer - хранит адрес перехода по прерыванию -- регистр - вход - ADDer - сумматор - - вход вход - выход NANDer - и-не - - вход вход - выход SHIFTer - lshift\rshift - - вход вход - выход MEMORY - память команд\данных - - вход вход - выход флаги и указатели стеков мапятся в память через ADDR регистр возможно имеет смысл сделать еще один регистр, относительно которого будем мапить флаги - это если захочется многозадачности. Все арифметические команды получают два операнда TOP SUBTOP возвращают TOP предполагаемые флаги: знак, заем, прерывание(маскирование), переполнение - туда же можно поместить RP & SP, хотя при реализации стека можно обойтись и без них. Прерывание сбрасывает флаг маскирования прерывания - после включения и инициализации прерывания неактивны - разрешать очередное прерывание нужно вручную\ адрес инициализируется нулем. Сдвиг арифметический через флаги [знак] -> [TOP] -> [заем] [знак] <- [TOP] <- [заем]. Флаги проявляются только двумя командами ADD AND или в ручную. Память адресуется побайтно. Минимальная разрядность данных 12 бит - максимальная 32. В принципе все команды распадаются на большее кол-во микроопераций, так что сложно говорить о том, сколько будет тактов на каждую команду. Нужно считать(еще не успел). Для начала можно все действия синхронизировать по фронту тактовой частоты. ( потом можно будет попробовать кое-что делать и по спаду). Набор команд: lit[n] - Единственная команда, которая выгребает данные за собой - вероятно многотактная из-за обращения к памяти if ( flag addr --> ) переход если не ноль -- неудобство в том, что нужно два такта на восстановление стека, но, вероятно не меньше уйдет на загрузку команды с нового адреса call ( addr --> ) может тоже условным сделать ;) dup\drop\over\r>\>r - вроде все понятно swap\fetch - не влияют на глубины стеков. add\nand\shift ( na nb --> nr ) store ( n addr --> ) - замечу, что addr всегда находится в TOP. остается либо ret либо nop выбрать 8) В первом случае адресуем память полубайтами. Во втором - длииинный многокомандный ret. Глубина стеков должна быть большая и скорее всего одинаковая. Так как придется часто пользоваться обоими стеками( при такой-то системе команд :) Что забыли?: Watchdog, Reset. |
Автор: | mOleg [ Вт авг 01, 2006 05:27 ] |
Заголовок сообщения: | |
Стоп! Только что подумалось, а если call сделать условным, то if == call r> drop ... ГЫ |
Автор: | WingLion [ Вт авг 01, 2006 13:15 ] |
Заголовок сообщения: | |
Вот я и сюда добрался Первое, что хочется сказать - надо делать проще! Не нужно плодить регистры типа TOP/SUBTOP. Надо просто сделать нормальный стек в виде "мегафункции", так, чтобы его вершина и второй элемент были доступны. Т.е. для начала делаем так: Код: -- AHDL source (for ALTERA)
TITLE "Stack" parameters ( width = 16, -- ширина данных стека depth = 8 -- глубина ( или двоичный логарифм глубины ) ); Subdesign stack ( clk : INPUT; -- ясно что di[width-1..0] : INPUT; - вход для записи данных в вершину dt[width-1..0] : OUTPUT; -- выход - вершина dn[width-1..0] : OUTPUT; -- выход - второй элемент стека cmd[1..0] : INPUT; -- команда(!) -- 00 - nop -- 01 - push -- 10 - pop, -- 11 - exx ena : INPUT = VCC; -- разрешение работы стека -- по умолчанию разрешено. EMPTY, FULL : OUTPUT; сигналы опустошения/переполнения ) VARIABLE ....... BEGIN ....... END В подобный же блок имеет смысл вынести АЛУ. Регистр ADDR кажется просто лишним. Для работы с памятью вершину стека данных надо грузить прямо в PC, а PC в этот момент сохранять на стеке возвратов, после того, как цикл памяти выполнен - мгновенный возврат (или загрузка в PC полученного литерала). Формально получается call fetch ret (call store ret). Таким образом, в процессоре остаются 1. Стек возвратов 2. Регистр команд/адреса 3. Стек данных 4. АЛУ 5. Управляющий блок дешифратора команд. Последний блок тоже можно сделать отдельно, тогда при необходимости что-то изменить не нужно перепахивать главный файл проекта. К регистру команд нужен еще инкрементатор (счет команд). Его можно дополнить декрементатором и при необходимости иметь команды работы с адресами с подтинк(дек)рементом. П.С. Именно по подобной схеме построен реальный Форт-процессор. |
Автор: | mOleg [ Вт авг 01, 2006 22:52 ] |
Заголовок сообщения: | |
WingLion писал(а): Первое, что хочется сказать - надо делать проще! Не нужно плодить регистры типа TOP/SUBTOP. Надо просто сделать нормальный стек в виде "мегафункции", так, чтобы его вершина и второй элемент были доступны. Можно. Но мне так проще представить. WingLion писал(а): В подобный же блок имеет смысл вынести АЛУ. Тоже можно. И даже будет проще. Но это уже при синтезе. А сейчас анализ WingLion писал(а): Регистр ADDR кажется просто лишним. Спорить не стану. Но так легче расписать порядок действий и их последовательность. WingLion писал(а): Для работы с памятью вершину стека данных надо грузить прямо в PC, а PC в этот момент сохранять на стеке возвратов, после того, как цикл памяти выполнен - мгновенный возврат (или загрузка в PC полученного литерала). Формально получается call fetch ret (call store ret).
Не думал. Возможно так будет лучше. |
Автор: | WingLion [ Вс авг 06, 2006 09:27 ] |
Заголовок сообщения: | |
Чем хороша 4 битная команда, это тем, что дешифратор для нее одноуровневый получается - группа LCELL-ов, на каждый из которых подается 4 двоичных сигнала. Хотя, если рассчитывать на новые ПЛИСы с 6-тивходовыми LUT в ячейках, то можно и больше команд |
Автор: | mOleg [ Вс авг 06, 2006 21:46 ] |
Заголовок сообщения: | |
То-то и оно. А еще доступ к памяти получается более простой. чем при 6-битной команде. Можно делать 8-битный доступ. |
Автор: | WingLion [ Вс авг 06, 2006 21:59 ] |
Заголовок сообщения: | |
Kэшировать надо доступ к памяти, и тогда будет без разницы количество бит в команде. И выбирать данные из SD-RAM лучше пачками, чем по одному слову(байту). С записью будет чуть посложнее, но запись - более редкая операция, чем чтение. |
Автор: | mOleg [ Пн авг 07, 2006 02:40 ] |
Заголовок сообщения: | |
Сейчас читаю Гасаненко. В одном месте он предлагает определить литерал таким образом: : LIT R@ @ R> CELL+ >R ; если бы не CELL+ можно было бы выкинуть литерал из набора. Правда литерал все-таки самая частая команда будет 8( |
Автор: | mOleg [ Вт авг 08, 2006 01:10 ] |
Заголовок сообщения: | |
Я тут еще посидел, поприкидывал, и понял, что стоит малость поменять стековую нотацию у двух команд: во-первых сделать неразрушающий if ( flag addr --> flag ) то есть флаг не удаляем. Очень часто в качестве флага выступает адрес и не всегда его стоит удалять, за одно нет необходимости убирать двойной разбаланс стека. во-вторых store ( n addr --> addr+1 ) почти те же преимущества чти и с if. всего один элемент снимается со стека, и за одно получаем возможность автоинкрементной компиляции полубайтов. Память адресовать полубайтами. хранить младщие разряды в младших адресах. Тогда последовательная запись чисел в память будет потихоньку "компилировать" младшие биты subtop-a. К тому же такой подход уменьшает кол-во линий связи. Кстати, как правильнее использовать встроенную в альтеровскую плис память? Я с этим пока не разбирался, а раньше оно мне не было надо. |
Автор: | WingLion [ Вт авг 08, 2006 06:19 ] |
Заголовок сообщения: | |
oleg писал(а): Кстати, как правильнее использовать встроенную в альтеровскую плис память?
Использовать можно как угодно Хоть как RAM, хоть как ROM, хоть как таблицу логических функций (например, можно организовать таблицу Y=X<sup>2</sup>). Правильнее всего, имхо, использовать альтеровскую мегафункцию памяти (однопортовую или двухпортовую в зависимости от серии). Сами функции и их входы/выходы можно подсмотреть в хелпе к MAX-Plus II. (Если есть сложности с пониманием хелпа, можно в форуме по MAX-Plus-у топик создать с вопросами на эту тему.) По скорости наиболее быстрая (как это ни странно) - синхронная схема, когда и адреса и данные защелкиваются в D-тригерах. |
Автор: | mOleg [ Вт авг 08, 2006 06:32 ] |
Заголовок сообщения: | |
WingLion писал(а): По скорости наиболее быстрая (как это ни странно) - синхронная схема, когда и адреса и данные защелкиваются в D-тригерах.
А мне тут кто-то предлагал исключить регистр ADDRESS из устройства |
Страница 1 из 5 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |