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