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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [tests/] [jtag/] [JTAGCPU.cpp] - Rev 2

Compare with Previous | Blame | View Log

// Copyright Jamie Iles, 2017
//
// This file is part of s80x86.
//
// s80x86 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// s80x86 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with s80x86.  If not, see <http://www.gnu.org/licenses/>.
 
#include <iostream>
#include <stdexcept>
#include <unistd.h>
 
#include <fstream>
#include "JTAGCPU.h"
 
extern "C" {
#include <jtag.h>
}
 
enum StatusControlBits {
    STATUS_CONTROL_RUN = (1 << 0),
    STATUS_CONTROL_RESET = (1 << 1),
    STATUS_CONTROL_WR_EN = (1 << 16),
};
 
union reg_converter {
    uint16_t v16;
    uint8_t v8[2];
};
 
using JTAGError = std::runtime_error;
 
JTAGCPU::JTAGCPU(const std::string &test_name) : test_name(test_name)
{
    if (jtag_open_virtual_device(0x00))
        throw JTAGError("Failed to open Virtual JTAG");
 
    write_scr(0);
    while (read_scr() & STATUS_CONTROL_RUN)
        continue;
}
 
JTAGCPU::~JTAGCPU()
{
    write_scr(STATUS_CONTROL_RUN);
    debug_run_proc(0, false);
    while (!(read_scr() & STATUS_CONTROL_RUN))
        continue;
}
 
void JTAGCPU::write_scr(uint16_t v)
{
    if (jtag_vir(1))
        throw JTAGError("Unable to write VIR");
    if (jtag_vdr(17, STATUS_CONTROL_WR_EN | v, NULL))
        throw JTAGError("Unable to write VIR");
}
 
uint16_t JTAGCPU::read_scr()
{
    uint32_t v;
 
    if (jtag_vir(1))
        throw JTAGError("Unable to write VIR");
    if (jtag_vdr(17, 0, &v))
        throw JTAGError("Unable to read VIR");
 
    return static_cast<uint16_t>(v);
}
 
uint16_t JTAGCPU::debug_read_data()
{
    uint32_t v;
 
    if (jtag_vir(2))
        throw JTAGError("Unable to write VIR");
 
    do {
        if (jtag_vdr(17, 0, &v))
            throw JTAGError("Unable to write VIR");
    } while (!(v & (1 << 16)));
 
    return static_cast<uint16_t>(v);
}
 
uint16_t JTAGCPU::debug_run_proc(unsigned addr, bool block)
{
    if (jtag_vir(3))
        throw JTAGError("Unable to write VIR");
    if (jtag_vdr(8, addr, NULL))
        throw JTAGError("Unable to write VIR");
 
    if (!block)
        return 0;
 
    while (read_scr() & STATUS_CONTROL_RUN)
        continue;
 
    return debug_read_data();
}
 
void JTAGCPU::debug_step()
{
    debug_run_proc(0x00);
}
 
void JTAGCPU::reset()
{
    write_scr(STATUS_CONTROL_RESET);
    write_scr(0);
    while (read_scr() & STATUS_CONTROL_RUN)
        continue;
 
    // All interrupts offset by 8 to not conflict with reserved vectors.
    write_io8(0xfff5, 8);
}
 
void JTAGCPU::write_reg(GPR regnum, uint16_t val)
{
    if (regnum == IP)
        write_ip(val);
    else if (regnum >= ES && regnum <= DS)
        write_sr(regnum, val);
    else
        write_gpr(regnum, val);
}
 
void JTAGCPU::write_sr(GPR regnum, uint16_t val)
{
    debug_write_data(val);
    debug_run_proc(0x13 + static_cast<int>(regnum));
}
 
void JTAGCPU::debug_write_data(uint16_t val)
{
    if (jtag_vir(2))
        throw JTAGError("Unable to write VIR");
    if (jtag_vdr(17, (1 << 16) | val, NULL))
        throw JTAGError("Unable to write VIR");
}
 
void JTAGCPU::write_ip(uint16_t val)
{
    debug_write_data(val);
    debug_run_proc(0x11);
}
 
void JTAGCPU::write_gpr(GPR regnum, uint16_t val)
{
    if (regnum < NUM_16BIT_REGS) {
        debug_write_data(val);
        debug_run_proc(0x13 + static_cast<int>(regnum));
    } else {
        auto regsel = (regnum - AL) & 0x3;
        reg_converter conv;
        conv.v16 = this->read_reg(static_cast<GPR>(regsel));
 
        conv.v8[regnum >= AH] = val;
 
        debug_write_data(conv.v16);
        debug_run_proc(0x13 + static_cast<int>(regsel));
    }
}
 
uint16_t JTAGCPU::read_reg(GPR regnum) const
{
    if (regnum == IP)
        return const_cast<JTAGCPU *>(this)->read_ip();
    else if (regnum >= ES && regnum <= DS)
        return const_cast<JTAGCPU *>(this)->read_sr(regnum);
    else
        return const_cast<JTAGCPU *>(this)->read_gpr(regnum);
}
 
