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

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [sim/] [vmips/] [main_tester.cpp] - Rev 2

Compare with Previous | Blame | View Log

/*
 * This file is subject to the terms and conditions of the GPL 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 <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
 
#include "shared_mem.h"
#include "vmips_emulator.h"
 
//------------------------------------------------------------------------------
 
volatile shared_mem_t *shared_ptr = NULL;
 
//------------------------------------------------------------------------------
 
 
#define GET(field, mask) \
    (shared_ptr->initial.field & mask)
 
void CPZero::initialize() {
    for(int i=0; i<64; i++) {
        tlb[i].entryHi = 0;
        tlb[i].entryHi |= GET(tlb[i].vpn, 0xFFFFF) << 12;
        tlb[i].entryHi |= GET(tlb[i].asid, 0x3F)   << 6;
 
        tlb[i].entryLo = 0;
        tlb[i].entryLo |= GET(tlb[i].pfn, 0xFFFFF) << 12;
        tlb[i].entryLo |= GET(tlb[i].n,   0x1)     << 11;
        tlb[i].entryLo |= GET(tlb[i].d,   0x1)     << 10;
        tlb[i].entryLo |= GET(tlb[i].v,   0x1)     << 9;
        tlb[i].entryLo |= GET(tlb[i].g,   0x1)     << 8;
    }
    for(int i=0; i<32; i++) reg[i] = 0; //cp0 regs
 
    reg[0] |= GET(index_p, 0x1)      << 31;
    reg[0] |= GET(index_index, 0x3F) << 8;
 
    reg[1] |= GET(random, 0x3F) << 8;
 
    reg[2] |= GET(entrylo_pfn, 0xFFFFF) << 12;
    reg[2] |= GET(entrylo_n,   0x1)     << 11;
    reg[2] |= GET(entrylo_d,   0x1)     << 10;
    reg[2] |= GET(entrylo_v,   0x1)     << 9;
    reg[2] |= GET(entrylo_g,   0x1)     << 8;
 
    reg[4] |= GET(context_ptebase, 0x7FF)   << 21;
    reg[4] |= GET(context_badvpn,  0x7FFFF) << 2;
 
    reg[8] |= GET(bad_vaddr, 0xFFFFFFFF);
 
    reg[10] |= GET(entryhi_vpn, 0xFFFFF) << 12;
    reg[10] |= GET(entryhi_asid, 0x3F)   << 6;
 
    reg[12] |= GET(sr_cp_usable,     0xF) << 28;
    reg[12] |= GET(sr_rev_endian,    0x1) << 25;
    reg[12] |= GET(sr_bootstrap_vec, 0x1) << 22;
    reg[12] |= GET(sr_tlb_shutdown,  0x1) << 21;
    reg[12] |= GET(sr_parity_err,    0x1) << 20;
    reg[12] |= GET(sr_cache_miss,    0x1) << 19;
    reg[12] |= GET(sr_parity_zero,   0x1) << 18;
    reg[12] |= GET(sr_switch_cache,  0x1) << 17;
    reg[12] |= GET(sr_isolate_cache, 0x1) << 16;
    reg[12] |= GET(sr_irq_mask,      0xFF) << 8;
    reg[12] |= GET(sr_ku_ie,         0x3F) << 0;
 
    reg[13] |= GET(cause_branch_delay, 0x1)  << 31;
    reg[13] |= GET(cause_cp_error,     0x3)  << 28;
    reg[13] |= GET(cause_irq_pending,  0x3)  << 8; //only 2 lowest bits
    reg[13] |= GET(cause_exc_code,     0x1F) << 2;
 
    reg[14] |= GET(epc, 0xFFFFFFFF);
 
    reg[15] |= 0x00000230; /* MIPS R3000A */
}
 
void CPU::initialize() {
 
    put_reg(0, 0);
    for(int i=1; i<32; i++) { put_reg(i, GET(reg[i-1], 0xFFFFFFFF)); }
 
    pc = GET(pc, 0xFFFFFFFF);
    //not comapred: hi = GET(hi, 0xFFFFFFFF);
    //not compared: lo = GET(lo, 0xFFFFFFFF);
 
    cpzero->initialize();
}
 
//------------------------------------------------------------------------------
 
#define PUT(field, val, mask) \
    shared_ptr->proc_vmips.report.state.field = (val) & mask
 
