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

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [sim/] [aoR3000/] [main_tester.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 <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
 
#include "VaoR3000.h"
#include "VaoR3000_aoR3000.h"
#include "VaoR3000_pipeline_rf.h"
#include "VaoR3000_pipeline_if.h"
#include "VaoR3000_pipeline_mem.h"
#include "VaoR3000_block_muldiv.h"
#include "VaoR3000_memory_tlb_ram.h"
#include "VaoR3000_block_cp0.h"
#include "VaoR3000_pipeline_exe.h"
#include "VaoR3000_model_true_dual_ram__W32_WB4.h"
#include "VaoR3000_model_simple_dual_ram__W20_WB5.h"
 
#include "verilated.h"
#include "verilated_vcd_c.h"
 
#include "shared_mem.h"
 
//------------------------------------------------------------------------------
 
volatile shared_mem_t *shared_ptr = NULL;
 
//------------------------------------------------------------------------------
 
#define GET(field, mask) \
    (shared_ptr->initial.field & mask)
 
void initialize(VaoR3000 *top) {
 
    top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[0] = top->v->pipeline_rf_inst->regs_b_inst->__PVT__mem[0] = 0;
    for(int i=1; i<32; i++) top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[i] = top->v->pipeline_rf_inst->regs_b_inst->__PVT__mem[i] = GET(reg[i-1], 0xFFFFFFFF);
 
    top->v->pipeline_if_inst->__PVT__exc_start_pc           = GET(pc, 0xFFFFFFFF);
    //not compared: top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__hi = GET(hi, 0xFFFFFFFF);
    //not compared: top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__lo = GET(lo, 0xFFFFFFFF);
 
    for(int i=0; i<64; i++) {
/*
[19:0]  vpn
[39:20] pfn
[45:40] asid
[46]    n noncachable
[47]    d dirty = write-enable
[48]    v valid
[49]    g global
*/
        uint64 entry = 0;
        entry |= (uint64)(GET(tlb[i].vpn, 0xFFFFF)) << 0;
        entry |= (uint64)(GET(tlb[i].asid, 0x3F))   << 40;
        entry |= (uint64)(GET(tlb[i].pfn, 0xFFFFF)) << 20;
        entry |= (uint64)(GET(tlb[i].n,   0x1))     << 46;
        entry |= (uint64)(GET(tlb[i].d,   0x1))     << 47;
        entry |= (uint64)(GET(tlb[i].v,   0x1))     << 48;
        entry |= (uint64)(GET(tlb[i].g,   0x1))     << 49;
 
        if((i % 8) == 0) top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[i/8]     = entry;
        if((i % 8) == 1) top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[8+(i/8)] = entry;
        if((i % 8) == 2) top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[i/8]     = entry;
        if((i % 8) == 3) top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[8+(i/8)] = entry;
        if((i % 8) == 4) top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[i/8]     = entry;
        if((i % 8) == 5) top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[8+(i/8)] = entry;
        if((i % 8) == 6) top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[i/8]     = entry;
        if((i % 8) == 7) top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[8+(i/8)] = entry;
    }
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_probe   = GET(index_p, 0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlbr_index  = GET(index_index, 0x3F);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_random  = GET(random, 0x3F);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn = GET(entrylo_pfn, 0xFFFFF);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n   = GET(entrylo_n,   0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d   = GET(entrylo_d,   0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v   = GET(entrylo_v,   0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g   = GET(entrylo_g,   0x1);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_ptebase = GET(context_ptebase, 0x7FF);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_badvpn  = GET(context_badvpn,  0x7FFFF);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__badvaddr    = GET(bad_vaddr, 0xFFFFFFFF);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn  = GET(entryhi_vpn, 0xFFFFF);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid = GET(entryhi_asid, 0x3F);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_coproc_usable     = GET(sr_cp_usable,     0xF);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_reverse_endian    = GET(sr_rev_endian,    0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_bev               = GET(sr_bootstrap_vec, 0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_tlb_shutdown      = GET(sr_tlb_shutdown,  0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_error      = GET(sr_parity_err,    0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_cm                = GET(sr_cache_miss,    0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_zero       = GET(sr_parity_zero,   0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_switch_caches = GET(sr_switch_cache,  0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_isolate_cache = GET(sr_isolate_cache, 0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_im                = GET(sr_irq_mask,      0xFF);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_ku_ie             = GET(sr_ku_ie,         0x3F);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_bd          = GET(cause_branch_delay, 0x1);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ce          = GET(cause_cp_error,     0x3);
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ip_writable = GET(cause_irq_pending,  0x3); //only 2 lowest bits
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_exccode     = GET(cause_exc_code,     0x1F);
 
    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__epc = GET(epc, 0xFFFFFFFF);
}
 
//------------------------------------------------------------------------------
 
#define PUT(field, val, mask) \
    shared_ptr->proc_ao.report.state.field = (val) & mask
 
void report(VaoR3000 *top, bool is_cp0_update, bool is_tlbr) {
 
    for(int i=1; i<32; i++) PUT(reg[i-1], top->v->pipeline_rf_inst->regs_a_inst->__PVT__mem[i], 0xFFFFFFFF);
 
    PUT(pc, top->v->pipeline_if_inst->__PVT__if_pc,                  0xFFFFFFFF);
    //not compared: PUT(hi, top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__hi, 0xFFFFFFFF);
    //not compared: PUT(lo, top->v->pipeline_mem_inst->block_muldiv_inst->__PVT__lo, 0xFFFFFFFF);
 
    if(is_tlbr) {
        PUT(entrylo_pfn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn, 0xFFFFF);
        PUT(entrylo_n,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n,   0x1);
        PUT(entrylo_d,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d,   0x1);
        PUT(entrylo_v,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v,   0x1);
        PUT(entrylo_g,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g,   0x1);
 
        PUT(entryhi_vpn,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn,  0xFFFFF);
        PUT(entryhi_asid, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid, 0x3F);
    }
 
    if(is_cp0_update == false) return;
 
    for(int i=0; i<64; i++) {
        uint64 entry = 0;
        if((i % 8) == 0) entry = top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[i/8];
        if((i % 8) == 1) entry = top->v->memory_tlb_ram_inst->tlb0_inst->__PVT__mem[8+(i/8)];
        if((i % 8) == 2) entry = top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[i/8];
        if((i % 8) == 3) entry = top->v->memory_tlb_ram_inst->tlb1_inst->__PVT__mem[8+(i/8)];
        if((i % 8) == 4) entry = top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[i/8];
        if((i % 8) == 5) entry = top->v->memory_tlb_ram_inst->tlb2_inst->__PVT__mem[8+(i/8)];
        if((i % 8) == 6) entry = top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[i/8];
        if((i % 8) == 7) entry = top->v->memory_tlb_ram_inst->tlb3_inst->__PVT__mem[8+(i/8)];
/*
[19:0]  vpn
[39:20] pfn
[45:40] asid
[46]    n noncachable
[47]    d dirty = write-enable
[48]    v valid
[49]    g global
*/
        PUT(tlb[i].vpn,  entry >> 0,  0xFFFFF);
        PUT(tlb[i].asid, entry >> 40, 0x3F);
 
        PUT(tlb[i].pfn,  entry >> 20, 0xFFFFF);
        PUT(tlb[i].n,    entry >> 46, 0x1);
        PUT(tlb[i].d,    entry >> 47, 0x1);
        PUT(tlb[i].v,    entry >> 48, 0x1);
        PUT(tlb[i].g,    entry >> 49, 0x1);
    }
 
    PUT(index_p,     top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_probe,  0x1);
    PUT(index_index, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlbr_index, 0x3F);
 
    PUT(random, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_random, 0x3F);
 
    PUT(entrylo_pfn, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_pfn, 0xFFFFF);
    PUT(entrylo_n,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_n,   0x1);
    PUT(entrylo_d,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_d,   0x1);
    PUT(entrylo_v,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_v,   0x1);
    PUT(entrylo_g,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entrylo_g,   0x1);
 
    PUT(context_ptebase, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_ptebase, 0x7FF);
    PUT(context_badvpn,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__tlb_badvpn,  0x7FFFF);
 
    PUT(bad_vaddr, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__badvaddr, 0xFFFFFFFF);
 
    PUT(entryhi_vpn,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_vpn,  0xFFFFF);
    PUT(entryhi_asid, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__entryhi_asid, 0x3F);
 
    PUT(sr_cp_usable,     top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_coproc_usable,     0xF);
    PUT(sr_rev_endian,    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_reverse_endian,    0x1);
    PUT(sr_bootstrap_vec, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_bev,               0x1);
    PUT(sr_tlb_shutdown,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_tlb_shutdown,      0x1);
    PUT(sr_parity_err,    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_error,      0x1);
    PUT(sr_cache_miss,    top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_cm,                0x1);
    PUT(sr_parity_zero,   top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_parity_zero,       0x1);
    PUT(sr_switch_cache,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_switch_caches, 0x1);
    PUT(sr_isolate_cache, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__config_isolate_cache, 0x1);
    PUT(sr_irq_mask,      top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_im,                0xFF);
    PUT(sr_ku_ie,         top->v->pipeline_mem_inst->block_cp0_inst->__PVT__sr_ku_ie,             0x3F);
 
    PUT(cause_branch_delay, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_bd,          0x1);
    PUT(cause_cp_error,     top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ce,          0x3);
    PUT(cause_irq_pending,  top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_ip_writable, 0x3); //only 2 lowest bits
    PUT(cause_exc_code,     top->v->pipeline_mem_inst->block_cp0_inst->__PVT__cause_exccode,     0x1F);
 
    PUT(epc, top->v->pipeline_mem_inst->block_cp0_inst->__PVT__epc, 0xFFFFFFFF);
}
 
//------------------------------------------------------------------------------
 
void usleep_or_finish() {
    if(shared_ptr->test_finished) {
        printf("Finishing.\n");
        exit(0);
    }
    usleep(1);
}
 
//------------------------------------------------------------------------------
 
int main(int argc, char **argv) {
 
    //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;
    }
 
    //--------------------------------------------------------------------------
 
    Verilated::commandArgs(argc, argv);
 
    Verilated::traceEverOn(true);
    VerilatedVcdC* tracer = new VerilatedVcdC;
 
    VaoR3000 *top = new VaoR3000();
    top->trace (tracer, 99);
    //tracer->rolloverMB(1000000);
    tracer->open("aoR3000.vcd");
 
    bool dump_enabled = true;
 
    //reset
    vluint64_t halfcycle = 0;
 
    top->clk = 0; top->rst_n = 1; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++;
    top->clk = 0; top->rst_n = 0; top->eval(); if(dump_enabled) { tracer->dump(halfcycle); } halfcycle++;
    top->rst_n = 1;
 
    printf("Waiting for initialize..."); fflush(stdout);
    while(shared_ptr->proc_ao.initialize_do == false) usleep_or_finish();
 
    initialize(top);
    shared_ptr->proc_ao.initialize_do = false;
    printf("done\n");
 
 
    //--------------------------------------------------------------------------
 
    uint32 event_counter = 0;
 
    struct read_t {
        uint32 count;
        uint32 byteenable;
        uint32 address;
    };
    read_t read[5];
    uint32 read_list_count = sizeof(read) / sizeof(read_t);
    memset(read, 0, sizeof(read));
 
    bool   stall_wait = false;
    uint32 stall_pc = 0;
    uint32 stall_branched = 0;   
    bool   stall_state = false;
 
    while(!Verilated::gotFinish()) {
 
        //---------------------------------------------------------------------- avalon master
 
        top->avm_waitrequest   = 0;
        top->avm_readdatavalid = 0;
        top->avm_readdata      = 0;
 
        if(top->avm_read) {
            bool found = false;
            for(uint32 i=0; i<read_list_count; i++) {
                if(read[i].count == 0) {
                    read[i].address    = top->avm_address & 0xFFFFFFFC;
                    read[i].byteenable = top->avm_byteenable;
                    read[i].count      = top->avm_burstcount;
 
                    found = true;
                    break;
                }
            }
            if(found == false) {
                printf("[aoR3000]: read fatal error: too many reads.\n");
                exit(-1);
            }
        }
        else if(read[0].count > 0) {
            top->avm_readdatavalid = 1;
 
            if(read[0].address < 0x08000000) {
                top->avm_readdata = shared_ptr->mem.ints[read[0].address/4];
            }
            else {
                shared_ptr->proc_ao.read_address    = read[0].address & 0xFFFFFFFC;
                shared_ptr->proc_ao.read_byteenable = read[0].byteenable;
                shared_ptr->proc_ao.read_do         = true;
 
                while(shared_ptr->proc_ao.read_do) usleep_or_finish();
 
                top->avm_readdata = shared_ptr->proc_ao.read_data;
            }
            read[0].address += 4;
            read[0].count--;
 
            if(read[0].count == 0) {
                memmove(&read[0], &read[1], sizeof(read) - sizeof(read_t));
            }
        }
 
        //----------------------------------------------------------------------
 
        uint32 cmd = top->v->pipeline_mem_inst->__PVT__mem_cmd & 0x7F;
 
        bool stall_start = cmd != 0   && stall_state == true;
        bool stall_end   = stall_wait && stall_state == false;
 
        uint32 was_instruction = ((cmd != 0) && stall_state == false) || stall_end;
        uint32 was_pc          = top->v->pipeline_mem_inst->__PVT__mem_pc_plus4;
 
        if(stall_start) {
            stall_wait = true;
            stall_pc = was_pc;
        }
        else if(stall_end) {
            stall_wait = false;
        }
 
        stall_state = (top->v->pipeline_mem_inst->__PVT__mem_stall & 1) != 0;
 
        report(top, true, false);
 
        //---------------------------------------------------------------------- interrupt
 
        top->interrupt_vector = (was_instruction && shared_ptr->irq2_at_event == (event_counter + 1))? 0x1 : 0;
 
        //---------------------------------------------------------------------- clock
        top->clk = 0;
        top->eval();
 
        if(dump_enabled) tracer->dump(halfcycle);
        halfcycle++;
 
        top->clk = 1;
        top->eval();
 
        if(dump_enabled) tracer->dump(halfcycle);
        halfcycle++;
 
        tracer->flush();
 
        //----------------------------------------------------------------------
        if(top->avm_write) {
            if(top->avm_burstcount != 1) {
                printf("[avalon master error]: top->avm_burstcount(%d) != 1\n", top->avm_burstcount);
                exit(-1);
            }
 
            uint32 mask = 0;
            uint32 byteena = top->avm_byteenable;
            for(uint32 i=0; i<4; i++) {
                if(byteena & 1) mask |= (0xFF << (i*8));
                byteena >>= 1;
            }
 
            shared_ptr->proc_ao.write_address    = top->avm_address & 0xFFFFFFFC;
            shared_ptr->proc_ao.write_byteenable = top->avm_byteenable;
            shared_ptr->proc_ao.write_data       = top->avm_writedata & mask;
            shared_ptr->proc_ao.write_do         = true;
 
            while(shared_ptr->proc_ao.write_do) usleep_or_finish();
        }
 
        uint32 is_exception = top->v->pipeline_if_inst->__PVT__exc_waiting & 1;
 
        if((is_exception && (event_counter > 0 || halfcycle >= (4*2))) || was_instruction) {
 
            was_pc       = (stall_end)? stall_pc       : was_pc;
 
            report(top, is_exception, cmd == 40); //TLBR
            shared_ptr->proc_ao.report.counter     = event_counter;
            shared_ptr->proc_ao.report.exception   = (is_exception)? 1 : 0;
 
            if(is_exception)    PUT(pc, top->v->pipeline_if_inst->__PVT__exc_start_pc, 0xFFFFFFFF);
            else                PUT(pc, was_pc, 0xFFFFFFFF);
 
            shared_ptr->proc_ao.report_do = true;
 
            while(shared_ptr->proc_ao.report_do) usleep_or_finish();
 
            event_counter++;
        }
    }
 
    top->final();
    delete top;
    return 0;
}
 
//------------------------------------------------------------------------------
 
/*
module aoR3000(
    input               clk,
    input               rst_n,
 
    //
    input       [5:0]   interrupt_vector,
 
    //
    output      [31:0]  avm_address,
    output      [31:0]  avm_writedata,
    output      [3:0]   avm_byteenable,
    output      [2:0]   avm_burstcount,
    output              avm_write,
    output              avm_read,
 
    input               avm_waitrequest,
    input               avm_readdatavalid,
    input       [31:0]  avm_readdata
);
*/
 
//------------------------------------------------------------------------------
 

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.