Чистая гарвардская архитектура обычно позволяет компьютеру с заданным уровнем сложности работать быстрее, чем архитектура фон Неймана, при условии, что между кодом и памятью данных не должно быть общих ресурсов. Если ограничения распиновки или другие факторы вынуждают использовать одну шину для доступа к обоим пространствам памяти, такие преимущества могут быть сведены на нет.
«Чистая» гарвардская архитектура будет ограничена выполнением кода, который помещается в память каким-либо механизмом, кроме процессора, который будет выполнять код. Это ограничивает полезность таких архитектур для устройств, назначение которых не установлено на заводе (или для тех, кто имеет специализированное оборудование для программирования). Для решения этой проблемы можно использовать два подхода:
Некоторые системы имеют отдельные области кода и памяти, но предоставляют специальное оборудование, которое можно попросить кратковременно захватить шину кода, выполнить некоторую операцию и вернуть управление ЦПУ после завершения такой операции. Некоторые такие системы требуют довольно сложного протокола для выполнения таких операций, некоторые имеют специальные инструкции для выполнения такой задачи, а некоторые даже следят за определенными адресами «памяти данных» и запускают захват / освобождение при попытке доступа к ним. , Ключевым аспектом таких систем является то, что существуют явно определенные области памяти для «кода» и «данных»; даже если ЦПУ может читать и записывать пространство «кода», оно все равно распознается как семантически отличное от пространства данных ».
Альтернативный подход, который используется в некоторых системах более высокого уровня, состоит в том, чтобы иметь контроллер с двумя шинами памяти, одна для кода и одна для данных, обе из которых подключаются к блоку арбитража памяти. Это устройство в свою очередь подключается к различным подсистемам памяти, используя отдельную шину памяти для каждой. Кодовый доступ к одной подсистеме памяти может обрабатываться одновременно с доступом к данным к другой; только если код и данные попытаются получить доступ к одной и той же подсистеме одновременно, придется ждать.
В системах, использующих этот подход, части программы, не критичные к производительности, могут просто игнорировать границы между подсистемами памяти. Если код и данные находятся в одной подсистеме памяти, все будет работать не так быстро, как если бы они были в разных подсистемах, но для многих частей типичной программы это не будет иметь значения. В типичной системе будет небольшая часть кода, где производительность действительно имеет значение, и она будет работать только с небольшой частью данных, хранящихся в системе. Если бы у вас была система с 16 КБ ОЗУ, которая была разделена на два раздела по 8 КБ, можно было использовать инструкции компоновщика, чтобы гарантировать, что критичный к производительности код был расположен в начале общего пространства памяти, а критичные к производительности данные были рядом с конец. Если общий размер кода увеличивается, например, до 9K, код в последнем 1K будет работать медленнее, чем код, размещенный в другом месте, но этот код не будет критичным для производительности. Аналогично, если бы код был, например, только 6 КБ, но объем данных вырос до 9 КБ, доступ к самым низким 1 КБ данных был бы медленным, но если бы данные, критичные для производительности, находились в другом месте, это не создавало бы проблем.
Обратите внимание, что, хотя производительность была бы оптимальной, если бы код был меньше 8 КБ, а данные были меньше 8 КБ, вышеупомянутая конструкция системы памяти не налагает какого-либо строгого разделения между кодом и пространством данных. Если программе требуется только 1 КБ данных, код может увеличиться до 15 КБ. Если ему требуется всего 2 КБ кода, данные могут увеличиться до 14 КБ. Гораздо более универсальный, чем область 8K только для кода и область 8K только для данных.