Увидеть, как инструкции получают Translated (компьютерная архитектура)

Немного путающий вопрос. Но Im действительно ищет изучение программирования на низком уровне. Дело в том, что доски Dev, такие как Arduino/Etc. действительно скрывают многое из того, что происходит.

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

Но вот о том, где он заканчивается.... и я хочу уметь понять, как инструкция (например, Hex/or Assembly/etc..) перемещается по простому компьютеру (много книг я ' вы использовали, как прямо с Гейтса, к компьютеру... без особого промежутка). Даже что-то простое, например..... сохранение значения в регистре или месте памяти (и, возможно, печать на пиксель? Или что-то еще).

Я думаю, что что-то интересное было бы, возможно, даже написанием эмулятора в конце концов. У меня есть опыт работы с языками высокого уровня, но я слышал, что что-то вроде 6502 может стать хорошим началом, поскольку вы используете много сборок, а набор команд не слишком велик.

Кто-нибудь знает какие-либо ресурсы/мысли/книги, которые могут помочь? Я прошел через "Elements of Computing Systems", и хотя... это хорошая книга, я действительно не чувствую, что она проходит через то, что происходит, и видя, как это происходит. Это может быть скорее вопрос Electronics.stackexchange, если я так извиняюсь.

Ответ 1

Попробуйте создать свой собственный простой процессор. Это не так сложно, как кажется: LOGISIM

Ответ 2

Обзор

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

My Take

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

SET(R1, 12) // Stores 12 into register 1

Пусть произвольно (потому что даже в любой стандартной архитектуре выбор действительно произволен) выберите, что инструкция SET преобразуется в следующее 16-битное двоичное значение I:

0001 0001 0000 1100

В принципе, я только что составил конвенцию. Но вот как я это сломаю. Я хочу разрешить биты я [15:12] (выраженные в big-endian обозначение) представляют собой определенную инструкцию. Я хочу, чтобы целое число 1 соответствовало команде SET. Теперь я решил, что это соглашение, я могу сказать, что если у меня есть инструкция SET, пусть бит я [11: 8] соответствует регистру. (Очевидно, что это означает, что у меня будет только 16 регистров: 4 ^ 2 = 16). Наконец, я разрешаю битам я [7: 0] соответствовать данным, которые я хочу сохранить в данном регистре. Позвольте снова взглянуть на SET (R1, 12) в двоичном формате (для ясности я разделяю каждую группу из четырех строк новой строки):

if I =  0001 0001 0000 1100
I[15:12] = 0001 (binary) = 1 (decimal) = SET instruction
I[11:8] = 0001 (binary) = 1 (decimal) = R1 since I[15:12] correspond to SET.
I[7:0] = 0000 1100 (8-bit binary) = 12 (decimal) = value to store in R1.

Как вы можете видеть, все остальное в микропроцессоре становится очень простым. Скажем, ваш магазин содержит 4 строки инструкций в ОЗУ. У вас есть счетчик, прикрепленный к часам. Счетчик подсчитывает строки в ОЗУ. Когда часы "тикают", новая инструкция выходит из барана. (Это следующая инструкция выходит из ОЗУ - хотя это может быть несколько произвольным, как только вы вставляете инструкции JUMP.) Выход ОЗУ проходит через несколько битовых селекторов. Вы выбираете биты я [15:12] и отправляете их в блок управления (CLU), который сообщает вам, какую команду вы пытаетесь передать. То есть SET, JUMP и т.д. Затем, в зависимости от того, какая команда найдена, вы можете разрешить запись регистров или регистров для добавления или что-то еще, что вы хотите включить в свою архитектуру.

К счастью, для вас уже выбраны произвольные условные обозначения для двоичных значений машинных команд (если вы хотите следовать им). Это именно то, что определяется архитектурой набора инструкций (ISA). Например MIPS, HERA и т.д. Просто для ясности, фактической реализации, которую вы создаете при разработке схемы и еще не называемой микроархитектурой.

Ресурсы для обучения

Тексты

Книга Харриса и Харриса является одним из самых известных текстов для курсов по компьютерной архитектуре. Это очень простой и полезный текст. Все это доступно в формате PDF здесь бесплатно в какой-то случайной школе. (Скачайте это быстро!) Я нашел его очень полезным. Он проходит через основные схемы, темы в дискретной математике, и к тому времени, когда вы доберетесь до главы 7, создание микропроцессора - это кусок пирога. Мне потребовалось ~ 3 дня, чтобы завершить 16-разрядный микропроцессор, прочитав эту книгу. (Конечно, у меня был опыт в дискретной математике, но это не очень важно.)

Еще одна полезная и очень стандартная книга - это книга Hennessy and Patterson, которая также доступна в формате PDF из какой-то случайной школы. (Скачайте это быстро!) Книга Харриса и Харриса была упрощением, основанным на этой книге. Эта книга намного подробнее.

Микропроцессоры с открытым исходным кодом

Там есть тонна микропроцессоров с открытым исходным кодом. Для меня было очень полезно иметь возможность ссылаться на них, когда я строил свой первый микропроцессор. Особенно приятно играть с файлами Logisim, потому что вы можете просматривать их графически и щелкнуть и с ними общаться. Вот несколько моих любимых сайтов и конкретных mps:

4 бита:

16-бит:

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

Инструменты

Logisim

Как упоминалось ранее, Logisim - отличный ресурс. Макет полностью графический, и вы можете очень легко увидеть, что происходит по-разному в любой момент времени, выбрав провод. Это на Java, поэтому я уверен, что он работает на любой машине, в которой вы хотите. Это также интересная историческая перспектива на графических языках программирования.

Моделирование

В Logisim вы можете моделировать фактическое запущенное программное обеспечение. Если у вас есть компилятор, который компилирует двоичные файлы для ISA, на который вы нацеливаетесь, вы можете просто загрузить двоичный или шестнадцатеричный файл в RAM Logisim и запустить программу. (Если у вас нет компилятора, все еще возможно и отличное упражнение, чтобы написать программу с четырьмя строками и перевести ее вручную.) Моделирование - безусловно самая крутая и самая приятная часть всего процесса!: D Logisim также предоставляет CLI для этого более программно.

ЛВП

Более современная форма создания/проектирования микроархитексов - использование языка описания аппаратных средств (HDL). Самые известные примеры включают Verilog и VHDL. Они часто (смутно!) Моделируются после последовательных языков, таких как Ada и C/С++. Однако это, безусловно, предпочтительный метод проектирования, потому что проверка модели/дизайна намного лучше определена. На мой взгляд, гораздо легче рассуждать о текстовом представлении, чем анализировать графически. Так же, как программисты могут плохо организовывать код, разработчики аппаратного обеспечения могут плохо организовать графическую компоновку графического дизайна микроархитектуры. (Хотя этот аргумент, безусловно, может быть применен к HDL.) Все еще легче документировать текстовое, чем графически, и проектировать более модульно в общем случае с использованием HDL.

Если вам интересно узнать об этом, есть тонны курсов для студентов с открытой учебной программой и лабораторными работами, обсуждающими и изучающих использование HDL для описания схем и микроархитексов. Вы можете найти их просто по поиску. Или вы также можете попытаться изучить HDL через следующий шаг - инструменты, которые конвертируют код C/С++ в HDL. Если вам интересно, Icarus Verilog является хорошим компилятором и симулятором с открытым исходным кодом для Verilog.

Моделирование

Используя такой инструмент, как Icarus Verilog, вы также можете легко имитировать реальную программу, запускаемую из двоичного файла. Вы просто переносите свой микропроцессор в другой Verilog script, который загружает файл или строку в RAM через некоторую шину. Кусок пирога!: D

HLS

В последние годы высокоуровневый синтез (HLS) также приобрел значительный плацдарм на рынке. Это преобразование кода C/С++ в реальные схемы. Это довольно невероятно, потому что существующие C/С++ могут (но не всегда) быть преобразованы в оборудование.

(Я говорю не всегда, потому что не весь синтез C/С++. В схеме поток бит существует повсюду сразу. В программном обеспечении мы считаем код последовательным. Это ужасный способ думать, если вы пытаетесь проектировать оборудование!)

Но поскольку вы можете угадать, эта способность невероятна для оптимизации определенных аспектов кода на оборудовании, таких как операции с матрицами или математика в целом. Однако это относится к вам, потому что вы можете использовать инструменты HLS, чтобы увидеть, как реализация C-точечного продукта (например) может быть переведена на HDL. Я лично чувствую, что это отличный способ узнать.

Моделирование

Моделирование HLS так же просто, как имитация HDL, потому что код высокого уровня просто преобразован в HDL. Затем вы можете имитировать и запускать тесты именно так, как я объяснил выше.

Ответ 3

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

   and #$00
   ora #$01
 top:
   rol
   bcc top
   and #$00

Да, мне хорошо известно, что я не загружаю симулятор должным образом. Я предполагаю, что этот двоичный код основан на адресе нуль, используя ассемблер xa65 (apt-get install xa65). Бинарный файл после сборки:

hexdump -C a.o65 
00000000  29 00 09 01 2a 90 fd 29  00                       |)...*..).|
00000009

