1use 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::decode_semihosting_syscall,
14 semihosting::{SemihostingCommand, UnknownCommandDetails},
15};
16use bitfield::bitfield;
17use communication_interface::{AbstractCommandErrorKind, RiscvCommunicationInterface, RiscvError};
18use registers::{FP, RA, RISCV_CORE_REGISTERS, RISCV_WITH_FP_CORE_REGISTERS, SP};
19use registers64::{FP64, PC64, RA64, RISCV64_CORE_REGISTERS, RISCV64_WITH_FP_CORE_REGISTERS, SP64};
20use std::{
21 marker::PhantomData,
22 sync::Arc,
23 time::{Duration, Instant},
24};
25
26#[macro_use]
27pub mod registers;
28pub mod registers64;
29pub use registers::PC;
30pub(crate) mod assembly;
31pub mod communication_interface;
32pub mod dtm;
33pub mod sequences;
34
35pub use dtm::jtag_dtm::JtagDtmBuilder;
36
37const SINGLE_STEP_TIMEOUT: Duration = Duration::from_millis(100);
39
40fn unpack_mcontrol64(raw: u64) -> (u32, Mcontrol) {
48 ((raw >> 60) as u32, Mcontrol(raw as u32))
49}
50
51fn repack_mcontrol64(raw: u64, ctrl: Mcontrol) -> u64 {
54 (raw & 0xFFFF_FFFF_0000_0000) | u64::from(ctrl.0)
55}
56
57mod sealed {
60 pub trait Sealed {}
61}
62
63pub trait XlenMode: sealed::Sealed + 'static {
69 fn configure_interface(interface: &mut RiscvCommunicationInterface);
71 fn core_type() -> CoreType;
73 fn registers(fp_present: bool) -> &'static CoreRegisters;
75 fn program_counter() -> &'static CoreRegister;
77 fn frame_pointer() -> &'static CoreRegister;
79 fn stack_pointer() -> &'static CoreRegister;
81 fn return_address() -> &'static CoreRegister;
83 fn csr_to_register_value(v: u64) -> RegisterValue;
85 fn register_value_to_csr(v: RegisterValue) -> Result<u64, Error>;
87 fn compressed_instruction_set() -> InstructionSet;
89 fn uncompressed_instruction_set() -> InstructionSet;
91 fn unpack_tdata1(raw: u64) -> (u32, u32);
96 fn repack_tdata1(raw: u64, ctrl_low32: u32) -> u64;
99 fn build_new_exec_tdata1(trigger_type: u32, ctrl_low32: u32) -> u64;
105 fn validate_bp_address(addr: u64) -> Result<u64, Error>;
107 fn handle_unknown_semihosting(
110 core: &mut RiscvCore<Self>,
111 details: UnknownCommandDetails,
112 ) -> Result<Option<SemihostingCommand>, Error>
113 where
114 Self: Sized;
115}
116
117pub struct Xlen32;
121pub struct Xlen64;
123
124impl sealed::Sealed for Xlen32 {}
125impl sealed::Sealed for Xlen64 {}
126
127impl XlenMode for Xlen32 {
128 fn configure_interface(_interface: &mut RiscvCommunicationInterface) {}
129
130 fn core_type() -> CoreType {
131 CoreType::Riscv
132 }
133
134 fn registers(fp_present: bool) -> &'static CoreRegisters {
135 if fp_present {
136 &RISCV_WITH_FP_CORE_REGISTERS
137 } else {
138 &RISCV_CORE_REGISTERS
139 }
140 }
141
142 fn program_counter() -> &'static CoreRegister {
143 &PC
144 }
145 fn frame_pointer() -> &'static CoreRegister {
146 &FP
147 }
148 fn stack_pointer() -> &'static CoreRegister {
149 &SP
150 }
151 fn return_address() -> &'static CoreRegister {
152 &RA
153 }
154
155 fn csr_to_register_value(v: u64) -> RegisterValue {
156 (v as u32).into()
157 }
158
159 fn register_value_to_csr(v: RegisterValue) -> Result<u64, Error> {
160 let u: u32 = v.try_into()?;
161 Ok(u64::from(u))
162 }
163
164 fn compressed_instruction_set() -> InstructionSet {
165 InstructionSet::RV32C
166 }
167 fn uncompressed_instruction_set() -> InstructionSet {
168 InstructionSet::RV32
169 }
170
171 fn unpack_tdata1(raw: u64) -> (u32, u32) {
172 debug_assert!(
173 raw <= u32::MAX as u64,
174 "RV32 tdata1 read returned value with high bits set"
175 );
176 let ctrl = Mcontrol(raw as u32);
177 (ctrl.type_(), ctrl.0)
178 }
179
180 fn repack_tdata1(_raw: u64, ctrl_low32: u32) -> u64 {
181 u64::from(ctrl_low32)
182 }
183
184 fn build_new_exec_tdata1(trigger_type: u32, ctrl_low32: u32) -> u64 {
185 let mut ctrl = Mcontrol(ctrl_low32);
186 ctrl.set_type(trigger_type);
187 ctrl.set_dmode(true);
188 u64::from(ctrl.0)
189 }
190
191 fn validate_bp_address(addr: u64) -> Result<u64, Error> {
192 valid_32bit_address(addr).map(u64::from)
193 }
194
195 fn handle_unknown_semihosting(
196 core: &mut RiscvCore<Xlen32>,
197 details: UnknownCommandDetails,
198 ) -> Result<Option<SemihostingCommand>, Error> {
199 core.sequence
200 .clone()
201 .on_unknown_semihosting_command(core, details)
202 }
203}
204
205impl XlenMode for Xlen64 {
206 fn configure_interface(interface: &mut RiscvCommunicationInterface) {
207 interface.set_xlen_64(true);
208 }
209
210 fn core_type() -> CoreType {
211 CoreType::Riscv64
212 }
213
214 fn registers(fp_present: bool) -> &'static CoreRegisters {
215 if fp_present {
216 &RISCV64_WITH_FP_CORE_REGISTERS
217 } else {
218 &RISCV64_CORE_REGISTERS
219 }
220 }
221
222 fn program_counter() -> &'static CoreRegister {
223 &PC64
224 }
225 fn frame_pointer() -> &'static CoreRegister {
226 &FP64
227 }
228 fn stack_pointer() -> &'static CoreRegister {
229 &SP64
230 }
231 fn return_address() -> &'static CoreRegister {
232 &RA64
233 }
234
235 fn csr_to_register_value(v: u64) -> RegisterValue {
236 RegisterValue::U64(v)
237 }
238
239 fn register_value_to_csr(v: RegisterValue) -> Result<u64, Error> {
240 v.try_into()
241 }
242
243 fn compressed_instruction_set() -> InstructionSet {
244 InstructionSet::RV64C
245 }
246 fn uncompressed_instruction_set() -> InstructionSet {
247 InstructionSet::RV64
248 }
249
250 fn unpack_tdata1(raw: u64) -> (u32, u32) {
251 let (trigger_type, ctrl) = unpack_mcontrol64(raw);
252 (trigger_type, ctrl.0)
253 }
254
255 fn repack_tdata1(raw: u64, ctrl_low32: u32) -> u64 {
256 repack_mcontrol64(raw, Mcontrol(ctrl_low32))
257 }
258
259 fn build_new_exec_tdata1(trigger_type: u32, ctrl_low32: u32) -> u64 {
260 (u64::from(trigger_type) << 60) | (1u64 << 59) | u64::from(ctrl_low32)
261 }
262
263 fn validate_bp_address(addr: u64) -> Result<u64, Error> {
264 Ok(addr)
265 }
266
267 fn handle_unknown_semihosting(
268 _core: &mut RiscvCore<Xlen64>,
269 details: UnknownCommandDetails,
270 ) -> Result<Option<SemihostingCommand>, Error> {
271 Ok(Some(SemihostingCommand::Unknown(details)))
272 }
273}
274
275pub struct RiscvCore<'state, X: XlenMode> {
282 interface: RiscvCommunicationInterface<'state>,
283 state: &'state mut RiscvCoreState,
284 sequence: Arc<dyn RiscvDebugSequence>,
285 _xlen: PhantomData<X>,
286}
287
288pub type Riscv32<'state> = RiscvCore<'state, Xlen32>;
290pub type Riscv64<'state> = RiscvCore<'state, Xlen64>;
292
293impl<'state> RiscvCore<'state, Xlen32> {
296 pub fn new(
298 interface: RiscvCommunicationInterface<'state>,
299 state: &'state mut RiscvCoreState,
300 sequence: Arc<dyn RiscvDebugSequence>,
301 ) -> Result<Self, RiscvError> {
302 Self::new_inner(interface, state, sequence)
303 }
304}
305
306impl<'state> RiscvCore<'state, Xlen64> {
307 pub fn new(
309 interface: RiscvCommunicationInterface<'state>,
310 state: &'state mut RiscvCoreState,
311 sequence: Arc<dyn RiscvDebugSequence>,
312 ) -> Result<Self, RiscvError> {
313 Self::new_inner(interface, state, sequence)
314 }
315}
316
317impl<'state, X: XlenMode> RiscvCore<'state, X> {
318 fn new_inner(
319 mut interface: RiscvCommunicationInterface<'state>,
320 state: &'state mut RiscvCoreState,
321 sequence: Arc<dyn RiscvDebugSequence>,
322 ) -> Result<Self, RiscvError> {
323 X::configure_interface(&mut interface);
324
325 if !state.misa_read {
326 let misa_val = interface
328 .read_csr(Misa::get_mmio_address() as u16)
329 .unwrap_or(0);
330 let isa_extensions = (misa_val & 0x3ff_ffff) as u32;
331 let fp_mask = (1 << 3) | (1 << 5) | (1 << 16);
332 state.fp_present = isa_extensions & fp_mask != 0;
333 state.misa_read = true;
334 }
335
336 Ok(Self {
337 interface,
338 state,
339 sequence,
340 _xlen: PhantomData,
341 })
342 }
343
344 fn resume_core(&mut self) -> Result<(), Error> {
347 self.state.semihosting_command = None;
348 self.interface.resume_core()?;
349 Ok(())
350 }
351
352 fn check_for_semihosting(&mut self) -> Result<Option<SemihostingCommand>, Error> {
358 const TRAP_INSTRUCTIONS: [u32; 3] = [
359 0x01f01013, 0x00100073, 0x40705013, ];
363
364 if let Some(command) = self.state.semihosting_command {
367 return Ok(Some(command));
368 }
369
370 let pc: u64 = self.interface.read_csr(X::program_counter().id.0)?;
371
372 let command = if pc < 4 {
373 None
374 } else {
375 let mut actual_instructions = [0u32; 3];
377 self.read_32(pc - 4, &mut actual_instructions)?;
378
379 tracing::debug!(
380 "Semihosting check pc={pc:#x} instructions={0:#08x} {1:#08x} {2:#08x}",
381 actual_instructions[0],
382 actual_instructions[1],
383 actual_instructions[2]
384 );
385
386 if TRAP_INSTRUCTIONS == actual_instructions {
387 let syscall = decode_semihosting_syscall(self)?;
388 if let SemihostingCommand::Unknown(details) = syscall {
389 X::handle_unknown_semihosting(self, details)?
390 } else {
391 Some(syscall)
392 }
393 } else {
394 None
395 }
396 };
397 self.state.semihosting_command = command;
398 Ok(command)
399 }
400
401 fn determine_number_of_hardware_breakpoints(&mut self) -> Result<u32, RiscvError> {
402 tracing::debug!("Determining number of HW breakpoints supported");
403
404 const TSELECT: u16 = 0x7a0;
405 const TDATA1: u16 = 0x7a1;
406 const TINFO: u16 = 0x7a4;
407
408 let mut tselect_index: u64 = 0;
409
410 loop {
412 tracing::debug!("Trying tselect={}", tselect_index);
413 if let Err(e) = self.interface.write_csr(TSELECT, tselect_index) {
414 match e {
415 RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception) => break,
416 other_error => return Err(other_error),
417 }
418 }
419
420 let readback = self.interface.read_csr(TSELECT)?;
421 if readback != tselect_index {
422 break;
423 }
424
425 match self.interface.read_csr(TINFO) {
426 Ok(tinfo_val) => {
427 if tinfo_val & 0xffff == 1 {
428 break;
430 } else {
431 tracing::info!(
432 "Discovered trigger with index {} and type {}",
433 tselect_index,
434 tinfo_val & 0xffff
435 );
436 }
437 }
438 Err(RiscvError::AbstractCommand(AbstractCommandErrorKind::Exception)) => {
440 let (trigger_type, _) = X::unpack_tdata1(self.interface.read_csr(TDATA1)?);
441 if trigger_type == 0 {
442 break;
443 }
444 tracing::info!(
445 "Discovered trigger with index {} and type {}",
446 tselect_index,
447 trigger_type,
448 );
449 }
450 Err(other) => return Err(other),
451 }
452
453 tselect_index += 1;
454 }
455
456 tracing::debug!("Target supports {} breakpoints.", tselect_index);
457 Ok(tselect_index as u32)
458 }
459
460 fn on_halted(&mut self) -> Result<(), Error> {
461 let status = self.status()?;
462 tracing::debug!("Core halted: {:#?}", status);
463 if status.is_halted() {
464 self.sequence.on_halt(&mut self.interface)?;
465 }
466 Ok(())
467 }
468}
469
470impl<X: XlenMode> CoreInterface for RiscvCore<'_, X> {
473 fn wait_for_core_halted(&mut self, timeout: Duration) -> Result<(), Error> {
474 self.interface.wait_for_core_halted(timeout)?;
475 self.on_halted()?;
476 self.state.pc_written = false;
477 Ok(())
478 }
479
480 fn core_halted(&mut self) -> Result<bool, Error> {
481 Ok(self.interface.core_halted()?)
482 }
483
484 fn status(&mut self) -> Result<CoreStatus, Error> {
485 let status: Dmstatus = self.interface.read_dm_register()?;
488
489 if status.allhalted() {
490 let dcsr = Dcsr(self.interface.read_csr(0x7b0)? as u32);
492
493 let reason = match dcsr.cause() {
494 1 => {
496 self.state.pc_written = false;
499 if let Some(cmd) = self.check_for_semihosting()? {
500 HaltReason::Breakpoint(BreakpointCause::Semihosting(cmd))
501 } else {
502 HaltReason::Breakpoint(BreakpointCause::Software)
503 }
504 }
508 2 => HaltReason::Breakpoint(BreakpointCause::Hardware),
510 3 => HaltReason::Request,
512 4 => HaltReason::Step,
514 5 => HaltReason::Exception,
516 _ => HaltReason::Unknown,
518 };
519
520 Ok(CoreStatus::Halted(reason))
521 } else if status.allrunning() {
522 Ok(CoreStatus::Running)
523 } else {
524 Err(Error::Other(
525 "Some cores are running while some are halted, this should not happen.".to_string(),
526 ))
527 }
528 }
529
530 fn halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
531 self.interface.halt(timeout)?;
532 self.on_halted()?;
533 Ok(self.interface.core_info()?)
534 }
535
536 fn run(&mut self) -> Result<(), Error> {
537 if !self.state.pc_written {
541 self.step()?;
542 }
543 self.resume_core()?;
545 Ok(())
546 }
547
548 fn reset(&mut self) -> Result<(), Error> {
549 self.reset_and_halt(Duration::from_secs(1))?;
550 self.resume_core()?;
551 Ok(())
552 }
553
554 fn reset_and_halt(&mut self, timeout: Duration) -> Result<CoreInformation, Error> {
555 self.sequence
556 .reset_system_and_halt(&mut self.interface, timeout)?;
557 self.state.hw_breakpoints_enabled = false;
559 self.on_halted()?;
560 let pc = self.interface.read_csr(0x7b1)?;
561 Ok(CoreInformation { pc })
562 }
563
564 fn step(&mut self) -> Result<CoreInformation, Error> {
565 let halt_reason = self.status()?;
566 if matches!(
567 halt_reason,
568 CoreStatus::Halted(HaltReason::Breakpoint(
569 BreakpointCause::Software | BreakpointCause::Semihosting(_)
570 ))
571 ) {
572 let mut debug_pc = self.read_core_reg(RegisterId(0x7b1))?;
575 if self.instruction_set()? == X::compressed_instruction_set() {
577 let instruction = self.read_word_32(debug_pc.try_into().unwrap())?;
580 if instruction & 0x3 != 0x3 {
581 debug_pc.increment_address(2)?;
583 } else {
584 debug_pc.increment_address(4)?;
585 }
586 } else {
587 debug_pc.increment_address(4)?;
588 }
589 self.write_core_reg(RegisterId(0x7b1), debug_pc)?;
590 return Ok(CoreInformation {
591 pc: debug_pc.try_into()?,
592 });
593 } else if matches!(
594 halt_reason,
595 CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
596 ) {
597 self.enable_breakpoints(false)?;
599 }
600
601 let mut dcsr = Dcsr(self.interface.read_csr(0x7b0)? as u32);
603 dcsr.set_step(true);
604 dcsr.set_stepie(false);
606 dcsr.set_stopcount(true);
607 self.interface.write_csr(0x7b0, u64::from(dcsr.0))?;
608
609 self.resume_core()?;
611 let step_result = self.wait_for_core_halted(SINGLE_STEP_TIMEOUT);
612
613 if step_result.is_err() {
616 tracing::warn!("Single step did not halt within {SINGLE_STEP_TIMEOUT:?}; forcing halt");
617 if let Err(e) = self.interface.halt(Duration::from_millis(100)) {
618 tracing::warn!("Could not force halt after failed single step: {:?}", e);
619 }
620 }
621
622 let mut dcsr = Dcsr(self.interface.read_csr(0x7b0)? as u32);
624 dcsr.set_step(false);
625 dcsr.set_stepie(true);
627 dcsr.set_stopcount(false);
628 self.interface.write_csr(0x7b0, u64::from(dcsr.0))?;
629
630 if matches!(
632 halt_reason,
633 CoreStatus::Halted(HaltReason::Breakpoint(BreakpointCause::Hardware))
634 ) {
635 self.enable_breakpoints(true)?;
637 }
638
639 step_result?;
640
641 let pc = self.read_core_reg(RegisterId(0x7b1))?;
642
643 self.on_halted()?;
644 self.state.pc_written = false;
645 Ok(CoreInformation { pc: pc.try_into()? })
646 }
647
648 fn read_core_reg(&mut self, address: RegisterId) -> Result<RegisterValue, Error> {
649 self.interface
650 .read_csr(address.0)
651 .map(X::csr_to_register_value)
652 .map_err(Error::from)
653 }
654
655 fn write_core_reg(&mut self, address: RegisterId, value: RegisterValue) -> Result<(), Error> {
656 let v = X::register_value_to_csr(value)?;
657 if address == X::program_counter().id {
658 self.state.pc_written = true;
659 }
660 self.interface.write_csr(address.0, v).map_err(Error::from)
661 }
662
663 fn available_breakpoint_units(&mut self) -> Result<u32, Error> {
664 match self.state.hw_breakpoints {
665 Some(bp) => Ok(bp),
666 None => {
667 let bp = self.determine_number_of_hardware_breakpoints()?;
668 self.state.hw_breakpoints = Some(bp);
669 Ok(bp)
670 }
671 }
672 }
673
674 fn hw_breakpoints(&mut self) -> Result<Vec<Option<u64>>, Error> {
678 let was_running = !self.core_halted()?;
681 if was_running {
682 self.halt(Duration::from_millis(100))?;
683 }
684
685 const TSELECT: u16 = 0x7a0;
686 const TDATA1: u16 = 0x7a1;
687 const TDATA2: u16 = 0x7a2;
688
689 let mut breakpoints = vec![];
690 let num_hw_breakpoints = self.available_breakpoint_units()? as usize;
691 for bp_unit_index in 0..num_hw_breakpoints {
692 self.interface.write_csr(TSELECT, bp_unit_index as u64)?;
694 let tdata_raw = self.interface.read_csr(TDATA1)?;
696 let (trigger_type, ctrl_low32) = X::unpack_tdata1(tdata_raw);
697 let tdata_value = Mcontrol(ctrl_low32);
698
699 tracing::debug!(
700 "Breakpoint {}: type={}, {:?}",
701 bp_unit_index,
702 trigger_type,
703 tdata_value
704 );
705
706 let trigger_any_mode_active = tdata_value.m() || tdata_value.s() || tdata_value.u();
708 let trigger_any_action_enabled =
709 tdata_value.execute() || tdata_value.store() || tdata_value.load();
710
711 if (trigger_type == 2 || trigger_type == 6)
714 && tdata_value.action() == 1
715 && tdata_value.match_() == 0
716 && trigger_any_mode_active
717 && trigger_any_action_enabled
718 {
719 let breakpoint = self.interface.read_csr(TDATA2)?;
720 breakpoints.push(Some(breakpoint));
721 } else {
722 breakpoints.push(None);
723 }
724 }
725
726 if was_running {
727 self.resume_core()?;
728 }
729
730 Ok(breakpoints)
731 }
732
733 fn enable_breakpoints(&mut self, state: bool) -> Result<(), Error> {
734 const TSELECT: u16 = 0x7a0;
735 const TDATA1: u16 = 0x7a1;
736
737 for bp_unit_index in 0..self.available_breakpoint_units()? as usize {
739 self.interface.write_csr(TSELECT, bp_unit_index as u64)?;
741 let tdata_raw = self.interface.read_csr(TDATA1)?;
743 let (trigger_type, ctrl_low32) = X::unpack_tdata1(tdata_raw);
744 let mut tdata_value = Mcontrol(ctrl_low32);
745
746 if (trigger_type == 2 || trigger_type == 6)
750 && tdata_value.action() == 1
751 && tdata_value.match_() == 0
752 && tdata_value.execute()
753 && ((tdata_value.m() && tdata_value.u()) || (!tdata_value.m() && !tdata_value.u()))
754 {
755 tracing::debug!(
756 "Will modify breakpoint enabled={} for {}: {:?}",
757 state,
758 bp_unit_index,
759 tdata_value
760 );
761 tdata_value.set_m(state);
762 tdata_value.set_u(state);
763 self.interface
764 .write_csr(TDATA1, X::repack_tdata1(tdata_raw, tdata_value.0))?;
765 }
766 }
767
768 self.state.hw_breakpoints_enabled = state;
769 Ok(())
770 }
771
772 fn set_hw_breakpoint(&mut self, bp_unit_index: usize, addr: u64) -> Result<(), Error> {
773 let addr = X::validate_bp_address(addr)?;
774
775 const TSELECT: u16 = 0x7a0;
776 const TDATA1: u16 = 0x7a1;
777 const TDATA2: u16 = 0x7a2;
778
779 tracing::info!("Setting breakpoint {} at {:#x}", bp_unit_index, addr);
780
781 self.interface.write_csr(TSELECT, bp_unit_index as u64)?;
783
784 let (trigger_type, _) = X::unpack_tdata1(self.interface.read_csr(TDATA1)?);
787 if trigger_type != 2 && trigger_type != 6 {
788 return Err(RiscvError::UnexpectedTriggerType(trigger_type).into());
789 }
790
791 let mut instruction_breakpoint = Mcontrol(0);
794 instruction_breakpoint.set_action(1);
796 instruction_breakpoint.set_match(0);
798 instruction_breakpoint.set_m(true);
799 instruction_breakpoint.set_u(true);
800 instruction_breakpoint.set_execute(true);
802 instruction_breakpoint.set_select(false);
804
805 let tdata1_val = X::build_new_exec_tdata1(trigger_type, instruction_breakpoint.0);
806
807 self.interface.write_csr(TDATA1, 0)?;
808 self.interface.write_csr(TDATA2, addr)?;
809 self.interface.write_csr(TDATA1, tdata1_val)?;
810
811 Ok(())
812 }
813
814 fn clear_hw_breakpoint(&mut self, unit_index: usize) -> Result<(), Error> {
815 tracing::info!("Clearing breakpoint {}", unit_index);
818
819 let was_running = !self.core_halted()?;
820 if was_running {
821 self.halt(Duration::from_millis(100))?;
822 }
823
824 const TSELECT: u16 = 0x7a0;
825 const TDATA1: u16 = 0x7a1;
826 const TDATA2: u16 = 0x7a2;
827
828 self.interface.write_csr(TSELECT, unit_index as u64)?;
829 self.interface.write_csr(TDATA1, 0)?;
830 self.interface.write_csr(TDATA2, 0)?;
831
832 if was_running {
833 self.resume_core()?;
834 }
835
836 Ok(())
837 }
838
839 fn registers(&self) -> &'static CoreRegisters {
840 X::registers(self.state.fp_present)
841 }
842
843 fn program_counter(&self) -> &'static CoreRegister {
844 X::program_counter()
845 }
846
847 fn frame_pointer(&self) -> &'static CoreRegister {
848 X::frame_pointer()
849 }
850
851 fn stack_pointer(&self) -> &'static CoreRegister {
852 X::stack_pointer()
853 }
854
855 fn return_address(&self) -> &'static CoreRegister {
856 X::return_address()
857 }
858
859 fn hw_breakpoints_enabled(&self) -> bool {
860 self.state.hw_breakpoints_enabled
861 }
862
863 fn architecture(&self) -> Architecture {
864 Architecture::Riscv
865 }
866
867 fn core_type(&self) -> CoreType {
868 X::core_type()
869 }
870
871 fn is_64_bit(&self) -> bool {
872 matches!(X::core_type(), CoreType::Riscv64)
873 }
874
875 fn instruction_set(&mut self) -> Result<InstructionSet, Error> {
876 let misa_val = self.interface.read_csr(0x301)?;
878 if misa_val & (1 << 2) != 0 {
879 Ok(X::compressed_instruction_set())
880 } else {
881 Ok(X::uncompressed_instruction_set())
882 }
883 }
884
885 fn floating_point_register_count(&mut self) -> Result<usize, Error> {
886 Ok(self
887 .registers()
888 .all_registers()
889 .filter(|r| r.register_has_role(crate::RegisterRole::FloatingPoint))
890 .count())
891 }
892
893 fn fpu_support(&mut self) -> Result<bool, Error> {
894 Ok(self.state.fp_present)
895 }
896
897 fn reset_catch_set(&mut self) -> Result<(), Error> {
898 self.sequence.reset_catch_set(&mut self.interface)?;
899 Ok(())
900 }
901
902 fn reset_catch_clear(&mut self) -> Result<(), Error> {
903 self.sequence.reset_catch_clear(&mut self.interface)?;
904 Ok(())
905 }
906
907 fn debug_core_stop(&mut self) -> Result<(), Error> {
908 self.interface.disable_debug_module()?;
909 Ok(())
910 }
911}
912
913impl<X: XlenMode> CoreMemoryInterface for RiscvCore<'_, X> {
914 type ErrorType = Error;
915
916 fn memory(&self) -> &dyn MemoryInterface<Self::ErrorType> {
917 &self.interface
918 }
919
920 fn memory_mut(&mut self) -> &mut dyn MemoryInterface<Self::ErrorType> {
921 &mut self.interface
922 }
923}
924
925#[derive(Debug)]
926pub struct RiscvCoreState {
928 hw_breakpoints_enabled: bool,
930
931 hw_breakpoints: Option<u32>,
932
933 pc_written: bool,
936
937 semihosting_command: Option<SemihostingCommand>,
939
940 fp_present: bool,
942
943 misa_read: bool,
945}
946
947impl RiscvCoreState {
948 pub(crate) fn new() -> Self {
949 Self {
950 hw_breakpoints_enabled: false,
951 hw_breakpoints: None,
952 pc_written: false,
953 semihosting_command: None,
954 fp_present: false,
955 misa_read: false,
956 }
957 }
958}
959
960memory_mapped_bitfield_register! {
961 pub struct Dmcontrol(u32);
963 0x10, "dmcontrol",
964 impl From;
965
966 pub _, set_haltreq: 31;
968
969 pub _, set_resumereq: 30;
971
972 pub hartreset, set_hartreset: 29;
974
975 pub _, set_ackhavereset: 28;
977
978 pub _, set_ackunavail: 27;
983
984 pub hasel, set_hasel: 26;
986
987 pub hartsello, set_hartsello: 25, 16;
989
990 pub hartselhi, set_hartselhi: 15, 6;
992
993 pub _, set_resethaltreq: 3;
995
996 pub _, set_clrresethaltreq: 2;
998
999 pub _, set_setkeepalive: 5;
1003
1004 pub _, set_clrkeepalive: 4;
1007
1008 pub ndmreset, set_ndmreset: 1;
1010
1011 pub dmactive, set_dmactive: 0;
1013}
1014
1015impl Dmcontrol {
1016 pub fn hartsel(&self) -> u32 {
1020 (self.hartselhi() << 10) | self.hartsello()
1021 }
1022
1023 pub fn set_hartsel(&mut self, value: u32) {
1028 self.set_hartsello(value & 0x3ff);
1029 self.set_hartselhi((value >> 10) & 0x3ff);
1030 }
1031}
1032
1033memory_mapped_bitfield_register! {
1034 pub struct Dmstatus(u32);
1038 0x11, "dmstatus",
1039 impl From;
1040
1041 pub ndmresetpending, _: 24;
1045
1046 pub stickyunavail, _: 23;
1051
1052 pub impebreak, _: 22;
1059
1060 pub allhavereset, _: 19;
1063
1064 pub anyhavereset, _: 18;
1067
1068 pub allresumeack, _: 17;
1071
1072 pub anyresumeack, _: 16;
1075
1076 pub allnonexistent, _: 15;
1079
1080 pub anynonexistent, _: 14;
1083
1084 pub allunavail, _: 13;
1086
1087 pub anyunavail, _: 12;
1089
1090 pub allrunning, _: 11;
1092
1093 pub anyrunning, _: 10;
1095
1096 pub allhalted, _: 9;
1098
1099 pub anyhalted, _: 8;
1101
1102 pub authenticated, _: 7;
1104
1105 pub authbusy, _: 6;
1107
1108 pub hasresethaltreq, _: 5;
1111
1112 pub confstrptrvalid, _: 4;
1114
1115 pub version, _: 3, 0;
1117}
1118
1119bitfield! {
1120 struct Dcsr(u32);
1121 impl Debug;
1122
1123 xdebugver, _: 31, 28;
1125 ebreakvs, set_ebreakvs: 17;
1127 ebreakvu, set_ebreakvu: 16;
1129 ebreakm, set_ebreakm: 15;
1130 ebreaks, set_ebreaks: 13;
1131 ebreaku, set_ebreaku: 12;
1132 stepie, set_stepie: 11;
1133 stopcount, set_stopcount: 10;
1134 stoptime, set_stoptime: 9;
1135 cause, set_cause: 8, 6;
1136 v, set_v: 5;
1139 mprven, set_mprven: 4;
1140 nmip, _: 3;
1141 step, set_step: 2;
1142 prv, set_prv: 1,0;
1143}
1144
1145memory_mapped_bitfield_register! {
1146 pub struct Abstractcs(u32);
1148 0x16, "abstractcs",
1149 impl From;
1150
1151 progbufsize, _: 28, 24;
1152 busy, _: 12;
1153 relaxedpriv, set_relaxedpriv: 11;
1157 cmderr, set_cmderr: 10, 8;
1158 datacount, _: 3, 0;
1159}
1160
1161memory_mapped_bitfield_register! {
1162 pub struct Hartinfo(u32);
1164 0x12, "hartinfo",
1165 impl From;
1166
1167 nscratch, _: 23, 20;
1168 dataaccess, _: 16;
1169 datasize, _: 15, 12;
1170 dataaddr, _: 11, 0;
1171}
1172
1173memory_mapped_bitfield_register! { pub struct Data0(u32); 0x04, "data0", impl From; }
1174memory_mapped_bitfield_register! { pub struct Data1(u32); 0x05, "data1", impl From; }
1175memory_mapped_bitfield_register! { pub struct Data2(u32); 0x06, "data2", impl From; }
1176memory_mapped_bitfield_register! { pub struct Data3(u32); 0x07, "data3", impl From; }
1177memory_mapped_bitfield_register! { pub struct Data4(u32); 0x08, "data4", impl From; }
1178memory_mapped_bitfield_register! { pub struct Data5(u32); 0x09, "data5", impl From; }
1179memory_mapped_bitfield_register! { pub struct Data6(u32); 0x0A, "data6", impl From; }
1180memory_mapped_bitfield_register! { pub struct Data7(u32); 0x0B, "data7", impl From; }
1181memory_mapped_bitfield_register! { pub struct Data8(u32); 0x0C, "data8", impl From; }
1182memory_mapped_bitfield_register! { pub struct Data9(u32); 0x0D, "data9", impl From; }
1183memory_mapped_bitfield_register! { pub struct Data10(u32); 0x0E, "data10", impl From; }
1184memory_mapped_bitfield_register! { pub struct Data11(u32); 0x0f, "data11", impl From; }
1185
1186memory_mapped_bitfield_register! { struct Command(u32); 0x17, "command", impl From; }
1187
1188memory_mapped_bitfield_register! { pub struct Progbuf0(u32); 0x20, "progbuf0", impl From; }
1189memory_mapped_bitfield_register! { pub struct Progbuf1(u32); 0x21, "progbuf1", impl From; }
1190memory_mapped_bitfield_register! { pub struct Progbuf2(u32); 0x22, "progbuf2", impl From; }
1191memory_mapped_bitfield_register! { pub struct Progbuf3(u32); 0x23, "progbuf3", impl From; }
1192memory_mapped_bitfield_register! { pub struct Progbuf4(u32); 0x24, "progbuf4", impl From; }
1193memory_mapped_bitfield_register! { pub struct Progbuf5(u32); 0x25, "progbuf5", impl From; }
1194memory_mapped_bitfield_register! { pub struct Progbuf6(u32); 0x26, "progbuf6", impl From; }
1195memory_mapped_bitfield_register! { pub struct Progbuf7(u32); 0x27, "progbuf7", impl From; }
1196memory_mapped_bitfield_register! { pub struct Progbuf8(u32); 0x28, "progbuf8", impl From; }
1197memory_mapped_bitfield_register! { pub struct Progbuf9(u32); 0x29, "progbuf9", impl From; }
1198memory_mapped_bitfield_register! { pub struct Progbuf10(u32); 0x2A, "progbuf10", impl From; }
1199memory_mapped_bitfield_register! { pub struct Progbuf11(u32); 0x2B, "progbuf11", impl From; }
1200memory_mapped_bitfield_register! { pub struct Progbuf12(u32); 0x2C, "progbuf12", impl From; }
1201memory_mapped_bitfield_register! { pub struct Progbuf13(u32); 0x2D, "progbuf13", impl From; }
1202memory_mapped_bitfield_register! { pub struct Progbuf14(u32); 0x2E, "progbuf14", impl From; }
1203memory_mapped_bitfield_register! { pub struct Progbuf15(u32); 0x2F, "progbuf15", impl From; }
1204
1205bitfield! {
1206 struct Mcontrol(u32);
1208 impl Debug;
1209
1210 type_, set_type: 31, 28;
1211 dmode, set_dmode: 27;
1212 maskmax, _: 26, 21;
1213 hit, set_hit: 20;
1214 select, set_select: 19;
1215 timing, set_timing: 18;
1216 sizelo, set_sizelo: 17, 16;
1217 action, set_action: 15, 12;
1218 chain, set_chain: 11;
1219 match_, set_match: 10, 7;
1220 m, set_m: 6;
1221 s, set_s: 4;
1222 u, set_u: 3;
1223 execute, set_execute: 2;
1224 store, set_store: 1;
1225 load, set_load: 0;
1226}
1227
1228bitfield! {
1229 struct Mcontrol6(u32);
1235 impl Debug;
1236
1237 type_, set_type: 31, 28;
1238 dmode, set_dmode: 27;
1239 hit1, set_hit1: 25;
1242 vs, set_vs: 24;
1244 vu, set_vu: 23;
1246 hit0, set_hit0: 22;
1248 select, set_select: 21;
1249 size, set_size: 19, 16;
1252 action, set_action: 15, 12;
1253 chain, set_chain: 11;
1254 match_, set_match: 10, 7;
1255 m, set_m: 6;
1256 s, set_s: 4;
1257 u, set_u: 3;
1258 execute, set_execute: 2;
1259 store, set_store: 1;
1260 load, set_load: 0;
1261}
1262
1263memory_mapped_bitfield_register! {
1264 pub struct Misa(u32);
1266 0x301, "misa",
1267 impl From;
1268
1269 mxl, _: 31, 30;
1271 extensions, _: 25, 0;
1273}