OpenCores
URL https://opencores.org/ocsvn/aor3000/aor3000/trunk

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [sim/] [tester/] [main_linux.cpp] - Rev 2

Compare with Previous | Blame | View Log

/*
 * This file is subject to the terms and conditions of the BSD License. See
 * the file "LICENSE" in the main directory of this archive for more details.
 *
 * Copyright (C) 2014 Aleksander Osman
 */
 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
 
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <pty.h>
#include <poll.h>
 
#include "shared_mem.h"
 
//------------------------------------------------------------------------------
 
volatile shared_mem_t *shared_ptr = NULL;
 
//------------------------------------------------------------------------------
 
//128MB
#define MAX_MEMORY   0x8000000
#define RESET_VECTOR 0x1FC00000
 
int main(int argc, char **argv) {
 
    if(argc != 2) {
        printf("Error: missing argument: path to vmlinux.bin file !\n");
        return -1;
    }
 
    int int_ret;
 
    //open file with truncate
    FILE *fp = fopen("shared_mem.dat", "wb");
    if(fp == NULL) {
        perror("Can not truncate file shared_mem.dat");
        return -1;
    }
    uint8 *buf = new uint8[sizeof(shared_mem_t)];
    memset(buf, 0, sizeof(shared_mem_t));
 
    int_ret = fwrite(buf, sizeof(shared_mem_t), 1, fp);
    delete buf;
    if(int_ret != 1) {
        perror("Can not zero-fill file shared_mem.dat");
        fclose(fp);
        return -2;
    }
    fclose(fp);
 
    //--------------------------------------------------------------------------
 
    //map shared memory
    int fd = open("./shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR);
 
    if(fd == -1) {
        perror("open() failed for shared_mem.dat");
        return -3;
    }
 
    shared_ptr = (shared_mem_t *)mmap(NULL, sizeof(shared_mem_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
    if(shared_ptr == MAP_FAILED) {
        perror("mmap() failed");
        close(fd);
        return -4;
    }
 
    //--------------------------------------------------------------------------
 
    srand(0);
 
    //----------------------------------------------------------------------
    memset((void *)shared_ptr, 0, sizeof(shared_mem_t));
 
    //load linux kernel binary from address 0
    FILE *kernel_fp = fopen(argv[1], "rb");
    if(kernel_fp == NULL) {
        printf("Error: can not open file: %s\n", argv[1]);
        return -1;
    }
    uint8 *kernel_ptr = (uint8 *)shared_ptr->mem.bytes;
    while(true) {
        int_ret = fread(kernel_ptr, 1, 8192, kernel_fp);
        if(int_ret == 0) break;
        kernel_ptr += int_ret;
    }
    fclose(kernel_fp);
 
    printf("loaded linux kernel size: %d bytes.\n", (kernel_ptr - shared_ptr->mem.bytes));
 
    //----------------------------------------------------------------------
 
    uint32 *reset_ptr = (uint32 *)shared_ptr->reset_vector;
 
    reset_ptr[0] = (0b000000 << 26) | (0 << 21) | (1 << 16) | (1 << 11) | (0b00000 << 6) | (0b100100);   //AND R1,R0,R1 -- clear R1
    reset_ptr[1] = (0b001111 << 26) | (0 << 21) | (1 << 16) | 0x8000;                                    //LUI R1,0x8000
    reset_ptr[2] = (0b001101 << 26) | (1 << 21) | (1 << 16) | 0x0400;                                    //ORI R1,R1,0x400
    reset_ptr[3] = (0b000000 << 26) | (1 << 21) | (0 << 16) | (0 << 11) | (0 << 6) | (0b001000);         //JR R1
    reset_ptr[4] = 0;                                                                                    //NOP
 
    shared_ptr->check_at_event = 10000;
 
    //----------------------------------------------------------------------
 
    FILE *early_console_fp = fopen("early_console.txt", "wb");
    FILE *jtag_console_fp = fopen("jtag_console.txt", "wb");
 
    //----------------------------------------------------------------------
 
    int master_fd = 0, slave_fd = 0;
    char slave_name[256];
    memset(slave_name, 0, sizeof(slave_name));
 
    int_ret = openpty(&master_fd, &slave_fd, slave_name, NULL, NULL);
    if(int_ret != 0) {
        printf("Can not openpty().\n");
        return -1;
    }
    printf("slave pty: %s\n", slave_name);
 
    //----------------------------------------------------------------------
 
    pid_t proc_vmips = fork();
    if(proc_vmips == 0) {
        system("cd ./../vmips && ./main_linux > ./vmips_output.txt");
        return 0;
    }
 
    pid_t proc_ao = fork();
    if(proc_ao == 0) {
        system("cd ./../aoR3000 && ./obj_dir/VaoR3000 > ./ao_output.txt");
        return 0;
    }
 
    //----------------------------------------------------------------------
 
    printf("Waiting for init of vmips..."); fflush(stdout);
    shared_ptr->proc_vmips.initialize_do = true;
 
    while(shared_ptr->proc_vmips.initialize_do) usleep(1);
    printf("done\n");
 
    printf("Waiting for init of aoR3000...");  fflush(stdout);
    shared_ptr->proc_ao.initialize_do = true;
 
    while(shared_ptr->proc_ao.initialize_do) usleep(1);
    printf("done\n");
 
    //irq setup
    shared_ptr->irq2_at_event = 0;
    shared_ptr->irq3_at_event = 0xFFFFFFFF;
 
    //jtag data
    bool jtag_read_irq_enable  = false;
    bool jtag_write_irq_enable = false;
 
    uint64 loop = 0;
 
    struct pollfd master_poll;
    memset(&master_poll, 0, sizeof(master_poll));
    master_poll.fd = master_fd;
    master_poll.events = POLLIN;
 
    std::deque<char> jtag_deque;
 
    while(true) {
        loop++;
        if((loop % 100000000) == 0) printf("loop: %lld, vmips: %d ao: %d\n", loop, shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
 
        //----------------------------------------------------------------------
 
        if((loop % 10000) == 0) {
            int_ret = poll(&master_poll, 1, 0);
            if(int_ret < 0) {
                printf("Error: poll() failed.\n");
                shared_ptr->test_finished = true;
                return -1;
            }
 
            if(int_ret == 1 && (master_poll.revents & POLLIN)) {
                char read_char = 0;
                int_ret = read(master_fd, &read_char, 1);
 
                jtag_deque.push_back(read_char);
                printf("read: %c\n", read_char);
            }
        }
 
        //----------------------------------------------------------------------
 
        uint32 retry = 0;
        while(shared_ptr->proc_vmips.check_do || shared_ptr->proc_ao.check_do) {
            if(shared_ptr->proc_vmips.check_do && shared_ptr->proc_ao.check_do) {
 
                //printf("check[%d, %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
 
                if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) {
                    printf("check counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
                    getchar();
                }
 
                shared_ptr->check_at_event += 10000;
 
                if(jtag_write_irq_enable == false) {
                    if(jtag_deque.empty()) {
                        if(shared_ptr->irq3_at_event != 0xFFFFFFFF) {
                            printf("jtag: disabling irq\n");
                            shared_ptr->irq3_at_event = 0xFFFFFFFF;
                        }
                    }
                    else {
                        shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10;
                        printf("jtag: enabling irq\n");
                    }
                }
 
                shared_ptr->proc_vmips.check_do = false;
                shared_ptr->proc_ao.check_do    = false;
            }
            else {
                usleep(10);
                retry++;
 
                if(retry == 500000) {
                    printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data);
                    printf("ao:    %08x %01x %08x\n", shared_ptr->proc_ao.write_address,    shared_ptr->proc_ao.write_byteenable,    shared_ptr->proc_ao.write_data);
 
                    printf("\nTEST FAILED. WAITING FOR CHECK [vmips: %d, ao: %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
                    shared_ptr->test_finished = true;
                    return -1;
                }
            }
        }
 
        retry = 0;
        while(shared_ptr->proc_vmips.write_do || shared_ptr->proc_ao.write_do) {
            if(shared_ptr->proc_vmips.write_do && shared_ptr->proc_ao.write_do) {
                if( shared_ptr->proc_vmips.write_address    == shared_ptr->proc_ao.write_address &&
                    shared_ptr->proc_vmips.write_byteenable == shared_ptr->proc_ao.write_byteenable &&
                    shared_ptr->proc_vmips.write_data       == shared_ptr->proc_ao.write_data)
                {
                    //printf("write[%d]: %08x %01x %08x\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data);
 
                    if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) {
                        printf("write instruction counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
                        getchar();
                    }
 
                    uint32 address = shared_ptr->proc_vmips.write_address;
                    uint32 byteena = shared_ptr->proc_vmips.write_byteenable;
                    uint32 value   = shared_ptr->proc_vmips.write_data;
 
                    if(address < MAX_MEMORY) {
                        for(uint32 i=0; i<4; i++) {
                            if(byteena & 1) shared_ptr->mem.bytes[shared_ptr->proc_vmips.write_address + i] = value & 0xFF;
                            value >>= 8;
                            byteena >>= 1;
                        }
                    }
                    else if(address >= RESET_VECTOR && address < RESET_VECTOR + sizeof(shared_ptr->reset_vector)) {
                        for(uint32 i=0; i<4; i++) {
                            uint8 *vector = (uint8 *)shared_ptr->reset_vector;
                            if(byteena & 1) vector[address - RESET_VECTOR + i] = value & 0xFF;
                            value >>= 8;
                            byteena >>= 1;
                        }
                    }
                    else if(address == 0x1FFFFFFC && byteena == 8) {
                        fprintf(early_console_fp, "%c", (value >> 24) & 0xFF);
                        fflush(early_console_fp);
                    }
                    else if(address == 0x1FFFFFF8 && byteena == 1) {
                        printf("timer irq ack\n");
                        shared_ptr->irq2_at_event = shared_ptr->proc_vmips.report.counter + 500000;
                    }
                    else if(address == 0x1FFFFFF0 && byteena == 0xF) {
                        printf("write jtaguart data: %08x\n", value);
 
                        char byte_to_write = (value & 0xFF);
 
                        fprintf(jtag_console_fp, "%c", byte_to_write);
                        fflush(jtag_console_fp);
 
                        write(master_fd, &byte_to_write, 1);
                    }
                    else if(address == 0x1FFFFFF4 && byteena == 0xF) {
                        printf("write jtaguart control: %08x\n", value);
 
                        jtag_read_irq_enable  = (value & 0x1)? true : false;
                        jtag_write_irq_enable = (value & 0x2)? true : false;
 
                        if(jtag_write_irq_enable || (jtag_read_irq_enable && jtag_deque.size() > 0))    shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10;
                        else                                                                            shared_ptr->irq3_at_event = 0xFFFFFFFF;
                    }
                    else {
                        printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data);
                        printf("ao:    %08x %01x %08x\n", shared_ptr->proc_ao.write_address,    shared_ptr->proc_ao.write_byteenable,    shared_ptr->proc_ao.write_data);
 
                        printf("\nTEST FAILED. MEM WRITE TO UNKNOWN.\n");
                        shared_ptr->test_finished = true;
                        return -1;
                    }
 
                    shared_ptr->proc_vmips.write_do = false;
                    shared_ptr->proc_ao.write_do    = false;
                }
                else {
                    printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data);
                    printf("ao:    %08x %01x %08x\n", shared_ptr->proc_ao.write_address,    shared_ptr->proc_ao.write_byteenable,    shared_ptr->proc_ao.write_data);
 
                    printf("\nTEST FAILED. MEM WRITE DIFF [%d].\n", shared_ptr->proc_vmips.report.counter);
                    shared_ptr->test_finished = true;
                    return -1;
                }
            }
            else {
                usleep(10);
                retry++;
 
                if(retry == 500000) {
                    printf("vmips: %08x %01x %08x\n", shared_ptr->proc_vmips.write_address, shared_ptr->proc_vmips.write_byteenable, shared_ptr->proc_vmips.write_data);
                    printf("ao:    %08x %01x %08x\n", shared_ptr->proc_ao.write_address,    shared_ptr->proc_ao.write_byteenable,    shared_ptr->proc_ao.write_data);
 
                    printf("\nTEST FAILED. WAITING FOR WRITE [vmips: %d, ao: %d]\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
                    shared_ptr->test_finished = true;
                    return -1;
                }
            }
        }
 
        retry = 0;
        while(shared_ptr->proc_vmips.read_do || shared_ptr->proc_ao.read_do) {
            if(shared_ptr->proc_vmips.read_do && shared_ptr->proc_ao.read_do) {
                if( shared_ptr->proc_vmips.read_address    == shared_ptr->proc_ao.read_address &&
                    shared_ptr->proc_vmips.read_byteenable == shared_ptr->proc_ao.read_byteenable)
                {
                    printf("read: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable);
 
                    if(shared_ptr->proc_vmips.report.counter != shared_ptr->proc_ao.report.counter) {
                        printf("read instruction counter mismatch: vmips: %d != %d\n", shared_ptr->proc_vmips.report.counter, shared_ptr->proc_ao.report.counter);
                        getchar();
                    }
 
                    uint32 address = shared_ptr->proc_vmips.read_address;
                    uint32 byteena = shared_ptr->proc_vmips.read_byteenable;
                    uint32 value   = 0xFFFFFFFF;
 
                    if(address == 0x1FFFFFF0 && byteena == 0xF) {
                        if(jtag_deque.empty()) value = 0;
                        else {
                            value = 
                                (jtag_deque.front() & 0xFF) |
                                (1 << 15) |
                                (((jtag_deque.size() - 1) & 0xFFFF) << 16);
 
                            jtag_deque.pop_front();
                        }
 
                        if(jtag_write_irq_enable == false) {
                            if(jtag_deque.empty()) {
                                shared_ptr->irq3_at_event = 0xFFFFFFFF;
                                printf("jtag: disabling irq\n");
                            }
                            else {
                                shared_ptr->irq3_at_event = shared_ptr->proc_vmips.report.counter + 10;
                                printf("jtag: enabling irq\n");
                            }
                        }
 
                        printf("read jtaguart data: %08x\n", value);
                    }
                    else if(address == 0x1FFFFFF4 && byteena == 0xF) {
                        value = 
                            ((jtag_read_irq_enable)?  1 : 0) |
                            ((jtag_write_irq_enable)? 2 : 0) |
                            (((jtag_deque.empty())? 0 : 1) << 8)  |     //read irq pending
                            (1 << 9)  |                                 //write irq pending
                            (1 << 10) |                                 //active
                            (0xFF << 16);                               //spaces left in write fifo
 
                        printf("read jtaguart control: %08x\n", value);
                    }
                    else
                    {
                        printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable);
                        printf("ao:    %08x %01x\n", shared_ptr->proc_ao.read_address,    shared_ptr->proc_ao.read_byteenable);
 
                        printf("\nRUN FAILED. MEM READ FROM UNKNOWN.\n");
                        shared_ptr->test_finished = true;
                        return -1;
 
                    }
 
                    shared_ptr->proc_vmips.read_data = value;
                    shared_ptr->proc_ao.read_data = value;
 
                    shared_ptr->proc_vmips.read_do = false;
                    shared_ptr->proc_ao.read_do    = false;
                }
                else {
                    printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable, shared_ptr->proc_vmips.read_data);
                    printf("ao:    %08x %01x\n", shared_ptr->proc_ao.read_address,    shared_ptr->proc_ao.read_byteenable,    shared_ptr->proc_ao.read_data);
 
                    printf("\nRUN FAILED. MEM READ DIFF.\n");
                    shared_ptr->test_finished = true;
                    return -1;
                }
            }
            else {
                usleep(10);
                retry++;
 
                if(retry == 500000) {
                    printf("vmips: %08x %01x\n", shared_ptr->proc_vmips.read_address, shared_ptr->proc_vmips.read_byteenable, shared_ptr->proc_vmips.read_data);
                    printf("ao:    %08x %01x\n", shared_ptr->proc_ao.read_address,    shared_ptr->proc_ao.read_byteenable,    shared_ptr->proc_ao.read_data);
 
                    printf("\nTEST FAILED. WAITING FOR READ.\n");
                    shared_ptr->test_finished = true;
                    return -1;
                }
            }
        }
    }
 
    //---------------------------------------------------------------------- wait for process end
    waitpid(proc_vmips, NULL, 0);
    waitpid(proc_ao, NULL, 0);
 
    return 0;
}
 
//------------------------------------------------------------------------------
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.