и это простая, сокращенная инструкция, симулятор

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE *fp;

#define MEMMASK 0xFFFF
unsigned char mem[MEMMASK+1];

unsigned short pc;
unsigned short dest;
unsigned char a;
unsigned char x;
unsigned char y;
unsigned char sr;
unsigned char sp;
unsigned char opcode;
unsigned char operand;

unsigned char temp;

int main ( void )
{
    memset(mem,0xFF,sizeof(mem)); //if we execute a 0xFF just exit

    fp=fopen("a.o65","rb");
    if(fp==NULL) return(1);
    fread(mem,1,sizeof(mem),fp);
    fclose(fp);

    //reset the cpu
    pc=0; //I know this is not right!
    a=0;
    x=0;
    y=0;
    sr=0;
    sp=0;
    //go
    while(1)
    {
        opcode=mem[pc];
        printf("\n0x%04X: 0x%02X\n",pc,opcode);
        pc++;
        if(opcode==0x29) //and
        {
            operand=mem[pc];
            printf("0x%04X: 0x%02X\n",pc,operand);
            pc++;
            printf("and #$%02X\n",operand);
            a&=operand;
            if(a==0) sr|=2; else sr&=(~2);
            sr&=0x7F; sr|=a&0x80;
            printf("a = $%02X sr = $%02X\n",a,sr);
            continue;
        }
        if(opcode==0x09) //ora
        {
            operand=mem[pc];
            printf("0x%04X: 0x%02X\n",pc,operand);
            pc++;
            printf("ora #$%02X\n",operand);
            a|=operand;
            if(a==0) sr|=2; else sr&=(~2);
            sr&=0x7F; sr|=a&0x80;
            printf("a = $%02X sr = $%02X\n",a,sr);
            continue;
        }
        if(opcode==0x2A) //rol
        {
            printf("rol\n");
            temp=a;
            a<<=1;
            a|=sr&0x01;
            sr&=(~0x01); if(temp&0x80) sr|=0x01;
            if(a==0) sr|=2; else sr&=(~2);
            sr&=0x7F; sr|=a&0x80;
            printf("a = $%02X sr = $%02X\n",a,sr);
            continue;
        }
        if(opcode==0x90) //bcc
        {
            operand=mem[pc];
            printf("0x%04X: 0x%02X\n",pc,operand);
            pc++;
            dest=operand;
            if(dest&0x80) dest|=0xFF00;
            dest+=pc;
            printf("bcc #$%04X\n",dest);
            if(sr&1)
            {
            }
            else
            {
                pc=dest;
            }
            continue;
        }
        printf("UNKNOWN OPCODE\n");
        break;
    }
    return(0);
}

