
Комментарии 12
Спасибо за статью. Всегда интересно посмотреть на чужой взгляд на давно устоявшиеся (и даже устаревшие) вещи.
Теперь немного критики. Вы так статарельно избегали погружения в устройство микропроцессоров, что незаметикли как допустили ошибку в выбранной концепции шины.
Вы правильно указали, что в i8080 имеются специальные инструкции для работы с портами ввода/вывода (как и во всех последующих сериях микропроцессоров Intel, кстати). Для реализации этих инструкций на корпус микропроцессора i8080 выведен специальный сигнал DBIN, который указывает на то, с чем будет осуществляться обмен - с памятью или с I/O устройством. Это означает, что адреса устройств могут пересекаться с адресами ячеек памяти и это не создает никаких проблем для аппаратуры, так как декодер адреса учитывает этот сигнал. В выбранной Вами модели шины данного сигнала нет, а значит возникает "конфликт интересов" выражающийся в отсутствии возможности использовать младшие адреса ячеек памяти которые по номерам пересекаются с портами ввода/вывода. Скорее всего этой проблемы Вы не заметили, так как работали в основном с MOS 6502, где I/O организован через memory-mapped регистры, но с i8080 и i8086 эта проблема выплывет и Вам придется переделать шину.
Выбранный Вами способ задания диапазонов устройств на шине не тольно не оптимальный, он неправильный. :) При реализации аппаратуры, блок I/O регистров конкретного устройства обычно задается в виде базового адреса и битовой маски (или префикса указывающего длину лидирующей части адреса). Это позволяет легко, одной операцией AND, вычислить тэг для определения утройства к которому производится обращение. Я думаю, Вам следовало бы сделать то же самое - сохранять в std::map карту тэгов и указателей на обьект Device. Это избавило бы от необходимости каждый раз вызывать метод find(), который итеративно бегает по массиву и бездарно потребляет процессорное время, а доступ к устройству - всего пара инструкций реального процессора.
Вообще, я настоятельно рекомендую ознакомиться с принципами реализации классических микропроцессоров, то есть слегка погрузиться в мир микроархитектуры. Вы найдете там очень много интересных и нестандартных, в то же время очень простых, решений, которые упростят Вам программирование Вашего симулятора. Еще раз спасибо.
Спасибо за такой развернутый комментарий! Приятно видеть, что кто-то нашел силы одолеть такой лонгрид :)
Я знаю про сигнал DBIN, и возможно вы не заметили, но я совершенно точно подчеркнул в тексте, что для I8080 я ввел дополнительный экземпляр шины, поэтому никакого конфликта интересов не возникает. В случае работы с памятью я обращаюсь к bus, а в случае работы с периферией (инструкции IN/OUT) я обращаюсь к dataBus. Да, это костыль, но в целом на данном этапе я считаю это решение приемлемым.
По поводу реализации маппинга адресов в шине я с вами полностью согласен. Решение сильно мозолит мне глаз, но пока я не смог найти ни времени ни сил переработать его. Сейчас оно пусть и медленнее, чем хотелось бы, зато достаточно прямолинейное чтобы его можно было понять.
Так или иначе замечания справедливые, и я обязательно обдумаю эти моменты ещё раз.
Вы правильно указали, что в i8080 имеются специальные инструкции для работы с портами ввода/вывода (как и во всех последующих сериях микропроцессоров Intel, кстати). Для реализации этих инструкций на корпус микропроцессора i8080 выведен специальный сигнал DBIN, который указывает на то, с чем будет осуществляться обмен - с памятью или с I/O устройством.
Здесь Вы ошибаетесь. Из собственно микропроцессора 8080 торчат сигналы, показывающие направление обмена, но не цель (память или порт). Чтобы определить, выполняется доступ к памяти или порту, необходимо запомнить байт состояния, выдаваемый микропроцессором на шину данных в сопровождении сигнала строба перед собственно обращением к памяти или порту. Это можно сделать как на рассыпной логике (так было сделано, например, в "Микро-80"), а можно использовать специальную микросхему типа 8228 или 8238. Если же этого нет, различить доступы к памяти и портам на 8080 невозможно.
Я имел дело с КР580ВМ80А в конце 80-х, так что таких подробностей уже не помню. :-) Действительно, DBIN показывет только направление, а для определения типа доступа необходима микросхема контроллера шины (8228). Спасибо.
Возможно, Вы спутали с Z80 (или, может, 8085) -- вроде б, там всё необходимое выдавал уже сам микропроцессор, и необходимость во внешней логике отсутствовала (ну, не считая простых буферов для увеличения нагрузочной способности). Но тут я уже не помню: с ними я не работал вообще (даже на Роботроне-1715, на котором проработал пару лет, я писал программы под 8080 -- для промышленных контроллеров на КР580ВМ80А; соответственно, полная система команд Z80 мне хоть и была доступна, но совершенно не требовалась, на "железную" сторону тоже не смотрел за ненадобностью).
Точно. Как и у всех в то время у меня был спектрум-совместымий ПК полу-заводской сборки. Сейчас посморел на распиновку Z80, в нём действительно присутствует сигнал /IORQ задающий тип доступа: к I/O или к памяти. Еще один плюс Zilog-у за то, что избавили разработчиков от лишнего гимора. :-)
PS: В i8086 тоже есть готовый сигнал M/IO.
2автор - в чем нарисованы картинки для статьи?
По литературе, скорее всего у вас уже есть, но на всякий случай моя первая и любимая книжка по Intel 8088 "Л.Дао - Программирование микропроцессора 8088". Я часами просиживал в библиотеке т.к. на руки такое сокровище не выдавали )) Совсем недавно мне любезно предоставили ссылки на тот самый русский вариант и его английский первоисточник.
Пара замечаний. Во-первых, Z80 не полностью совместим с 8080, но об этом мало кто знает -- я, например, узнал только в этом году (впрочем, специально под Z80 я никогда и не писал). Разница заключается в регистре флагов: один из его битов может по-разному устанавливаться в 8080 и Z80, что сделает использующую его программу непереносимой.
Второе. x86 -- это неофициальное обозначение архитектуры. Подозреваю, что официальным для 8086 был MCS86, а вот для 80386 и последующих 32-разрядных микропроцессоров официальным названием совершенно точно является IA-32, но никак не x86. Ну а современные 64-разрядные -- это AMD64 (Интел скопировала это расширение архитектуры у АМД, но, поскольку им религия не позволяет прямо указать автора, после некоторых колебаний закрепилось название Intel 64 -- не путать с IA-64, которое обозначает архитектуру процессоров, известных по их торговой марке Itanium).
От MOS6502 к x86: эволюция эмулятора микропроцессоров