void CPZero::report() {
    for(int i=0; i<64; i++) {
        PUT(tlb[i].vpn,  tlb[i].entryHi >> 12, 0xFFFFF);
        PUT(tlb[i].asid, tlb[i].entryHi >> 6,  0x3F);
 
        PUT(tlb[i].pfn,  tlb[i].entryLo >> 12, 0xFFFFF);
        PUT(tlb[i].n,    tlb[i].entryLo >> 11, 0x1);
        PUT(tlb[i].d,    tlb[i].entryLo >> 10, 0x1);
        PUT(tlb[i].v,    tlb[i].entryLo >> 9, 0x1);
        PUT(tlb[i].g,    tlb[i].entryLo >> 8, 0x1);
    }
 
    PUT(index_p,     reg[0] >> 31, 0x1);
    PUT(index_index, reg[0] >> 8,  0x3F);
 
    PUT(random, reg[1] >> 8, 0x3F);
 
    PUT(entrylo_pfn, reg[2] >> 12, 0xFFFFF);
    PUT(entrylo_n,   reg[2] >> 11, 0x1);
    PUT(entrylo_d,   reg[2] >> 10, 0x1);
    PUT(entrylo_v,   reg[2] >> 9,  0x1);
    PUT(entrylo_g,   reg[2] >> 8,  0x1);
 
    PUT(context_ptebase, reg[4] >> 21, 0x7FF);
    PUT(context_badvpn,  reg[4] >> 2,  0x7FFFF);
 
    PUT(bad_vaddr, reg[8], 0xFFFFFFFF);
 
    PUT(entryhi_vpn,  reg[10] >> 12, 0xFFFFF);
    PUT(entryhi_asid, reg[10] >> 6,  0x3F);
 
    PUT(sr_cp_usable,     reg[12] >> 28, 0xF);
    PUT(sr_rev_endian,    reg[12] >> 25, 0x1);
    PUT(sr_bootstrap_vec, reg[12] >> 22, 0x1);
    PUT(sr_tlb_shutdown,  reg[12] >> 21, 0x1);
    PUT(sr_parity_err,    reg[12] >> 20, 0x1);
    PUT(sr_cache_miss,    reg[12] >> 19, 0x1);
    PUT(sr_parity_zero,   reg[12] >> 18, 0x1);
    PUT(sr_switch_cache,  reg[12] >> 17, 0x1);
    PUT(sr_isolate_cache, reg[12] >> 16, 0x1);
    PUT(sr_irq_mask,      reg[12] >> 8,  0xFF);
    PUT(sr_ku_ie,         reg[12] >> 0,  0x3F);
 
    PUT(cause_branch_delay, reg[13] >> 31, 0x1);
    PUT(cause_cp_error,     reg[13] >> 28, 0x3);
    PUT(cause_irq_pending,  reg[13] >> 8,  0x3); //only 2 lowest bits
    PUT(cause_exc_code,     reg[13] >> 2,  0x1F);
 
    PUT(epc, reg[14], 0xFFFFFFFF);
}
 
void CPU::report() {
    for(int i=1; i<32; i++) PUT(reg[i-1], get_reg(i), 0xFFFFFFFF);
 
    PUT(pc, pc, 0xFFFFFFFF);
    //not compared: PUT(hi, hi, 0xFFFFFFFF);
    //not compared: PUT(lo, lo, 0xFFFFFFFF);
 
    cpzero->report();
}
 
//------------------------------------------------------------------------------
 
CPU *cpu = NULL;
uint32 event_counter = 0;
 
void usleep_or_finish() {
    if(shared_ptr->test_finished) {
        printf("Finishing.\n");
        exit(0);
    }
    usleep(1);
}
 
uint32 ao_interrupts() {
    return (shared_ptr->irq2_at_event == event_counter)? 1 << 10 : 0;
}
 
uint8 ao_fetch_byte(uint32 addr, bool cacheable, bool isolated) {
    //DBE IBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    if(addr < 0x8000000) {
        return shared_ptr->mem.bytes[addr];
    }
 
    shared_ptr->proc_vmips.read_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x3 : 0x4;
    shared_ptr->proc_vmips.read_do         = true;
 
    while(shared_ptr->proc_vmips.read_do) usleep_or_finish();
 
    return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : ((addr % 4) == 1)? 8 : ((addr % 4) == 2)? 16 : 24 )) & 0xFF;
}
 
