| Код ошибки: 0 (0x0000) Операция выполнена успешно. Код ошибки: 1 (0x0001) Неверная функция. Код ошибки: 2 (0x0002) Системе не удается найти указанный файл. Код ошибки: 3 (0x0003) Системе не удается найти указанный путь. Код ошибки: 4 (0x0004) Системе не удается открыть файл. Код ошибки: 5 (0x0005) Нет доступа. Код ошибки: 6 (0x0006) Неверный дескриптор. Код ошибки: 7 (0x0007) Повреждены управляющие блоки памяти. Код ошибки: 8 (0x0008) Недостаточно памяти для обработки команды. Код ошибки: 9 (0x0009) Неверный адрес управляющего блока памяти. Код ошибки: 10 (0x000A) Ошибка в среде. Код ошибки: 11 (0x000B) Была сделана попытка загрузить программу, имеющую неверный формат. Код ошибки: 12 (0x000C) Код доступа неверен. Код ошибки: 13 (0x000D) Ошибка в данных. Код ошибки: 14 (0x000E) Недостаточно памяти для завершения операции. Код ошибки: 15 (0x000F) Системе не удается найти указанный диск. Код ошибки: 16 (0x0010) Не удается удалить папку Код ошибки: 17 (0x0011) Системе не удается переместить файл на другой диск. Код ошибки: 18 (0x0012) Больше файлов не осталось. Код ошибки: 19 (0x0013) Носитель защищен от записи. Код ошибки: 20 (0x0014) Системе не удается найти указанное устройство. Код ошибки: 21 (0x0015) Устройство не готово. Код ошибки: 22 (0x0016) Устройство не опознает команду. Код ошибки: 23 (0x0017) Ошибка в данных (CRC) Код ошибки: 24 (0x0018) Длина выданной программой команды слишком велика. Код ошибки: 25 (0x0019) Не удается найти заданную область или дорожку на диске. Код ошибки: 26 (0x001A) Нет доступа к диску или дискете. Код ошибки: 27 (0x001B) Не удается найти заданный сектор на диске. Код ошибки: 28 (0x001C) Нет бумаги в принтере. Код ошибки: 29 (0x001D) Системе не удается произвести запись на устройство. Код ошибки: 30 (0x001E) Системе не удается произвести чтение с устройства. Код ошибки: 31 (0x001F) Присоединенное к системе устройство не работает. Код ошибки: 32 (0x0020) Процесс не может получить доступ к файлу, так как этот файл занят другим процессом. Код ошибки: 33 (0x0021) Процесс не может получить доступ к файлу, так как часть этого файла заблокирована другим процессом. Код ошибки: 34 (0x0022) В устройство вставлен неверный диск. Вставьте %2 (серийный номер тома: %3) в устройство %1. Код ошибки: 36 (0x0024) Слишком много файлов открыто для совместного доступа. Код ошибки: 38 (0x0026) Достигнут конец файла. Код ошибки: 39 (0x0027) Диск заполнен до конца. Код ошибки: 50 (0x0032) Сетевой запрос не поддерживается. Код ошибки: 51 (0x0033) Удаленный компьютер недоступен. Код ошибки: 52 (0x0034) В сети существуют совпадающие имена. Код ошибки: 53 (0x0035) Не найден сетевой путь. Код ошибки: 54 (0x0036) Сеть занята. Код ошибки: 55 (0x0037) Сетевой ресурс или устройство более недоступно. Код ошибки: 56 (0x0038) Достигнут предел числа команд NetBIOS. Код ошибки: 57 (0x0039) Аппаратная ошибка сетевой платы. Код ошибки: 58 (0x003A) Указанный сервер не может выполнить требуемую операцию. Код ошибки: 59 (0x003B) Неожиданная ошибка в сети. Код ошибки: 60 (0x003C) Несовместимый удаленный адаптер. Код ошибки: 61 (0x003D) Очередь печати переполнена. Код ошибки: 62 (0x003E) На сервере отсутствует место для записи файла, выводимого на печать. Код ошибки: 63 (0x003F) Ваш файл, находившийся в очереди вывода на печать, был удален. Код ошибки: 64 (0x0040) Указанное сетевое имя более недоступно. Код ошибки: 65 (0x0041) Отсутствует доступ к сети. Код ошибки: 66 (0x0042) Неверно указан тип сетевого ресурса. Код ошибки: 67 (0x0043) Не найдено сетевое имя. Превышен предел по числу имен для локальной сетевой платы компьютера. Код ошибки: 69 (0x0045) Превышен предел по числу сеансов NetBIOS. Код ошибки: 70 (0x0046) Сервер сети был остановлен или находится в процессе запуска. Код ошибки: 71 (0x0047) Дополнительные подключения к этому удаленному компьютеру в настоящее
время невозможны, поскольку число подключений к компьютеру достигло
предела. Код ошибки: 72 (0x0048) Работа указанного принтера или дискового накопителя была остановлена. Код ошибки: 80 (0x0050) Файл существует. Код ошибки: 82 (0x0052) Не удается создать файл или папку. Код ошибки: 83 (0x0053) Ошибка при обращении к прерыванию INT 24 Код ошибки: 84 (0x0054) Недостаточно памяти для обработки запроса. Код ошибки: 85 (0x0055) Имя локального устройства уже используется. Код ошибки: 86 (0x0056) Сетевой пароль указан неверно. Код ошибки: 87 (0x0057) Параметр задан неверно. Код ошибки: 88 (0x0058) Ошибка записи в сети. Код ошибки: 89 (0x0059) В настоящее время системе не удается запустить другой процесс. Код ошибки: 100 (0x0064) Не удается создать еще один системный семафор. Код ошибки: 101 (0x0065) Семафор эксклюзивного доступа занят другим процессом. Код ошибки: 102 (0x0066) Семафор установлен и не может быть закрыт. Код ошибки: 103 (0x0067) Семафор не может быть установлен повторно. Код ошибки: 104 (0x0068) Запросы к семафорам эксклюзивного доступа на время выполнения прерываний не допускаются. Код ошибки: 105 (0x0069) Этот семафор более не принадлежит использовавшему его процессу. Код ошибки: 106 (0x006A) Вставьте диск в устройство %1. Код ошибки: 107 (0x006B) Программа была остановлена, так как нужный диск вставлен не был. Код ошибки: 108 (0x006C) Диск занят или заблокирован другим процессом. Код ошибки: 109 (0x006D) Канал был закрыт. Код ошибки: 110 (0x006E) Системе не удается открыть указанное устройство или файл. Код ошибки: 111 (0x006F) Указано слишком длинное имя файла. Код ошибки: 112 (0x0070) Недостаточно места на диске. Код ошибки: 113 (0x0071) Исчерпаны внутренние идентификаторы файлов. Код ошибки: 114 (0x0072) Результирующий внутренний идентификатор файла неправилен. Код ошибки: 117 (0x0075) Вызов IOCTL приложением произведен неверно. Код ошибки: 118 (0x0076) Параметр проверки записи данных имеет неверное значение. Код ошибки: 119 (0x0077) Система не может обработать полученную команду. Код ошибки: 120 (0x0078) Эта функция допустима только в режиме Win32. Код ошибки: 121 (0x0079) Истек интервал ожидания семафора. Код ошибки: 122 (0x007A) Область данных, переданная по системному вызову, слишком мала. Код ошибки: 123 (0x007B) Синтаксическая ошибка в имени файла, имени папки или метке тома. Код ошибки: 124 (0x007C) Неверный уровень системного вызова. Код ошибки: 125 (0x007D) У диска отсутствует метка тома. Код ошибки: 126 (0x007E) Не найден указанный модуль. Код ошибки: 127 (0x007F) Не найдена указанная процедура. Код ошибки: 128 (0x0080) Дочерние процессы, окончания которых требуется ожидать, отсутствуют. Код ошибки: 129 (0x0081) Приложение %1 нельзя запустить в режиме Win32. Код ошибки: 130 (0x0082) Попытка использовать дескриптор файла для открытия раздела диска и выполнения операции, отличающейся от ввода/вывода нижнего уровня. Код ошибки: 131 (0x0083) Попытка поместить указатель на файл перед началом файла. |
Справочник программиста на персональном компьютере фирмы IBM.Роберт Журден
Справочник программиста на персональном компьютере фирмы IBM.Роберт ЖурденГлава 1. Системные ресурсы.
Раздел 3. Управление программами.
1.3.1 Манипуляции с памятью.
Kогда MS DOS загружает программу, то она помещается в младшую область памяти, сразу же за COMMAND.
| ZSEG SEGMENT | |
| ; | |
| ZSEG ENDS |
В ассемблере IBM PC ZSEG будет последним сегментом, так как сегменты располагаются в алфавитном порядке. С другими ассемблерами нужно действительно поместить эти строки в конце программы. В самой программе достаточно поставить оператор MOV AX,ZSEG и AX будет указывать на первый свободный сегмент памяти за программой.
Такой подход будет работать до тех пор, пока программа не будет предполагать о наличии памяти, которой на самом деле нет.
Прежде чем отвести память, существующий блок (вся память от начала программы до конца) должен быть обрезан до размера программы.
Затем, при создании блока, DOS создает 16-байтный управляющий блок памяти, который расположен непосредственно перед блоком памяти. Первые 5 байтов этого блока имеют следующее значение:
байт 0 ASCII 90 - если последний блок в цепочке, иначе
ASCII 77.
байты 1-2 0 если блок освобожден
байты 3-4 размер блока в 16-байтных параграфах
DOS обращается к блокам по цепочке. Адрес первого блока хранится во внутренней переменной. Значение этой переменной позволяет DOS определить положение первого отведенного блока, а из информации, содержащейся в нем, может быть найден следующий блок и т.д., как показано на рис. 1-4. Kак только Вы начали использовать систему распределения памяти DOS, то Вы обязаны придерживаться ее. Если программа изменит содержимое управляющего блока, то цепочка будет разорвана и DOS начнет выдавать сообщения об ошибке.
MS DOS обеспечивает три функции распределения памяти, номера от 48H до 4AH прерывания 21H. Функция 48H отводит блок памяти, а 49H — освобождает блок памяти.
Третья функция («SETBLOCK») меняет размер памяти, отведенной для программы; эта функция должна быть использована перед двумя остальными. После ее выполнения можно спокойно отводить и освобождать блоки памяти. Программа должна освободить все отведенные ею блоки перед завершением. Иначе эта память будет недоступной для последующего использования.
Средний уровень.
Все три функции распределения памяти прерывания 21H используют 16-битный адрес начала блока памяти, с которым они оперируют. Этот адрес соответствует сегменту, с которого начинается блок (блок всегда начинается со смещения 0 данного сегмента). Таким образом реальный адрес ячейки начала блока равен этому адресу, умноженному на 16. Также, для всех трех функций, BX содержит число 16-байтных разделов памяти (параграфов), которые будут отводиться или освобождаться. Если функция не может быть выполнена, то устанавливается флаг переноса, а в AX возвращается код ошибки, объясняющий причину. Возможны три кода ошибки:
7 разрушен управляющий блок памяти 8 недостаточно памяти для выполнения функции 9 неверный адрес блока памятиФункция отведения блока использует коды 7 и 8, а освобождения — 7 и 9, в то время как функция изменения блока использует все три кода.
В следующем примере сначала отводится блок, размером 1024 байта. При этом BX содержит требуемое число 16-байтных параграфов, а при завершении стартовый адрес блока равен AX:0 (т.е. смещение 0 в сегменте со значением, содержащимся в AX). Вторая часть примера освобождает этот же блок, как и требуется при завершении программы. В данном случае значение полученное в AX помещается в ES. DOS следит за размером блока и знает какое количество параграфов надо освободить.| ;—отведение блока размером 1024 байта | |
| MOV AH,48H | ;номер функции |
| MOV BX,64 | ;требуем 64 параграфа |
| INT 21H | ;пытаемся отвести блок |
| JC ERROR | ;обрабатываем ошибку в случае неудачи |
| MOV BLOCK_SEG,AX | ;иначе сохраняем адрес блока |
| . | |
| ;—освобождаем тот же блок | |
| MOV AX,BLOCK_SEG | ;получаем стартовый адрес блока |
| MOV ES,AX | ;помещаем его в ES |
| MOV AH,49H | ;номер требуемой функции |
| INT 21H | ;освобождаем блок памяти |
Hаконец, приведем пример использования функции 4AH.
ES содержит значение сегмента PSP, т.е. самого первого байта памяти, с которого загружена программа. Это значение присваивается ES при старте задачи. Для использования SETBLOCK надо либо вызывать эту функцию в самом начале программы (прежде чем ES будет изменен), либо сохранить его начальное значение для последующего использования.
BX содержит требуемый размер блока в 16-байтных параграфах. Для определения этого размера поместите добавочный «искуственный» сегмент в конец программы. В макроасссемблере IBM PC сегменты располагаются в алфавитном порядке, поэтому Вы можете поместить его в любое место программы, при условии, что его имя это что-то вроде «ZSEG». В других ассемблерах действительно помещайте фиктивный сегмент в конец программы. Программа может прочитать позицию этого сегмента и, сравнивая ее со стартовым сегментом, получить количество памяти, требуемое самой программе. В момент загрузки программы и ES и DS содержат номер параграфа самого начала программы в префиксе программного сегмента; для COM файлов CS также указывает на эту позицию, но для EXE файлов это не так.
| MOV BX,ZSEG | ;получаем # параграфа конца программы + 1 |
| MOV AX,ES | ;получаем # параграфа начала программы |
| SUB BX,AX | ;вычисляем размер программы в параграфах |
| MOV AH,4AH | ;номер функции |
| INT 21H | ;освобождаем память |
| JC MEMORY_ERROR | ;проверяем на ошибку |
| ;— | |
| ZSEG SEGMENT | |
| ZSEG ENDS |
Раздел 3. Управление программами.
Содержание
1.3.2 Запуск одной программы из другой.-~>
Сайт управляется системой uCoz
пейджинг — ошибка страницы в операционной системе.(неверная адресация или страница не в основной памяти)
спросил
Изменено 5 лет, 6 месяцев назад
Просмотрено 2к раз
я читаю об ошибках страниц в пейджинге по запросу.
ошибки страницы происходят, когда
1) обращение к памяти является незаконным
2) страница действительна, но отсутствует в основной памяти
я читал, что с допустимым битом вы можете сказать, находится ли память не в логическом адресное пространство, потому что соответствующий бит будет помечен как недействительный.
один и тот же бит допустимого-недопустимого значения используется для идентификации вышеуказанного 2 условия.
мой вопрос, как ОС узнает, что доступ к памяти является незаконным или если страница действительна, но не находится в основной памяти только с одним допустимым битом? спасибо!
- операционная система
- подкачка
- ошибка страницы
- пейджинг по запросу
1
В Пейджинг по запросу , если бит действительного-недействительного установлен (1), это означает, что соответствующая страница является допустимой и находится в памяти.
Однако, если бит действительно-недействителен не установлен (0), это означает следующее:
- Либо страница
недействительна. Это означает, что страница не находится в процесселогического адресного пространства. ИЛИ - Соответствующая
страницанаходится надиске.
Недопустимый доступ к странице вызывает ловушку ошибки страницы . И лечим его следующим образом. Цитата из Принципов операционных систем Зильбершатца, Галвина, Ганя
- Мы проверяем внутреннюю таблицу (обычно хранящуюся в блоке управления процессом) для этого процесса, чтобы определить, была ли ссылка действительной. или недопустимый доступ к памяти.
- Если ссылка недействительна, мы завершаем процесс. Если он был действителен, но мы еще не ввели эту страницу, мы теперь вводим ее.
- Находим свободный кадр(взяв, например, один из списка свободных кадров).
- Мы планируем дисковую операцию для чтения нужной страницы во вновь выделенный фрейм.
- Когда чтение с диска завершено, мы модифицируем внутреннюю таблицу, хранящуюся вместе с процессом, и таблицу страниц, чтобы указать, что страница теперь в памяти.
- Перезапускаем прерванную ловушкой инструкцию. Теперь процесс может получить доступ к странице, как если бы она всегда находилась в Память.
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя адрес электронной почты и пароль
Опубликовать как гость
Электронная почта
Обязательно, но не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
pyrtl.
memory — документация PyRTL 0.10.1 """ Определяет память PyRTL. Эти блоки памяти можно читать (потенциально асинхронно) и записывать (синхронно). MemBlocks поддерживает любое количество следующих операций: * читать: `d = память [адрес]` * напишите: `mem[адрес] <<= d` * запись с разрешением: `mem[адрес] <<= MemBlock.EnabledWrite(d,enable=we)` На основе количества операций чтения и записи будет сделан вывод о памяти. с правильным количеством портов для поддержки этого """ из __future__ import print_function, unicode_literals импорт коллекций из .pyrtlexceptions импортировать PyrtlError из .core импортировать working_block, LogicNet, _NameIndexer из .wire импортировать WireVector, Const, next_tempvar_name из .corecircuits импортировать as_wires # -------------------------------------------------- ----------------------- # # ___ __ __ __ __ __ # |\/| |__ |\/| / \ |__) \ / |__) | / \ / ` |__/ # | | |___ | | \__/ | \ | |__) |___ \__/ \__, | \ # _memIndex = _NameIndexer() _MemAssignment = collections.namedtuple('_MemAssignment', 'правая сторона, is_conditional') """_MemAssignment — это тип, возвращаемый из присваивания |= или <<=""" защита _reset_memory_indexer(): глобальный _memIndex _memIndex = _NameIndexer() класс _MemIndexed (WireVector): """ Объект, используемый внутренне для правильного распределения памяти. Обычный пользователь PyRTL никогда не должен знать, что этот класс существует, отсюда и подчеркивание в имени. Он представляет собой очень похожий интерфейс на WireVectors (все обычные операции с векторами проволоки должны работать), но если вы попытаетесь *установить* значение с помощью <<= или |=, тогда будет сгенерировано _MemAssignment вместо обычного проводного назначения. """ def __init__(я, память, индекс): self.mem = память self.index = индекс self.wire = Нет def __ilshift__(я, другой): вернуть _MemAssignment (rhs = другое, is_conditional = False) def __ior__(я, другой): вернуть _MemAssignment (rhs = другое, is_conditional = True) def _two_var_op(я, другой, оператор): вернуть as_wires(self).
_two_var_op(другое, op) защита __invert__(я): вернуть as_wires(self).__invert__() def __getitem__(я, предмет): вернуть as_wires(я).__getitem__(элемент) защита __len__(я): вернуть self.mem.bitwidth def sign_extended (я, битовая ширина): вернуть as_wires (я). sign_extended (битовая ширина) def zero_extended (я, битовая ширина): вернуть as_wires (я). Zero_extended (битовая ширина) @имущество имя защиты (я): вернуть as_wires(я).имя # поднять PyrtlError("MemIndexed является временным объектом и поэтому не имеет имени") @name.setter имя защиты (я, n): as_wires(self).name = n
[документы]класс MemBlock(объект): """ MemBlock — это объект для указания блоков памяти. индексируется как массив для чтения и записи. Пишет под условным автоматически преобразуются в разрешенные записи. Например, рассмотрим следующее примеры, где `addr`, `data` и `we` являются WireVectors.
Применение:: data = memory[addr] (выведите порт чтения) memory[addr] <<= data (вывести порт записи) mem[адрес] <<= MemBlock.EnabledWrite (данные, включить = мы) Когда адрес памяти назначается с помощью объекта EnableWrite элементы будут записываться в память только тогда, когда активен WireVector. установить на высокий уровень (1). """ # FIXME: порты записи предполагают, что только один порт находится под управлением условного EnabledWrite = collections.namedtuple('EnabledWrite', 'данные, включить') """ Разрешает бит разрешения для каждого порта записи, где данные (первое поле в кортеж) — обычный адрес данных, а enable (второе поле) — единица. битовый сигнал, указывающий, что запись должна произойти (т.е. активный высокий уровень)."""
[документы] def __init__(self, bitwidth, addrwidth, name='', max_read_ports=2, max_write_ports=1, асинхронный = Ложь, блок = Нет): """ Создайте память для чтения и записи PyRTL.
:param int bitwidth: определяет разрядность каждого элемента в памяти. :param int addrwidth: Число битов, используемых для адресации элемента Память. Это также определяет размер памяти :param str name: Идентификатор памяти :param max_read_ports: ограничивает количество портов чтения для каждого блок можно создать; передача `None` указывает на отсутствие ограничений :param max_write_ports: ограничивает количество портов записи для каждого блок можно создать; передача `None` указывает на отсутствие ограничений :param bool asynchronous: если false, убедитесь, что выполняется только чтение памяти. используя значения прямо из регистра. (также убедитесь, что чтение синхронно) :param basestring name: Имя памяти. По умолчанию автоматически сгенерированный имя :param block: Блок, в который его нужно добавить, по умолчанию является рабочим блоком. Лучше всего убедиться, что ваша блочная память/fifos читает/записывает операции начинаются по тактовой частоте, если вы хотите, чтобы они синтезировались на эффективном оборудовании.
MemBlocks обеспечит это, убедившись, что вы обращаетесь к ним только с помощью регистра или ввода, если вы явно не объявляете память как асинхронная с флагом `asynchronous=True`. Обратите внимание, что асинхронные мемы иногда очень удобны и заманчивы, но редко являются хорошей идеей. Они не могут быть сопоставлены с блочными поршнями в FPGA и будут преобразованы в регистры большинством инструменты проектирования, хотя PyRTL без проблем справляется с ними. Для любой памяти за пределами несколько сотен записей — это нереальный вариант. Каждое чтение или запись в память будет создавать новый «порт» (либо порт чтения, либо порт записи). порт соответственно). По умолчанию память ограничена 2 портами чтения и 1 портом записи, но чтобы сохранить эффективность дизайна по умолчанию, но эти значения можно установить в качестве параметров. Примечание что память с большим количеством портов может быть невозможно сопоставить с физической памятью такие как блочные ОЗУ или существующие аппаратные макросы памяти.
""" self.max_read_ports = max_read_ports self.num_read_ports = 0 self.block = рабочий_блок (блок) имя = имя_следующей_темппеременной (имя) если битовая ширина <= 0: поднять PyrtlError('разрядность должна быть >= 1') если адресная ширина <= 0: поднять PyrtlError('addrwidth должен быть >= 1') self.bitwidth = битовая ширина self.name = имя self.addrwidth = адресная ширина self.readport_nets = [] self.id = _memIndex.next_index() самостоятельный.асинхронный = асинхронный self.block._add_memblock(я) self.max_write_ports = max_write_ports self.num_write_ports = 0 self.writeport_nets = []
@имущество деф read_ports (я): поднять PyrtlError («read_ports теперь для ясности называется num_read_ports») def __getitem__(я, предмет): """ Создает схему для извлечения элемента из памяти """ item = as_wires(item, bitwidth=self.
addrwidth, truncating=False) если len(item) > self.addrwidth: поднять PyrtlError('разрядность индекса памяти> разрядность адреса') вернуть _MemIndexed (память = я, индекс = элемент) def __setitem__(я, предмет, задание): """ Создает схему для установки элемента в память """ если isinstance (назначение, _MemAssignment): self._assignment(item,assignment.rhs,is_conditional=assignment.is_conditional) еще: поднять PyrtlError('ошибка, назначение памяти должно использовать "<<=" не "=" оператор') def _readaccess(я, адрес): # FIXME: добавить порты условного чтения вернуть self._build_read_port (адрес) def _build_read_port (я, адрес): если self.max_read_ports не None: self.num_read_ports += 1 если self.num_read_ports > self.max_read_ports: поднять PyrtlError('максимальное количество портов чтения (%d) превышено' % self.max_read_ports) данные = WireVector (битовая ширина = self.
bitwidth) readport_net = LogicNet( оп = 'м', op_param=(self.id, я), аргументы=(адрес,), назначения = (данные,)) work_block().add_net(readport_net) self.readport_nets.append(readport_net) возвращаемые данные def _assignment(self, item, val, is_conditional): из .условного импорта _build item = as_wires(item, bitwidth=self.addrwidth, truncating=False) если len(item) > self.addrwidth: поднять PyrtlError('ошибка, провод, индексирующий разрядность памяти > addrwidth') адрес = элемент если isinstance(val, MemBlock.EnabledWrite): данные, включить = знач.данные, знач.включить еще: данные, включить = val, Const (1, битовая ширина = 1) data = as_wires(data, bitwidth=self.bitwidth, truncating=False) enable = as_wires (включить, битовая ширина = 1, усечение = ложь) если len(данные) != self.bitwidth: поднять PyrtlError('ошибка, запись данных больше, чем разрядность памяти') если len(включить) != 1: поднять PyrtlError('ошибка, разрешающий сигнал не точно 1 бит') если is_conditional: _build(я, (адрес, данные, включить)) еще: self.
_build (адрес, данные, включить) def _build (я, адрес, данные, включение): """ Создает порт записи. """ если self.max_write_ports не None: self.num_write_ports += 1 если self.num_write_ports > self.max_write_ports: поднять PyrtlError('максимальное количество портов записи (%d) превышено' % self.max_write_ports) writeport_net = LogicNet( оп='@', op_param=(self.id, я), args=(адрес, данные, включить), назначения=кортеж()) work_block().add_net(writeport_net) self.writeport_nets.append(writeport_net) def _make_copy (я, блок = нет): блок = рабочий_блок (блок) вернуть MemBlock (битовая ширина = self.bitwidth, адресная ширина=self.addrwidth, имя=я.имя, max_read_ports=self.max_read_ports, max_write_ports=self.max_write_ports, асинхронный = self.
асинхронный, блок=блок)
[документы]класс RomBlock(MemBlock): """ Память только для чтения PyRTL. RomBlocks — это блоки памяти только для чтения для PyRTL. Они поддерживают один и тот же интерфейс чтения и нормальная память, но запись в них невозможна (т.е. нет портов записи). ПЗУ должно быть инициализировано некоторыми значениями и конструкциями с помощью `romdata`, который является памятью для системы. """
[документы] def __init__(self, bitwidth, addrwidth, romdata, name='', max_read_ports=2, build_new_roms = Ложь, асинхронный = Ложь, pad_with_zeros = Ложь, блок = Нет): """Создайте память только для чтения Python. :param int bitwidth: Битовая ширина каждого элемента, хранящегося в ПЗУ. :param int addrwidth: Разрядность адресной шины (определяет количество адресов) :param romdata: Это может быть либо функция, либо массив (итерируемый), который отображает адрес как вход к результату как выход :param str name: Идентификатор памяти :param max_read_ports: ограничивает количество портов чтения, которые может создать каждый блок; передача `None` указывает на отсутствие ограничений :param bool build_new_roms: указывает, нужно ли создавать и передавать новые RomBlocks во время `__getitem__`, чтобы избежать превышения `max_read_ports` :param bool asynchronous: если false, убедитесь, что выполняется только чтение памяти.
используя значения прямо из регистра. (иначе убедитесь, что читает синхронны) :param bool pad_with_zeros: если true, дополнить все отсутствующие romdata нулями до тех пор, пока размер ромблока, чтобы любой доступ к рому был четко определен. В противном случае симуляция должна выдавать ошибку при доступе к неинициализированным данным. Если вы генерируете verilog из рома, вам нужно будет указать значение для каждого адреса (в этом случае установка этого значения в True поможет), однако для тестирования и моделирования полезно знать, вы находитесь за пределами явно указанных значений (поэтому по умолчанию False) :param block: блок для добавления, по умолчанию рабочий блок """ super(RomBlock, self).__init__(bitwidth=bitwidth, addrwidth=addrwidth, name=name, max_read_ports=max_read_ports, max_write_ports=0, асинхронный = асинхронный, блок = блок) self.
data = ромданные self.build_new_roms = build_new_roms self.current_copy = я self.pad_with_zeros = pad_with_zeros
def __getitem__(я, предмет): импортировать номера если isinstance (элемент, числа. Число): поднять PyrtlError("Нет смысла индексировать RomBlock с целым числом." "Вместо этого получите значение из исходных данных для этого рома") # Если вы действительно знаете, что делаете, используйте вместо этого Const WireVector. вернуть super(RomBlock, self).__getitem__(item) def __setitem__(я, предмет, задание): поднять PyrtlError('запись в постоянную память невозможна') def _get_read_data (я, адрес): типы импорта пытаться: если адрес < 0 или адрес > 2**self.addrwidth - 1: поднять PyrtlError("Неверный адрес, " + str(адрес) + " указанный") кроме TypeError: поднять PyrtlError ("Адрес: {} с указанным недопустимым типом".
формат (адрес)) если isinstance (self.data, types.FunctionType): пытаться: значение = self.data(адрес) кроме исключения: поднять PyrtlError("Недопустимая функция данных для RomBlock") еще: пытаться: значение = self.data[адрес] кроме KeyError: если self.pad_with_zeros: значение = 0 еще: поднять PyrtlError( "Ключ RomBlock недействителен", "Рассмотрите возможность использования pad_with_zeros=True для значений по умолчанию" ) кроме IndexError: если self.pad_with_zeros: значение = 0 еще: поднять PyrtlError( "Индекс RomBlock недействителен", "Рассмотрите возможность использования pad_with_zeros=True для значений по умолчанию" ) кроме исключения: поднять PyrtlError ("недопустимый тип для объекта данных RomBlock") пытаться: если значение <0 или значение >= 2**self.









