probe_rs/architecture/riscv/
communication_interface.rs

1//! Debug Module Communication
2//!
3//! This module implements communication with a
4//! Debug Module, as described in the RISC-V debug
5//! specification v0.13.2 .
6
7use crate::architecture::riscv::dtm::dtm_access::DtmAccess;
8use crate::{
9    Error as ProbeRsError, architecture::riscv::*, config::Target, memory_mapped_bitfield_register,
10    probe::DeferredResultIndex,
11};
12use std::any::Any;
13use std::collections::HashMap;
14use std::ops::Range;
15
16/// Some error occurred when working with the RISC-V core.
17#[derive(thiserror::Error, Debug)]
18pub enum RiscvError {
19    /// An error occurred during transport
20    #[error("Error during transport")]
21    DtmOperationFailed,
22    /// DMI operation is in progress
23    #[error("Transport operation in progress")]
24    DtmOperationInProcess,
25    /// An error with operating the debug probe occurred.
26    #[error("Debug Probe Error")]
27    DebugProbe(#[from] DebugProbeError),
28    /// A timeout occurred during DMI access.
29    #[error("Timeout during DMI access.")]
30    Timeout,
31    /// An error occurred during the execution of an abstract command.
32    #[error("Error occurred during execution of an abstract command: {0:?}")]
33    AbstractCommand(AbstractCommandErrorKind),
34    /// The request for reset, resume or halt was not acknowledged.
35    #[error("The core did not acknowledge a request for reset, resume or halt")]
36    RequestNotAcknowledged,
37    /// This debug transport module (DTM) version is currently not supported.
38    #[error("The version '{0}' of the debug transport module (DTM) is currently not supported.")]
39    UnsupportedDebugTransportModuleVersion(u8),
40    /// This version of the debug module is not supported.
41    #[error("The version '{0:?}' of the debug module is currently not supported.")]
42    UnsupportedDebugModuleVersion(DebugModuleVersion),
43    /// The provided csr address was invalid/unsupported
44    #[error("CSR at address '{0:x}' is unsupported.")]
45    UnsupportedCsrAddress(u16),
46    /// The given program buffer register is not supported.
47    #[error("Program buffer register '{0}' is currently not supported.")]
48    UnsupportedProgramBufferRegister(usize),
49    /// The program buffer is too small for the supplied program.
50    #[error(
51        "Program buffer is too small for supplied program. Required: {required}, Actual: {actual}"
52    )]
53    ProgramBufferTooSmall {
54        /// The required size of the program buffer.
55        required: usize,
56        /// The actual size of the program buffer.
57        actual: usize,
58    },
59    /// Memory width larger than 32 bits is not supported yet.
60    #[error("Memory width larger than 32 bits is not supported yet.")]
61    UnsupportedBusAccessWidth(RiscvBusAccess),
62    /// An error during system bus access occurred.
63    #[error("Error using system bus")]
64    SystemBusAccess,
65    /// The given trigger type is not available for the address breakpoint.
66    #[error("Unexpected trigger type {0} for address breakpoint.")]
67    UnexpectedTriggerType(u32),
68    /// The connected target is not a RISC-V device.
69    #[error("Connected target is not a RISC-V device.")]
70    NoRiscvTarget,
71    /// The target does not support halt after reset.
72    #[error("The target does not support halt after reset.")]
73    ResetHaltRequestNotSupported,
74    /// The result index of a batched command is not available.
75    #[error("The requested data is not available due to a previous error.")]
76    BatchedResultNotAvailable,
77    /// The hart is unavailable
78    #[error("The requested hart is unavailable.")]
79    HartUnavailable,
80}
81
82impl From<RiscvError> for ProbeRsError {
83    fn from(err: RiscvError) -> Self {
84        match err {
85            RiscvError::DebugProbe(e) => e.into(),
86            other => ProbeRsError::Riscv(other),
87        }
88    }
89}
90
91/// Errors which can occur while executing an abstract command.
92#[derive(Debug)]
93pub enum AbstractCommandErrorKind {
94    /// An abstract command was executing
95    /// while command, `abstractcs`, or `abstractauto`
96    /// was written, or when one of the `data` or `progbuf`
97    /// registers was read or written. This status is only
98    /// written if `cmderr` contains 0.
99    Busy = 1,
100    /// The requested command is not supported
101    NotSupported = 2,
102    /// An exception occurred while executing the command (e.g. while executing the Program Buffer).
103    Exception = 3,
104    /// The abstract command couldn’t
105    /// execute because the hart wasn’t in the required
106    /// state (running/halted), or unavailable.
107    HaltResume = 4,
108    /// The abstract command failed due to a
109    /// bus error (e.g. alignment, access size, or timeout).
110    Bus = 5,
111    /// A reserved code. Should not occur.
112    _Reserved = 6,
113    /// The command failed for another reason.
114    Other = 7,
115}
116
117impl From<AbstractCommandErrorKind> for RiscvError {
118    fn from(err: AbstractCommandErrorKind) -> Self {
119        RiscvError::AbstractCommand(err)
120    }
121}
122
123impl AbstractCommandErrorKind {
124    fn parse(status: Abstractcs) -> Result<(), Self> {
125        let err = match status.cmderr() {
126            0 => return Ok(()),
127            1 => Self::Busy,
128            2 => Self::NotSupported,
129            3 => Self::Exception,
130            4 => Self::HaltResume,
131            5 => Self::Bus,
132            6 => Self::_Reserved,
133            7 => Self::Other,
134            _ => unreachable!("cmderr is a 3 bit value, values higher than 7 should not occur."),
135        };
136
137        Err(err)
138    }
139}
140
141/// List of all debug module versions.
142///
143/// The version of the debug module can be read from the version field of the `dmstatus`
144/// register.
145#[derive(Debug, Copy, Clone, PartialEq, Eq)]
146pub enum DebugModuleVersion {
147    /// There is no debug module present.
148    NoModule,
149    /// The debug module conforms to the version 0.11 of the RISC-V Debug Specification.
150    Version0_11,
151    /// The debug module conforms to the version 0.13 of the RISC-V Debug Specification.
152    Version0_13,
153    /// The debug module is present, but does not conform to any available version of the RISC-V Debug Specification.
154    NonConforming,
155    /// Unknown debug module version.
156    Unknown(u8),
157}
158
159impl From<u8> for DebugModuleVersion {
160    fn from(raw: u8) -> Self {
161        match raw {
162            0 => Self::NoModule,
163            1 => Self::Version0_11,
164            2 => Self::Version0_13,
165            15 => Self::NonConforming,
166            other => Self::Unknown(other),
167        }
168    }
169}
170
171#[derive(Copy, Clone, Debug)]
172struct CoreRegisterAbstractCmdSupport(u8);
173
174impl CoreRegisterAbstractCmdSupport {
175    const READ: Self = Self(1 << 0);
176    const WRITE: Self = Self(1 << 1);
177    const BOTH: Self = Self(Self::READ.0 | Self::WRITE.0);
178
179    fn supports(&self, o: Self) -> bool {
180        self.0 & o.0 == o.0
181    }
182
183    fn unset(&mut self, o: Self) {
184        self.0 &= !(o.0);
185    }
186}
187
188/// Save stack of a scratch register.
189// TODO: we probably only need an Option, we don't seem to use scratch registers in nested situations.
190#[derive(Debug, Default)]
191struct ScratchState {
192    stack: Vec<u32>,
193}
194
195impl ScratchState {
196    fn push(&mut self, value: u32) {
197        self.stack.push(value);
198    }
199
200    fn pop(&mut self) -> Option<u32> {
201        self.stack.pop()
202    }
203}
204
205/// Describes the method which should be used to access memory.
206#[derive(Default, Debug)]
207pub struct MemoryAccessConfig {
208    /// Describes, which memory access method should be used for a given access width
209    default_method: HashMap<RiscvBusAccess, MemoryAccessMethod>,
210
211    region_override: HashMap<(Range<u64>, RiscvBusAccess), MemoryAccessMethod>,
212}
213
214impl MemoryAccessConfig {
215    /// Sets the default memory access method for the given access width.
216    pub fn set_default_method(&mut self, access: RiscvBusAccess, method: MemoryAccessMethod) {
217        self.default_method.insert(access, method);
218    }
219
220    /// Sets a memory access method override for the given access size and address range.
221    pub fn set_region_override(
222        &mut self,
223        access: RiscvBusAccess,
224        range: Range<u64>,
225        method: MemoryAccessMethod,
226    ) {
227        self.region_override.insert((range, access), method);
228    }
229
230    /// Returns the default memory access method for the given access width.
231    pub fn default_method(&self, access: RiscvBusAccess) -> MemoryAccessMethod {
232        self.default_method
233            .get(&access)
234            .copied()
235            .unwrap_or(MemoryAccessMethod::ProgramBuffer)
236    }
237
238    /// Returns the memory access method for the given address and access width.
239    pub fn method(&self, address: u64, access: RiscvBusAccess) -> MemoryAccessMethod {
240        for ((range, method_access), method) in &self.region_override {
241            if range.contains(&address) && method_access == &access {
242                return *method;
243            }
244        }
245
246        self.default_method(access)
247    }
248
249    /// Returns the memory access method for the given address range and access width.
250    pub fn range_method(
251        &self,
252        address_range: Range<u64>,
253        access: RiscvBusAccess,
254    ) -> MemoryAccessMethod {
255        fn range_overlaps(range: &Range<u64>, address_range: &Range<u64>) -> bool {
256            range.start < address_range.end && address_range.start < range.end
257        }
258
259        let mut max = self.default_method(access);
260
261        for ((range, method_access), method) in &self.region_override {
262            if range_overlaps(range, &address_range) && method_access == &access {
263                max = std::cmp::min(*method, max);
264            }
265        }
266
267        max
268    }
269}
270
271/// A state to carry all the state data across multiple core switches in a session.
272#[derive(Debug)]
273pub struct RiscvCommunicationInterfaceState {
274    /// Debug specification version
275    debug_version: DebugModuleVersion,
276
277    /// Size of the program buffer, in 32-bit words
278    progbuf_size: u8,
279
280    /// Cache for the program buffer.
281    progbuf_cache: [u32; 16],
282
283    /// Implicit `ebreak` instruction is present after the
284    /// the program buffer.
285    implicit_ebreak: bool,
286
287    /// Number of data registers for abstract commands
288    data_register_count: u8,
289
290    /// Number of scratch registers
291    nscratch: u8,
292
293    /// Whether the target supports autoexecuting the program buffer
294    supports_autoexec: bool,
295
296    /// Pointer to the configuration string
297    confstrptr: Option<u128>,
298
299    /// Width of the `hartsel` register
300    hartsellen: u8,
301
302    /// Number of harts
303    num_harts: u32,
304
305    /// describes, if the given register can be read / written with an
306    /// abstract command
307    abstract_cmd_register_info: HashMap<RegisterId, CoreRegisterAbstractCmdSupport>,
308
309    /// First scratch register's state
310    s0: ScratchState,
311
312    /// Second scratch register's state
313    s1: ScratchState,
314
315    /// Bitfield of enabled harts
316    enabled_harts: u32,
317
318    /// The index of the last selected hart
319    last_selected_hart: u32,
320
321    /// Store the value of the `hasresethaltreq` bit of the `dmstatus` register.
322    hasresethaltreq: Option<bool>,
323
324    /// Whether the core is currently halted.
325    is_halted: bool,
326
327    /// The current value of the `dmcontrol` register.
328    current_dmcontrol: Dmcontrol,
329
330    memory_access_config: MemoryAccessConfig,
331
332    sw_breakpoint_debug_enabled: bool,
333}
334
335/// Timeout for RISC-V operations.
336const RISCV_TIMEOUT: Duration = Duration::from_secs(5);
337
338/// RiscV only supports 12bit CSRs. See
339/// [Zicsr](https://riscv.org/wp-content/uploads/2019/06/riscv-spec.pdf#chapter.9) extension
340const RISCV_MAX_CSR_ADDR: u16 = 0xFFF;
341
342impl RiscvCommunicationInterfaceState {
343    /// Create a new interface state.
344    pub fn new() -> Self {
345        RiscvCommunicationInterfaceState {
346            // Set to the minimum here, will be set to the correct value below
347            progbuf_size: 0,
348            progbuf_cache: [0u32; 16],
349
350            debug_version: DebugModuleVersion::NonConforming,
351
352            // Assume the implicit ebreak is not present
353            implicit_ebreak: false,
354
355            // Set to the minimum here, will be set to the correct value below
356            data_register_count: 1,
357
358            nscratch: 0,
359
360            supports_autoexec: false,
361
362            confstrptr: None,
363
364            // Assume maximum value, will be determined exactly alter.
365            hartsellen: 20,
366
367            // We assume only a singe hart exisits initially
368            num_harts: 1,
369
370            abstract_cmd_register_info: HashMap::new(),
371
372            s0: ScratchState::default(),
373            s1: ScratchState::default(),
374            enabled_harts: 0,
375            last_selected_hart: 0,
376            hasresethaltreq: None,
377            is_halted: false,
378
379            current_dmcontrol: Dmcontrol(0),
380
381            memory_access_config: MemoryAccessConfig::default(),
382
383            sw_breakpoint_debug_enabled: false,
384        }
385    }
386
387    /// Get the memory access method which should be used for an
388    /// access with the specified width.
389    fn memory_access_method(
390        &mut self,
391        access_width: RiscvBusAccess,
392        address: u64,
393    ) -> MemoryAccessMethod {
394        self.memory_access_config.method(address, access_width)
395    }
396
397    fn memory_range_access_method(
398        &self,
399        width: RiscvBusAccess,
400        address_range: Range<u64>,
401    ) -> MemoryAccessMethod {
402        self.memory_access_config.range_method(address_range, width)
403    }
404}
405
406impl Default for RiscvCommunicationInterfaceState {
407    fn default() -> Self {
408        Self::new()
409    }
410}
411
412/// The combined state of a RISC-V debug module and its transport interface.
413pub struct RiscvDebugInterfaceState {
414    pub(super) interface_state: RiscvCommunicationInterfaceState,
415    pub(super) dtm_state: Box<dyn Any + Send>,
416}
417
418impl RiscvDebugInterfaceState {
419    pub(super) fn new(dtm_state: Box<dyn Any + Send>) -> Self {
420        Self {
421            interface_state: RiscvCommunicationInterfaceState::new(),
422            dtm_state,
423        }
424    }
425}
426
427/// A single-use factory for creating RISC-V communication interfaces and their states.
428pub trait RiscvInterfaceBuilder<'probe> {
429    /// Creates a new RISC-V communication interface state object.
430    ///
431    /// The state object needs to be stored separately from the communication interface
432    /// and can be used to restore the state of the interface at a later time.
433    fn create_state(&self) -> RiscvDebugInterfaceState;
434
435    /// Consumes the factory and creates a communication interface
436    /// object initialised with the given state.
437    fn attach<'state>(
438        self: Box<Self>,
439        state: &'state mut RiscvDebugInterfaceState,
440    ) -> Result<RiscvCommunicationInterface<'state>, DebugProbeError>
441    where
442        'probe: 'state;
443
444    /// Consumes the factory and creates a communication interface
445    /// object using a JTAG tunnel initialised with the given state.
446    fn attach_tunneled<'state>(
447        self: Box<Self>,
448        _tunnel_ir_id: u32,
449        _tunnel_ir_width: u32,
450        _state: &'state mut RiscvDebugInterfaceState,
451    ) -> Result<RiscvCommunicationInterface<'state>, DebugProbeError>
452    where
453        'probe: 'state,
454    {
455        Err(DebugProbeError::InterfaceNotAvailable {
456            interface_name: "Tunneled RISC-V",
457        })
458    }
459
460    /// Consumes the factory and creates a communication interface
461    /// object initialised with the given state.
462    ///
463    /// Automatically determines whether to use JTAG tunneling or not from the target.
464    fn attach_auto<'state>(
465        self: Box<Self>,
466        target: &Target,
467        state: &'state mut RiscvDebugInterfaceState,
468    ) -> Result<RiscvCommunicationInterface<'state>, DebugProbeError>
469    where
470        'probe: 'state,
471    {
472        let maybe_tunnel = target.jtag.as_ref().and_then(|j| j.riscv_tunnel.as_ref());
473        if let Some(tunnel) = maybe_tunnel {
474            self.attach_tunneled(tunnel.ir_id, tunnel.ir_width, state)
475        } else {
476            self.attach(state)
477        }
478    }
479}
480
481/// A interface that implements controls for RISC-V cores.
482#[derive(Debug)]
483pub struct RiscvCommunicationInterface<'state> {
484    /// The Debug Transport Module (DTM) is used to
485    /// communicate with the Debug Module on the target chip.
486    dtm: Box<dyn DtmAccess + 'state>,
487    state: &'state mut RiscvCommunicationInterfaceState,
488}
489
490impl<'state> RiscvCommunicationInterface<'state> {
491    /// Creates a new RISC-V communication interface with a given probe driver.
492    pub fn new(
493        dtm: Box<dyn DtmAccess + 'state>,
494        state: &'state mut RiscvCommunicationInterfaceState,
495    ) -> Self {
496        Self { dtm, state }
497    }
498
499    /// Select current hart
500    pub fn select_hart(&mut self, hart: u32) -> Result<(), RiscvError> {
501        if !self.hart_enabled(hart) {
502            return Err(RiscvError::HartUnavailable);
503        }
504
505        if self.state.last_selected_hart == hart {
506            return Ok(());
507        }
508
509        // Since we changed harts, we don't know the state of the Dmcontrol register anymore.
510        let mut control = self.read_dm_register::<Dmcontrol>()?;
511        control.set_dmactive(true);
512        control.set_hartsel(hart);
513        self.schedule_write_dm_register(control)?;
514        self.state.last_selected_hart = hart;
515        Ok(())
516    }
517
518    /// Check if the given hart is enabled
519    pub fn hart_enabled(&self, hart: u32) -> bool {
520        self.state.enabled_harts & (1 << hart) != 0
521    }
522
523    /// Assert the target reset
524    pub fn target_reset_assert(&mut self) -> Result<(), DebugProbeError> {
525        self.dtm.target_reset_assert()
526    }
527
528    /// Deassert the target reset.
529    pub fn target_reset_deassert(&mut self) -> Result<(), DebugProbeError> {
530        self.dtm.target_reset_deassert()
531    }
532
533    /// Read the targets idcode used as hint for chip detection
534    pub fn read_idcode(&mut self) -> Result<Option<u32>, DebugProbeError> {
535        self.dtm.read_idcode()
536    }
537
538    fn save_s0(&mut self) -> Result<bool, RiscvError> {
539        let s0 = self.abstract_cmd_register_read(&registers::S0)?;
540
541        self.state.s0.push(s0);
542
543        Ok(true)
544    }
545
546    fn restore_s0(&mut self, saved: bool) -> Result<(), RiscvError> {
547        if saved {
548            let s0 = self.state.s0.pop().unwrap();
549
550            self.abstract_cmd_register_write(&registers::S0, s0)?;
551        }
552
553        Ok(())
554    }
555
556    fn save_s1(&mut self) -> Result<bool, RiscvError> {
557        let s1 = self.abstract_cmd_register_read(&registers::S1)?;
558
559        self.state.s1.push(s1);
560
561        Ok(true)
562    }
563
564    fn restore_s1(&mut self, saved: bool) -> Result<(), RiscvError> {
565        if saved {
566            let s1 = self.state.s1.pop().unwrap();
567
568            self.abstract_cmd_register_write(&registers::S1, s1)?;
569        }
570
571        Ok(())
572    }
573
574    /// Enable the debug module on the target and detect which features
575    /// are supported.
576    pub fn enter_debug_mode(&mut self) -> Result<(), RiscvError> {
577        tracing::debug!("Building RISC-V interface");
578        self.dtm.init()?;
579
580        // Reset error bits from previous connections
581        self.dtm.clear_error_state()?;
582
583        // enable the debug module
584        let mut control = Dmcontrol(0);
585        control.set_dmactive(true);
586        self.schedule_write_dm_register(control)?;
587
588        // read the  version of the debug module
589        let status: Dmstatus = self.read_dm_register()?;
590
591        self.state.progbuf_cache.fill(0);
592        self.state.memory_access_config = MemoryAccessConfig::default();
593        self.state.debug_version = DebugModuleVersion::from(status.version() as u8);
594        self.state.is_halted = status.allhalted();
595
596        // Only version of 0.13 of the debug specification is currently supported.
597        if self.state.debug_version != DebugModuleVersion::Version0_13 {
598            return Err(RiscvError::UnsupportedDebugModuleVersion(
599                self.state.debug_version,
600            ));
601        }
602
603        self.state.implicit_ebreak = status.impebreak();
604
605        // check if the configuration string pointer is valid, and retrieve it, if valid
606        self.state.confstrptr = if status.confstrptrvalid() {
607            let confstrptr_0: Confstrptr0 = self.read_dm_register()?;
608            let confstrptr_1: Confstrptr1 = self.read_dm_register()?;
609            let confstrptr_2: Confstrptr2 = self.read_dm_register()?;
610            let confstrptr_3: Confstrptr3 = self.read_dm_register()?;
611            let confstrptr = (u32::from(confstrptr_0) as u128)
612                | ((u32::from(confstrptr_1) as u128) << 8)
613                | ((u32::from(confstrptr_2) as u128) << 16)
614                | ((u32::from(confstrptr_3) as u128) << 32);
615            Some(confstrptr)
616        } else {
617            None
618        };
619
620        tracing::debug!("dmstatus: {:?}", status);
621
622        // Select all harts to determine the width
623        // of the hartsel register.
624        let mut control = Dmcontrol(0);
625        control.set_dmactive(true);
626        control.set_hartsel(0xffff_ffff);
627
628        self.schedule_write_dm_register(control)?;
629
630        let control = self.read_dm_register::<Dmcontrol>()?;
631
632        self.state.hartsellen = control.hartsel().count_ones() as u8;
633
634        tracing::debug!("HARTSELLEN: {}", self.state.hartsellen);
635
636        // Determine number of harts
637
638        let max_hart_index = 2u32.pow(self.state.hartsellen as u32);
639
640        // Hart 0 exists on every chip
641        let mut num_harts = 1;
642        self.state.enabled_harts = 1;
643
644        // Check if anynonexistent is avaliable.
645        // Some chips that have only one hart do not implement anynonexistent and allnonexistent.
646        // So let's check max hart index to see if we can use it reliably,
647        // or else we will assume only one hart exists.
648        let mut control = Dmcontrol(0);
649        control.set_dmactive(true);
650        control.set_hartsel(max_hart_index - 1);
651        self.schedule_write_dm_register(control)?;
652
653        // Check if the anynonexistent works
654        let status: Dmstatus = self.read_dm_register()?;
655
656        if status.anynonexistent() {
657            for hart_index in 1..max_hart_index {
658                let mut control = Dmcontrol(0);
659                control.set_dmactive(true);
660                control.set_hartsel(hart_index);
661
662                self.schedule_write_dm_register(control)?;
663
664                // Check if the current hart exists
665                let status: Dmstatus = self.read_dm_register()?;
666
667                if status.anynonexistent() {
668                    break;
669                }
670
671                if !status.allunavail() {
672                    self.state.enabled_harts |= 1 << num_harts;
673                }
674
675                num_harts += 1;
676            }
677        } else {
678            tracing::debug!("anynonexistent not supported, assuming only one hart exists")
679        }
680
681        tracing::debug!("Number of harts: {}", num_harts);
682
683        self.state.num_harts = num_harts;
684
685        // Select hart 0 again - assuming all harts are same in regards of discovered features
686        let mut control = Dmcontrol(0);
687        control.set_dmactive(true);
688        control.set_hartsel(0);
689
690        self.schedule_write_dm_register(control)?;
691
692        // determine size of the program buffer, and number of data
693        // registers for abstract commands
694        let abstractcs: Abstractcs = self.read_dm_register()?;
695
696        self.state.progbuf_size = abstractcs.progbufsize() as u8;
697        tracing::debug!("Program buffer size: {}", self.state.progbuf_size);
698
699        self.state.data_register_count = abstractcs.datacount() as u8;
700        tracing::debug!(
701            "Number of data registers: {}",
702            self.state.data_register_count
703        );
704
705        // determine more information about hart
706        let hartinfo: Hartinfo = self.read_dm_register()?;
707
708        self.state.nscratch = hartinfo.nscratch() as u8;
709        tracing::debug!("Number of dscratch registers: {}", self.state.nscratch);
710
711        // determine if autoexec works
712        let mut abstractauto = Abstractauto(0);
713        abstractauto.set_autoexecprogbuf(2u32.pow(self.state.progbuf_size as u32) - 1);
714        abstractauto.set_autoexecdata(2u32.pow(self.state.data_register_count as u32) - 1);
715
716        self.schedule_write_dm_register(abstractauto)?;
717
718        let abstractauto_readback: Abstractauto = self.read_dm_register()?;
719
720        self.state.supports_autoexec = abstractauto_readback == abstractauto;
721        tracing::debug!("Support for autoexec: {}", self.state.supports_autoexec);
722
723        // clear abstractauto
724        abstractauto = Abstractauto(0);
725        self.schedule_write_dm_register(abstractauto)?;
726
727        // determine support system bus access
728        let sbcs = self.read_dm_register::<Sbcs>()?;
729
730        // Only version 1 is supported, this means that
731        // the system bus access conforms to the debug
732        // specification 13.2.
733        if sbcs.sbversion() == 1 {
734            // When possible, we use system bus access for memory access
735
736            if sbcs.sbaccess8() {
737                self.state
738                    .memory_access_config
739                    .set_default_method(RiscvBusAccess::A8, MemoryAccessMethod::SystemBus);
740            }
741
742            if sbcs.sbaccess16() {
743                self.state
744                    .memory_access_config
745                    .set_default_method(RiscvBusAccess::A16, MemoryAccessMethod::SystemBus);
746            }
747
748            if sbcs.sbaccess32() {
749                self.state
750                    .memory_access_config
751                    .set_default_method(RiscvBusAccess::A32, MemoryAccessMethod::SystemBus);
752            }
753
754            if sbcs.sbaccess64() {
755                self.state
756                    .memory_access_config
757                    .set_default_method(RiscvBusAccess::A64, MemoryAccessMethod::SystemBus);
758            }
759
760            if sbcs.sbaccess128() {
761                self.state
762                    .memory_access_config
763                    .set_default_method(RiscvBusAccess::A128, MemoryAccessMethod::SystemBus);
764            }
765        } else {
766            tracing::debug!(
767                "System bus interface version {} is not supported.",
768                sbcs.sbversion()
769            );
770        }
771
772        Ok(())
773    }
774
775    /// Disable debugging on the target.
776    pub fn disable_debug_module(&mut self) -> Result<(), RiscvError> {
777        self.debug_on_sw_breakpoint(false)?;
778
779        let mut control = Dmcontrol(0);
780        control.set_dmactive(false);
781        self.write_dm_register(control)?;
782
783        Ok(())
784    }
785
786    /// Halt all harts on the target.
787    pub fn halt(&mut self, timeout: Duration) -> Result<(), RiscvError> {
788        // Fast path.
789        // Try to do the halt, in a single step.
790        let mut dmcontrol = self.state.current_dmcontrol;
791        tracing::debug!(
792            "Before requesting halt, the Dmcontrol register value was: {:?}",
793            dmcontrol
794        );
795
796        dmcontrol.set_dmactive(true);
797        dmcontrol.set_haltreq(true);
798
799        self.schedule_write_dm_register(dmcontrol)?;
800
801        let result_status_idx = self.schedule_read_dm_register::<Dmstatus>()?;
802
803        // clear the halt request
804        dmcontrol.set_haltreq(false);
805        self.write_dm_register(dmcontrol)?;
806
807        let result_status = Dmstatus(self.dtm.read_deferred_result(result_status_idx)?.into_u32());
808
809        if result_status.allhalted() {
810            self.state.is_halted = true;
811            // Cores have halted, we have nothing else to do but return.
812            return Ok(());
813        }
814
815        // Not every core has halted in time. Let's do things slowly.
816
817        // set the halt request again
818        dmcontrol.set_haltreq(true);
819        self.write_dm_register(dmcontrol)?;
820
821        // Wait until halted state is active again.
822        self.wait_for_core_halted(timeout)?;
823
824        // clear the halt request
825        dmcontrol.set_haltreq(false);
826        self.write_dm_register(dmcontrol)?;
827
828        if !self.state.sw_breakpoint_debug_enabled {
829            self.debug_on_sw_breakpoint(true)?;
830        }
831
832        Ok(())
833    }
834
835    /// Halts the core and returns `true` if the core was running before the halt.
836    pub(crate) fn halt_with_previous(&mut self, timeout: Duration) -> Result<bool, RiscvError> {
837        let was_running = if self.state.is_halted {
838            // Core is already halted, we don't need to do anything.
839            false
840        } else {
841            // If we have not halted the core, it may still be halted on a breakpoint, for example.
842            // Let's check status.
843            let status_idx = self.schedule_read_dm_register::<Dmstatus>()?;
844            self.halt(timeout)?;
845            let before_status = Dmstatus(self.dtm.read_deferred_result(status_idx)?.into_u32());
846
847            !before_status.allhalted()
848        };
849
850        Ok(was_running)
851    }
852
853    pub(crate) fn core_info(&mut self) -> Result<CoreInformation, RiscvError> {
854        let pc: u64 = self
855            .read_csr(super::registers::PC.id().0)
856            .map(|v| v.into())?;
857
858        Ok(CoreInformation { pc })
859    }
860
861    /// Return whether or not the core is halted.
862    pub fn core_halted(&mut self) -> Result<bool, RiscvError> {
863        if !self.state.is_halted {
864            let dmstatus: Dmstatus = self.read_dm_register()?;
865
866            tracing::trace!("{:?}", dmstatus);
867
868            self.state.is_halted = dmstatus.allhalted();
869        }
870
871        Ok(self.state.is_halted)
872    }
873
874    pub(crate) fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), RiscvError> {
875        // Wait until halted state is active again.
876        let start = Instant::now();
877
878        while !self.core_halted()? {
879            if start.elapsed() >= timeout {
880                return Err(RiscvError::Timeout);
881            }
882            // Wait a bit before polling again.
883            std::thread::sleep(Duration::from_millis(1));
884        }
885
886        Ok(())
887    }
888
889    pub(crate) fn halted_access<R>(
890        &mut self,
891        op: impl FnOnce(&mut Self) -> Result<R, RiscvError>,
892    ) -> Result<R, RiscvError> {
893        let was_running = self.halt_with_previous(Duration::from_millis(100))?;
894
895        let result = op(self);
896
897        if was_running {
898            self.resume_core()?;
899        }
900
901        result
902    }
903
904    pub(super) fn read_csr(&mut self, address: u16) -> Result<u32, RiscvError> {
905        // We need to use the "Access Register Command",
906        // which has cmdtype 0
907
908        // write needs to be clear
909        // transfer has to be set
910
911        tracing::debug!("Reading CSR {:#x}", address);
912
913        // always try to read register with abstract command, fallback to program buffer,
914        // if not supported
915        match self.abstract_cmd_register_read(address) {
916            Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
917                tracing::debug!(
918                    "Could not read core register {:#x} with abstract command, falling back to program buffer",
919                    address
920                );
921                self.read_csr_progbuf(address)
922            }
923            other => other,
924        }
925    }
926
927    /// Schedules a DM register read, flushes the queue and returns the result.
928    pub fn read_dm_register<R: MemoryMappedRegister<u32>>(&mut self) -> Result<R, RiscvError> {
929        tracing::debug!(
930            "Reading DM register '{}' at {:#010x}",
931            R::NAME,
932            R::get_mmio_address()
933        );
934
935        let register_value = self.read_dm_register_untyped(R::get_mmio_address())?.into();
936
937        tracing::debug!(
938            "Read DM register '{}' at {:#010x} = {:x?}",
939            R::NAME,
940            R::get_mmio_address(),
941            register_value
942        );
943
944        Ok(register_value)
945    }
946
947    /// Schedules a DM register read, flushes the queue and returns the untyped result.
948    ///
949    /// Use the [`Self::read_dm_register()`] function if possible.
950    fn read_dm_register_untyped(&mut self, address: u64) -> Result<u32, RiscvError> {
951        let read_idx = self.schedule_read_dm_register_untyped(address)?;
952        let register_value = self.dtm.read_deferred_result(read_idx)?.into_u32();
953
954        Ok(register_value)
955    }
956
957    /// Schedules a DM register write and flushes the queue.
958    pub fn write_dm_register<R: MemoryMappedRegister<u32>>(
959        &mut self,
960        register: R,
961    ) -> Result<(), RiscvError> {
962        // write write command to dmi register
963
964        tracing::debug!(
965            "Write DM register '{}' at {:#010x} = {:x?}",
966            R::NAME,
967            R::get_mmio_address(),
968            register
969        );
970
971        self.write_dm_register_untyped(R::get_mmio_address(), register.into())
972    }
973
974    /// Write to a DM register
975    ///
976    /// Use the [`Self::write_dm_register()`] function if possible.
977    fn write_dm_register_untyped(&mut self, address: u64, value: u32) -> Result<(), RiscvError> {
978        self.cache_write(address, value);
979        self.dtm.write_with_timeout(address, value, RISCV_TIMEOUT)?;
980
981        Ok(())
982    }
983
984    fn cache_write(&mut self, address: u64, value: u32) {
985        if address == Dmcontrol::ADDRESS_OFFSET {
986            self.state.current_dmcontrol = Dmcontrol(value);
987        }
988    }
989
990    fn schedule_write_progbuf(&mut self, index: usize, value: u32) -> Result<(), RiscvError> {
991        match index {
992            0 => self.schedule_write_dm_register(Progbuf0(value)),
993            1 => self.schedule_write_dm_register(Progbuf1(value)),
994            2 => self.schedule_write_dm_register(Progbuf2(value)),
995            3 => self.schedule_write_dm_register(Progbuf3(value)),
996            4 => self.schedule_write_dm_register(Progbuf4(value)),
997            5 => self.schedule_write_dm_register(Progbuf5(value)),
998            6 => self.schedule_write_dm_register(Progbuf6(value)),
999            7 => self.schedule_write_dm_register(Progbuf7(value)),
1000            8 => self.schedule_write_dm_register(Progbuf8(value)),
1001            9 => self.schedule_write_dm_register(Progbuf9(value)),
1002            10 => self.schedule_write_dm_register(Progbuf10(value)),
1003            11 => self.schedule_write_dm_register(Progbuf11(value)),
1004            12 => self.schedule_write_dm_register(Progbuf12(value)),
1005            13 => self.schedule_write_dm_register(Progbuf13(value)),
1006            14 => self.schedule_write_dm_register(Progbuf14(value)),
1007            15 => self.schedule_write_dm_register(Progbuf15(value)),
1008            e => Err(RiscvError::UnsupportedProgramBufferRegister(e)),
1009        }
1010    }
1011
1012    pub(crate) fn schedule_setup_program_buffer(&mut self, data: &[u32]) -> Result<(), RiscvError> {
1013        let required_len = if self.state.implicit_ebreak {
1014            data.len()
1015        } else {
1016            data.len() + 1
1017        };
1018
1019        if required_len > self.state.progbuf_size as usize {
1020            return Err(RiscvError::ProgramBufferTooSmall {
1021                required: required_len,
1022                actual: self.state.progbuf_size as usize,
1023            });
1024        }
1025
1026        if data == &self.state.progbuf_cache[..data.len()] {
1027            // Check if we actually have to write the program buffer
1028            tracing::debug!("Program buffer is up-to-date, skipping write.");
1029            return Ok(());
1030        }
1031
1032        for (index, word) in data.iter().enumerate() {
1033            self.schedule_write_progbuf(index, *word)?;
1034        }
1035
1036        // Add manual ebreak if necessary.
1037        //
1038        // This is necessary when we either don't need the full program buffer,
1039        // or if there is no implict ebreak after the last program buffer word.
1040        if !self.state.implicit_ebreak || data.len() < self.state.progbuf_size as usize {
1041            self.schedule_write_progbuf(data.len(), assembly::EBREAK)?;
1042        }
1043
1044        // Update the cache
1045        self.state.progbuf_cache[..data.len()].copy_from_slice(data);
1046
1047        Ok(())
1048    }
1049
1050    /// Perform a single read from a memory location, using system bus access.
1051    fn perform_memory_read_sysbus<V: RiscvValue32>(
1052        &mut self,
1053        address: u32,
1054    ) -> Result<V, RiscvError> {
1055        let mut sbcs = Sbcs(0);
1056
1057        sbcs.set_sbaccess(V::WIDTH as u32);
1058        sbcs.set_sbreadonaddr(true);
1059
1060        self.schedule_write_dm_register(sbcs)?;
1061        self.schedule_write_dm_register(Sbaddress0(address))?;
1062
1063        let mut results = vec![];
1064        self.schedule_read_large_dtm_register::<V, Sbdata>(&mut results)?;
1065
1066        // Check that the read was succesful
1067        let sbcs = self.read_dm_register::<Sbcs>()?;
1068
1069        if sbcs.sberror() != 0 {
1070            Err(RiscvError::SystemBusAccess)
1071        } else {
1072            V::read_scheduled_result(self, &mut results)
1073        }
1074    }
1075
1076    /// Perform multiple reads from consecutive memory locations
1077    /// using system bus access.
1078    /// Only reads up to a width of 32 bits are currently supported.
1079    fn perform_memory_read_multiple_sysbus<V: RiscvValue32>(
1080        &mut self,
1081        address: u32,
1082        data: &mut [V],
1083    ) -> Result<(), RiscvError> {
1084        if data.is_empty() {
1085            return Ok(());
1086        }
1087
1088        let mut sbcs = Sbcs(0);
1089
1090        sbcs.set_sbaccess(V::WIDTH as u32);
1091
1092        sbcs.set_sbreadonaddr(true);
1093
1094        sbcs.set_sbreadondata(true);
1095        sbcs.set_sbautoincrement(true);
1096
1097        self.schedule_write_dm_register(sbcs)?;
1098
1099        self.schedule_write_dm_register(Sbaddress0(address))?;
1100
1101        let data_len = data.len();
1102
1103        let mut read_results = Vec::with_capacity(data_len);
1104        for _ in data[..data_len - 1].iter() {
1105            self.schedule_read_large_dtm_register::<V, Sbdata>(&mut read_results)?;
1106        }
1107
1108        self.schedule_write_dm_register(Sbcs(0))?;
1109
1110        // Read last value
1111        self.schedule_read_large_dtm_register::<V, Sbdata>(&mut read_results)?;
1112
1113        let sbcs = self.read_dm_register::<Sbcs>()?;
1114
1115        for out in data.iter_mut() {
1116            *out = V::read_scheduled_result(self, &mut read_results)?;
1117        }
1118
1119        // Check that the read was succesful
1120        if sbcs.sberror() != 0 {
1121            Err(RiscvError::SystemBusAccess)
1122        } else {
1123            Ok(())
1124        }
1125    }
1126
1127    // TODO: this would be best executed on the probe. RiscvCommunicationInterface should be refactored to allow that.
1128    fn wait_for_idle(&mut self, timeout: Duration) -> Result<(), RiscvError> {
1129        let start = Instant::now();
1130        loop {
1131            let status: Abstractcs = self.read_dm_register()?;
1132            match AbstractCommandErrorKind::parse(status) {
1133                Ok(_) => return Ok(()),
1134                Err(AbstractCommandErrorKind::Busy) => {}
1135                Err(other) => return Err(other.into()),
1136            }
1137
1138            if start.elapsed() > timeout {
1139                return Err(RiscvError::Timeout);
1140            }
1141        }
1142    }
1143
1144    /// Perform memory read from a single location using the program buffer.
1145    /// Only reads up to a width of 32 bits are currently supported.
1146    fn perform_memory_read_progbuf<V: RiscvValue32>(
1147        &mut self,
1148        address: u32,
1149        wait_for_idle: bool,
1150    ) -> Result<V, RiscvError> {
1151        self.halted_access(|core| {
1152            // assemble
1153            //  lb s1, 0(s0)
1154
1155            let s0 = core.save_s0()?;
1156
1157            let lw_command = assembly::lw(0, 8, V::WIDTH as u8, 8);
1158
1159            core.schedule_setup_program_buffer(&[lw_command])?;
1160
1161            core.schedule_write_dm_register(Data0(address))?;
1162
1163            // Write s0, then execute program buffer
1164            let mut command = AccessRegisterCommand(0);
1165            command.set_cmd_type(0);
1166            command.set_transfer(true);
1167            command.set_write(true);
1168
1169            // registers are 32 bit, so we have size 2 here
1170            command.set_aarsize(RiscvBusAccess::A32);
1171            command.set_postexec(true);
1172
1173            // register s0, ie. 0x1008
1174            command.set_regno((registers::S0).id.0 as u32);
1175
1176            core.schedule_write_dm_register(command)?;
1177
1178            if wait_for_idle {
1179                core.wait_for_idle(Duration::from_millis(10))?;
1180            }
1181
1182            // Read back s0
1183            let value = core.abstract_cmd_register_read(&registers::S0)?;
1184
1185            // Restore s0 register
1186            core.restore_s0(s0)?;
1187
1188            Ok(V::from_register_value(value))
1189        })
1190    }
1191
1192    fn perform_memory_read_multiple_progbuf<V: RiscvValue32>(
1193        &mut self,
1194        address: u32,
1195        data: &mut [V],
1196        wait_for_idle: bool,
1197    ) -> Result<(), RiscvError> {
1198        if data.is_empty() {
1199            return Ok(());
1200        }
1201
1202        if data.len() == 1 {
1203            data[0] = self.perform_memory_read_progbuf(address, wait_for_idle)?;
1204            return Ok(());
1205        }
1206
1207        self.halted_access(|core| {
1208            // Backup registers s0 and s1
1209            let s0 = core.save_s0()?;
1210            let s1 = core.save_s1()?;
1211
1212            // Load a word from address in register 8 (S0), with offset 0, into register 9 (S9)
1213            let lw_command: u32 = assembly::lw(0, 8, V::WIDTH as u8, 9);
1214
1215            core.schedule_setup_program_buffer(&[
1216                lw_command,
1217                assembly::addi(8, 8, V::WIDTH.byte_width() as i16),
1218            ])?;
1219
1220            core.schedule_write_dm_register(Data0(address))?;
1221
1222            // Write s0, then execute program buffer
1223            let mut command = AccessRegisterCommand(0);
1224            command.set_cmd_type(0);
1225            command.set_transfer(true);
1226            command.set_write(true);
1227
1228            // registers are 32 bit, so we have size 2 here
1229            command.set_aarsize(RiscvBusAccess::A32);
1230            command.set_postexec(true);
1231
1232            // register s0, ie. 0x1008
1233            command.set_regno((registers::S0).id.0 as u32);
1234
1235            core.schedule_write_dm_register(command)?;
1236
1237            if wait_for_idle {
1238                core.wait_for_idle(Duration::from_millis(10))?;
1239            }
1240
1241            let data_len = data.len();
1242
1243            let mut result_idxs = Vec::with_capacity(data_len - 1);
1244            for out_idx in 0..data_len - 1 {
1245                let mut command = AccessRegisterCommand(0);
1246                command.set_cmd_type(0);
1247                command.set_transfer(true);
1248                command.set_write(false);
1249
1250                // registers are 32 bit, so we have size 2 here
1251                command.set_aarsize(RiscvBusAccess::A32);
1252                command.set_postexec(true);
1253
1254                command.set_regno((registers::S1).id.0 as u32);
1255
1256                core.schedule_write_dm_register(command)?;
1257
1258                // Read back s1
1259                let value_idx = core.schedule_read_dm_register::<Data0>()?;
1260
1261                result_idxs.push((out_idx, value_idx));
1262
1263                if wait_for_idle {
1264                    core.wait_for_idle(Duration::from_millis(10))?;
1265                }
1266            }
1267
1268            // Now read the last value. This will also reset `postexec` to false, so we don't have to wait for the program buffer to execute.
1269            let last_value = core.abstract_cmd_register_read(&registers::S1)?;
1270            data[data.len() - 1] = V::from_register_value(last_value);
1271
1272            for (out_idx, value_idx) in result_idxs {
1273                let value = core.dtm.read_deferred_result(value_idx)?.into_u32();
1274
1275                data[out_idx] = V::from_register_value(value);
1276            }
1277
1278            let status: Abstractcs = core.read_dm_register()?;
1279            AbstractCommandErrorKind::parse(status)?;
1280
1281            core.restore_s0(s0)?;
1282            core.restore_s1(s1)?;
1283
1284            Ok(())
1285        })
1286    }
1287
1288    /// Memory write using system bus
1289    fn perform_memory_write_sysbus<V: RiscvValue>(
1290        &mut self,
1291        address: u32,
1292        data: &[V],
1293    ) -> Result<(), RiscvError> {
1294        if data.is_empty() {
1295            return Ok(());
1296        }
1297        let mut sbcs = Sbcs(0);
1298
1299        // Set correct access width
1300        sbcs.set_sbaccess(V::WIDTH as u32);
1301        sbcs.set_sbautoincrement(true);
1302
1303        self.schedule_write_dm_register(sbcs)?;
1304
1305        self.schedule_write_dm_register(Sbaddress0(address))?;
1306
1307        for value in data {
1308            self.schedule_write_large_dtm_register::<V, Sbdata>(*value)?;
1309        }
1310
1311        // Check that the write was succesful
1312        let sbcs = self.read_dm_register::<Sbcs>()?;
1313
1314        if sbcs.sberror() != 0 {
1315            Err(RiscvError::SystemBusAccess)
1316        } else {
1317            Ok(())
1318        }
1319    }
1320
1321    /// Perform memory write to a single location using the program buffer.
1322    /// Only writes up to a width of 32 bits are currently supported.
1323    fn perform_memory_write_progbuf<V: RiscvValue32>(
1324        &mut self,
1325        address: u32,
1326        data: V,
1327        wait_for_idle: bool,
1328    ) -> Result<(), RiscvError> {
1329        self.halted_access(|core| {
1330            tracing::debug!(
1331                "Memory write using progbuf - {:#010x} = {:#?}",
1332                address,
1333                data
1334            );
1335
1336            // Backup registers s0 and s1
1337            let s0 = core.save_s0()?;
1338            let s1 = core.save_s1()?;
1339
1340            let sw_command = assembly::sw(0, 8, V::WIDTH as u32, 9);
1341
1342            core.schedule_setup_program_buffer(&[sw_command])?;
1343
1344            // write address into s0
1345            core.abstract_cmd_register_write(&registers::S0, address)?;
1346
1347            // write data into data 0
1348            core.schedule_write_dm_register(Data0(data.into()))?;
1349
1350            // Write s1, then execute program buffer
1351            let mut command = AccessRegisterCommand(0);
1352            command.set_cmd_type(0);
1353            command.set_transfer(true);
1354            command.set_write(true);
1355
1356            // registers are 32 bit, so we have size 2 here
1357            command.set_aarsize(RiscvBusAccess::A32);
1358            command.set_postexec(true);
1359
1360            // register s1, ie. 0x1009
1361            command.set_regno((registers::S1).id.0 as u32);
1362
1363            core.schedule_write_dm_register(command)?;
1364
1365            if wait_for_idle && let Err(error) = core.wait_for_idle(Duration::from_millis(10)) {
1366                tracing::error!(
1367                    "Executing the abstract command for write_{} failed: {:?}",
1368                    V::WIDTH.byte_width() * 8,
1369                    error
1370                );
1371
1372                return Err(error);
1373            }
1374
1375            core.restore_s0(s0)?;
1376            core.restore_s1(s1)?;
1377
1378            Ok(())
1379        })
1380    }
1381
1382    /// Perform multiple memory writes to consecutive locations using the program buffer.
1383    /// Only writes up to a width of 32 bits are currently supported.
1384    fn perform_memory_write_multiple_progbuf<V: RiscvValue32>(
1385        &mut self,
1386        address: u32,
1387        data: &[V],
1388        wait_for_idle: bool,
1389    ) -> Result<(), RiscvError> {
1390        if data.is_empty() {
1391            return Ok(());
1392        }
1393
1394        if data.len() == 1 {
1395            self.perform_memory_write_progbuf(address, data[0], wait_for_idle)?;
1396            return Ok(());
1397        }
1398
1399        self.halted_access(|core| {
1400            let s0 = core.save_s0()?;
1401            let s1 = core.save_s1()?;
1402
1403            // Setup program buffer for multiple writes
1404            // Store value from register s9 into memory,
1405            // then increase the address for next write.
1406            core.schedule_setup_program_buffer(&[
1407                assembly::sw(0, 8, V::WIDTH as u32, 9),
1408                assembly::addi(8, 8, V::WIDTH.byte_width() as i16),
1409            ])?;
1410
1411            // write address into s0
1412            core.abstract_cmd_register_write(&registers::S0, address)?;
1413
1414            for value in data {
1415                // write data into data 0
1416                core.schedule_write_dm_register(Data0((*value).into()))?;
1417
1418                // Write s0, then execute program buffer
1419                let mut command = AccessRegisterCommand(0);
1420                command.set_cmd_type(0);
1421                command.set_transfer(true);
1422                command.set_write(true);
1423
1424                // registers are 32 bit, so we have size 2 here
1425                command.set_aarsize(RiscvBusAccess::A32);
1426                command.set_postexec(true);
1427
1428                // register s1
1429                command.set_regno((registers::S1).id.0 as u32);
1430
1431                core.schedule_write_dm_register(command)?;
1432
1433                if wait_for_idle && let Err(error) = core.wait_for_idle(Duration::from_millis(10)) {
1434                    tracing::error!(
1435                        "Executing the abstract command for write_multiple_{} failed: {:?}",
1436                        V::WIDTH.byte_width() * 8,
1437                        error,
1438                    );
1439
1440                    return Err(error);
1441                }
1442            }
1443
1444            // Restore register s0 and s1
1445
1446            core.restore_s0(s0)?;
1447            core.restore_s1(s1)?;
1448
1449            Ok(())
1450        })
1451    }
1452
1453    pub(crate) fn execute_abstract_command(&mut self, command: u32) -> Result<(), RiscvError> {
1454        // ensure that preconditions are fullfileld
1455        // haltreq      = 0
1456        // resumereq    = 0
1457        // ackhavereset = 0
1458
1459        let mut dmcontrol = self.state.current_dmcontrol;
1460        dmcontrol.set_dmactive(true);
1461        dmcontrol.set_haltreq(false);
1462        dmcontrol.set_resumereq(false);
1463        dmcontrol.set_ackhavereset(false);
1464        self.schedule_write_dm_register(dmcontrol)?;
1465
1466        fn do_execute_abstract_command(
1467            core: &mut RiscvCommunicationInterface,
1468            command: Command,
1469        ) -> Result<(), RiscvError> {
1470            // Clear any previous command errors.
1471            let mut abstractcs_clear = Abstractcs(0);
1472            abstractcs_clear.set_cmderr(0x7);
1473
1474            core.schedule_write_dm_register(abstractcs_clear)?;
1475            core.schedule_write_dm_register(command)?;
1476
1477            let start_time = Instant::now();
1478
1479            // Poll busy flag in abstractcs.
1480            let mut abstractcs;
1481            loop {
1482                abstractcs = core.read_dm_register::<Abstractcs>()?;
1483
1484                if !abstractcs.busy() {
1485                    break;
1486                }
1487
1488                if start_time.elapsed() > RISCV_TIMEOUT {
1489                    return Err(RiscvError::Timeout);
1490                }
1491            }
1492
1493            tracing::debug!("abstracts: {:?}", abstractcs);
1494
1495            // Check command result for error.
1496            AbstractCommandErrorKind::parse(abstractcs)?;
1497
1498            Ok(())
1499        }
1500
1501        match do_execute_abstract_command(self, Command(command)) {
1502            err @ Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::HaltResume)) => {
1503                if !self.core_halted()? {
1504                    // This command requires the core to be halted.
1505                    // We can do that, so let's try again.
1506                    self.halted_access(|core| do_execute_abstract_command(core, Command(command)))
1507                } else {
1508                    // This command requires the core to be resumed. This is a bit more drastic than
1509                    // what we want to do here, so we bubble up the error.
1510                    err
1511                }
1512            }
1513            other => other,
1514        }
1515    }
1516
1517    /// Check if a register can be accessed via abstract commands
1518    fn check_abstract_cmd_register_support(
1519        &self,
1520        regno: RegisterId,
1521        rw: CoreRegisterAbstractCmdSupport,
1522    ) -> bool {
1523        if let Some(status) = self.state.abstract_cmd_register_info.get(&regno) {
1524            status.supports(rw)
1525        } else {
1526            // If not cached yet, assume the register is accessible
1527            true
1528        }
1529    }
1530
1531    /// Remember, that the given register can not be accessed via abstract commands
1532    fn set_abstract_cmd_register_unsupported(
1533        &mut self,
1534        regno: RegisterId,
1535        rw: CoreRegisterAbstractCmdSupport,
1536    ) {
1537        let entry = self
1538            .state
1539            .abstract_cmd_register_info
1540            .entry(regno)
1541            .or_insert(CoreRegisterAbstractCmdSupport::BOTH);
1542
1543        entry.unset(rw);
1544    }
1545
1546    // Read a core register using an abstract command
1547    pub(crate) fn abstract_cmd_register_read(
1548        &mut self,
1549        regno: impl Into<RegisterId>,
1550    ) -> Result<u32, RiscvError> {
1551        let regno = regno.into();
1552
1553        // Check if the register was already tried via abstract cmd
1554        if !self.check_abstract_cmd_register_support(regno, CoreRegisterAbstractCmdSupport::READ) {
1555            return Err(RiscvError::AbstractCommand(
1556                AbstractCommandErrorKind::NotSupported,
1557            ));
1558        }
1559
1560        // read from data0
1561        let mut command = AccessRegisterCommand(0);
1562        command.set_cmd_type(0);
1563        command.set_transfer(true);
1564        command.set_aarsize(RiscvBusAccess::A32);
1565
1566        command.set_regno(regno.0 as u32);
1567
1568        match self.execute_abstract_command(command.0) {
1569            Ok(_) => (),
1570            err @ Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
1571                // Remember, that this register is unsupported
1572                self.set_abstract_cmd_register_unsupported(
1573                    regno,
1574                    CoreRegisterAbstractCmdSupport::READ,
1575                );
1576                err?;
1577            }
1578            Err(e) => return Err(e),
1579        }
1580
1581        let register_value: Data0 = self.read_dm_register()?;
1582
1583        Ok(register_value.into())
1584    }
1585
1586    pub(crate) fn abstract_cmd_register_write<V: RiscvValue>(
1587        &mut self,
1588        regno: impl Into<RegisterId>,
1589        value: V,
1590    ) -> Result<(), RiscvError> {
1591        let regno = regno.into();
1592
1593        // Check if the register was already tried via abstract cmd
1594        if !self.check_abstract_cmd_register_support(regno, CoreRegisterAbstractCmdSupport::WRITE) {
1595            return Err(RiscvError::AbstractCommand(
1596                AbstractCommandErrorKind::NotSupported,
1597            ));
1598        }
1599
1600        // write to data0
1601        let mut command = AccessRegisterCommand(0);
1602        command.set_cmd_type(0);
1603        command.set_transfer(true);
1604        command.set_write(true);
1605        command.set_aarsize(V::WIDTH);
1606
1607        command.set_regno(regno.0 as u32);
1608
1609        self.schedule_write_large_dtm_register::<V, Arg0>(value)?;
1610
1611        match self.execute_abstract_command(command.0) {
1612            Ok(_) => Ok(()),
1613            err @ Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
1614                // Remember, that this register is unsupported
1615                self.set_abstract_cmd_register_unsupported(
1616                    regno,
1617                    CoreRegisterAbstractCmdSupport::WRITE,
1618                );
1619                err
1620            }
1621            Err(e) => Err(e),
1622        }
1623    }
1624
1625    /// Read the CSR `progbuf` register.
1626    pub fn read_csr_progbuf(&mut self, address: u16) -> Result<u32, RiscvError> {
1627        self.halted_access(|core| {
1628            tracing::debug!("Reading CSR {:#04x}", address);
1629
1630            // Validate that the CSR address is valid
1631            if address > RISCV_MAX_CSR_ADDR {
1632                return Err(RiscvError::UnsupportedCsrAddress(address));
1633            }
1634
1635            let s0 = core.save_s0()?;
1636
1637            // Read csr value into register 8 (s0)
1638            let csrr_cmd = assembly::csrr(8, address);
1639
1640            core.schedule_setup_program_buffer(&[csrr_cmd])?;
1641
1642            // command: postexec
1643            let mut postexec_cmd = AccessRegisterCommand(0);
1644            postexec_cmd.set_postexec(true);
1645
1646            core.execute_abstract_command(postexec_cmd.0)?;
1647
1648            // read the s0 value
1649            let reg_value = core.abstract_cmd_register_read(&registers::S0)?;
1650
1651            // restore original value in s0
1652            core.restore_s0(s0)?;
1653
1654            Ok(reg_value)
1655        })
1656    }
1657
1658    /// Write the CSR `progbuf` register.
1659    pub fn write_csr_progbuf(&mut self, address: u16, value: u32) -> Result<(), RiscvError> {
1660        self.halted_access(|core| {
1661            tracing::debug!("Writing CSR {:#04x}={}", address, value);
1662
1663            // Validate that the CSR address is valid
1664            if address > RISCV_MAX_CSR_ADDR {
1665                return Err(RiscvError::UnsupportedCsrAddress(address));
1666            }
1667
1668            // Backup register s0
1669            let s0 = core.save_s0()?;
1670
1671            // Write value into s0
1672            core.abstract_cmd_register_write(&registers::S0, value)?;
1673
1674            // Built the CSRW command to write into the program buffer
1675            let csrw_cmd = assembly::csrw(address, 8);
1676            core.schedule_setup_program_buffer(&[csrw_cmd])?;
1677
1678            // command: postexec
1679            let mut postexec_cmd = AccessRegisterCommand(0);
1680            postexec_cmd.set_postexec(true);
1681
1682            core.execute_abstract_command(postexec_cmd.0)?;
1683
1684            // command: transfer, regno = 0x1008
1685            // restore original value in s0
1686            core.restore_s0(s0)?;
1687
1688            Ok(())
1689        })
1690    }
1691
1692    fn read_word<V: RiscvValue32>(&mut self, address: u32) -> Result<V, crate::Error> {
1693        let result = match self.state.memory_access_method(V::WIDTH, address as u64) {
1694            MemoryAccessMethod::ProgramBuffer => {
1695                self.perform_memory_read_progbuf(address, false)?
1696            }
1697            MemoryAccessMethod::WaitingProgramBuffer => {
1698                self.perform_memory_read_progbuf(address, true)?
1699            }
1700            MemoryAccessMethod::SystemBus => self.perform_memory_read_sysbus(address)?,
1701            MemoryAccessMethod::AbstractCommand => {
1702                unimplemented!("Memory access using abstract commands is not implemted")
1703            }
1704        };
1705
1706        Ok(result)
1707    }
1708
1709    fn read_multiple<V: RiscvValue32>(
1710        &mut self,
1711        address: u32,
1712        data: &mut [V],
1713    ) -> Result<(), crate::Error> {
1714        let start = address as u64;
1715        let address_range = start..(start + (data.len() * V::WIDTH.byte_width()) as u64);
1716        let access_method = self
1717            .state
1718            .memory_range_access_method(V::WIDTH, address_range);
1719        tracing::debug!(
1720            "read_multiple({:?}) from {:#08x} using {:?}",
1721            V::WIDTH,
1722            address,
1723            access_method
1724        );
1725
1726        match access_method {
1727            MemoryAccessMethod::ProgramBuffer => {
1728                self.perform_memory_read_multiple_progbuf(address, data, false)?;
1729            }
1730            MemoryAccessMethod::WaitingProgramBuffer => {
1731                self.perform_memory_read_multiple_progbuf(address, data, true)?;
1732            }
1733            MemoryAccessMethod::SystemBus => {
1734                self.perform_memory_read_multiple_sysbus(address, data)?;
1735            }
1736            MemoryAccessMethod::AbstractCommand => {
1737                unimplemented!("Memory access using abstract commands is not implemted")
1738            }
1739        };
1740
1741        Ok(())
1742    }
1743
1744    fn write_word<V: RiscvValue32>(&mut self, address: u32, data: V) -> Result<(), crate::Error> {
1745        match self.state.memory_access_method(V::WIDTH, address as u64) {
1746            MemoryAccessMethod::ProgramBuffer => {
1747                self.perform_memory_write_progbuf(address, data, false)?
1748            }
1749            MemoryAccessMethod::WaitingProgramBuffer => {
1750                self.perform_memory_write_progbuf(address, data, true)?
1751            }
1752            MemoryAccessMethod::SystemBus => self.perform_memory_write_sysbus(address, &[data])?,
1753            MemoryAccessMethod::AbstractCommand => {
1754                unimplemented!("Memory access using abstract commands is not implemted")
1755            }
1756        };
1757
1758        Ok(())
1759    }
1760
1761    fn write_multiple<V: RiscvValue32>(
1762        &mut self,
1763        address: u32,
1764        data: &[V],
1765    ) -> Result<(), crate::Error> {
1766        let start = address as u64;
1767        let address_range = start..(start + (data.len() * V::WIDTH.byte_width()) as u64);
1768        let access_method = self
1769            .state
1770            .memory_range_access_method(V::WIDTH, address_range);
1771        match access_method {
1772            MemoryAccessMethod::SystemBus => self.perform_memory_write_sysbus(address, data)?,
1773            MemoryAccessMethod::ProgramBuffer => {
1774                self.perform_memory_write_multiple_progbuf(address, data, false)?
1775            }
1776            MemoryAccessMethod::WaitingProgramBuffer => {
1777                self.perform_memory_write_multiple_progbuf(address, data, true)?
1778            }
1779            MemoryAccessMethod::AbstractCommand => {
1780                unimplemented!("Memory access using abstract commands is not implemted")
1781            }
1782        }
1783
1784        Ok(())
1785    }
1786
1787    pub(crate) fn schedule_write_dm_register<R: MemoryMappedRegister<u32>>(
1788        &mut self,
1789        register: R,
1790    ) -> Result<(), RiscvError> {
1791        // write write command to dmi register
1792
1793        tracing::debug!(
1794            "Write DM register '{}' at {:#010x} = {:x?}",
1795            R::NAME,
1796            R::get_mmio_address(),
1797            register
1798        );
1799
1800        self.schedule_write_dm_register_untyped(R::get_mmio_address(), register.into())?;
1801        Ok(())
1802    }
1803
1804    /// Write to a DM register
1805    ///
1806    /// Use the [`Self::schedule_write_dm_register()`] function if possible.
1807    fn schedule_write_dm_register_untyped(
1808        &mut self,
1809        address: u64,
1810        value: u32,
1811    ) -> Result<Option<DeferredResultIndex>, RiscvError> {
1812        self.cache_write(address, value);
1813        self.dtm.schedule_write(address, value)
1814    }
1815
1816    pub(super) fn schedule_read_dm_register<R: MemoryMappedRegister<u32>>(
1817        &mut self,
1818    ) -> Result<DeferredResultIndex, RiscvError> {
1819        tracing::debug!(
1820            "Reading DM register '{}' at {:#010x}",
1821            R::NAME,
1822            R::get_mmio_address()
1823        );
1824
1825        self.schedule_read_dm_register_untyped(R::get_mmio_address())
1826    }
1827
1828    /// Read from a DM register
1829    ///
1830    /// Use the [`Self::schedule_read_dm_register()`] function if possible.
1831    fn schedule_read_dm_register_untyped(
1832        &mut self,
1833        address: u64,
1834    ) -> Result<DeferredResultIndex, RiscvError> {
1835        // Prepare the read by sending a read request with the register address
1836        self.dtm.schedule_read(address)
1837    }
1838
1839    fn schedule_read_large_dtm_register<V, R>(
1840        &mut self,
1841        results: &mut Vec<DeferredResultIndex>,
1842    ) -> Result<(), RiscvError>
1843    where
1844        V: RiscvValue,
1845        R: LargeRegister,
1846    {
1847        V::schedule_read_from_register::<R>(self, results)
1848    }
1849
1850    fn schedule_write_large_dtm_register<V, R>(
1851        &mut self,
1852        value: V,
1853    ) -> Result<Option<DeferredResultIndex>, RiscvError>
1854    where
1855        V: RiscvValue,
1856        R: LargeRegister,
1857    {
1858        V::schedule_write_to_register::<R>(self, value)
1859    }
1860
1861    /// Check if the connected device supports halt after reset.
1862    ///
1863    /// Returns a cached value if available, otherwise queries the
1864    /// `hasresethaltreq` bit in the `dmstatus` register.
1865    pub(crate) fn supports_reset_halt_req(&mut self) -> Result<bool, RiscvError> {
1866        if let Some(has_reset_halt_req) = self.state.hasresethaltreq {
1867            Ok(has_reset_halt_req)
1868        } else {
1869            let dmstatus: Dmstatus = self.read_dm_register()?;
1870
1871            self.state.hasresethaltreq = Some(dmstatus.hasresethaltreq());
1872
1873            Ok(dmstatus.hasresethaltreq())
1874        }
1875    }
1876
1877    /// Resume the core.
1878    pub fn resume_core(&mut self) -> Result<(), RiscvError> {
1879        self.state.is_halted = false; // `false` will re-query the DM, so it's safe to write
1880
1881        // set resume request.
1882        let mut dmcontrol = self.state.current_dmcontrol;
1883        dmcontrol.set_dmactive(true);
1884        dmcontrol.set_resumereq(true);
1885        self.schedule_write_dm_register(dmcontrol)?;
1886
1887        // check if request has been acknowleged.
1888        let status_idx = self.schedule_read_dm_register::<Dmstatus>()?;
1889
1890        // clear resume request.
1891        dmcontrol.set_resumereq(false);
1892        self.write_dm_register(dmcontrol)?;
1893
1894        let status = Dmstatus(self.dtm.read_deferred_result(status_idx)?.into_u32());
1895        if !status.allresumeack() {
1896            return Err(RiscvError::RequestNotAcknowledged);
1897        }
1898
1899        Ok(())
1900    }
1901
1902    /// Perform a reset of all harts on the target and halt them at the first instruction.
1903    pub fn reset_hart_and_halt(&mut self, timeout: Duration) -> Result<(), RiscvError> {
1904        tracing::debug!("Resetting core, setting hartreset bit");
1905
1906        let mut dmcontrol = self.state.current_dmcontrol;
1907        dmcontrol.set_dmactive(true);
1908        dmcontrol.set_hartreset(true);
1909        dmcontrol.set_haltreq(true);
1910
1911        self.write_dm_register(dmcontrol)?;
1912
1913        // Read back register to verify reset is supported
1914        let readback: Dmcontrol = self.read_dm_register()?;
1915
1916        if readback.hartreset() {
1917            tracing::debug!("Clearing hartreset bit");
1918            // Reset is performed by setting the bit high, and then low again
1919            let mut dmcontrol = readback;
1920            dmcontrol.set_dmactive(true);
1921            dmcontrol.set_haltreq(true);
1922            dmcontrol.set_hartreset(false);
1923
1924            self.write_dm_register(dmcontrol)?;
1925        } else {
1926            // Hartreset is not supported, whole core needs to be reset
1927            //
1928            // TODO: Cache this
1929            tracing::debug!("Hartreset bit not supported, using ndmreset");
1930            dmcontrol.set_hartreset(false);
1931            dmcontrol.set_ndmreset(true);
1932            dmcontrol.set_haltreq(true);
1933
1934            self.write_dm_register(dmcontrol)?;
1935
1936            tracing::debug!("Clearing ndmreset bit");
1937            dmcontrol.set_ndmreset(false);
1938            dmcontrol.set_haltreq(true);
1939
1940            self.write_dm_register(dmcontrol)?;
1941        }
1942
1943        let start = Instant::now();
1944
1945        loop {
1946            // check that cores have reset
1947            let readback: Dmstatus = self.read_dm_register()?;
1948
1949            if readback.allhavereset() && readback.allhalted() {
1950                break;
1951            }
1952
1953            if start.elapsed() > timeout {
1954                return Err(RiscvError::RequestNotAcknowledged);
1955            }
1956            self.write_dm_register(dmcontrol)?;
1957        }
1958
1959        // clear the reset request
1960        dmcontrol.set_haltreq(false);
1961        dmcontrol.set_ackhavereset(true);
1962        dmcontrol.set_hartreset(false);
1963        dmcontrol.set_ndmreset(false);
1964
1965        self.write_dm_register(dmcontrol)?;
1966
1967        // Reenable halt on breakpoint because this gets disabled if we reset the core
1968        self.debug_on_sw_breakpoint(true)?;
1969
1970        Ok(())
1971    }
1972
1973    fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), RiscvError> {
1974        let mut dcsr = Dcsr(self.read_csr(0x7b0)?);
1975
1976        dcsr.set_ebreakm(enabled);
1977        dcsr.set_ebreaks(enabled);
1978        dcsr.set_ebreaku(enabled);
1979
1980        match self.abstract_cmd_register_write(0x7b0, dcsr.0) {
1981            Ok(()) => {
1982                self.state.sw_breakpoint_debug_enabled = enabled;
1983                Ok(())
1984            }
1985            Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
1986                tracing::debug!(
1987                    "Could not write core register {:#x} with abstract command, falling back to program buffer",
1988                    0x7b0
1989                );
1990                self.write_csr_progbuf(0x7b0, dcsr.0)
1991            }
1992            other => other,
1993        }
1994    }
1995
1996    /// Returns a mutable reference to the memory access configuration.
1997    pub fn memory_access_config(&mut self) -> &mut MemoryAccessConfig {
1998        &mut self.state.memory_access_config
1999    }
2000}
2001
2002pub(crate) trait LargeRegister {
2003    const R0_ADDRESS: u8;
2004    const R1_ADDRESS: u8;
2005    const R2_ADDRESS: u8;
2006    const R3_ADDRESS: u8;
2007}
2008
2009struct Sbdata {}
2010
2011impl LargeRegister for Sbdata {
2012    const R0_ADDRESS: u8 = Sbdata0::ADDRESS_OFFSET as u8;
2013    const R1_ADDRESS: u8 = Sbdata1::ADDRESS_OFFSET as u8;
2014    const R2_ADDRESS: u8 = Sbdata2::ADDRESS_OFFSET as u8;
2015    const R3_ADDRESS: u8 = Sbdata3::ADDRESS_OFFSET as u8;
2016}
2017
2018struct Arg0 {}
2019
2020impl LargeRegister for Arg0 {
2021    const R0_ADDRESS: u8 = Data0::ADDRESS_OFFSET as u8;
2022    const R1_ADDRESS: u8 = Data1::ADDRESS_OFFSET as u8;
2023    const R2_ADDRESS: u8 = Data2::ADDRESS_OFFSET as u8;
2024    const R3_ADDRESS: u8 = Data3::ADDRESS_OFFSET as u8;
2025}
2026
2027/// Helper trait, limited to RiscvValue no larger than 32 bits
2028pub(crate) trait RiscvValue32: RiscvValue + Into<u32> {
2029    fn from_register_value(value: u32) -> Self;
2030}
2031
2032impl RiscvValue32 for u8 {
2033    fn from_register_value(value: u32) -> Self {
2034        value as u8
2035    }
2036}
2037impl RiscvValue32 for u16 {
2038    fn from_register_value(value: u32) -> Self {
2039        value as u16
2040    }
2041}
2042impl RiscvValue32 for u32 {
2043    fn from_register_value(value: u32) -> Self {
2044        value
2045    }
2046}
2047
2048/// Marker trait for different values which
2049/// can be read / written using the debug module.
2050pub(crate) trait RiscvValue: std::fmt::Debug + Copy + Sized {
2051    const WIDTH: RiscvBusAccess;
2052
2053    fn schedule_read_from_register<R>(
2054        interface: &mut RiscvCommunicationInterface,
2055        results: &mut Vec<DeferredResultIndex>,
2056    ) -> Result<(), RiscvError>
2057    where
2058        R: LargeRegister;
2059
2060    fn read_scheduled_result(
2061        interface: &mut RiscvCommunicationInterface,
2062        results: &mut Vec<DeferredResultIndex>,
2063    ) -> Result<Self, RiscvError>;
2064
2065    fn schedule_write_to_register<R>(
2066        interface: &mut RiscvCommunicationInterface,
2067        value: Self,
2068    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2069    where
2070        R: LargeRegister;
2071}
2072
2073impl RiscvValue for u8 {
2074    const WIDTH: RiscvBusAccess = RiscvBusAccess::A8;
2075
2076    fn schedule_read_from_register<R>(
2077        interface: &mut RiscvCommunicationInterface,
2078        results: &mut Vec<DeferredResultIndex>,
2079    ) -> Result<(), RiscvError>
2080    where
2081        R: LargeRegister,
2082    {
2083        results.push(interface.schedule_read_dm_register_untyped(R::R0_ADDRESS as u64)?);
2084        Ok(())
2085    }
2086
2087    fn read_scheduled_result(
2088        interface: &mut RiscvCommunicationInterface,
2089        results: &mut Vec<DeferredResultIndex>,
2090    ) -> Result<Self, RiscvError> {
2091        let result = interface.dtm.read_deferred_result(results.remove(0))?;
2092
2093        Ok(result.into_u32() as u8)
2094    }
2095
2096    fn schedule_write_to_register<R>(
2097        interface: &mut RiscvCommunicationInterface,
2098        value: Self,
2099    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2100    where
2101        R: LargeRegister,
2102    {
2103        interface.schedule_write_dm_register_untyped(R::R0_ADDRESS as u64, value as u32)
2104    }
2105}
2106
2107impl RiscvValue for u16 {
2108    const WIDTH: RiscvBusAccess = RiscvBusAccess::A16;
2109
2110    fn schedule_read_from_register<R>(
2111        interface: &mut RiscvCommunicationInterface,
2112        results: &mut Vec<DeferredResultIndex>,
2113    ) -> Result<(), RiscvError>
2114    where
2115        R: LargeRegister,
2116    {
2117        results.push(interface.schedule_read_dm_register_untyped(R::R0_ADDRESS as u64)?);
2118        Ok(())
2119    }
2120
2121    fn read_scheduled_result(
2122        interface: &mut RiscvCommunicationInterface,
2123        results: &mut Vec<DeferredResultIndex>,
2124    ) -> Result<Self, RiscvError> {
2125        let result = interface.dtm.read_deferred_result(results.remove(0))?;
2126
2127        Ok(result.into_u32() as u16)
2128    }
2129
2130    fn schedule_write_to_register<R>(
2131        interface: &mut RiscvCommunicationInterface,
2132        value: Self,
2133    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2134    where
2135        R: LargeRegister,
2136    {
2137        interface.schedule_write_dm_register_untyped(R::R0_ADDRESS as u64, value as u32)
2138    }
2139}
2140
2141impl RiscvValue for u32 {
2142    const WIDTH: RiscvBusAccess = RiscvBusAccess::A32;
2143
2144    fn schedule_read_from_register<R>(
2145        interface: &mut RiscvCommunicationInterface,
2146        results: &mut Vec<DeferredResultIndex>,
2147    ) -> Result<(), RiscvError>
2148    where
2149        R: LargeRegister,
2150    {
2151        results.push(interface.schedule_read_dm_register_untyped(R::R0_ADDRESS as u64)?);
2152        Ok(())
2153    }
2154
2155    fn read_scheduled_result(
2156        interface: &mut RiscvCommunicationInterface,
2157        results: &mut Vec<DeferredResultIndex>,
2158    ) -> Result<Self, RiscvError> {
2159        let result = interface.dtm.read_deferred_result(results.remove(0))?;
2160
2161        Ok(result.into_u32())
2162    }
2163
2164    fn schedule_write_to_register<R>(
2165        interface: &mut RiscvCommunicationInterface,
2166        value: Self,
2167    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2168    where
2169        R: LargeRegister,
2170    {
2171        interface.schedule_write_dm_register_untyped(R::R0_ADDRESS as u64, value)
2172    }
2173}
2174
2175impl RiscvValue for u64 {
2176    const WIDTH: RiscvBusAccess = RiscvBusAccess::A64;
2177
2178    fn schedule_read_from_register<R>(
2179        interface: &mut RiscvCommunicationInterface,
2180        results: &mut Vec<DeferredResultIndex>,
2181    ) -> Result<(), RiscvError>
2182    where
2183        R: LargeRegister,
2184    {
2185        results.push(interface.schedule_read_dm_register_untyped(R::R1_ADDRESS as u64)?);
2186        results.push(interface.schedule_read_dm_register_untyped(R::R0_ADDRESS as u64)?);
2187        Ok(())
2188    }
2189
2190    fn read_scheduled_result(
2191        interface: &mut RiscvCommunicationInterface,
2192        results: &mut Vec<DeferredResultIndex>,
2193    ) -> Result<Self, RiscvError> {
2194        let r1 = interface.dtm.read_deferred_result(results.remove(0))?;
2195        let r0 = interface.dtm.read_deferred_result(results.remove(0))?;
2196
2197        Ok(((r1.into_u32() as u64) << 32) | (r0.into_u32() as u64))
2198    }
2199
2200    fn schedule_write_to_register<R>(
2201        interface: &mut RiscvCommunicationInterface,
2202        value: Self,
2203    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2204    where
2205        R: LargeRegister,
2206    {
2207        let upper_bits = (value >> 32) as u32;
2208        let lower_bits = (value & 0xffff_ffff) as u32;
2209
2210        // R0 has to be written last, side effects are triggerd by writes from
2211        // this register.
2212
2213        interface.schedule_write_dm_register_untyped(R::R1_ADDRESS as u64, upper_bits)?;
2214        interface.schedule_write_dm_register_untyped(R::R0_ADDRESS as u64, lower_bits)
2215    }
2216}
2217
2218impl RiscvValue for u128 {
2219    const WIDTH: RiscvBusAccess = RiscvBusAccess::A128;
2220
2221    fn schedule_read_from_register<R>(
2222        interface: &mut RiscvCommunicationInterface,
2223        results: &mut Vec<DeferredResultIndex>,
2224    ) -> Result<(), RiscvError>
2225    where
2226        R: LargeRegister,
2227    {
2228        results.push(interface.schedule_read_dm_register_untyped(R::R3_ADDRESS as u64)?);
2229        results.push(interface.schedule_read_dm_register_untyped(R::R2_ADDRESS as u64)?);
2230        results.push(interface.schedule_read_dm_register_untyped(R::R1_ADDRESS as u64)?);
2231        results.push(interface.schedule_read_dm_register_untyped(R::R0_ADDRESS as u64)?);
2232        Ok(())
2233    }
2234
2235    fn read_scheduled_result(
2236        interface: &mut RiscvCommunicationInterface,
2237        results: &mut Vec<DeferredResultIndex>,
2238    ) -> Result<Self, RiscvError> {
2239        let r3 = interface.dtm.read_deferred_result(results.remove(0))?;
2240        let r2 = interface.dtm.read_deferred_result(results.remove(0))?;
2241        let r1 = interface.dtm.read_deferred_result(results.remove(0))?;
2242        let r0 = interface.dtm.read_deferred_result(results.remove(0))?;
2243
2244        Ok(((r3.into_u32() as u128) << 96)
2245            | ((r2.into_u32() as u128) << 64)
2246            | ((r1.into_u32() as u128) << 32)
2247            | (r0.into_u32() as u128))
2248    }
2249
2250    fn schedule_write_to_register<R>(
2251        interface: &mut RiscvCommunicationInterface,
2252        value: Self,
2253    ) -> Result<Option<DeferredResultIndex>, RiscvError>
2254    where
2255        R: LargeRegister,
2256    {
2257        let bits_3 = (value >> 96) as u32;
2258        let bits_2 = (value >> 64) as u32;
2259        let bits_1 = (value >> 32) as u32;
2260        let bits_0 = (value & 0xffff_ffff) as u32;
2261
2262        // R0 has to be written last, side effects are triggerd by writes from
2263        // this register.
2264
2265        interface.schedule_write_dm_register_untyped(R::R3_ADDRESS as u64, bits_3)?;
2266        interface.schedule_write_dm_register_untyped(R::R2_ADDRESS as u64, bits_2)?;
2267        interface.schedule_write_dm_register_untyped(R::R1_ADDRESS as u64, bits_1)?;
2268        interface.schedule_write_dm_register_untyped(R::R0_ADDRESS as u64, bits_0)
2269    }
2270}
2271
2272impl MemoryInterface for RiscvCommunicationInterface<'_> {
2273    fn supports_native_64bit_access(&mut self) -> bool {
2274        false
2275    }
2276
2277    fn read_word_64(&mut self, address: u64) -> Result<u64, crate::error::Error> {
2278        let address = valid_32bit_address(address)?;
2279        let mut ret = self.read_word::<u32>(address)? as u64;
2280        ret |= (self.read_word::<u32>(address + 4)? as u64) << 32;
2281
2282        Ok(ret)
2283    }
2284
2285    fn read_word_32(&mut self, address: u64) -> Result<u32, crate::Error> {
2286        let address = valid_32bit_address(address)?;
2287        tracing::debug!("read_word_32 from {:#08x}", address);
2288        self.read_word(address)
2289    }
2290
2291    fn read_word_16(&mut self, address: u64) -> Result<u16, crate::Error> {
2292        let address = valid_32bit_address(address)?;
2293        tracing::debug!("read_word_16 from {:#08x}", address);
2294        self.read_word(address)
2295    }
2296
2297    fn read_word_8(&mut self, address: u64) -> Result<u8, crate::Error> {
2298        let address = valid_32bit_address(address)?;
2299        tracing::debug!("read_word_8 from {:#08x}", address);
2300        self.read_word(address)
2301    }
2302
2303    fn read_64(&mut self, address: u64, data: &mut [u64]) -> Result<(), crate::error::Error> {
2304        let address = valid_32bit_address(address)?;
2305        tracing::debug!("read_64 from {:#08x}", address);
2306
2307        for (i, d) in data.iter_mut().enumerate() {
2308            *d = self.read_word_64((address + (i as u32 * 8)).into())?;
2309        }
2310
2311        Ok(())
2312    }
2313
2314    fn read_32(&mut self, address: u64, data: &mut [u32]) -> Result<(), crate::Error> {
2315        let address = valid_32bit_address(address)?;
2316        tracing::debug!("read_32 from {:#08x}", address);
2317        self.read_multiple(address, data)
2318    }
2319
2320    fn read_16(&mut self, address: u64, data: &mut [u16]) -> Result<(), crate::Error> {
2321        let address = valid_32bit_address(address)?;
2322        tracing::debug!("read_16 from {:#08x}", address);
2323        self.read_multiple(address, data)
2324    }
2325
2326    fn read_8(&mut self, address: u64, data: &mut [u8]) -> Result<(), crate::Error> {
2327        let address = valid_32bit_address(address)?;
2328        tracing::debug!("read_8 from {:#08x}", address);
2329
2330        self.read_multiple(address, data)
2331    }
2332
2333    fn write_word_64(&mut self, address: u64, data: u64) -> Result<(), crate::error::Error> {
2334        let address = valid_32bit_address(address)?;
2335        let low_word = data as u32;
2336        let high_word = (data >> 32) as u32;
2337
2338        self.write_word(address, low_word)?;
2339        self.write_word(address + 4, high_word)
2340    }
2341
2342    fn write_word_32(&mut self, address: u64, data: u32) -> Result<(), crate::Error> {
2343        let address = valid_32bit_address(address)?;
2344        self.write_word(address, data)
2345    }
2346
2347    fn write_word_16(&mut self, address: u64, data: u16) -> Result<(), crate::Error> {
2348        let address = valid_32bit_address(address)?;
2349        self.write_word(address, data)
2350    }
2351
2352    fn write_word_8(&mut self, address: u64, data: u8) -> Result<(), crate::Error> {
2353        let address = valid_32bit_address(address)?;
2354        self.write_word(address, data)
2355    }
2356
2357    fn write_64(&mut self, address: u64, data: &[u64]) -> Result<(), crate::error::Error> {
2358        let address = valid_32bit_address(address)?;
2359        tracing::debug!("write_64 to {:#08x}", address);
2360
2361        for (i, d) in data.iter().enumerate() {
2362            self.write_word_64((address + (i as u32 * 8)).into(), *d)?;
2363        }
2364
2365        Ok(())
2366    }
2367
2368    fn write_32(&mut self, address: u64, data: &[u32]) -> Result<(), crate::Error> {
2369        let address = valid_32bit_address(address)?;
2370        tracing::debug!("write_32 to {:#08x}", address);
2371
2372        self.write_multiple(address, data)
2373    }
2374
2375    fn write_16(&mut self, address: u64, data: &[u16]) -> Result<(), crate::Error> {
2376        let address = valid_32bit_address(address)?;
2377        tracing::debug!("write_16 to {:#08x}", address);
2378
2379        self.write_multiple(address, data)
2380    }
2381
2382    fn write_8(&mut self, address: u64, data: &[u8]) -> Result<(), crate::Error> {
2383        let address = valid_32bit_address(address)?;
2384        tracing::debug!("write_8 to {:#08x}", address);
2385
2386        self.write_multiple(address, data)
2387    }
2388
2389    fn supports_8bit_transfers(&self) -> Result<bool, crate::Error> {
2390        Ok(true)
2391    }
2392
2393    fn flush(&mut self) -> Result<(), crate::Error> {
2394        Ok(())
2395    }
2396}
2397
2398/// Access width for bus access.
2399/// This is used both for system bus access (`sbcs` register),
2400/// as well for abstract commands.
2401#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Debug)]
2402pub enum RiscvBusAccess {
2403    /// 1 byte
2404    A8 = 0,
2405    /// 2 bytes
2406    A16 = 1,
2407    /// 4 bytes
2408    A32 = 2,
2409    /// 8 bytes
2410    A64 = 3,
2411    /// 16 bytes.
2412    A128 = 4,
2413}
2414
2415impl RiscvBusAccess {
2416    /// Width of an access in bytes
2417    const fn byte_width(&self) -> usize {
2418        match self {
2419            RiscvBusAccess::A8 => 1,
2420            RiscvBusAccess::A16 => 2,
2421            RiscvBusAccess::A32 => 4,
2422            RiscvBusAccess::A64 => 8,
2423            RiscvBusAccess::A128 => 16,
2424        }
2425    }
2426}
2427
2428impl From<RiscvBusAccess> for u8 {
2429    fn from(value: RiscvBusAccess) -> Self {
2430        value as u8
2431    }
2432}
2433
2434/// Different methods of memory access,
2435/// which can be supported by a debug module.
2436///
2437/// The `AbstractCommand` method for memory access is not implemented.
2438#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
2439pub enum MemoryAccessMethod {
2440    /// Memory access using an abstract command is supported
2441    AbstractCommand,
2442    /// Memory access using the program buffer is supported, with explicit waiting for the instructions to complete
2443    WaitingProgramBuffer,
2444    /// Memory access using the program buffer is supported
2445    ProgramBuffer,
2446    /// Memory access using system bus access supported
2447    SystemBus,
2448}
2449
2450memory_mapped_bitfield_register! {
2451    /// Abstract command register, located at address 0x17
2452    /// This is not for all commands, only for the ones
2453    /// from the debug spec.
2454    pub struct AccessRegisterCommand(u32);
2455    0x17, "command",
2456    impl From;
2457    /// This is 0 to indicate Access Register Command.
2458    pub _, set_cmd_type: 31, 24;
2459    /// 2: Access the lowest 32 bits of the register.\
2460    /// 3: Access the lowest 64 bits of the register.\
2461    /// 4: Access the lowest 128 bits of the register.
2462    ///
2463    /// If `aarsize` specifies a size larger than the register’s
2464    /// actual size, then the access must fail. If a register is accessible, then reads of `aarsize` less than
2465    /// or equal to the register’s actual size must be supported.
2466    ///
2467    /// This field controls the Argument Width as referenced in Table 3.1.
2468    pub u8, from into RiscvBusAccess, _, set_aarsize: 22, 20;
2469    /// 0: No effect. This variant must be supported.\
2470    /// 1: After a successful register access, `regno` is incremented (wrapping around to 0). Supporting
2471    /// this variant is optional.
2472    pub _, set_aarpostincrement: 19;
2473    /// 0: No effect. This variant must be supported, and
2474    /// is the only supported one if `progbufsize` is 0.\
2475    /// 1: Execute the program in the Program Buffer
2476    /// exactly once after performing the transfer, if any.
2477    /// Supporting this variant is optional.
2478    pub _, set_postexec: 18;
2479    /// 0: Don’t do the operation specified by write.\
2480    /// 1: Do the operation specified by write.
2481    /// This bit can be used to just execute the Program Buffer without having to worry about placing valid values into `aarsize` or `regno`
2482    pub _, set_transfer: 17;
2483    /// When transfer is set: 0: Copy data from the specified register into arg0 portion of data.
2484    /// 1: Copy data from arg0 portion of data into the
2485    /// specified register.
2486    pub _, set_write: 16;
2487    /// Number of the register to access, as described in
2488    /// Table 3.3. dpc may be used as an alias for PC if
2489    /// this command is supported on a non-halted hart.
2490    pub _, set_regno: 15, 0;
2491}
2492
2493memory_mapped_bitfield_register! {
2494    /// System Bus Access Control and Status (see 3.12.18)
2495    pub struct Sbcs(u32);
2496    0x38, "sbcs",
2497    impl From;
2498    /// 0: The System Bus interface conforms to mainline
2499    /// drafts of this spec older than 1 January, 2018.\
2500    /// 1: The System Bus interface conforms to this version of the spec.
2501    ///
2502    /// Other values are reserved for future versions
2503    sbversion, _: 31, 29;
2504    /// Set when the debugger attempts to read data
2505    /// while a read is in progress, or when the debugger initiates a new access while one is already in
2506    /// progress (while `sbbusy` is set). It remains set until
2507    /// it’s explicitly cleared by the debugger.
2508    /// While this field is set, no more system bus accesses
2509    /// can be initiated by the Debug Module.
2510    sbbusyerror, set_sbbusyerror: 22;
2511    /// When 1, indicates the system bus master is busy.
2512    /// (Whether the system bus itself is busy is related,
2513    /// but not the same thing.) This bit goes high immediately when a read or write is requested for
2514    /// any reason, and does not go low until the access
2515    /// is fully completed.
2516    ///
2517    /// Writes to `sbcs` while `sbbusy` is high result in undefined behavior. A debugger must not write to
2518    /// sbcs until it reads `sbbusy` as 0.
2519    sbbusy, _: 21;
2520    /// When 1, every write to `sbaddress0` automatically
2521    /// triggers a system bus read at the new address.
2522    sbreadonaddr, set_sbreadonaddr: 20;
2523    /// Select the access size to use for system bus accesses.
2524    ///
2525    /// 0: 8-bit\
2526    /// 1: 16-bit\
2527    /// 2: 32-bit\
2528    /// 3: 64-bit\
2529    /// 4: 128-bit
2530    ///
2531    /// If `sbaccess` has an unsupported value when the
2532    /// DM starts a bus access, the access is not performed and `sberror` is set to 4.
2533    sbaccess, set_sbaccess: 19, 17;
2534    /// When 1, `sbaddress` is incremented by the access
2535    /// size (in bytes) selected in `sbaccess` after every system bus access.
2536    sbautoincrement, set_sbautoincrement: 16;
2537    /// When 1, every read from `sbdata0` automatically
2538    /// triggers a system bus read at the (possibly autoincremented) address.
2539    sbreadondata, set_sbreadondata: 15;
2540    /// When the Debug Module’s system bus master encounters an error, this field gets set. The bits in
2541    /// this field remain set until they are cleared by writing 1 to them. While this field is non-zero, no
2542    /// more system bus accesses can be initiated by the
2543    /// Debug Module.
2544    /// An implementation may report “Other” (7) for any error condition.
2545    ///
2546    /// 0: There was no bus error.\
2547    /// 1: There was a timeout.\
2548    /// 2: A bad address was accessed.\
2549    /// 3: There was an alignment error.\
2550    /// 4: An access of unsupported size was requested.\
2551    /// 7: Other.
2552    sberror, set_sberror: 14, 12;
2553    /// Width of system bus addresses in bits. (0 indicates there is no bus access support.)
2554    sbasize, _: 11, 5;
2555    /// 1 when 128-bit system bus accesses are supported.
2556    sbaccess128, _: 4;
2557    /// 1 when 64-bit system bus accesses are supported.
2558    sbaccess64, _: 3;
2559    /// 1 when 32-bit system bus accesses are supported.
2560    sbaccess32, _: 2;
2561    /// 1 when 16-bit system bus accesses are supported.
2562    sbaccess16, _: 1;
2563    /// 1 when 8-bit system bus accesses are supported.
2564    sbaccess8, _: 0;
2565}
2566
2567memory_mapped_bitfield_register! {
2568    /// Abstract Command Autoexec (see 3.12.8)
2569    #[derive(Eq, PartialEq)]
2570    pub struct Abstractauto(u32);
2571    0x18, "abstractauto",
2572    impl From;
2573    /// When a bit in this field is 1, read or write accesses to the corresponding `progbuf` word cause
2574    /// the command in command to be executed again.
2575    autoexecprogbuf, set_autoexecprogbuf: 31, 16;
2576    /// When a bit in this field is 1, read or write accesses to the corresponding data word cause the
2577    /// command in command to be executed again.
2578    autoexecdata, set_autoexecdata: 11, 0;
2579}
2580
2581memory_mapped_bitfield_register! {
2582    /// Abstract command register, located at address 0x17
2583    /// This is not for all commands, only for the ones
2584    /// from the debug spec. (see 3.6.1.3)
2585    pub struct AccessMemoryCommand(u32);
2586    0x17, "command",
2587    /// This is 2 to indicate Access Memory Command.
2588    _, set_cmd_type: 31, 24;
2589    /// An implementation does not have to implement
2590    /// both virtual and physical accesses, but it must
2591    /// fail accesses that it doesn’t support.
2592    ///
2593    /// 0: Addresses are physical (to the hart they are
2594    /// performed on).\
2595    /// 1: Addresses are virtual, and translated the way
2596    /// they would be from M-mode, with `MPRV` set.
2597    pub _, set_aamvirtual: 23;
2598    /// 0: Access the lowest 8 bits of the memory location.\
2599    /// 1: Access the lowest 16 bits of the memory location.\
2600    /// 2: Access the lowest 32 bits of the memory location.\
2601    /// 3: Access the lowest 64 bits of the memory location.\
2602    /// 4: Access the lowest 128 bits of the memory location.
2603    pub _, set_aamsize: 22,20;
2604    /// After a memory access has completed, if this bit
2605    /// is 1, increment arg1 (which contains the address
2606    /// used) by the number of bytes encoded in `aamsize`.
2607    pub _, set_aampostincrement: 19;
2608    /// 0: Copy data from the memory location specified
2609    /// in arg1 into arg0 portion of data.\
2610    /// 1: Copy data from arg0 portion of data into the
2611    /// memory location specified in arg1.
2612    pub _, set_write: 16;
2613    /// These bits are reserved for target-specific uses.
2614    pub _, set_target_specific: 15, 14;
2615}
2616
2617impl From<AccessMemoryCommand> for u32 {
2618    fn from(register: AccessMemoryCommand) -> Self {
2619        let mut reg = register;
2620        reg.set_cmd_type(2);
2621        reg.0
2622    }
2623}
2624
2625impl From<u32> for AccessMemoryCommand {
2626    fn from(value: u32) -> Self {
2627        Self(value)
2628    }
2629}
2630
2631memory_mapped_bitfield_register! { pub struct Sbaddress0(u32); 0x39, "sbaddress0", impl From; }
2632memory_mapped_bitfield_register! { pub struct Sbaddress1(u32); 0x3a, "sbaddress1", impl From; }
2633memory_mapped_bitfield_register! { pub struct Sbaddress2(u32); 0x3b, "sbaddress2", impl From; }
2634memory_mapped_bitfield_register! { pub struct Sbaddress3(u32); 0x37, "sbaddress3", impl From; }
2635
2636memory_mapped_bitfield_register! { pub struct Sbdata0(u32); 0x3c, "sbdata0", impl From; }
2637memory_mapped_bitfield_register! { pub struct Sbdata1(u32); 0x3d, "sbdata1", impl From; }
2638memory_mapped_bitfield_register! { pub struct Sbdata2(u32); 0x3e, "sbdata2", impl From; }
2639memory_mapped_bitfield_register! { pub struct Sbdata3(u32); 0x3f, "sbdata3", impl From; }
2640
2641memory_mapped_bitfield_register! { pub struct Confstrptr0(u32); 0x19, "confstrptr0", impl From; }
2642memory_mapped_bitfield_register! { pub struct Confstrptr1(u32); 0x1a, "confstrptr1", impl From; }
2643memory_mapped_bitfield_register! { pub struct Confstrptr2(u32); 0x1b, "confstrptr2", impl From; }
2644memory_mapped_bitfield_register! { pub struct Confstrptr3(u32); 0x1c, "confstrptr3", impl From; }