uint16 ao_fetch_halfword(uint32 addr, bool cacheable, bool isolated) {
    //AdE
    if (addr % 2 != 0) {
        cpu->exception(AdEL,DATALOAD);
        return 0xffff;
    }
 
    //DBE IBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    if(addr < 0x8000000) {
        return shared_ptr->mem.shorts[addr/2];
    }
 
    shared_ptr->proc_vmips.read_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.read_byteenable = ((addr % 4) == 0)? 0x3 : 0xC;
    shared_ptr->proc_vmips.read_do         = true;
 
    while(shared_ptr->proc_vmips.read_do) usleep_or_finish();
 
    return (shared_ptr->proc_vmips.read_data >> ( ((addr % 4) == 0)? 0 : 16 )) & 0xFFFF;
}
 
uint32 ao_fetch_word(uint32 addr, int32 mode, bool cacheable, bool isolated) {
    //AdE
    if (addr % 4 != 0) {
        cpu->exception(AdEL,mode);
        return 0xffffffff;
    }
 
    //DBE IBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    if(addr < 0x8000000) {
        return shared_ptr->mem.ints[addr/4];
    }
 
    shared_ptr->proc_vmips.read_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.read_byteenable = 0xF;
    shared_ptr->proc_vmips.read_do         = true;
 
    while(shared_ptr->proc_vmips.read_do) usleep_or_finish();
 
    return (shared_ptr->proc_vmips.read_data) & 0xFFFFFFFF;
}
 
void ao_store_byte(uint32 addr, uint8 data, bool cacheable, bool isolated) {
    //DBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    shared_ptr->proc_vmips.write_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x1 : ((addr % 4) == 1)? 0x2 : ((addr % 4) == 2)? 0x4 : 0x8;
    shared_ptr->proc_vmips.write_data       = ((addr % 4) == 0)? data : ((addr % 4) == 1)? data << 8 : ((addr % 4) == 2)? data << 16 : data << 24;
    shared_ptr->proc_vmips.write_do         = true;
 
    while(shared_ptr->proc_vmips.write_do) usleep_or_finish();
}
 
void ao_store_halfword(uint32 addr, uint16 data, bool cacheable, bool isolated) {
    //AdE
    if (addr % 2 != 0) {
        cpu->exception(AdES,DATASTORE);
        return;
    }
 
    //DBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    shared_ptr->proc_vmips.write_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.write_byteenable = ((addr % 4) == 0)? 0x3 : 0xC;
    shared_ptr->proc_vmips.write_data       = ((addr % 4) == 0)? data : data << 16;
    shared_ptr->proc_vmips.write_do         = true;
 
    while(shared_ptr->proc_vmips.write_do) usleep_or_finish();
}
 
void ao_store_word(uint32 addr, uint32 data, bool cacheable, bool isolated, uint32 byteenable) {
    //AdE
    if (addr % 4 != 0) {
        cpu->exception(AdES,DATASTORE);
        return;
    }
 
    //DBE
    //cpu->exception((mode == INSTFETCH / DATALOAD ? IBE : DBE), mode);
 
    shared_ptr->proc_vmips.write_address    = addr & 0xFFFFFFFC;
    shared_ptr->proc_vmips.write_byteenable = byteenable;
    shared_ptr->proc_vmips.write_data       = data;
    shared_ptr->proc_vmips.write_do         = true;
 
    while(shared_ptr->proc_vmips.write_do) usleep_or_finish();
}
 
void fatal_error(const char *error, ...) {
    printf("[fatal_error]: %s\n", error);
    exit(-1);
}
 
//------------------------------------------------------------------------------
 
 
int main() {
    //map shared memory
    int fd = open("./../tester/shared_mem.dat", O_RDWR, S_IRUSR | S_IWUSR);
 
    if(fd == -1) {
        perror("open() failed for shared_mem.dat");
        return -1;
    }
 
    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 -2;
    }
 
    cpu = new CPU();
    cpu->reset();
 
    printf("Waiting for initialize..."); fflush(stdout);
    while(shared_ptr->proc_vmips.initialize_do == false) usleep_or_finish();
 
    cpu->initialize();
    shared_ptr->proc_vmips.initialize_do = false;
    printf("done\n");
 
    while(true) {
        int exception_pending = cpu->step();
 
        cpu->report();
        shared_ptr->proc_vmips.report.counter     = event_counter;
        shared_ptr->proc_vmips.report.exception   = (exception_pending > 0)? 1 : 0;
 
        if(cpu->was_delayed_transfer && exception_pending == 0) shared_ptr->proc_vmips.report.state.pc = cpu->was_delayed_pc;
 
        shared_ptr->proc_vmips.report_do = true;
 
        while(shared_ptr->proc_vmips.report_do) usleep_or_finish();
 
        event_counter++;
    }
    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.