Russian

From jmips


Russian BDBengali BGBulgarian CN ENEnglish ESSpanish ETEstonian FR DE IN IT JP PLPolish RO RURussian

Authors: fse1378, fse4919


Contents

MIPS процессор в Java

jMIPS это простой в использовании Java процессор с открытым исходным кодом MIPS. Возможно вы уже скачали архив (копии находятся на страницах проекта jMIPS (http:

Ознакомление с программным обеспечением позволяет понять аппаратную архитектуру MIPS, а также дает возможность ознакомиться с более общей концепцией компьютерных систем и архитектур.

Cуществует пять моделей процессоров для наблюдений и работы в архиве. В нашем случае числа возрастают с увеличением сложности от 1 до 5, таким образом:

  1. Основной неконвейерный процессор (текущие страницы)
  2. Неоптимизированный конвейерный процессор
  3. Оптимизированный конвейерный процессор
  4. Oптимизированный конвейерный процессор с кэш-памятью
  5. Oптимизированный конвейерный процессор с кэш-памятью и обработкой прерываний
Архитектура на основном MIPS процессоре

Далее вы можете ознакомиться c процессoм использования, и возможно, созданием базовой модели процессоров в деталях, а затем перейти к рассмотрению других моделей. Эти модели не отличаются в сборке или использовании - это только внутренности, которые отличаются в каждом конкретном случае и в определенном контексте результаты одной модели может превосходить другие модели в скорости.

С целью улучшения модели Вы можете работать с каждой моделью процессора, чтобы заставить ее работать еще быстрее.

Сколько потребуется времени запустить в целом и в каждой инструкции один из стандартных печатных выводов? Если Вам нужна статистика такая как сколько времени необходимо для выполнения некоторых классов в конкретных обстоятельствах, вам придется добавить в код для этого самостоятельно. Это открытый источник! Вы можете сделать это. Код четко написан и объяснен на страницах здесь.


Как запустить основной процессор MIPS модель

Там должен быть Java archive файл (jar) в прилагаемом архиве zip или сжатый tar файл ( можете скачать эти файлы на странице проекта по этой ссылке (http:

Вы должны извлечь jar файл из архива с (например, имя архива зависит от вашего выбора загрузки)

% unzip jMIPS-1.7.zip jMIPS-1.7/lib/CPU.jar

или

% tar xzvf jMIPS-1.7.tgz jMIPS-1.7/lib/CPU.jar

Кроме того, извлечь некоторые содержания misc каталога с

% unzip jMIPS-1.7.zip jMIPS-1.7/misc/hello_mips32

или

% tar xzvf jMIPS-1.7.tgz jMIPS-1.7/lib/hello_mips32

Затем класс Cpu1 может быть запущен на Java Virtual Machine (JVM), на любой платформе. Вы можете делать это под Linux c

% java -cp jMIPS-1.7/lib/CPU.jar CPU.Cpu1 -q jMIPS-1.7/misc/hello_mips32

Например:

% java -cp jMIPS-1.7/lib/CPU.jar CPU.Cpu1 -q jMIPS-1.7/misc/hello_mips32
  Hello world
%

Если вы распаковки 1.7d или архив, вы получите графический интерфейс для запуска пяти готовых моделей. Выполнить

% jMIPS-1.7d/lib/CPU.jar
%

и вы получите окно, показанное на рисунке справа. В окне было выбрано hello_mips32 исполняемый файл из разное/подкаталог исходный архив, так что он показал как имеющиеся в наличии и по умолчанию готов к запуску, и "quiet" переключателя уже была выбрана!

Чтобы изменить модель процессора (установлен на уровне "3" по образу и подобию), использовать "model"(модель) управления. Затем нажмите кнопку "Run"(Выполнить) и откроется окно содержащее вывод перспективе.

(Если вы хотите увидеть UML "схема деятельности" для пользователей, взаимодействующих с данным графическим интерфейсом, просто нажмите на эту иконку:UML GUI Activity Diagram).

Как компилировать основной процессор MIPS модели

Если вы хотите или должны компилировать исходной код Java для получения исполняемого кода, вы могли бы сделать это следующим образом, в зависимости от инструмента в наличии. Так как существуют различные наборы инструментов, которые люди привыкли использовать на различных операционных системах, следующие подразделы специфичны для операционной системы.

Компилирование под Linux или Unix

Если вы используете Mac, а также используете HFS или HFS+ файловой системе, зайдите в свойства системы и включите case sensitivity к нему. В противном случае, вы получите несколько имен файлов в столкновение друг с другом, которого вы не хотите.

Разархивирование zip или сжатый tar файл (можете скачать эти файлы на странице проекта по этой ссылке (http:

% unzip jMIPS-1.7.zip

или

% tar xzvf jMIPS-1.7.tgz

соответственно.

Затем найдите src/ каталог, в недавно распакованном файле и измените текущий каталог (используйте cd jMIPS-1.7/src команду для смены каталога). Я предпочитаю, произвести generic Java bytecode для Java Virtual Machine (JVM), с

% javac CPU/Cpu1.java

В src/ каталоге, а затем полученный Cpu1.class файл может быть запущен JVM на любой платформе. Вы можете сделать это под Linux c

% java CPU/Cpu1 -q ../misc/hello_mips32

Например:

% java CPU/Cpu1 -q ../misc/hello_mips32
  Hello world
%

Создание jar файлa, вопрос coздания всеx файлoв Java-класса:

% javac CPU/*.java
%

и потом использовать jar файл с

% jar cf ../lib/CPU.jar CPU/*.class
%

В действительности, jar просто zip архиватор пакета производится без сжатия, а с одним дополнительным файлoм manifest также включены. Таким образом, вы можете сделать это, используя только zip архиватор в место использование приборов jar. Посмотрите подробную информацию на учебном сайте Java (

Компиляция под Windows

Чтобы импортировать источник в Java NetBeans IDE, запуститe новый NB проект (так называемый `jMIPS, по-видимому), убедившись, что для диалог IDE вы поставили птичку в `Main Class' и т.д., непроверены.

После создание IDE все каталоги и файлы управления, что необходимо, скопируйте src/CPU/ каталог *.java файлы из архива исходного кода в новую src/CPU/ поддиректорию jMIPS проект, который был только что создан NetBeans. Используйте копию команд операционной системы прямо внутри zip архива, если это возможно, чтобы избежать файлового касания диска на своем пути. В противном случае Windows может сбросить некоторые из имен файлов. Если Netbeans имеет меню выбора import from zip, или compile from zip, былo бы идеальнo.

IDE обнаружит область исходнoгo кодa и он будет расширять свое 'Исходные' дерева (jMIPS/src каталог), чтобы включить "пакет" CPU процессорa и Java-файлов.

Если вы предпочитаете, вы можете систематически переименовать класс Java для каждой модели процессора из Cpu1.java, Cpu2.java и т.д., на WinCpu1.java, WinCpu2.java и т.д. Вам нужно будет переименовать класс within каждoм файлe, чтобы соответствовать.

Заметки о запуске модели процессора

Параметры командной строки выглядят следующим образом:

  • Без вариантов: запуск модели без опций (в частности, без-q т.е. без "quiet") будут перечислены каждые команды машинного кода.
% java CPU.Cpu1  hello_mips32
0:      0.000000007s:   0x80030080:     addiu $29, $29, -32
1:      0.000000012s:   0x80030084:     sw $31, 28($29)
2:      0.000000019s:   0x80030088:     sw $30, 24($29)
3:      0.000000024s:   0x8003008c:     addu $30, $29, $0
4:      0.000000030s:   0x80030090:     sw $28, 16($29)
...
218:    0.000001567s:   0x8003000c:     lui $3, -20480
219:    0.000001573s:   0x80030010:     ori $3, $3, 16
220:    0.000001580s:   0x80030014:     sb $3, 0($3)
%

Это команда выполняется в 220 инструкции 0,000001580 моделируемых секунд (тактовая частота составляет 1 ГГц моделирования). Это было около 5 тактов на выполнение инструкции.

  • -q: с помощью -q ("quiet") подавляет список демонтированнoгo машиннoгo кодa, когда они работают. Другими словами, с -q Вы видите только то, что программы должны производить, и никаких дополнительных шумов.
% java CPU.Cpu1 -q hello_mips32
Hello world
%
  • -d: дополнительная информация выводится, если -d ("debug") дается. Повторные -d варианты увеличения объема отладки шума.
% java CPU.Cpu1 -d hello_mips32
text start at virtual addr 0x80030000 file offset 0x10000
text end   at virtual addr 0x800300e0 file offset 0x100e0
text entry at virtual addr 0x80030080 file offset 0x10080
read 224B at offset 65536 from file 'hello_mips32'
stack start at virtual addr 0xb0000000
stack end   at virtual addr 0xb0100000
0:      0.000000007s:   0x80030080:     addiu $29, $29, -32
1:      0.000000012s:   0x80030084:     sw $31, 28($29)
2:      0.000000019s:   0x80030088:     sw $30, 24($29)
...
%
  • -o: Вы можете установить некоторые внутренние переменные в моделировании с помощью -o MEMORY_LATENCY=1000 (к примеру). Посмотрите код в 'Cmdline.java и добавтe свои собственные возможные опции!

Пожалуйста, просто изменитe в источникe для того, чтобы добавить все, что вы хотите, добавьте себя в список кредитов в верхней части исходного кода в файл и отправитe в измененный код - или опубликуйте его себе в другом месте, как вы хотите .


Производство MIPS машинный код для работы процессорa

программа "Hello world" готова, построенный в MIPS R3000 машинный код находится в архиве, как hello_mips32 файл в misc/ подкаталоге.

Исходный код (C язык)находится в hello_mips32.c файл в архиве misc/ каталог, и MIPS ассемблер для этого hello_mips32.s.Машинный код был составлен довольно стандартно из данного источника, чтобы дать машинный код, с помощью

% gcc -static -o hello_mips32 -Wl,-e,f hello_mips32.c

на реальной машине MIPS. Проверьте на странице справочника gcc команду (например, "man gcc"), чтобы выяснить, какие именно параметры, указанные в этой командной строке имеются в виду.

На не-MIPS, но Unix платформах, следующие должны достичь того же результата, используя mips-gcc кросс-компилятор пакет (возможно, вам обычно нужно запустить "setup MIPS" команды в среде оболочки для того, чтобы установить исполняемый путь поиска, чтобы забрать часть кросс-компиляторa в компонент):

% mips-gcc -DMIPS -mips1 -mabi=32 -c hello_mips32.c
% mips-ld -Ttext 0x80003000 -e f -o hello_mips32 hello_mips32.o

Программная модель процессора MIPS удобнa для реальной машины MIPS при запуске "Hello world" машиннoгo кодa.

% java CPU/Cpu1 -q hello_mips32
Hello world

Однако, более сложные машинные коды с участием прерываний и периферийных устройств могут преодолеть данную модель.


Попасть в исходный код

Некоторые советы о том, каким образом можно перейти в исходной код.

  • Выберите самую простую часть исходного кода Java класса CPU1 и прокомментируйте его по своему. Вы знаете что это хорошо прокомментировано но, будут места где вы чувствуете, что нужно больше (или меньше, или другое).

Исправьте это, довертесь самому себе и отправьте изменения в проект. Как правило, это хороший способ узнать о полученном коде. Пожаловаться о том, как плохо написано и что очень трудно понять, и исправить ее. Вы найдете многочисленные записи кода в следующем разделе. Вы хотите, сверить код с теми заметками что вы имеете? Заметки окажутся наиболее полезным с точки зрения понимания крупномасштабной функции, оставив только нюансы, объяснить через комментарии исходного кода.

  • Добавить bgezal и bltzal инструкции к набору инструкций MIPS обрабатываются в один большой цикл эмулятора.

Сначала проверьте на сайте,что делает инструкция и какой формат машинного кода для них! Можно сказать, они должны быть между отраслевой и прыжок-и-ссылка инструкции только по имени. Предположим, bgezal является такой же, как bgez но в случае успешных испытаний он делает то же самое делает команда jal (местами адрес следующей команды в регистр адреса возврата, ra). Это полезно для реализации условного вызова подпрограммы. Проверьте в Google!

Изменить машинный код для Hello world с бинарным редактором («bvi» хорошо работает на Unix, если вы являетесь пользователем vi; emacs пользователи уже знают, что emacs имеет двоичном режиме редактора) и заменить bnez v0, foo; с машинным кодом bgezal v0, foo. Проверьте изменение эмулятора на изменение машинного кода. Вам нужно сделать компенсирующие изменения в программу для того, чтобы сохранять и восстанавливать $rа обратный адрес регистрации по отрасли, но вы увидите, что новая отраслевая инструкция работает сама.

Заметки по основным кодом модели MIPS процессора

Регулярность набора инструкции MIPS архитектуры приводит к очень прозрачным коду симулятора.Симуляторный код также был написан с целью получения кода, который будет не очень сложным.

В результате, вы можете проверить, что любые инструкции MIPS делают визуальный контроль соответствующей области кода.

Минимум объектно-ориентированная изоляции необходимо для кода класса CPU1 только для того, чтобы сделать его лего читаемым. Это машинная состояние! И это так на самом деле. Чтобы понять модель процессора CPU1 вам достаточно посмотреть код в класс CPU1.

Вы увидите только одну большую петлю в коде. Она работает обобщенном цикле Вона Неймана выборка-расшифровка-(чтение данных)-выполнить- (запись данных) (см. прилагаемую рисунок справа), как это реализовано во всех основных конструкций процессоров с 1940 года, и все действия встроены в эту длительный цикл, с одной короткой непрерывной частью посвященных каждому виду обучения MIPS. Таким образом, вы найдете их около 10 или 12 коротким сопредельных участков, составляющих тело цикла.

Например, в части касающейся инструкций перехода выглядит следующим образом ("выборка" уже было сделано в начале тела цикла, для того, чтобы прочитать следующую инструкцию в IR-регистра). В основном это блок комментарий:

    /*
     *  Jump instructions
     *
     *  format  J  : 000010 jjjjj jjjjj jjjjjjjjjjjjjjjj 
     *          JAL: 000011 jjjjj jjjjj jjjjjjjjjjjjjjjj
     *
     *  action  of J, JAL:
     *  PC <- (bigpageof(PC) << 28) | (jjj...jjj << 2);
     *
     *  extra action of JAL:
     *  RA <- PC
     */
  if (op == J || op == JAL) {
      conf.jjjjjjjjjjjjjjjjjjjjjjjjjj = IR.jDST();              // decode:  IR register
      pc = PC.read();                                           // read:    PC register
                                                                // execute: (not present)
      if (op == JAL)                                            // write:   RA and PC register
          register_unit.write (R_RA, pc);
      PC.write((bigpageof(pc) << 28) | (conf.jjjjjjjjjjjjjjjjjjjjjjjjjj << 2));
  }

Только 6 строк реального кода, не считая строк комментариев.

Таким образом, модель кодируется класса CPU1 олицетворяет абстрактный дизайн процессора Вон Неймана без низкоуровневых деталях, как именно электроны перемешиваются вокруг, и вы не должны иметь никаких проблем при взгляде на код и будете понимать как он работает как оборудования (совет: если вы посмотрите на небольшой участок любого исходного кода, с конкретным вопросом, например, выяснить, как функция X используется так что вы можете использовать его сами, и игнорировать все остальное, повторите до готовности).

Разница по отношению к реальным оборудованием,то что этот код может сделать только одно за раз, в то время как реальные физический результаты оборудование делают все эти вещи в последовательно в то же время как цикл процессора.

Тем не менее, выполнения приурочено использованием методов класса Clock и окончательный расчет произойдет только тогда, когда полный цикл процессора подниматься.Таким образом, порядок вещей сделано в программно между этими точками, не особенно важно. До тех пор, как порядок имеет логический смысл, модель работает.

Например, код jump пишет регистрации данных RA, считанных из инструкции в IR-регистра. В реальном оборудовании, эти две вещи одновременно, в результате потенциал электрического поля передается через проводящие провода. В приведенном выше коде для чтения происходит до записи, поскольку реализация Java требует именно так! Мы не можем писать на Java " читать A и писать результат в B одновременно». Физика реальной вселенной, позволяет делать это легко на самом деле!В учете задействованные элементы, однако, запись того момента времени моделирования возникновения и для чтения и записи, и это все, что вы увидите в конце.

Расположение класса

Существуют следующие классы верхнего уровня в исходном коде. Только первые пять или около того содержать любой код который стоит обсуждать, и обсуждение следует ниже таблице:

Cpu1 (содержащий основную точку входа) устанавливает и запускает процессор моделирования
CPU1 в непрерывном режиме цикла выборка-расшифровка-выполнить
RegistersUnit эмуляция регистров в блок процессора
ALU эмуляции ALU в процессоре
Memory эмуляция запоминающего устройство
IOBus эмуляции шины ввода/вывода
StopClock специальный блок ввода/вывода, который обращается с системными часами
Register эмуляции единого реестра, которые содержатся в RegistersUnit
SignExtend эмуляция 16-32 битного знака расширительного блока в процессоре
Console эмуляция ввода/вывода, байты входа из клавиатуры и экспорт байт на экран, отображаются в адреса в памяти через блок памяти
Clock единый глобальный эмуляция часов, эмуляции тактового сигнала в процессоре
Utility Класс содержащий полезные программы - заменимость байта и т.д.
Globals класс содержащий все мировые константы, такие как числовое значение кода операции для JAL
Cmdline этот класс обрабатывает параметры симулятора командной строки и аргументов
OptionT Класс инкапсуляции описания опции командной строки , для использования CmdLine процедуры
Elf Класс моделирование структуры стандартного исполняемого файла (`ELF') files&nbsp формата на диске, как производства, такие как gcc компиляторы , используется для чтения исполняемый файл и захватить программный код внутри нее, вызываются из main()
RegReturnT Класс моделирования пары значений одновременно читать из регистров устройства в процессор
AluReturnT Класс моделирования пары значений одновременно выход из ALU в процессоре
DecodeReturnT Класс моделирования набора атрибутов (код операции, индекс источник регистре, смещение филиала и т.д.) декодируется из инструкций машинного кода в IR в процессоре.
InstructionRegister Класс содержащий методы для декодирования инструкций машинного кода в IR в процессоре
Debug Класс содержащий методы, которые отображают работу процессора на экране

Это так называемый домен-модель проект. Классы в программном коде соответствуют реальным физическим компонентам в аппаратном процессоре MIPS. Аппаратные компоненты могут делать методы соответствующим реальным физическим операциям. Виртуальные операции,которые могут быть составлены как комбинации простых операций никогда не реализуются в программном обеспечении, независимо от того, насколько "удобно", казалось бы, так как они не имеют физического существования.

UML class diagram for jMIPS code

Диаграмма классов справа показывает зависимость.

Если вы хотите добавить один шаг объекта в симуляторе CPU1, вы должны взять на себя один большой выборки-декодирования, в то время как выполнять петли в CPU1 код и сделать его пауза для ввода данных пользователем перед началом каждого нового цикла. Вы должны сделать ("шаг") от пользователя выполнить другую цикл; ("продолжить") должны отправить его обратно к велосипеде непрерывно; («печать») и ряд регистр или адрес памяти должен показать регистр или содержимое памяти ; ("дисплей") должна быть, как печать, но привести к распечатке происходит на каждом шагу.

Основная программа в Cpu1

Это краткий конспект основной программы в CPU1, класс-оболочка, чья работа заключается в понимании команды Java строк которые вы использовали, а затем установить CPU1 модель процессора следующим образом:

public void main(String argv[]) {

    Cmdline.analyse(..., argv);                                    // parse command line

    Elf elf[] = new Elf[Cmdline.args.length];
    for (int j = 0; j < Cmdline.args.length; j++) {                // load `ELF format' executable files
        String filename = Cmdline.args[j];
        elf[j] = new Elf(filename);
    }
    byte stack[] = new byte[STACK_END - STACK_START];              // prepare the CPU's stack memory area

    CPU1 cpu = new CPU1();                                         // build the CPU
    {                                                              // initialize the stack area
        cpu.memory.addRegion(stack, STACK_START, STACK_END);
        for (int j = 0; j < elf.length; j++) {                     // initialize program code areas
            cpu.memory.addRegion(elf[j].text, elf[j].text_start, elf[j].text_end);
        }
    }
    cpu.SP.write(STACK_END);                                       // set stack pointer to top of stack
    cpu.PC.write(elf[0].text_entry);                               // set program counter to 1st entry pt
    cpu.run();                                                     // run the simulation!
}

Вы видите здесь, что основной анализирует командную строку, используя метод анализа Cmdline, для получения списка исполняемых файлов, код которого будет выполняться.Исполняемые файлы находятся в так называемом `ELF формат'.

ELF является кросс-платформенным стандартом, используемым во многих операционных системах сегодня, и это формат производства GCC MIPS компиляторов и ассемблеров. Основная программа загружает эти ELF файлы.

То есть, он вызывает Elf конструктор на имя каждого файла, который анализирует содержимое файла и извлекает информацию, такую ​​как точки входа, предназначенные места виртуального адреса, и т.д., все из которых помещяются в итоговом Elf объекте.

Затем основной строит главный стек области памяти и процессора, и говорит блоку памяти процессора о стеке и его предполагаемом виртуальном адресе путем вызова addRegion метода. Также сообщает блоку памяти о различных участках кода программы которые были взяты из файлов ELF исполняемый через несколько вызовов addRegion.

Осталось положить регистр SP ('указатель стека') процессора ​​, чтобы указать на вершину стека, и установить регистр ПК ('счетчик') процессора, чтобы получить адрес намеченной точки входа в программу - полученный из первого файла, указанного в командной строке - а затем вызвать вновь построенный и нацеленный run метод процессора.

Вот и все. Все нижеследующее программист должен знать о CPU1:

Cpu1
static void main (String args[]) entry point; handles command line options, builds CPU, runs it

Следующас секция расскажет о том, что значит 'runs it'.

Модель процессора CPU1

Программист должен знать о классе процессора П1 в приведенном ниже. Это конструктор и один метод.

CPU1
CPU1() CPU1 constructor
void run() fetch/decode/execute cycle


Код метода run неявляется концептуально сложным. Это одна большая петля:

public void run() {
    while (Clock.running()) {
         ... /* interior of Von Neumann fetch-decode-execute cycle */ ...
    }
}

Как говорится в комментарии, цикл содержит внутри выборка-декодирования-выполнить цикл. Вот оно выглядит:

// FETCH!

int pc  = PC.read();                                          // read PC
int ir  = memory.read32be(pc);                                // read instr at address given by PC
IR.write(ir);                                                 // write instruction to IR
pc      = feAlu.execute(ALU_ADDU, pc, 4).c;                   // add 4 to PC value using  adder
PC.write(pc);                                                 // route incremented PC value to PC

// DECODE!

byte op = InstructionRegister.OPCODE(ir);                     // decode opcode
DecodeReturnT conf = new DecodeReturnT();
{
    conf.op = op;                                             // decode output to wires op,ir,pc
    conf.ir = ir;
    conf.pc = pc;                                             // NB: "original PC"+4 is in conf.pc
}
switch(op) { 
  case 0:                                                     // deal with ALU ops

    conf.sssss = InstructionRegister.aluopSRC1(ir);           // decode remaining instr fields 
    conf.ttttt = InstructionRegister.aluopSRC2(ir);
    conf.ddddd = InstructionRegister.aluopDST (ir);
    conf.func  = InstructionRegister.aluopOP  (ir);

    Clock.increment(DECODE_LATENCY);                          // update here for decode

    // READ!                                                  // read designated register contents

    RegReturnT r = register_unit.read(conf.sssss, conf.ttttt);

    // EXECUTE!

    AluReturnT s = alu.execute(conf.func, r.a, r.b);          // do the designated arithmetic

    // WRITE!

    register_unit.write(conf.ddddd, s.c);                     // route result to designated register
    break;                                                    // ESAC

Абстрактной выборки/декодирования/(чтение)/выполнение/(записи) последовательность отчетливо видна в коде. Там есть один условный блок посвященных каждому виду обучения (например, по одному на различных кодов операций).Фрагмент выше показан блок посвященный выполнению ALU операций, которые имеют код операции 0. Различные виды операций ALU отличаются различные значения функции поля в инструкции (за последние 6 битов младшего конца слова в большой байтов раскладки). Все различных областях инструкция в IR вспыхнул, в том числе функции, в разделе под названием Декодировать!, А затем функциональные инструкции, осуществляется в короткие участки кода Java надписью Читать!, Выполнить!, Писать!

Какой код приемлем и какой не приемлем в модели процессора

Обратите внимание, что код в код CPU1 в перспективе будет использовать эмулируемый процессор для выполнения работы.

Вместо добавления значения 4 к ПК, используя язык программирования Java ("компьютер + = 4"), например, раздел FETCH читает компьютер с помощью PC объекта метода read, добавляет 4 с помощью метода execute, и возвращает результат обратно к компьютеру с помощью объекта компьютера метода write. Это долгий путь, где "компьютер + = 4", возможно, сделал работу! Что происходит! Что позволено здесь, а что нет?

Это приемлемо в модели Java label (отмечать) значения на единицу оборудования и использовать их в качестве вклада в других единицах оборудования. Мы сделали это с "рс = ...» и "... = Рс. Такого рода вещи составляют с помощью простых кабелей для подключения сигналов данных через процессор схемы в пределах одного такта. Это нормально.

Но ничего, даже такой существенной, как +4 на "компьютер" будет cheating (обман), чтобы сделать в Java, потому что это требует времени и схемы, чтобы сделать это в реальной жизни.

Java-объекты находяться в процессоре компоненты (АLU, register_unit и т.д.) имеют сроки встроенные в них и их использование в коде Java делает моделирование часов заранее правильно. Их можно использовать для вычислений. Для вычисления потребуется время, чтобы сделать в реальной жизни. Методы продвижения Java объектов для моделирования времени. Это хорошо.

Использование Java кода, как "компьютер + = 4" может достигнуть требуемого эффекта, не принимая любое время моделирования,и не занимать моделируемое оборудования снова! Это не эмуляция реальной жизненной ситуации, которая эмулируемая магия. Не совсем хорошо.

Таким образом, любое арифметическое вычисление должно быть сделано с помощью Java-объектов, представляющих компоненты аппарутуры процессора, а не Java арифметики.

Поскольку DECODE раздел делался на Java-код здесь, что может показаться, что нет времени на все, чтобы сделать в модельное время, явное обновление часов было заложено в конце DECODE код для того, чтобы сохранить симулятор времени верным.

Наоборот, FETCH, раздел не нуждается в дополнительном времени для обновления, так как затраченное время доминируют над инструкцией чтения из кэша / памяти.

Правило писания кода симулятора, как этот, тот где можно использовать переменные Java-кода для хранения значений, но не более (менее) чему является концептуально один интервал моделированных часов. Это как временное значение сигнала. Любой значение сигнала, которое сохраняется для одного интервала моделированных часов или более, должны содержаться в регистрах.

Это то, что сделано в CPU1 run методе .

Теоретически, переходной компьютер и ик значения направляется на ПК и ИК на хранение через интервалы нескольких часов .

Объект conf, который объединяет выход декодирования, похоже сохранится, но как только ИК измениться на следующий цикл conf тоже будет изменен. Так что это только концептуально представляет собой набор проводов подключенных к IR через некоторые схемы декодирования и без дополнительного хранения.


Компоненты класса ЦПУ

В оставшейся части этого раздела документы Java классов, которые представляют собой компоненты внутри процессора. Это справочный документ!

Класс компонента RegisterUnit (юнит регистрации)

Этот компонент включает в себя "небольшую и быструю память" внутри процессора.

RegisterUnit
RegisterUnit() конструктор единицы регистра
RegReturnT read (byte, byte) считывание двух цельных чисел с двух нумерованных регистров
void write (byte, int) записывает цельное число с нумерованного регистра
void write (byte, byte, int, int) записывает два цельных числа с двух нумерованных регистров соответственно

Единицы регистрации состоят из массива r из 32-х (на самом деле немного больше для того, чтобы включить компьютер и ИК-а) регистров.

В read и write методах нет ничего удивительного. Читайте и/или записывайте все, что может быть сделано или записано на аппаратные регистры. Число аргументов, показывает, сколько регистров в одно и то же время читаются и записыватся (поддерживается одновременно до двух операций чтения и одна запись). Тип "Байт" для индекса выступает в качестве аргумента,не путайте аргументы, которые являются 5-битными индексами регистров с аргументами, которые в 32-битной содержание регистров. Да, мы могли бы использовать "int", чтобы представить оба, но вы не можете see (видеть) те которые смотрят на подпись типа метода и программные ошибки будет появляться дальше.

private RegReturnT readAndWrite (byte x1, byte x2, bool w_e, int d1) {

        RegReturnT res = new RegReturnT ();
        Clock.increment (REGISTER_LATENCY);             // keep timing up to date
        res.a = r[x1].read ();                          // read two registers
        res.b = r[x2].read ();
        if (w_e && x1 != 0)                             // if write enabled, write one register
            r[x1].write (d1);
        return res;                                     // return read register (old) contents
}
public RegReturnT write (byte x1, int d1) {             // write one register, return old value
        
        return readAndWrite (x1, 0, true, d1);
}
public RegReturnT read (byte x1, byte x2) {             // read two registers
 
        return readAndWrite (x1, x2, false, 0);
}

Любое действие отмечает автоматическое обновление часов при использовании регистров устройства. Это гарантирует, что с помощью этого компонента приводит к точному времени в симуляции. Чтение и запись происходят одновременно. Когда мы смотрим на код класса компонента регистра, мы увидим, что запись использует эффект next cycle (следующий цикл), так что можно сделать много различных чтений и одну запись в регистр каждого цикла программного обеспечения, и это будет выглядеть, как будто он все произошло сразу на тренажере в конце цикла.

Класс ALU (АЛУ)

Компонент ALU выполняет арифметические вычисления внутри процессора.

ALU
ALU () конструктор АЛУ
AluReturnT execute (byte, int, int) выполняет операции АЛУ определяется кодом операции по два целых числа возвращающих в качестве результата целое число

Класс ALU является существенной частью кода, но это совсем упрощенно. Код метода execute состоит из большого оператора выключателя, который выбирает короткий блок кода для выполнения, в зависимости от функций func (код функции) значения, указанное в качестве аргумента. Код сочетает в себе два целых числа а и в соответствующим образом для получения результата с и переноса или нулевого показателья z:

public AluReturnT execute(byte func, int a, int b)
{
    AluReturnT res = new AluReturnT ();               // prepare to return two 32-bit words
    switch (func) {
      case ALU_ADD:
        long r = a; r += b;                           // internally 64-bit signed addition
        res.c = (int) (r & 0xffffffff);               // capture bottom 32 bits of result
        res.z = (int) ((r >> 32) & 0xffffffff);       // capture top 32 bits of result
        break;
      ... 
        // other ALU ops treated
    }
    Clock.increment(ALU_LATENCY);                     // note the automatic clock update
    return res;
}

Вышепоказаное только код операции сложения, но он вполне представительный. Ни один из кода АЛУ более сложный, чем этот.

Класс памяти компонент

Память компонент представляет оперативной памяти (RAM), как показано на процессоре. Реализация здесь действительно смешивает вместе два реальных аппаратных компонента, менеджер памяти и запоминающие устройства. Было бы немного "суетливой" выделить два разных компонентов , потому что мы имеем дело не с моделированием памяти в том же подробно, как мы моделируем процессор, и мы хотели бы посмотреть на памяти на данный момент, как блестящий, гладкий, черный ящик.

Память
Memory () базовый конструктор блок памяти
void addRegion(byte[], int, int) создать новую область памяти (например, стек, текст программы, ...)
int read32be (int) читать 4-байтовые целые из bigendian место в памяти дает 32-разрядное адресное
void write32be (int, int) написать 4 байта bigendian Янов место в памяти дает 32-разрядное адресное
byte read8 (int) прочитать один байт из места в памяти дает 32-разрядное адресное
void write8 (int, byte) написать один байт на место в памяти дает 32-разрядное адресное

Объект памяти внутренне состоит из массива области. Они действительно существуют, как "зона границ" настроена в сторону менеджера памяти нашей памяти устройства.

Каждый регион представляет собой первый адрес в памяти, последний адрес, а также последовательность байтов представляющий содержимое области памяти. В реальной жизни, один раз настроить (и изменения конфигурации на лету, как один процесс за другим, входит в процессор), менеджер памяти накладывает различные политики по различным регионам. В одном регионе может быть только для чтения, другой может быть чтения и записи. Можно кэшировать, другой нет.

AddRegion метод используется для настройки еще одного региона в памяти устройства.

Read32be метод, то просто цикл по массиву регионов ищет один из которых содержит по указанному адресу для поиска и возвращает данные, хранящиеся в регионе в прилагаемой к зачету, когда он находит нужную область.Write32be метода дополняют друг друга:

public int read32be(int addr) {

    for (int i = 0; i < nRegions; i++) {
        if (region[i].start <= addr && addr < region[i].end) {
            int data = Utility.grab32be(region[i].text, addr - region[i].start);
            Clock.increment(MEMORY_LATENCY);                      // часы обновления
            return data;
        }
    }                                                             // недостающая память - ноль
    return 0;
}
public void write32be(int addr, int data) {

    for (int i = 0; i < nRegions; i++) {
        if (region[i].start <= addr && addr < region[i].end) {
            Utility.put32be(region[i].text, addr - region[i].start, data);
            Clock.increment(MEMORY_LATENCY);                      // часы обновления
            return;
        }
    }                                                             // недостающая память проигнорирована
}

Можно было бы в конечном счете хотеть сигнализировать исключение, когда отсутствие (то есть, неформируемая) область обращена, но прямо сейчас этот кодекс делает простую вещь и игнорирует проблему.

Единица памяти также содержит read и write8 методы, которые читают и пишут только один байт за один раз.

Хотя они могут показаться только для удобства (и действительно, внутренне они читают и пишут 4 байта в то время, когда они могут, используя read32be и write32be), их реальное использование находится в выполнении нанесенный на карту ввод / вывод памяти.

Когда поставляемый адрес правильный, единица памяти read8 и write8 методы передает попытку доступа на iobus вместо к памяти.

Позади шины и приложенный к нему лежат несколько единиц ввода / вывода.

Код будет более подробно описано ниже, но наиболее важные вещи, чтобы взять в данный момент является то, что этот механизм означает, что говорить на специальный адрес памяти позволяет символы, которые будут читать с клавиатуры и выводятся на экран. Она называется отображается в память ввода / вывода.

Путем точки пересечения iobus осуществлены в код единицы памяти, как это:

    public byte read8 (int addr) {
   
        byte data;

        if (addr == GETCHAR_ADDRESS) {
            try {
                data = iobus.read8(0);             // чтение ввода / вывода с клавиатуры консоли
            } catch (Exception e) {
                data = 0;
            }
            return data;
        }
        ...
    }
    public void write8 (int addr, byte data) {
   
        if (addr == PUTCHAR_ADDRESS) {
            try {
                iobus.write8(1, data);             // запись ввода / вывода на консоль экрана
            } catch (Exception e) {
                // was best effort
            }
            return;
        }
        ...
    }

"0" шины ввода / вывода адрес ввода с клавиатуры консоли, и "1" Адрес шины ввода / вывода в выходной дисплей консоли. Через эти перехваты запоминающее устройство считывает данные из памяти GETCHAR_ADDRESS адрес читает шины ввода / вывода адрес 0, шины переводится как говорится в консоли прилагается к нему. Аналогично для PUTCHAR_ADDRESS и пишет на консоль.