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