Внедрение DoubleBuffering, переадресация регистра и «конвейерная обработка» в виртуальной машине C - PullRequest
0 голосов
/ 04 мая 2020

Ниже приведена реализация своего рода виртуальной машины, и хотя она работает методом одной команды за раз, занимая все 4 цикла (выборка, декодирование, выполнение, сохранение), а затем переходя к следующей команде. Что я пытаюсь выяснить, если это возможно, и если да, то как я могу отредактировать свою программу, чтобы я мог выполнять несколько команд параллельно? Под этим я подразумеваю, что команда 1 проходит через Fetch и переходит к декодированию, а команда декодирования 1, команда 2 проходит через Fetch. Сначала я хотел использовать два логических значения и два массива команд fetchresult / current. Однако я понимаю, что это можно сделать с помощью двойной буферизации, но тогда, когда одновременно запускаются несколько команд, необходимо также считать риск записи в текущий момент в регистр или наоборот, так что переадресация регистра будет необходимо. Может ли кто-нибудь дать мне пример того, как это можно сделать, и если это вообще возможно сделать в этом типе виртуальной машины?

VM. c

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

#define MAXMEM 1024
#define NUM_REGS 16
int regs[ NUM_REGS];
uint8_t memory[MAXMEM];
uint8_t fetchresult[5];
//globals to be used throughout processing
bool Call = false;
int pc = 0;
int opcode = 0;
int reg1 = 0;
int reg2 = 0;
int reg3 = 0;
int imm = 0;
int br1 = 0;
int br2 = 0;
int stack_op = 0;
int stack_op2 = 0;
int br_op = 0;
uint8_t callnxt = 0;
int sp = -1;
int stored = 0;

void showRegs();
void printStack();

size_t loads (char *filename)
{

    FILE *file = fopen(filename, "rb");
    if(!file) {
    perror("Failed to read file");
    exit( EXIT_FAILURE);
    }
    fseek(file, 0, SEEK_END);
    int filesize = ftell(file);
    //printf("filesize is %d\n", filesize);
    sp = filesize;
    rewind(file);
    return fread(memory, sizeof(memory), filesize, file);

}

void fetch(){
    //printf("%02x\n", memory[pc]);
    fetchresult[0] = memory[pc];
    fetchresult[1] = memory[pc+1];
    fetchresult[2] = memory[pc+2];
    fetchresult[3] = memory[pc+3];
    fetchresult[4] = memory[pc+4];
    pc+=2;
    }
int running = 1; // shows vm is running until flag is 0

void decode () {
    opcode = (fetchresult[0]) >> 4;
    //printf("opcode is %d\n", opcode);
    reg1 = (fetchresult[0])&0xf;
    //printf("reg1 is %d\n", reg1);
    reg2 = (fetchresult[1]) >> 4;
    //printf("reg2 is %d\n", reg2);
    reg3 = (fetchresult[1])&0xf;
    //printf("reg3 is %d\n", reg3);
    imm = (fetchresult[1] & 0xFF);
    //printf("immediate value is %d\n", imm);
    br1 = (fetchresult[2] << 8 | fetchresult[3]);
    //printf("br1 value is %d\n", br1);
    br2 = (fetchresult[1] << 16 | br1);
    //printf("br2 value is %d\n", br2);
    stack_op = fetchresult[1] >> 4;
    //printf("stack_op value is %d\n", stack_op);
    stack_op2 = fetchresult[1] & 0xf;
    //printf("stack_op2 value is %d\n", stack_op2);
    br_op = (fetchresult[0] &0xf);
    //printf("br_op value is %d\n", br_op);
    callnxt = (fetchresult[4]);
    //printf("Callnxt is %02x\n", callnxt);
    }

void eval() {
    switch (opcode)
        {
        case 0:
            printf("halt\n");
            running = 0;
            break;
        case 11:
            printf("Move r%d with value of %d\n", reg1, imm);
            regs[reg1] += imm;
            break;
        case 1:
            printf("add r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] += regs[reg1] + regs[reg2];
            break;
        case 2: 
            printf("and r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] & regs[reg2];
            break;
        case 3:
            printf("divide r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] / regs[reg2];
            break;
        case 4:
            printf("multiply r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] * regs[reg2];
            break;
        case 5:
            printf("subtract r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] - regs[reg2];
            break;
        case 6:
            printf("or r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] | regs[reg2];
            break;
        case 7:
            switch(br_op)
                {
                case 0: // branchifless
                    if(regs[reg2] < regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 1: //branch if less or equal
                    if(regs[reg2] <= regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 2: // branch if equal
                    if(regs[reg2] == regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 3: // branch if not equal
                    if(regs[reg2] != regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 4: // branch if greater then
                    if(regs[reg2] > regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 5: // branch if greater than or equal
                    if(regs[reg2] >= regs[reg3]){
                        pc += 2*br2;
                    }
                    break;
                case 6: // call & return
                    printf("Call %d\n", br2);
                    regs[15] = pc + 2;
                    //printf("Reg 15 is %02x\n", regs[15]);
                    Call = true;
                    pc += 2*br2;
                    break;
                case 7: // jump X
                    printf("Jump %d\n", br1);
                    pc += 2*br2;
                }
            break;
        case 8: // load 
            //printf("sp is at start of load %d\n", sp);
            sp;
            int loaded = sp + (regs[reg3] + (imm * 2));
            //printf("Loaded is %d\n", loaded);
            regs[reg1] = memory[loaded];
            printf("Loaded value in r%d is %d\n", reg1, regs[reg1]);
            break;
        case 9: // store 
            sp += sp++;
            stored = sp + (regs[reg3] + (imm * 2));
            //printf("Stored is %d\n", stored);
            //sp += stored;
            //printf("sp after add with stored is %d\n", sp);
            //printf("sp is %d\n", sp);
            memory[stored] = regs[reg1];
            printf("Stored value is %d\n", memory[stored]);
            break;
        case 10: // pop/push/return  
            switch(stack_op){ 
                case 0:
                    switch(stack_op2){
                            case 0:// return
                                printf("Return to instruction following call\n");
                                pc = regs[15];

                                break;
                            case 1:// push
                                sp = sp - 4;
                                memory[sp] = regs[reg1];
                                printf("Pushing value of %d to stack\n", regs[reg1]);
                                break;
                            }
                    break;
                case 1: // pop
                    regs[reg1] = memory[sp];
                    printf("popping value of %d from stack into r%d\n", memory[sp], regs[reg1]-1);
                    sp = sp + 4;
                    break;
                    }
            break;
        case 12: // interrupt
            switch(br_op){
                case 0:
                    printf("Interrupt 0, showing registers\n");
                    showRegs();
                    exit(0);
                    break;
                case 1:
                    printf("Interrupt 1, showing memory\n");
                    printStack();
                    exit(0);
                    break;
                }
            break;
            }
        }

void showRegs() {
    int i;
    for (i=0; i< NUM_REGS; i++){
        printf("register %d is %d", i, regs[i] );
        printf("\n");
    }
}

void printStack() {
    //printf("Values in memory? %d\n", memory[sp]);
    for(int i = 0; i < MAXMEM; i++) {
        printf("0x%02x ", memory[i]);
        if((i + 1) %4 == 0) {
            printf("\n");
            }
        }
        if(sp != 0) {
            printf("\n");
            }
        }

void run(){
    while(running){
        fetch();
        decode();
        eval();
        }
    //showRegs();
    }

int main(int argc, char **argv) {

    if(argc <= 1){
        printf("No File Found\n");
        return -1;
        }
    char *filename = argv[1];
    loads(filename);
    run();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...