и выход симулятора для этой простой программы.

0x0000: 0x29
0x0001: 0x00
and #$00
a = $00 sr = $02

0x0002: 0x09
0x0003: 0x01
ora #$01
a = $01 sr = $00

0x0004: 0x2A
rol
a = $02 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $04 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $08 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $10 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $20 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $40 sr = $00

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $80 sr = $80

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0004: 0x2A
rol
a = $00 sr = $03

0x0005: 0x90
0x0006: 0xFD
bcc #$0004

0x0007: 0x29
0x0008: 0x00
and #$00
a = $00 sr = $03

0x0009: 0xFF
UNKNOWN OPCODE

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

6502 по-прежнему большой проект, если вы реализуете все это, не так много, как z80, но такие вещи, как risc16, могут быть полчаса, чтобы понять и написать весь симулятор (а затем еще полчаса, чтобы сделать ассемблер). pic12, 14 или 16 - это больше, чем risc16, но не слишком много, может быстро пробиваться через него и представляет собой образовательный опыт с тем, насколько прост в дизайне. pdp11 и msp430, без сомнения, связаны каким-то образом, оба документально задокументированы (все из них я хорошо документирован) и красиво/в основном ортогонально, а декодирование в виде risc - это другой опыт, чем cisc вроде 6502/z80/x86. (pdp11 поддерживается изначально gcc/gnu). Mips очень просто, если вы можете работать с вашим алгоритмом вокруг слота отложенного ветки.

удачи, получайте удовольствие...

Ответ 4

MIT помещает все ресурсы для своего класса Computation Structures, 6.004 в Интернете. Это, по сути, класс "Введение в компьютерную архитектуру", в котором основное внимание уделяется проектно-ориентированному обучению.

Версия OpenCourseWare здесь. Я бы особенно сосредоточился на labs, особенно 2, 3, 5 и 6, которые заставляют вас строить ADDER до и ALU полностью к очень простому процессору (бета-версия).

Ссылка на последние материалы курса здесь.

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

Ответ 5

Один текст, который делает шаг за шагом от ворот до полностью функционального компьютера и за его пределами, - это элементы вычислительных систем Noam Nisan и Shimon Schocken 2005 ISBN 9780262640688. Их веб-сайт находится на www.nand2tetris.org

Ответ 6

В первых главах "Искусство языка сборки" рассказывается о том, как биты хранятся физически с помощью защелок и идет о том, как они используются для сборки регистры для хранения байтов данных и как такие команды, как сдвиг влево/вправо, могут быть реализованы на аппаратном уровне. Наверное, не так подробно, как вы ищите, но это действительно открыло мне глаза, когда я прочитал этот материал.