namedtuple('_MemAssignment', 'правая сторона, is_conditional')
"""_MemAssignment — это тип, возвращаемый из присваивания |= или <<="""
защита _reset_memory_indexer():
глобальный _memIndex
_memIndex = _NameIndexer()
класс _MemIndexed (WireVector):
""" Объект, используемый внутренне для правильного распределения памяти.
Обычный пользователь PyRTL никогда не должен знать, что этот класс существует,
отсюда и подчеркивание в имени. Он представляет собой очень похожий интерфейс на
WireVectors (все обычные операции с векторами проволоки должны работать),
но если вы попытаетесь *установить* значение с помощью <<= или |=, тогда будет сгенерировано
_MemAssignment вместо обычного проводного назначения.
"""
def __init__(я, память, индекс):
self.mem = память
self.index = индекс
self.wire = Нет
def __ilshift__(я, другой):
вернуть _MemAssignment (rhs = другое, is_conditional = False)
def __ior__(я, другой):
вернуть _MemAssignment (rhs = другое, is_conditional = True)
def _two_var_op(я, другой, оператор):
вернуть as_wires(self).
_two_var_op(другое, op)
защита __invert__(я):
вернуть as_wires(self).__invert__()
def __getitem__(я, предмет):
вернуть as_wires(я).__getitem__(элемент)
защита __len__(я):
вернуть self.mem.bitwidth
def sign_extended (я, битовая ширина):
вернуть as_wires (я). sign_extended (битовая ширина)
def zero_extended (я, битовая ширина):
вернуть as_wires (я). Zero_extended (битовая ширина)
@имущество
имя защиты (я):
вернуть as_wires(я).имя
# поднять PyrtlError("MemIndexed является временным объектом и поэтому не имеет имени")
@name.setter
имя защиты (я, n):
as_wires(self).name = n
Применение::
data = memory[addr] (выведите порт чтения)
memory[addr] <<= data (вывести порт записи)
mem[адрес] <<= MemBlock.EnabledWrite (данные, включить = мы)
Когда адрес памяти назначается с помощью объекта EnableWrite
элементы будут записываться в память только тогда, когда активен WireVector.
установить на высокий уровень (1).
"""
# FIXME: порты записи предполагают, что только один порт находится под управлением условного
EnabledWrite = collections.namedtuple('EnabledWrite', 'данные, включить')
""" Разрешает бит разрешения для каждого порта записи, где данные (первое поле в
кортеж) — обычный адрес данных, а enable (второе поле) — единица.
битовый сигнал, указывающий, что запись должна произойти (т.е. активный высокий уровень)."""
:param int bitwidth: определяет разрядность каждого элемента в памяти.
:param int addrwidth: Число битов, используемых для адресации элемента
Память. Это также определяет размер памяти
:param str name: Идентификатор памяти
:param max_read_ports: ограничивает количество портов чтения для каждого
блок можно создать; передача `None` указывает на отсутствие ограничений
:param max_write_ports: ограничивает количество портов записи для каждого
блок можно создать; передача `None` указывает на отсутствие ограничений
:param bool asynchronous: если false, убедитесь, что выполняется только чтение памяти.
используя значения прямо из регистра. (также убедитесь, что
чтение синхронно)
:param basestring name: Имя памяти. По умолчанию автоматически сгенерированный
имя
:param block: Блок, в который его нужно добавить, по умолчанию является рабочим блоком.
Лучше всего убедиться, что ваша блочная память/fifos читает/записывает
операции начинаются по тактовой частоте, если вы хотите, чтобы они синтезировались на эффективном оборудовании.
MemBlocks обеспечит это, убедившись, что
вы обращаетесь к ним только с помощью регистра или ввода, если вы явно не объявляете
память как асинхронная с флагом `asynchronous=True`. Обратите внимание, что асинхронные мемы
иногда очень удобны и заманчивы, но редко являются хорошей идеей.
Они не могут быть сопоставлены с блочными поршнями в FPGA и будут преобразованы в регистры большинством
инструменты проектирования, хотя PyRTL без проблем справляется с ними. Для любой памяти за пределами
несколько сотен записей — это нереальный вариант.
Каждое чтение или запись в память будет создавать новый «порт» (либо порт чтения, либо порт записи).
порт соответственно). По умолчанию память ограничена 2 портами чтения и 1 портом записи, но
чтобы сохранить эффективность дизайна по умолчанию, но эти значения можно установить в качестве параметров. Примечание
что память с большим количеством портов может быть невозможно сопоставить с физической памятью
такие как блочные ОЗУ или существующие аппаратные макросы памяти.
"""
self.max_read_ports = max_read_ports
self.num_read_ports = 0
self.block = рабочий_блок (блок)
имя = имя_следующей_темппеременной (имя)
если битовая ширина <= 0:
поднять PyrtlError('разрядность должна быть >= 1')
если адресная ширина <= 0:
поднять PyrtlError('addrwidth должен быть >= 1')
self.bitwidth = битовая ширина
self.name = имя
self.addrwidth = адресная ширина
self.readport_nets = []
self.id = _memIndex.next_index()
самостоятельный.асинхронный = асинхронный
self.block._add_memblock(я)
self.max_write_ports = max_write_ports
self.num_write_ports = 0
self.writeport_nets = []
addrwidth, truncating=False)
если len(item) > self.addrwidth:
поднять PyrtlError('разрядность индекса памяти> разрядность адреса')
вернуть _MemIndexed (память = я, индекс = элемент)
def __setitem__(я, предмет, задание):
""" Создает схему для установки элемента в память """
если isinstance (назначение, _MemAssignment):
self._assignment(item,assignment.rhs,is_conditional=assignment.is_conditional)
еще:
поднять PyrtlError('ошибка, назначение памяти должно использовать "<<=" не "=" оператор')
def _readaccess(я, адрес):
# FIXME: добавить порты условного чтения
вернуть self._build_read_port (адрес)
def _build_read_port (я, адрес):
если self.max_read_ports не None:
self.num_read_ports += 1
если self.num_read_ports > self.max_read_ports:
поднять PyrtlError('максимальное количество портов чтения (%d) превышено' % self.max_read_ports)
данные = WireVector (битовая ширина = self.
bitwidth)
readport_net = LogicNet(
оп = 'м',
op_param=(self.id, я),
аргументы=(адрес,),
назначения = (данные,))
work_block().add_net(readport_net)
self.readport_nets.append(readport_net)
возвращаемые данные
def _assignment(self, item, val, is_conditional):
из .условного импорта _build
item = as_wires(item, bitwidth=self.addrwidth, truncating=False)
если len(item) > self.addrwidth:
поднять PyrtlError('ошибка, провод, индексирующий разрядность памяти > addrwidth')
адрес = элемент
если isinstance(val, MemBlock.EnabledWrite):
данные, включить = знач.данные, знач.включить
еще:
данные, включить = val, Const (1, битовая ширина = 1)
data = as_wires(data, bitwidth=self.bitwidth, truncating=False)
enable = as_wires (включить, битовая ширина = 1, усечение = ложь)
если len(данные) != self.bitwidth:
поднять PyrtlError('ошибка, запись данных больше, чем разрядность памяти')
если len(включить) != 1:
поднять PyrtlError('ошибка, разрешающий сигнал не точно 1 бит')
если is_conditional:
_build(я, (адрес, данные, включить))
еще:
self.
_build (адрес, данные, включить)
def _build (я, адрес, данные, включение):
""" Создает порт записи. """
если self.max_write_ports не None:
self.num_write_ports += 1
если self.num_write_ports > self.max_write_ports:
поднять PyrtlError('максимальное количество портов записи (%d) превышено' %
self.max_write_ports)
writeport_net = LogicNet(
оп='@',
op_param=(self.id, я),
args=(адрес, данные, включить),
назначения=кортеж())
work_block().add_net(writeport_net)
self.writeport_nets.append(writeport_net)
def _make_copy (я, блок = нет):
блок = рабочий_блок (блок)
вернуть MemBlock (битовая ширина = self.bitwidth,
адресная ширина=self.addrwidth,
имя=я.имя,
max_read_ports=self.max_read_ports,
max_write_ports=self.max_write_ports,
асинхронный = self.
асинхронный,
блок=блок)
используя значения прямо из регистра. (иначе убедитесь, что читает
синхронны)
:param bool pad_with_zeros: если true, дополнить все отсутствующие romdata нулями до тех пор, пока
размер ромблока, чтобы любой доступ к рому был четко определен. В противном случае
симуляция должна выдавать ошибку при доступе к неинициализированным данным. Если вы генерируете
verilog из рома, вам нужно будет указать значение для каждого адреса (в этом случае
установка этого значения в True поможет), однако для тестирования и моделирования полезно знать,
вы находитесь за пределами явно указанных значений (поэтому по умолчанию False)
:param block: блок для добавления, по умолчанию рабочий блок
"""
super(RomBlock, self).__init__(bitwidth=bitwidth, addrwidth=addrwidth, name=name,
max_read_ports=max_read_ports, max_write_ports=0,
асинхронный = асинхронный, блок = блок)
self.
data = ромданные
self.build_new_roms = build_new_roms
self.current_copy = я
self.pad_with_zeros = pad_with_zeros
формат (адрес))
если isinstance (self.data, types.FunctionType):
пытаться:
значение = self.data(адрес)
кроме исключения:
поднять PyrtlError("Недопустимая функция данных для RomBlock")
еще:
пытаться:
значение = self.data[адрес]
кроме KeyError:
если self.pad_with_zeros:
значение = 0
еще:
поднять PyrtlError(
"Ключ RomBlock недействителен",
"Рассмотрите возможность использования pad_with_zeros=True для значений по умолчанию"
)
кроме IndexError:
если self.pad_with_zeros:
значение = 0
еще:
поднять PyrtlError(
"Индекс RomBlock недействителен",
"Рассмотрите возможность использования pad_with_zeros=True для значений по умолчанию"
)
кроме исключения:
поднять PyrtlError ("недопустимый тип для объекта данных RomBlock")
пытаться:
если значение <0 или значение >= 2**self.