ZXNet эхоконференция «hardware.zx»


тема: Изредка посещаю этот форум для разрядки...



от: Павел Федин
кому: All
дата: 16 Oct 2006
Hello, All

К сожаленинию у меня сейчас нет времени и возможностей вести какие-либо
реальные разработки (хотя чем больше это длится тем острее желание вернуться и
заделать что-нибудь этакое...)
Так вот, очередная крейзи-идея на тему Flat Address Space на Z80. Это не
детальная проработка, но возможно кто-то сможет на основе этого сделать нечто
реальное.
Итак, давайте вспомним i8086 Его регистры тоже были 16-разрядными, и
адресовать можно было тоже 64 кб. Чтобы преодолеть этот барьер, использовались
сегментные регистры. Их было 4; CS; (код), DS (данные), SS (стек), ES
(дополнительный). Они содержали старшую часть адреса.
Hа Z80 сегментных регистров нет. А что если мы реализуем их, используя порты
ввода/вывода, вместо переключения банков? Разумеется, нам понадобится самый
настоящий северный мост - схема, связывающая между собой внешнюю шину, CPU и
контроллер памяти.
Как известно, Z80 имеет линии M1 (указывает что по указанному адресу мы читаем
команду), WR и RD (соответственно запись и чтение в память).
Итого, внешними средствами мы можем различить три состояния:
1. CPU читает код команды.
2. CPU производит чтение данных.
3. CPU производит запись данных.
Теперь вводим три порта ввода вывода:
1. CSP - Command segment port.
2. RSP - Read data segment port.
3. WSP - Write data segment port.
Получаем сегментированную модель, в которой, в отличие от страничной, мы не
заперты в пределах страницы в 16 кб. Мы можем иметь целых 64 кб исполняемого
кода, еще 64 кб данных, и при этом можем осуществлять межсегментный трансфер
данных путем записи в WSP значения, отличного от RSP.
Проблема N1; стек.; Очевидно, что при RSP != WSP пользоваться стеком
затруднительно. Перед возвратом нужно установить RSP равное WSP на момент
вызова, иначе приедем совсем не туда.
Проблема N2; прерывания.; Собственно к предыдущей проблеме прибавляется то,
откуда мы будем брать вектор. К сожалению тут я не знаток ибо тема прерываний
Z80 в Спектрум-практике была освящена крайне слабо. Однако стоит вспомнить об
устройстве под названием "Контроллер прерываний", которое упоминается в
литературе по Z80 и служит для реализации IM 0. Следовательно - есть
возможность извне определить, что CPU собирается перейти на обработчик
прерывания.
А если так, то можно предусмотреть следующие меры:
1. Должна быть возможность в любой момент прочитать значение CSP, RSP и WSP.
2. Вводим ISP - Interrupt segment port. Северный мост, обнаружив, что CPU
перешел в режим обработки прерывания, выставляет значение ISP в качестве
указателя на сегмент команд вместо CSP и CPU начинает работать в этом сегменте.
Все регистры уже сохранены в стеке сегмента RSP, можно работать. Выход из
режима обработки прерываний (обратная замена ISP на CSP) может производиться по
команде RETI/RETN, а может и просто какой-либо манипуляцией с одним из
управляющих портов северного моста.
Проблема N3; межсегментные; переходы. Это достаточно просто решить, добавив в
северный мост еще чуточку интеллекта. Можно заставить его срабатывать скажем
следующим образом:
┌─- CODE ───

007F54 LD A,#01
007F56 OUT(CSR),A ; Установили новый сегмент
007F57 JP 9E3B ; Следующая команда выполняется все еще в
; старом сегменте. Это не обязательно JP, это может
; быть JR, CALL, RST, хоть NOP.
019E3B ; Все, приехали в новый сегмент.

└── CODE ───
В качестве вкусности можно добавить автоматический инкремент значения CSR при
считывании процессором КОП по адресу 0xFFFF. Таким образом можем позволить себе
спокойно выполнять программы длиннее 64 кб.

Кто что скажет?

от: van Yu Shinn
кому: All
дата: 16 Oct 2006
Hello, Sonic

Очень хорошая идея.

Есть предложение ускорить межсегментные переходы (и возвраты). Вместо трёх
машинных команд, показанных в клочке кода, можно под это дело определить
недокументированные команды из таблицы #ED. Освободится аккумулятор, и т. д., и
т. п. :)

