probe_rs/architecture/riscv/
mod.rs

1//! All the interface bits for RISC-V.
2
3use crate::{
4    CoreInterface, CoreRegister, CoreStatus, CoreType, Error, HaltReason, InstructionSet,
5    MemoryInterface, MemoryMappedRegister,
6    architecture::riscv::sequences::RiscvDebugSequence,
7    core::{
8        Architecture, BreakpointCause, CoreInformation, CoreRegisters, RegisterId, RegisterValue,
9    },
10    memory::{CoreMemoryInterface, valid_32bit_address},
11    memory_mapped_bitfield_register,
12    probe::DebugProbeError,
13    semihosting::SemihostingCommand,
14    semihosting::decode_semihosting_syscall,
15};
16use bitfield::bitfield;
17use communication_interface::{AbstractCommandErrorKind, RiscvCommunicationInterface, RiscvError};
18use registers::{FP, RA, RISCV_CORE_REGISTERS, RISCV_WITH_FP_CORE_REGISTERS, SP};
19use std::{
20    sync::Arc,
21    time::{Duration, Instant},
22};
23
24#[macro_use]
25pub mod registers;
26pub use registers::PC;
27pub(crate) mod assembly;
28pub mod communication_interface;
29pub(crate) mod dtm;
30pub mod sequences;
31
32pub use dtm::jtag_dtm::JtagDtmBuilder;
33
34/// An interface to operate a RISC-V core.
35pub struct Riscv32<'state> {
36    interface: RiscvCommunicationInterface<'state>,
37    state: &'state mut RiscvCoreState,
38    sequence: Arc<dyn RiscvDebugSequence>,
39}
40
41impl<'state> Riscv32<'state> {
42    /// Create a new RISC-V interface for a particular hart.
43    pub fn new(
44        interface: RiscvCommunicationInterface<'state>,
45        state: &'state mut RiscvCoreState,
46        sequence: Arc<dyn RiscvDebugSequence>,
47    ) -> Result<Self, RiscvError> {
48        // Determine FPU presence from MISA extensions (F, D, or Q)
49        let mut tmp_interface = interface;
50        let misa_val = tmp_interface
51            .read_csr(Misa::get_mmio_address() as u16)
52            .unwrap_or(0);
53        let isa_extensions = Misa::from(misa_val).extensions();
54        let fp_mask = (1 << 3) | (1 << 5) | (1 << 16);
55        state.fp_present = isa_extensions & fp_mask != 0;
56
57        Ok(Self {
58            interface: tmp_interface,
59            state,
60            sequence,
61        })
62    }
63
64    fn read_csr(&mut self, address: u16) -> Result<u32, RiscvError> {
65        self.interface.read_csr(address)
66    }
67
68    fn write_csr(&mut self, address: u16, value: u32) -> Result<(), RiscvError> {
69        tracing::debug!("Writing CSR {:#x}", address);
70
71        match self.interface.abstract_cmd_register_write(address, value) {
72            Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::NotSupported)) => {
73                tracing::debug!(
74                    "Could not write core register {:#x} with abstract command, falling back to program buffer",
75                    address
76                );
77                self.interface.write_csr_progbuf(address, value)
78            }
79            other => other,
80        }
81    }
82
83    /// Resume the core.
84    fn resume_core(&mut self) -> Result<(), crate::Error> {
85        self.state.semihosting_command = None;
86        self.interface.resume_core()?;
87
88        Ok(())
89    }
90
91    /// Check if the current breakpoint is a semihosting call
92    fn check_for_semihosting(&mut self) -> Result<Option<SemihostingCommand>, Error> {
93        // The Riscv Semihosting Specification, specificies the following sequence of instructions,
94        // to trigger a semihosting call:
95        // <https://github.com/riscv-software-src/riscv-semihosting/blob/main/riscv-semihosting-spec.adoc>
96
97        const TRAP_INSTRUCTIONS: [u32; 3] = [
98            0x01f01013, // slli x0, x0, 0x1f (Entry Nop)
99            0x00100073, // ebreak (Break to debugger)
100            0x40705013, // srai x0, x0, 7 (NOP encoding the semihosting call number 7)
101        ];
102
103        // We only want to decode the semihosting command once, since answering it might change some of the registers
104        if let Some(command) = self.state.semihosting_command {
105            return Ok(Some(command));
106        }
107
108        let pc: u32 = self.read_core_reg(self.program_counter().id)?.try_into()?;
109
110        // Read the actual instructions, starting at the instruction before the ebreak (PC-4)
111        let mut actual_instructions = [0u32; 3];
112        self.read_32((pc - 4) as u64, &mut actual_instructions)?;
113        let actual_instructions = actual_instructions.as_slice();
114
115        tracing::debug!(
116            "Semihosting check pc={pc:#x} instructions={0:#08x} {1:#08x} {2:#08x}",
117            actual_instructions[0],
118            actual_instructions[1],
119            actual_instructions[2]
120        );
121
122        let command = if TRAP_INSTRUCTIONS == actual_instructions {
123            let syscall = decode_semihosting_syscall(self)?;
124            if let SemihostingCommand::Unknown(details) = syscall {
125                self.sequence
126                    .clone()
127                    .on_unknown_semihosting_command(self, details)?
128            } else {
129                Some(syscall)
130            }
131        } else {
132            None
133        };
134        self.state.semihosting_command = command;
135
136        Ok(command)
137    }
138
139    fn determine_number_of_hardware_breakpoints(&mut self) -> Result<u32, RiscvError> {
140        tracing::debug!("Determining number of HW breakpoints supported");
141
142        let tselect = 0x7a0;
143        let tdata1 = 0x7a1;
144        let tinfo = 0x7a4;
145
146        let mut tselect_index = 0;
147
148        // These steps follow the debug specification 0.13, section 5.1 Enumeration
149        loop {
150            tracing::debug!("Trying tselect={}", tselect_index);
151            if let Err(e) = self.write_csr(tselect, tselect_index) {
152                match e {
153                    RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception) => break,
154                    other_error => return Err(other_error),
155                }
156            }
157
158            let readback = self.read_csr(tselect)?;
159
160            if readback != tselect_index {
161                break;
162            }
163
164            match self.read_csr(tinfo) {
165                Ok(tinfo_val) => {
166                    if tinfo_val & 0xffff == 1 {
167                        // Trigger doesn't exist, break the loop
168                        break;
169                    } else {
170                        tracing::info!(
171                            "Discovered trigger with index {} and type {}",
172                            tselect_index,
173                            tinfo_val & 0xffff
174                        );
175                    }
176                }
177                Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception)) => {
178                    // An exception means we have to read tdata1 to discover the type
179                    let tdata_val = self.read_csr(tdata1)?;
180
181                    // Read the mxl field from the misa register (see RISC-V Privileged Spec, 3.1.1)
182                    let misa_value = Misa(self.read_csr(0x301)?);
183                    let xlen = u32::pow(2, misa_value.mxl() + 4);
184
185                    let trigger_type = tdata_val >> (xlen - 4);
186
187                    if trigger_type == 0 {
188                        break;
189                    }
190
191                    tracing::info!(
192                        "Discovered trigger with index {} and type {}",
193                        tselect_index,
194                        trigger_type,
195                    );
196                }
197                Err(other) => return Err(other),
198            }
199
200            tselect_index += 1;
201        }
202
203        tracing::debug!("Target supports {} breakpoints.", tselect_index);
204
205        Ok(tselect_index)
206    }
207
208    fn on_halted(&mut self) -> Result<(), Error> {
209        let status = self.status()?;
210        tracing::debug!("Core halted: {:#?}", status);
211
212        if status.is_halted() {
213            self.sequence.on_halt(&mut self.interface)?;
214        }
215
216        Ok(())
217    }
218}
219
220impl CoreInterface for Riscv32<'_> {
221    fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), crate::Error> {
222        self.interface.wait_for_core_halted(timeout)?;
223        self.on_halted()?;
224        self.state.pc_written = false;
225        Ok(())
226    }
227
228    fn core_halted(&mut self) -> Result<bool, crate::Error> {
229        Ok(self.interface.core_halted()?)
230    }
231
232    fn status(&mut self) -> Result<crate::core::CoreStatus, crate::Error> {
233        // TODO: We should use hartsum to determine if any hart is halted
234        //       quickly
235
236        let status: Dmstatus = self.interface.read_dm_register()?;
237
238        if status.allhalted() {
239            // determine reason for halt
240            let dcsr = Dcsr(self.read_core_reg(RegisterId::from(0x7b0))?.try_into()?);
241
242            let reason = match dcsr.cause() {
243                // An ebreak instruction was hit
244                1 => {
245                    // The chip initiated this halt, therefore we need to update pc_written state
246                    self.state.pc_written = false;
247                    if let Some(cmd) = self.check_for_semihosting()? {
248                        HaltReason::Breakpoint(BreakpointCause::Semihosting(cmd))
249                    } else {
250                        HaltReason::Breakpoint(BreakpointCause::Software)
251                    }
252                    // TODO: Add testcase to probe-rs-debugger-test to validate semihosting exit/abort work and unknown semihosting operations are skipped
253                }
254                // Trigger module caused halt
255                2 => HaltReason::Breakpoint(BreakpointCause::Hardware),
256                // Debugger requested a halt
257                3 => HaltReason::Request,
258                // Core halted after single step
259                4 => HaltReason::Step,
260                // Core halted directly after reset
261                5 => HaltReason::Exception,
262                // Reserved for future use in specification
263                _ => HaltReason::Unknown,
264            };
265
266            Ok(CoreStatus::Halted(reason))
267        } else if status.allrunning() {
268            Ok(CoreStatus::Running)
269        } else {
270            Err(Error::Other(
271                "Some cores are running while some are halted, this should not happen.".to_string(),
272            ))
273        }
274    }
275
276    fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
277        self.interface.halt(timeout)?;
278        self.on_halted()?;
279        Ok(self.interface.core_info()?)
280    }
281
282    fn run(&mut self) -> Result<(), Error> {
283        if !self.state.pc_written {
284            // Before we run, we always perform a single instruction step, to account for possible breakpoints that might get us stuck on the current instruction.
285            self.step()?;
286        }
287
288        // resume the core.
289        self.resume_core()?;
290
291        Ok(())
292    }
293
294    fn reset(&mut self) -> Result<(), Error> {
295        self.reset_and_halt(Duration::from_secs(1))?;
296        self.resume_core()?;
297
298        Ok(())
299    }
300
301    fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
302        self.sequence
303            .reset_system_and_halt(&mut self.interface, timeout)?;
304
305        self.on_halted()?;
306        let pc = self.read_core_reg(RegisterId(0x7b1))?;
307
308        Ok(CoreInformation { pc: pc.try_into()? })
309    }
310
311    fn step(&mut self) -> Result<CoreInformation, crate::Error> {
312        let halt_reason = self.status()?;
313        if matches!(
314            halt_reason,
315            CoreStatus::Halted(HaltReason::Breakpoint(
316                BreakpointCause::Software | BreakpointCause::Semihosting(_)
317            ))
318        ) {
319            // If we are halted on a software breakpoint, we can skip the single step and manually advance the dpc.
320            let mut debug_pc = self.read_core_reg(RegisterId(0x7b1))?;
321            // Advance the dpc by the size of the EBREAK (ebreak or c.ebreak) instruction.
322            if matches!(self.instruction_set()?, InstructionSet::RV32C) {
323                // We may have been halted by either an EBREAK or a C.EBREAK instruction.
324                // We need to read back the instruction to determine how many bytes we need to skip.
325                let instruction = self.read_word_32(debug_pc.try_into().unwrap())?;
326                if instruction & 0x3 != 0x3 {
327                    // Compressed instruction.
328                    debug_pc.increment_address(2)?;
329                } else {
330                    debug_pc.increment_address(4)?;
331                }
332            } else {
333                debug_pc.increment_address(4)?;
334            }
335
336            self.write_core_reg(RegisterId(0x7b1), debug_pc)?;
337            return Ok(CoreInformation {
338                pc: debug_pc.try_into()?,
339            });
340        } else if matches!(
341            halt_reason,
342            CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
343        ) {
344            // If we are halted on a hardware breakpoint.
345            self.enable_breakpoints(false)?;
346        }
347
348        let mut dcsr = Dcsr(self.read_core_reg(RegisterId(0x7b0))?.try_into()?);
349        // Set it up, so that the next `self.run()` will only do a single step
350        dcsr.set_step(true);
351        // Disable any interrupts during single step.
352        dcsr.set_stepie(false);
353        dcsr.set_stopcount(true);
354        self.write_csr(0x7b0, dcsr.0)?;
355
356        // Now we can resume the core for the single step.
357        self.resume_core()?;
358        self.wait_for_core_halted(Duration::from_millis(100))?;
359
360        let pc = self.read_core_reg(RegisterId(0x7b1))?;
361
362        // clear step request
363        let mut dcsr = Dcsr(self.read_core_reg(RegisterId(0x7b0))?.try_into()?);
364        dcsr.set_step(false);
365        //Re-enable interrupts for single step.
366        dcsr.set_stepie(true);
367        dcsr.set_stopcount(false);
368        self.write_csr(0x7b0, dcsr.0)?;
369
370        // Re-enable breakpoints before we continue.
371        if matches!(
372            halt_reason,
373            CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
374        ) {
375            // If we are halted on a hardware breakpoint.
376            self.enable_breakpoints(true)?;
377        }
378
379        self.on_halted()?;
380        self.state.pc_written = false;
381        Ok(CoreInformation { pc: pc.try_into()? })
382    }
383
384    fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, crate::Error> {
385        self.read_csr(address.0)
386            .map(|v| v.into())
387            .map_err(|e| e.into())
388    }
389
390    fn write_core_reg(
391        &mut self,
392        address: RegisterId,
393        value: RegisterValue,
394    ) -> Result<(), crate::Error> {
395        let value: u32 = value.try_into()?;
396
397        if address == self.program_counter().id {
398            self.state.pc_written = true;
399        }
400
401        self.write_csr(address.0, value).map_err(|e| e.into())
402    }
403
404    fn available_breakpoint_units(&mut self) -> Result<u32, crate::Error> {
405        match self.state.hw_breakpoints {
406            Some(bp) => Ok(bp),
407            None => {
408                let bp = self.determine_number_of_hardware_breakpoints()?;
409                self.state.hw_breakpoints = Some(bp);
410                Ok(bp)
411            }
412        }
413    }
414
415    /// See docs on the [`CoreInterface::hw_breakpoints`] trait
416    /// NOTE: For riscv, this assumes that only execution breakpoints are used.
417    fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
418        // this can be called w/o halting the core via Session::new - temporarily halt if not halted
419
420        let was_running = !self.core_halted()?;
421        if was_running {
422            self.halt(Duration::from_millis(100))?;
423        }
424
425        let tselect = 0x7a0;
426        let tdata1 = 0x7a1;
427        let tdata2 = 0x7a2;
428
429        let mut breakpoints = vec![];
430        let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
431        for bp_unit_index in 0..num_hw_breakpoints {
432            // Select the trigger.
433            self.write_csr(tselect, bp_unit_index as u32)?;
434
435            // Read the trigger "configuration" data.
436            let tdata_value = Mcontrol(self.read_csr(tdata1)?);
437
438            tracing::debug!("Breakpoint {}: {:?}", bp_unit_index, tdata_value);
439
440            // The trigger must be active in at least a single mode
441            let trigger_any_mode_active = tdata_value.m() || tdata_value.s() || tdata_value.u();
442
443            let trigger_any_action_enabled =
444                tdata_value.execute() || tdata_value.store() || tdata_value.load();
445
446            // Only return if the trigger if it is for an execution debug action in all modes.
447            if tdata_value.type_() == 0b10
448                && tdata_value.action() == 1
449                && tdata_value.match_() == 0
450                && trigger_any_mode_active
451                && trigger_any_action_enabled
452            {
453                let breakpoint = self.read_csr(tdata2)?;
454                breakpoints.push(Some(breakpoint as u64));
455            } else {
456                breakpoints.push(None);
457            }
458        }
459
460        if was_running {
461            self.resume_core()?;
462        }
463
464        Ok(breakpoints)
465    }
466
467    fn enable_breakpoints(&mut self, state: bool) -> Result<(), crate::Error> {
468        // Loop through all triggers, and enable/disable them.
469        let tselect = 0x7a0;
470        let tdata1 = 0x7a1;
471
472        for bp_unit_index in 0..self.available_breakpoint_units()? as usize {
473            // Select the trigger.
474            self.write_csr(tselect, bp_unit_index as u32)?;
475
476            // Read the trigger "configuration" data.
477            let mut tdata_value = Mcontrol(self.read_csr(tdata1)?);
478
479            // Only modify the trigger if it is for an execution debug action in all modes(probe-rs enabled it) or no modes (we previously disabled it).
480            if tdata_value.type_() == 2
481                && tdata_value.action() == 1
482                && tdata_value.match_() == 0
483                && tdata_value.execute()
484                && ((tdata_value.m() && tdata_value.u()) || (!tdata_value.m() && !tdata_value.u()))
485            {
486                tracing::debug!(
487                    "Will modify breakpoint enabled={} for {}: {:?}",
488                    state,
489                    bp_unit_index,
490                    tdata_value
491                );
492                tdata_value.set_m(state);
493                tdata_value.set_u(state);
494                self.write_csr(tdata1, tdata_value.0)?;
495            }
496        }
497
498        self.state.hw_breakpoints_enabled = state;
499        Ok(())
500    }
501
502    fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), crate::Error> {
503        let addr = valid_32bit_address(addr)?;
504
505        // select requested trigger
506        let tselect = 0x7a0;
507        let tdata1 = 0x7a1;
508        let tdata2 = 0x7a2;
509
510        tracing::info!("Setting breakpoint {}", bp_unit_index);
511
512        self.write_csr(tselect, bp_unit_index as u32)?;
513
514        // verify the trigger has the correct type
515
516        let tdata_value = Mcontrol(self.read_csr(tdata1)?);
517
518        // This should not happen
519        let trigger_type = tdata_value.type_();
520        if trigger_type != 0b10 {
521            return Err(RiscvError::UnexpectedTriggerType(trigger_type).into());
522        }
523
524        // Setup the trigger
525
526        let mut instruction_breakpoint = Mcontrol(0);
527
528        // Enter debug mode
529        instruction_breakpoint.set_action(1);
530
531        // Match exactly the value in tdata2
532        instruction_breakpoint.set_type(2);
533        instruction_breakpoint.set_match(0);
534
535        instruction_breakpoint.set_m(true);
536
537        instruction_breakpoint.set_u(true);
538
539        // Trigger when instruction is executed
540        instruction_breakpoint.set_execute(true);
541
542        instruction_breakpoint.set_dmode(true);
543
544        // Match address
545        instruction_breakpoint.set_select(false);
546
547        self.write_csr(tdata1, 0)?;
548        self.write_csr(tdata2, addr)?;
549        self.write_csr(tdata1, instruction_breakpoint.0)?;
550
551        Ok(())
552    }
553
554    fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), crate::Error> {
555        // this can be called w/o halting the core via Session::new - temporarily halt if not halted
556        tracing::info!("Clearing breakpoint {}", unit_index);
557
558        let was_running = !self.core_halted()?;
559        if was_running {
560            self.halt(Duration::from_millis(100))?;
561        }
562
563        let tselect = 0x7a0;
564        let tdata1 = 0x7a1;
565        let tdata2 = 0x7a2;
566
567        self.write_csr(tselect, unit_index as u32)?;
568        self.write_csr(tdata1, 0)?;
569        self.write_csr(tdata2, 0)?;
570
571        if was_running {
572            self.resume_core()?;
573        }
574
575        Ok(())
576    }
577
578    fn registers(&self) -> &'static CoreRegisters {
579        if self.state.fp_present {
580            &RISCV_WITH_FP_CORE_REGISTERS
581        } else {
582            &RISCV_CORE_REGISTERS
583        }
584    }
585
586    fn program_counter(&self) -> &'static CoreRegister {
587        &PC
588    }
589
590    fn frame_pointer(&self) -> &'static CoreRegister {
591        &FP
592    }
593
594    fn stack_pointer(&self) -> &'static CoreRegister {
595        &SP
596    }
597
598    fn return_address(&self) -> &'static CoreRegister {
599        &RA
600    }
601
602    fn hw_breakpoints_enabled(&self) -> bool {
603        self.state.hw_breakpoints_enabled
604    }
605
606    fn debug_on_sw_breakpoint(&mut self, enabled: bool) -> Result<(), Error> {
607        self.interface.debug_on_sw_breakpoint(enabled)?;
608        Ok(())
609    }
610
611    fn architecture(&self) -> Architecture {
612        Architecture::Riscv
613    }
614
615    fn core_type(&self) -> CoreType {
616        CoreType::Riscv
617    }
618
619    fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
620        let misa_value = Misa(self.read_csr(0x301)?);
621
622        // Check if the Bit at position 2 (signifies letter C, for compressed) is set.
623        if misa_value.extensions() & (1 << 2) != 0 {
624            Ok(InstructionSet::RV32C)
625        } else {
626            Ok(InstructionSet::RV32)
627        }
628    }
629
630    /// Returns the number of fpu registers defined in this register file, or `None` if there are none.
631    fn floating_point_register_count(&mut self) -> Result<usize, Error> {
632        Ok(self
633            .registers()
634            .all_registers()
635            .filter(|r| r.register_has_role(crate::RegisterRole::FloatingPoint))
636            .count())
637    }
638
639    fn fpu_support(&mut self) -> Result<bool, crate::error::Error> {
640        Ok(self.state.fp_present)
641    }
642
643    fn reset_catch_set(&mut self) -> Result<(), Error> {
644        self.sequence.reset_catch_set(&mut self.interface)?;
645        Ok(())
646    }
647
648    fn reset_catch_clear(&mut self) -> Result<(), Error> {
649        self.sequence.reset_catch_clear(&mut self.interface)?;
650        Ok(())
651    }
652
653    fn debug_core_stop(&mut self) -> Result<(), Error> {
654        self.interface.disable_debug_module()?;
655        Ok(())
656    }
657}
658
659impl CoreMemoryInterface for Riscv32<'_> {
660    type ErrorType = Error;
661
662    fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
663        &self.interface
664    }
665    fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
666        &mut self.interface
667    }
668}
669
670#[derive(Debug)]
671/// Flags used to control the [`SpecificCoreState`](crate::core::SpecificCoreState) for RiscV architecture
672pub struct RiscvCoreState {
673    /// A flag to remember whether we want to use hw_breakpoints during stepping of the core.
674    hw_breakpoints_enabled: bool,
675
676    hw_breakpoints: Option<u32>,
677
678    /// Whether the PC was written since we last halted. Used to avoid incrementing the PC on
679    /// resume.
680    pc_written: bool,
681
682    /// The semihosting command that was decoded at the current program counter
683    semihosting_command: Option<SemihostingCommand>,
684
685    /// Whether the core has FPU support (F, D, or Q extensions present)
686    fp_present: bool,
687}
688
689impl RiscvCoreState {
690    pub(crate) fn new() -> Self {
691        Self {
692            hw_breakpoints_enabled: false,
693            hw_breakpoints: None,
694            pc_written: false,
695            semihosting_command: None,
696            fp_present: false,
697        }
698    }
699}
700
701memory_mapped_bitfield_register! {
702    /// `dmcontrol` register, located at address 0x10
703    pub struct Dmcontrol(u32);
704    0x10, "dmcontrol",
705    impl From;
706
707    /// Requests the currently selected harts to halt.
708    pub _, set_haltreq: 31;
709
710    /// Requests the currently selected harts to resume.
711    pub _, set_resumereq: 30;
712
713    /// Requests the currently selected harts to reset. Optional.
714    pub hartreset, set_hartreset: 29;
715
716    /// Writing 1 clears the `havereset` flag of selected harts.
717    pub _, set_ackhavereset: 28;
718
719    /// Selects the definition of currently selected harts. If 1, multiple harts may be selected.
720    pub hasel, set_hasel: 26;
721
722    /// The lower 10 bits of the currently selected harts.
723    pub hartsello, set_hartsello: 25, 16;
724
725    /// The upper 10 bits of the currently selected harts.
726    pub hartselhi, set_hartselhi: 15, 6;
727
728    /// Writes the halt-on-reset request bit for all currently selected hart. Optional.
729    pub _, set_resethaltreq: 3;
730
731    /// Clears the halt-on-reset request bit for all currently selected harts. Optional.
732    pub _, set_clrresethaltreq: 2;
733
734    /// This bit controls the reset signal from the DM to the rest of the system.
735    pub ndmreset, set_ndmreset: 1;
736
737    /// Reset signal for the debug module.
738    pub dmactive, set_dmactive: 0;
739}
740
741impl Dmcontrol {
742    /// Currently selected harts
743    ///
744    /// Combination of the `hartselhi` and `hartsello` registers.
745    pub fn hartsel(&self) -> u32 {
746        (self.hartselhi() << 10) | self.hartsello()
747    }
748
749    /// Set the currently selected harts
750    ///
751    /// This sets the `hartselhi` and `hartsello` registers.
752    /// This is a 20 bit register, larger values will be truncated.
753    pub fn set_hartsel(&mut self, value: u32) {
754        self.set_hartsello(value & 0x3ff);
755        self.set_hartselhi((value >> 10) & 0x3ff);
756    }
757}
758
759memory_mapped_bitfield_register! {
760    /// Readonly `dmstatus` register.
761    ///
762    /// Located at address 0x11
763    pub struct Dmstatus(u32);
764    0x11, "dmstatus",
765    impl From;
766
767    /// If 1, then there is an implicit ebreak instruction
768    /// at the non-existent word immediately after the
769    /// Program Buffer. This saves the debugger from
770    /// having to write the ebreak itself, and allows the
771    /// Program Buffer to be one word smaller.
772    /// This must be 1 when progbufsize is 1.
773    pub impebreak, _: 22;
774
775    /// This field is 1 when all currently selected harts
776    /// have been reset and reset has not been acknowledged for any of them.
777    pub allhavereset, _: 19;
778
779    /// This field is 1 when at least one currently selected hart
780    /// has been reset and reset has not been acknowledged for any of them.
781    pub anyhavereset, _: 18;
782
783    /// This field is 1 when all currently selected harts
784    /// have acknowledged their last resume request.
785    pub allresumeack, _: 17;
786
787    /// This field is 1 when any currently selected hart
788    /// has acknowledged its last resume request.
789    pub anyresumeack, _: 16;
790
791    /// This field is 1 when all currently selected harts do
792    /// not exist in this platform.
793    pub allnonexistent, _: 15;
794
795    /// This field is 1 when any currently selected hart
796    /// does not exist in this platform.
797    pub anynonexistent, _: 14;
798
799    /// This field is 1 when all currently selected harts are unavailable.
800    pub allunavail, _: 13;
801
802    /// This field is 1 when any currently selected hart is unavailable.
803    pub anyunavail, _: 12;
804
805    /// This field is 1 when all currently selected harts are running.
806    pub allrunning, _: 11;
807
808    /// This field is 1 when any currently selected hart is running.
809    pub anyrunning, _: 10;
810
811    /// This field is 1 when all currently selected harts are halted.
812    pub allhalted, _: 9;
813
814    /// This field is 1 when any currently selected hart is halted.
815    pub anyhalted, _: 8;
816
817    /// If 0, authentication is required before using the DM.
818    pub authenticated, _: 7;
819
820    /// If 0, the authentication module is ready to process the next read/write to `authdata`.
821    pub authbusy, _: 6;
822
823    /// 1 if this Debug Module supports halt-on-reset functionality controllable by the
824    /// `setresethaltreq` and `clrresethaltreq` bits.
825    pub hasresethaltreq, _: 5;
826
827    /// 1 if `confstrptr0`–`confstrptr3` hold the address of the configuration string.
828    pub confstrptrvalid, _: 4;
829
830    /// Version of the debug module.
831    pub version, _: 3, 0;
832}
833
834bitfield! {
835    struct Dcsr(u32);
836    impl Debug;
837
838    xdebugver, _: 31, 28;
839    ebreakm, set_ebreakm: 15;
840    ebreaks, set_ebreaks: 13;
841    ebreaku, set_ebreaku: 12;
842    stepie, set_stepie: 11;
843    stopcount, set_stopcount: 10;
844    stoptime, set_stoptime: 9;
845    cause, set_cause: 8, 6;
846    mprven, set_mprven: 4;
847    nmip, _: 3;
848    step, set_step: 2;
849    prv, set_prv: 1,0;
850}
851
852memory_mapped_bitfield_register! {
853    /// Abstract Control and Status (see 3.12.6)
854    pub struct Abstractcs(u32);
855    0x16, "abstractcs",
856    impl From;
857
858    progbufsize, _: 28, 24;
859    busy, _: 12;
860    cmderr, set_cmderr: 10, 8;
861    datacount, _: 3, 0;
862}
863
864memory_mapped_bitfield_register! {
865    /// Hart Info (see 3.12.3)
866    pub struct Hartinfo(u32);
867    0x12, "hartinfo",
868    impl From;
869
870    nscratch, _: 23, 20;
871    dataaccess, _: 16;
872    datasize, _: 15, 12;
873    dataaddr, _: 11, 0;
874}
875
876memory_mapped_bitfield_register! { pub struct Data0(u32); 0x04, "data0", impl From; }
877memory_mapped_bitfield_register! { pub struct Data1(u32); 0x05, "data1", impl From; }
878memory_mapped_bitfield_register! { pub struct Data2(u32); 0x06, "data2", impl From; }
879memory_mapped_bitfield_register! { pub struct Data3(u32); 0x07, "data3", impl From; }
880memory_mapped_bitfield_register! { pub struct Data4(u32); 0x08, "data4", impl From; }
881memory_mapped_bitfield_register! { pub struct Data5(u32); 0x09, "data5", impl From; }
882memory_mapped_bitfield_register! { pub struct Data6(u32); 0x0A, "data6", impl From; }
883memory_mapped_bitfield_register! { pub struct Data7(u32); 0x0B, "data7", impl From; }
884memory_mapped_bitfield_register! { pub struct Data8(u32); 0x0C, "data8", impl From; }
885memory_mapped_bitfield_register! { pub struct Data9(u32); 0x0D, "data9", impl From; }
886memory_mapped_bitfield_register! { pub struct Data10(u32); 0x0E, "data10", impl From; }
887memory_mapped_bitfield_register! { pub struct Data11(u32); 0x0f, "data11", impl From; }
888
889memory_mapped_bitfield_register! { struct Command(u32); 0x17, "command", impl From; }
890
891memory_mapped_bitfield_register! { pub struct Progbuf0(u32); 0x20, "progbuf0", impl From; }
892memory_mapped_bitfield_register! { pub struct Progbuf1(u32); 0x21, "progbuf1", impl From; }
893memory_mapped_bitfield_register! { pub struct Progbuf2(u32); 0x22, "progbuf2", impl From; }
894memory_mapped_bitfield_register! { pub struct Progbuf3(u32); 0x23, "progbuf3", impl From; }
895memory_mapped_bitfield_register! { pub struct Progbuf4(u32); 0x24, "progbuf4", impl From; }
896memory_mapped_bitfield_register! { pub struct Progbuf5(u32); 0x25, "progbuf5", impl From; }
897memory_mapped_bitfield_register! { pub struct Progbuf6(u32); 0x26, "progbuf6", impl From; }
898memory_mapped_bitfield_register! { pub struct Progbuf7(u32); 0x27, "progbuf7", impl From; }
899memory_mapped_bitfield_register! { pub struct Progbuf8(u32); 0x28, "progbuf8", impl From; }
900memory_mapped_bitfield_register! { pub struct Progbuf9(u32); 0x29, "progbuf9", impl From; }
901memory_mapped_bitfield_register! { pub struct Progbuf10(u32); 0x2A, "progbuf10", impl From; }
902memory_mapped_bitfield_register! { pub struct Progbuf11(u32); 0x2B, "progbuf11", impl From; }
903memory_mapped_bitfield_register! { pub struct Progbuf12(u32); 0x2C, "progbuf12", impl From; }
904memory_mapped_bitfield_register! { pub struct Progbuf13(u32); 0x2D, "progbuf13", impl From; }
905memory_mapped_bitfield_register! { pub struct Progbuf14(u32); 0x2E, "progbuf14", impl From; }
906memory_mapped_bitfield_register! { pub struct Progbuf15(u32); 0x2F, "progbuf15", impl From; }
907
908bitfield! {
909    struct Mcontrol(u32);
910    impl Debug;
911
912    type_, set_type: 31, 28;
913    dmode, set_dmode: 27;
914    maskmax, _: 26, 21;
915    hit, set_hit: 20;
916    select, set_select: 19;
917    timing, set_timing: 18;
918    sizelo, set_sizelo: 17, 16;
919    action, set_action: 15, 12;
920    chain, set_chain: 11;
921    match_, set_match: 10, 7;
922    m, set_m: 6;
923    s, set_s: 4;
924    u, set_u: 3;
925    execute, set_execute: 2;
926    store, set_store: 1;
927    load, set_load: 0;
928}
929
930memory_mapped_bitfield_register! {
931    /// Isa and Extensions (see RISC-V Privileged Spec, 3.1.1)
932    pub struct Misa(u32);
933    0x301, "misa",
934    impl From;
935
936    /// Machine XLEN
937    mxl, _: 31, 30;
938    /// Standard RISC-V extensions
939    extensions, _: 25, 0;
940}