use anyhow::Result;
use clap::Args;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use std::path::PathBuf;
use std::time::Duration;
use crate::app::TransportWrapper;
use crate::debug::openocd::OpenOcd;
use crate::dif::lc_ctrl::LcCtrlReg;
use crate::impl_serializable_error;
#[derive(Debug, Args, Clone)]
pub struct JtagParams {
#[arg(long, default_value = "openocd")]
pub openocd: PathBuf,
#[arg(long, default_value = "1000")]
pub adapter_speed_khz: u64,
#[arg(long, default_value = "false")]
pub log_stdio: bool,
}
impl JtagParams {
pub fn create<'t>(&self, transport: &'t TransportWrapper) -> Result<Box<dyn JtagChain + 't>> {
let jtag = transport.jtag(self)?;
Ok(jtag)
}
}
#[derive(Error, Debug, Deserialize, Serialize)]
pub enum JtagError {
#[error("Operation not valid on selected JTAG TAP: {0:?}")]
Tap(JtagTap),
#[error("JTAG timeout")]
Timeout,
#[error("JTAG busy")]
Busy,
#[error("Generic error {0}")]
Generic(String),
}
impl_serializable_error!(JtagError);
pub trait JtagChain {
fn connect(self: Box<Self>, tap: JtagTap) -> Result<Box<dyn Jtag>>;
fn into_raw(self: Box<Self>) -> Result<OpenOcd>;
}
pub trait Jtag {
fn into_raw(self: Box<Self>) -> Result<OpenOcd>;
fn as_raw(&mut self) -> Result<&mut OpenOcd>;
fn disconnect(self: Box<Self>) -> Result<()>;
fn tap(&self) -> JtagTap;
fn read_lc_ctrl_reg(&mut self, reg: &LcCtrlReg) -> Result<u32>;
fn write_lc_ctrl_reg(&mut self, reg: &LcCtrlReg, value: u32) -> Result<()>;
fn read_memory(&mut self, addr: u32, buf: &mut [u8]) -> Result<usize>;
fn read_memory32(&mut self, addr: u32, buf: &mut [u32]) -> Result<usize>;
fn write_memory(&mut self, addr: u32, buf: &[u8]) -> Result<()>;
fn write_memory32(&mut self, addr: u32, buf: &[u32]) -> Result<()>;
fn halt(&mut self) -> Result<()>;
fn wait_halt(&mut self, timeout: Duration) -> Result<()>;
fn resume(&mut self) -> Result<()>;
fn resume_at(&mut self, addr: u32) -> Result<()>;
fn step(&mut self) -> Result<()>;
fn step_at(&mut self, addr: u32) -> Result<()>;
fn reset(&mut self, run: bool) -> Result<()>;
fn read_riscv_reg(&mut self, reg: &RiscvReg) -> Result<u32>;
fn write_riscv_reg(&mut self, reg: &RiscvReg, val: u32) -> Result<()>;
fn set_breakpoint(&mut self, addr: u32, hw: bool) -> Result<()>;
fn remove_breakpoint(&mut self, addr: u32) -> Result<()>;
fn remove_all_breakpoints(&mut self) -> Result<()>;
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
pub enum JtagTap {
RiscvTap,
LcTap,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
#[strum(serialize_all = "lowercase")]
pub enum RiscvGpr {
RA,
SP,
GP,
TP,
T0,
T1,
T2,
FP,
S1,
A0,
A1,
A2,
A3,
A4,
A5,
A6,
A7,
S2,
S3,
S4,
S5,
S6,
S7,
S8,
S9,
S10,
S11,
T3,
T4,
T5,
T6,
}
impl RiscvGpr {
pub fn name(self) -> &'static str {
self.into()
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, strum::IntoStaticStr)]
#[strum(serialize_all = "lowercase")]
#[non_exhaustive]
pub enum RiscvCsr {
MSTATUS,
MISA,
MIE,
MTVEC,
MCOUNTINHIBIT,
MHPMEVENT3,
MHPMEVENT4,
MHPMEVENT5,
MHPMEVENT6,
MHPMEVENT7,
MHPMEVENT8,
MHPMEVENT9,
MHPMEVENT10,
MHPMEVENT11,
MHPMEVENT12,
MHPMEVENT13,
MHPMEVENT14,
MHPMEVENT15,
MHPMEVENT16,
MHPMEVENT17,
MHPMEVENT18,
MHPMEVENT19,
MHPMEVENT20,
MHPMEVENT21,
MHPMEVENT22,
MHPMEVENT23,
MHPMEVENT24,
MHPMEVENT25,
MHPMEVENT26,
MHPMEVENT27,
MHPMEVENT28,
MHPMEVENT29,
MHPMEVENT30,
MHPMEVENT31,
MSCRATCH,
MEPC,
MCAUSE,
MTVAL,
MIP,
PMPCFG0,
PMPCFG1,
PMPCFG2,
PMPCFG3,
PMPADDR0,
PMPADDR1,
PMPADDR2,
PMPADDR3,
PMPADDR4,
PMPADDR5,
PMPADDR6,
PMPADDR7,
PMPADDR8,
PMPADDR9,
PMPADDR10,
PMPADDR11,
PMPADDR12,
PMPADDR13,
PMPADDR14,
PMPADDR15,
SCONTEXT,
MSECCFG,
MSECCFGH,
TSELECT,
TDATA1,
TDATA2,
TDATA3,
MCONTEXT,
MSCONTEXT,
DCSR,
DPC,
DSCRATCH0,
DSCRATCH1,
MCYCLE,
MINSTRET,
MHPMCOUNTER3,
MHPMCOUNTER4,
MHPMCOUNTER5,
MHPMCOUNTER6,
MHPMCOUNTER7,
MHPMCOUNTER8,
MHPMCOUNTER9,
MHPMCOUNTER10,
MHPMCOUNTER11,
MHPMCOUNTER12,
MHPMCOUNTER13,
MHPMCOUNTER14,
MHPMCOUNTER15,
MHPMCOUNTER16,
MHPMCOUNTER17,
MHPMCOUNTER18,
MHPMCOUNTER19,
MHPMCOUNTER20,
MHPMCOUNTER21,
MHPMCOUNTER22,
MHPMCOUNTER23,
MHPMCOUNTER24,
MHPMCOUNTER25,
MHPMCOUNTER26,
MHPMCOUNTER27,
MHPMCOUNTER28,
MHPMCOUNTER29,
MHPMCOUNTER30,
MHPMCOUNTER31,
MCYCLEH,
MINSTRETH,
MHPMCOUNTER3H,
MHPMCOUNTER4H,
MHPMCOUNTER5H,
MHPMCOUNTER6H,
MHPMCOUNTER7H,
MHPMCOUNTER8H,
MHPMCOUNTER9H,
MHPMCOUNTER10H,
MHPMCOUNTER11H,
MHPMCOUNTER12H,
MHPMCOUNTER13H,
MHPMCOUNTER14H,
MHPMCOUNTER15H,
MHPMCOUNTER16H,
MHPMCOUNTER17H,
MHPMCOUNTER18H,
MHPMCOUNTER19H,
MHPMCOUNTER20H,
MHPMCOUNTER21H,
MHPMCOUNTER22H,
MHPMCOUNTER23H,
MHPMCOUNTER24H,
MHPMCOUNTER25H,
MHPMCOUNTER26H,
MHPMCOUNTER27H,
MHPMCOUNTER28H,
MHPMCOUNTER29H,
MHPMCOUNTER30H,
MHPMCOUNTER31H,
MVENDORID,
MARCHID,
MIMPID,
MHARTID,
#[strum(serialize = "csr_cpuctrl")]
CPUCTRL,
#[strum(serialize = "csr_secureseed")]
SECURESEED,
}
impl RiscvCsr {
pub fn name(self) -> &'static str {
self.into()
}
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum RiscvReg {
Gpr(RiscvGpr),
Csr(RiscvCsr),
}
impl RiscvReg {
pub fn name(self) -> &'static str {
match self {
Self::Gpr(gpr) => gpr.name(),
Self::Csr(csr) => csr.name(),
}
}
}
impl From<RiscvGpr> for RiscvReg {
fn from(gpr: RiscvGpr) -> Self {
Self::Gpr(gpr)
}
}
impl From<RiscvCsr> for RiscvReg {
fn from(csr: RiscvCsr) -> Self {
Self::Csr(csr)
}
}