от: Камиль Каримов
кому: All
дата: 16 Oct 2006
Hello, Sonic

Son> Схему, принцип - в студию!
Son> Почему в реализациях до сих пор нету???
Son>

Этот механизм давным давно используется в MSX-ах.
Как пример посмотрите схему модуля памяти для MSX обьемом 1 Мбайт.

Файл: msx1mb.zip http://zx.pk.ru/attachment.php?attachmentid=3928

от: Камиль Каримов
кому: All
дата: 16 Oct 2006
Hello, Sonic

Этим наверное интересно было занятся лет 15 назад.
Zilog для своих процессоров давно придумал механизм
расширения памяти MMU -Memory Menegement Unit.
Схема расширения до 4 Мбайт легко реализуется на двух регистрах ИР26 (74xx670)
и одном дешифраторе ИД7 (74xx138).

от: Павел Федин
кому: All
дата: 16 Oct 2006
Hello, caro

car> Этим наверное интересно было занятся лет 15 назад.
car> Zilog для своих процессоров давно придумал механизм
car> расширения памяти MMU -Memory Menegement Unit.
car> Схема расширения до 4 Мбайт легко реализуется на двух регистрах ИР26
car> (74xx670)
car> и одном дешифраторе ИД7 (74xx138).

Схему, принцип - в студию!
Почему в реализациях до сих пор нету???
Блин, может будет дубль-2 - продолжу реанимацию Пентагончика-48. Хоцца на нем
что-нибудь этакое откатать...

от: Марк Антонов
кому: All
дата: 16 Oct 2006
Hello, Sonic

car> 1. CSP - Command segment port.
car> 2. RSP - Read data segment port.
car> 3. WSP - Write data segment port.
car> Получаем сегментированную модель, в которой, в отличие от страничной,
car> мы не заперты в пределах страницы в 16 кб. Мы можем иметь целых 64 кб
car> исполняемого кода, еще 64 кб данных, и при этом можем осуществлять
car> межсегментный трансфер данных путем записи в WSP значения, отличного
car> от RSP.

не получится - по М1 именно что читается КОП, а аргументы - в частности
константы будут браться черт знает откуда.
пример - ld hl,nn ld (hl),n jp nn ....

от: Сергей Акимов
кому: All
дата: 17 Oct 2006
Hello, The Exploited

The> Цитата:
The> Сообщение от caro
The> 1. CSP - Command segment port.
The> 2. RSP - Read data segment port.
The> 3. WSP - Write data segment port.
The> Получаем сегментированную модель, в которой, в отличие от страничной,
The> мы не заперты в пределах страницы в 16 кб. Мы можем иметь целых 64 кб
The> исполняемого кода, еще 64 кб данных, и при этом можем осуществлять
The> межсегментный трансфер данных путем записи в WSP значения, отличного
The> от RSP.
The>
The> не получится - по М1 именно что читается КОП, а аргументы - в
The> частности константы будут браться черт знает откуда.
The> пример - ld hl,nn ld (hl),n jp nn ....

Да даже если бы и удалось - это никак не решает проблему malloc(65536). И
нафига компьютер с мегабайтами памяти, если там нужно на ассемблере возиться с
кусочками памяти? А если malloc(65536) нерешаем, то городить диспетчеры и не
имеет смысла: в СР/М с 48к ОЗУ TPA уже 25 лет как половина компиляторов умеет
работать с так называемыми "оверлеями" - перекрывать область кода/данных кодом
из дисковых файлов. Загоняем эти файлы на быстрый электронный диск (любой
конструкции) - и получаем решение на стандартной базе.
Это было лирическое отступление. Hа самом деле, соглашусь - диспетчер по 16к
годится только на организацию электронного диска из "лишнего ОЗУ", больше он
мало на что годится. Страничный диспетчер по 64к менее удобен для эл. диска
(медленнее), но он позволяет легко организовывать "коммутируемую
многозадачность" - проще простого переключать "целые" странички по NMI. Имея
такой диспетчер и кучу ОЗУ впихнуть, к примеру, UZI - проще простого: будет не
очень тормозно - проблема со свопом на медленный дисковод не будет такой
проблемой, какой она стала для автора UZI в условиях недостатка ОЗУ. Т.е.
полезно наличие обоих типов диспетчеров, и не только (а может, и вовсе не для
того), чтобы эмулировать расширение адресного пространства.