uint16_t JTAGCPU::read_ip()
{
    return debug_run_proc(0x0f);
}
 
uint16_t JTAGCPU::read_gpr(GPR regnum)
{
    if (regnum < NUM_16BIT_REGS)
        return debug_run_proc(0x03 + static_cast<int>(regnum));
 
    auto regsel = static_cast<int>(regnum - AL) & 0x3;
    reg_converter conv;
 
    conv.v16 = debug_run_proc(0x03 + static_cast<int>(regsel));
 
    return conv.v8[regnum >= AH];
}
 
uint16_t JTAGCPU::read_sr(GPR regnum)
{
    return debug_run_proc(0x03 + static_cast<int>(regnum));
}
 
size_t JTAGCPU::step()
{
    ++num_cycles;
 
    this->debug_step();
 
    return 0;
}
 
void JTAGCPU::write_flags(uint16_t val)
{
    debug_write_data(val);
    debug_run_proc(0x12);
}
 
uint16_t JTAGCPU::read_flags() const
{
    return const_cast<JTAGCPU *>(this)->debug_run_proc(0x10);
}
 
bool JTAGCPU::has_trapped()
{
    auto int_cs = read_mem16(0, VEC_INT + 2);
    auto int_ip = read_mem16(0, VEC_INT + 0);
 
    return read_sr(CS) == int_cs && read_ip() == int_ip;
}
 
void JTAGCPU::write_mem8(uint16_t segment, uint16_t addr, uint8_t val)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
    write_mar(addr);
    write_mdr(val);
    debug_run_proc(0x23); // Write mem 8
    write_reg(DS, prev_ds);
}
 
void JTAGCPU::write_mem16(uint16_t segment, uint16_t addr, uint16_t val)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
    write_mar(addr);
    write_mdr(val);
    debug_run_proc(0x24); // Write mem 16
    write_reg(DS, prev_ds);
}
 
void JTAGCPU::write_vector8(uint16_t segment,
                            uint16_t addr,
                            const std::vector<uint8_t> &v)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
 
    write_mar(addr);
    for (auto &b : v) {
        write_mdr(b);
        debug_run_proc(0x23); // Write mem 8
    }
 
    write_reg(DS, prev_ds);
}
 
void JTAGCPU::write_vector16(uint16_t segment,
                             uint16_t addr,
                             const std::vector<uint16_t> &v)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
 
    write_mar(addr);
    for (auto &b : v) {
        write_mdr(b);
        debug_run_proc(0x24); // Write mem 16
    }
 
    write_reg(DS, prev_ds);
}
 
void JTAGCPU::write_mem32(uint16_t segment, uint16_t addr, uint32_t val)
{
    write_mem16(segment, addr, val & 0xffff);
    write_mem16(segment, addr + 2, val >> 16);
}
 
void JTAGCPU::write_mar(uint16_t v)
{
    debug_write_data(v);
    debug_run_proc(0x1f);
}
 
void JTAGCPU::write_mdr(uint16_t v)
{
    debug_write_data(v);
    debug_run_proc(0x20);
}
 
uint8_t JTAGCPU::read_mem8(uint16_t segment, uint16_t addr)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
    write_mar(addr);
    uint8_t val = debug_run_proc(0x21); // Read mem 8
 
    write_reg(DS, prev_ds);
 
    return val;
}
 
uint16_t JTAGCPU::read_mem16(uint16_t segment, uint16_t addr)
{
    auto prev_ds = read_reg(DS);
 
    write_reg(DS, segment);
    write_mar(addr);
    uint16_t val = debug_run_proc(0x22); // Read mem 16
 
    write_reg(DS, prev_ds);
 
    return val;
}
 
uint32_t JTAGCPU::read_mem32(uint16_t segment, uint16_t addr)
{
    return read_mem16(segment, addr) |
           (static_cast<uint32_t>(read_mem16(segment, addr + 2)) << 16);
}
 
void JTAGCPU::write_io8(uint32_t addr, uint8_t val)
{
    write_mar(addr);
    write_mdr(val);
    debug_run_proc(0x27); // Write io 8
}
 
void JTAGCPU::write_io16(uint32_t addr, uint16_t val)
{
    write_mar(addr);
    write_mdr(val);
    debug_run_proc(0x28); // Write io 16
}
 
uint8_t JTAGCPU::read_io8(uint32_t addr)
{
    write_mar(addr);
    return debug_run_proc(0x25); // Read io 8
}
 
uint16_t JTAGCPU::read_io16(uint32_t addr)
{
    write_mar(addr);
    return debug_run_proc(0x26); // Read io 16
}
 
uint32_t JTAGCPU::idcode()
{
    uint32_t idcode = 0;
    jtag_vir(0);
    jtag_vdr(32, 0, &idcode);
 
    return idcode;
}
 

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.