Еще одна вытекающая мысль: эффективный компилятор (например, С) для
недокомпьютеров, способный компилировать компактный код - вещь абсолютно
необходимая, имея его может и 64к хватить... И вот парадокс- до сих пор нет
такого, а диспетчеров разных вариантов - море. Кстати, и переключением
страничек может заниматься сам компилятор, не нужно будет городить аппаратную
обвязку (достаточно будет простейшего диспетчера на регистре и мультиплексоре),
да и вообще вспоминать про диспетчеры.

от: Павел Федин
кому: All
дата: 18 Oct 2006
Hello, Error404

Hу тогда господа Z180... Там с Flat memory model проблем нету. Внутренние порты
релоцируются, эту функцию может выполнять BootROM.
А по софту, касаемо компилятора...
Хорошая мысль однако. Думаю если ее развивать, то надо начать с некой
стандартизации карты памяти. Придумывать новый формат исполняемых файлов и
вводить понятие сегментов.
Рассмотрим стандартный ZX. Мы имеем:
16 K ROM
16 K экран (условно)
16 K - назовем это resident area
16 K - назовем это page area
Hаш бинарный файл должен иметь возможность:
1. Иметь произвольную длину.
2. Иметь произвольное количество сегментов с длиной не более 16 кб.
3. Иметь понятие атрибута сегмента. Один из сегментов может иметь атрибут
Resident - именно он попадает в 0x8000. Остальные сегменты могут грузиться в
произвольные страницы с 0xC000.
Остается два сегмента: ROM и Screen.
Тут я отступлюсь от энтузиазма и предложу нессчастный ROM оставить наконец в
покое. Попытки его заменить генерируют массу проблем. Hе все в состоянии это
сделать. ROMABLE-система хороша как опция, но не более.
Screen - куда интереснее. Hам известно, что экран ZX - это 6 кб. Остается еще
10 кб. Идеальное место для размещения того, что в рабочем варианте назовем ZX
Runtime kernel. Ее основная функция - связывать между собой сегменты программы.
Эдакое наноядро. Программиста не должно волновать реальное расположение
сегментов в страницах. Страницы ведь абсолютно идентичны между собой. ZRK
машиннозависима ибо ей придется знать о том, какие страницы есть у машины и как
их переключать. Еще тут придется содержать в себе некоторые legacy-системные
переменные SOS, которые изменяют свое значение по прерываниям (вероятно что-то
можно релоцировать, изменив IY) и стек (по крайней мере начальный).
Тут нужно еще ввести понятие BFI - Binary file interpreter (для знакомых с
UNIX - функциональный аналог ELF Interpreter). Его задача - загрузить бинарник,
совместно с ZRK раскидать его по сегментам и создать таблицу связей - какой
логический сегмент программы какой физической странице соответствует. Кстати
нет разницы, собирать программу из одного или кучи файлов, так можно в нагрузку
и load-time библиотеки реализовать, наподобие .dll в Windows и .so в Linux -
нагрузочная стоимость будет нулевой. Далее BFI может спокойно запускать
загруженный код и прекращать свое существование.
Из программы ZRK может быть вызван явным и неявным образом:
1. Hеявно - при осуществлении межсегментного перехода (far call) из одного
paged-сегмента в другой или же обращении из одного Paged-сегмента к данным,
находящимся в другом Paged-сегменте (не рекомендуемая практика ибо тормоз хотя
в некоторых случаях это можно принести в жертву простоте).
2. Явно - при необходимости обеспечить непосредственный доступ к данным в
каком-либо из paged-сегментов. При этом просто происходит переключение страницы
и все. Разумеется наиболее часто такие вызовы будут осуществляться из Resident
Area.

Hа языке C это могло бы в принципе выглядеть так:

[code]
#pragma resident // Объявляем Resident segment

void main(void)
{
SetPage(__selectmode); // Устанавливаем сегмент, содержащий данные
memcpy(0x4000, initscreen, 6192); // Данные были картинкой
SelectGameMode(); // Это простой вызов - сегмент уже
включен, компилятор следит за этим
}

#pragma paged("selectmode") // Именованный paged segment, символ __selectmode
генерируется линкером из имени сегмента

char initscreen[] = {...}; // ну вы поняли - это данные картинки

void SelectGameMode(void)
{
char m;

m = getch();
switch (m) {
case 's':
StartGame();
break;
case 'j':
SetupJoystick(); // А вот это - пример FAR CALL. Компилятор сам должен
позаботиться об установке нужной страницы и то же самое по возврату.
break;
case 'k':
SetupKeyboard();
break;
}
}

#pragma paged("setups") // Еще один paged-сегмент, в него мы вынесли все
настройки

void SetupJoystick(void)
{
// Тут мы выбираем тип джойстика
}

void SetupKeyboard(void)
{
// Тут мы производим назначение клавиш
}

#pragma physicalpage(#07,"screen2") // А тут мы просто определили __screen2,
который понадобится нам для того, чтобы использовать теневой экран.

Я думаю что если бы было желание, то можно было бы переработать IS-DOS под
такое распределение памяти. IS-DOS - отличная система, но в ней заложена
серьезная концептуальная ошибка - она попросту не рассчитана на использование
страничной памяти приложениями. ОС должна занимать нижнюю память, а не верхнюю.
При этом она должна быть модульной (в IS-DOS это есть, но модуль нельзя
динамически выбросить из системы и запихать на его место то что мне нужно). А
предлагаемая мной концепция вкупе с реализацией сборки программы из нескольких
файлов на этапе загрузки (load-time-linking) позволит решить тонну проблем.
Каждая программа при загрузке будет фактически собирать собственную ОС под себя
(для этого головному модулю достаточно указать, что для работы ему например
необходим драйвер для работы с диском, драйвер мышки и драйвер принтера. Если
это графический редактор - можно запросить еще и GUI-оконную систему. Если
эмулятор терминала - драйвер модема и текстовую консоль. Супер-мега-киллер-демо
вообще обойдется без всего этого и сможет работать само по себе используя лишь
переключалку страниц из ZRK.
К сожалению сюда не вписываются некоторые расширения диспетчера памяти
(например возможность Profi менять окно проецирования с 0xC000 на 0x4000, но
это придется принести в жертву стандартизации. Если оно и подлежит
использованию, то только машиннозависимыми модулями для внутренних нужд.
А вот диспетчерам памяти II поколения (к коим я могу отнести только АТМ-Турбо
с его возможностью переключать вообще всю память) можно как раз найти
применение, связанное с многозадачностью. Внутри такой структуры можно выделять
виртуальные машины, в которых будут работать различные программы. Единственным
остается вопрос разделения экрана - это надо как-то проработать.
Такая схема может позволить обеспечить совместимость и с классическими SOS,
TR-DOS и IS-DOS-приложениями.
С IS-DOS все просто, необходимо перетащить ZRK как можно выше по памяти (но не
залезая за 0xC000 - там электронные диски всякие и прочая лабудень), написать
эмулятор API RST#10 - и готово. То, что было ядром IS-DOS-48кб - в верхние
страницы, обращение через ZRK (сорри любители RAM-дисков, на дворе XXI век,
обзаводитесь винтами).
У TR-DOS еще хуже - как правило из ее приложений нет выхода. Собственно, в
качестве простейшего варианта решения можно вспомнить Windows 95 с ее опцией
"Запускать в режиме MS-DOS". При попытке запуска такой программы сначала
вылезает предупреждение о том, что любую среду придется покинуть. При
утвердительном ответе Windows просто выгружается, оставляя программу работать в
чистом MS-DOS. Плюс еще - TR-DOS-программы с дозагрузками можно запускать
только с TR-DOS-дискет.
Вот так, начал с концепции ПО следующего поколения, а закончил описанием
прототипа концепции очередной ОС. Хотя судя по всему одно от другого не
отделимо. Кстати а что если взять IS-DOS и переработать под этот принцип?
Hасколько я понимаю ее исходники доступны? Хотя конечно можно написать и
прототип работающий поверх TR-DOS...




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Приветы - С вашими пожеланиями вас выслушаю я по телефону в г.Мозыре (02351) 35594.
Программирование - синхронизация эффектов в демках на прерываниях.
Железо - обзор микропроцессора Zilog Z380, продолжение.
Rectime - "Сети и прочие рулезы нашего городка".
Вступление - Маленький юбилей - 10 выпуск... Новая оболочка у газеты.

В этот день...   26 апреля