@@ -173,7 +173,7 @@ pub struct Cpu {
173173
174174 // Supervisor and CSR
175175 pub cycle : u64 ,
176- csr : Box < [ u64 ] > , // XXX this should be replaced with individual registers
176+ csr : csr :: CsrFile ,
177177 reservation : Option < u64 > ,
178178
179179 // Wait-For-Interrupt; relax and await further instruction
@@ -237,15 +237,11 @@ impl Cpu {
237237 cycle : 0 ,
238238 wfi : false ,
239239 pc : 0 ,
240- csr : vec ! [ 0 ; 4096 ] . into_boxed_slice ( ) , // XXX MUST GO AWAY SOON
240+ csr : CsrFile :: new ( ) ,
241241 mmu,
242242 reservation : None ,
243243 flush_icache : false ,
244244 } ;
245- cpu. csr [ Csr :: Misa as usize ] = 1 << 63 ; // RV64
246- for c in "SUIMAFDC" . bytes ( ) {
247- cpu. csr [ Csr :: Misa as usize ] |= 1 << ( c as usize - 65 ) ;
248- }
249245 cpu. mmu . mstatus = 2 << MSTATUS_UXL_SHIFT | 2 << MSTATUS_SXL_SHIFT | 3 << MSTATUS_MPP_SHIFT ;
250246 cpu. write_x ( x ( 11 ) , 0x1020 ) ; // start of DTB (XXX could put that elsewhere);
251247 cpu
@@ -334,7 +330,7 @@ impl Cpu {
334330 fn step_cpu ( & mut self , uop_cache : & mut IntMap < u64 , Uop > ) -> Result < ( ) , Exception > {
335331 self . cycle = self . cycle . wrapping_add ( 1 ) ;
336332 if self . wfi {
337- if self . mmu . mip & self . read_csr_raw ( Csr :: Mie ) != 0 {
333+ if self . mmu . mip & self . csr . mie != 0 {
338334 self . wfi = false ;
339335 }
340336 return Ok ( ( ) ) ;
@@ -400,7 +396,7 @@ impl Cpu {
400396 use self :: Trap :: SupervisorExternalInterrupt ;
401397 use self :: Trap :: SupervisorSoftwareInterrupt ;
402398 use self :: Trap :: SupervisorTimerInterrupt ;
403- let minterrupt = self . mmu . mip & self . read_csr_raw ( Csr :: Mie ) ;
399+ let minterrupt = self . mmu . mip & self . csr . mie ;
404400 if minterrupt == 0 {
405401 return ;
406402 }
@@ -442,16 +438,16 @@ impl Cpu {
442438 // First, determine which privilege mode should handle the trap.
443439 // @TODO: Check if this logic is correct
444440 let mdeleg = if is_interrupt {
445- self . read_csr_raw ( Csr :: Mideleg )
441+ self . csr . mideleg
446442 } else {
447- self . read_csr_raw ( Csr :: Medeleg )
443+ self . csr . medeleg
448444 } ;
449445 let sdeleg = if is_interrupt {
450- self . read_csr_raw ( Csr :: Sideleg )
446+ self . csr . sideleg
451447 } else {
452- self . read_csr_raw ( Csr :: Sedeleg )
448+ self . csr . sedeleg
453449 } ;
454- let pos = cause & 0xffff ;
450+ let pos = cause & 63 ;
455451
456452 let new_priv_mode = if ( mdeleg >> pos) & 1 == 0 {
457453 PrivMode :: M
@@ -468,11 +464,11 @@ impl Cpu {
468464 let current_status = match self . mmu . prv {
469465 PrivMode :: M => self . read_csr_raw ( Csr :: Mstatus ) ,
470466 PrivMode :: S => self . read_csr_raw ( Csr :: Sstatus ) ,
471- PrivMode :: U => self . read_csr_raw ( Csr :: Ustatus ) ,
467+ PrivMode :: U => self . csr . ustatus ,
472468 } ;
473469
474470 let ie = match new_priv_mode {
475- PrivMode :: M => self . read_csr_raw ( Csr :: Mie ) ,
471+ PrivMode :: M => self . csr . mie ,
476472 PrivMode :: S => self . read_csr_raw ( Csr :: Sie ) ,
477473 PrivMode :: U => self . read_csr_raw ( Csr :: Uie ) ,
478474 } ;
@@ -582,16 +578,15 @@ impl Cpu {
582578 PrivMode :: S => Csr :: Stval ,
583579 PrivMode :: U => Csr :: Utval ,
584580 } ;
585- let csr_tvec_address = match self . mmu . prv {
586- PrivMode :: M => Csr :: Mtvec ,
587- PrivMode :: S => Csr :: Stvec ,
588- PrivMode :: U => Csr :: Utvec ,
581+ self . pc = match self . mmu . prv {
582+ PrivMode :: M => self . read_csr_raw ( Csr :: Mtvec ) ,
583+ PrivMode :: S => self . read_csr_raw ( Csr :: Stvec ) ,
584+ PrivMode :: U => self . read_csr_raw ( Csr :: Utvec ) ,
589585 } ;
590586
591587 self . write_csr_raw ( csr_epc_address, insn_addr) ;
592588 self . write_csr_raw ( csr_cause_address, cause) ;
593589 self . write_csr_raw ( csr_tval_address, exc. tval ) ;
594- self . pc = self . read_csr_raw ( csr_tvec_address) ;
595590
596591 // Add 4 * cause if tvec has vector type address
597592 if self . pc & 3 != 0 {
@@ -663,6 +658,7 @@ impl Cpu {
663658 if self . mmu . prv == S && self . mmu . mstatus & MSTATUS_TVM != 0 {
664659 return illegal;
665660 }
661+ return Ok ( self . mmu . satp ) ;
666662 }
667663 _ => { }
668664 }
@@ -671,7 +667,6 @@ impl Cpu {
671667
672668 #[ allow( clippy:: cast_sign_loss) ]
673669 fn write_csr ( & mut self , csrno : u16 , value : u64 ) -> Result < ( ) , Exception > {
674- let mut value = value;
675670 let illegal = Err ( Exception {
676671 trap : Trap :: IllegalInstruction ,
677672 tval : 0 ,
@@ -687,10 +682,6 @@ impl Cpu {
687682 }
688683
689684 match csr {
690- Csr :: Mstatus => {
691- let mask = MSTATUS_MASK & !( MSTATUS_VS | MSTATUS_UXL_MASK | MSTATUS_SXL_MASK ) ;
692- value = value & mask | self . mmu . mstatus & !mask;
693- }
694685 Csr :: Fflags | Csr :: Frm | Csr :: Fcsr => self . check_float_access_and_dirty ( 0 ) ?,
695686 Csr :: Cycle => {
696687 log:: info!( "** deny cycle writing" ) ;
@@ -708,6 +699,10 @@ impl Cpu {
708699 log:: warn!( "wrote illegal value {value:x} to satp" ) ;
709700 return illegal;
710701 }
702+
703+ self . mmu . satp = value;
704+ self . mmu . clear_page_cache ( ) ;
705+ return Ok ( ( ) ) ;
711706 }
712707 _ => { }
713708 }
@@ -720,82 +715,96 @@ impl Cpu {
720715 #[ allow( clippy:: cast_sign_loss) ]
721716 fn read_csr_raw ( & self , csr : Csr ) -> u64 {
722717 match csr {
718+ Csr :: Cycle | Csr :: Mcycle | Csr :: Minstret => self . cycle ,
719+ Csr :: Fcsr => self . read_fcsr ( ) ,
723720 Csr :: Fflags => u64:: from ( self . read_fflags ( ) ) ,
724721 Csr :: Frm => self . read_frm ( ) as u64 ,
725- Csr :: Fcsr => self . read_fcsr ( ) ,
726- Csr :: Sstatus => {
727- let mut sstatus = self . mmu . mstatus ;
728- sstatus &= !MSTATUS_FS ;
729- sstatus |= u64:: from ( self . fs ) << MSTATUS_FS_SHIFT ;
730- sstatus &= 0x8000_0003_000d_e162 ;
722+ Csr :: Mcause => self . csr . mcause ,
723+ Csr :: Medeleg => self . csr . medeleg ,
724+ Csr :: Mepc => self . csr . mepc ,
725+ Csr :: Mhartid => self . csr . mhartid ,
726+ Csr :: Mideleg => self . csr . mideleg ,
727+ Csr :: Mie => self . csr . mie ,
728+ Csr :: Mip => self . mmu . mip ,
729+ Csr :: Misa => self . csr . misa ,
730+ Csr :: Mscratch => self . csr . mscratch ,
731+ Csr :: Mstatus => {
732+ let mut mstatus = self . mmu . mstatus ;
733+ mstatus &= !MSTATUS_FS ;
734+ mstatus |= u64:: from ( self . fs ) << MSTATUS_FS_SHIFT ;
731735 if self . fs == 3 {
732- sstatus |= 1 << 63 ;
736+ mstatus |= 1 << 63 ;
733737 }
734- sstatus
738+ mstatus
735739 }
736- Csr :: Mstatus => {
740+ Csr :: Mtval => self . csr . mtval ,
741+ Csr :: Mtvec => self . csr . mtvec ,
742+ Csr :: Satp => self . mmu . satp ,
743+ Csr :: Scause => self . csr . scause ,
744+ Csr :: Sedeleg => self . csr . sedeleg ,
745+ Csr :: Sepc => self . csr . sepc ,
746+ Csr :: Sideleg => self . csr . sideleg ,
747+ Csr :: Sie => self . csr . mie & self . csr . mideleg ,
748+ Csr :: Sip => self . mmu . mip & self . csr . mideleg ,
749+ Csr :: Sscratch => self . csr . sscratch ,
750+ Csr :: Sstatus => {
737751 let mut mstatus = self . mmu . mstatus ;
738752 mstatus &= !MSTATUS_FS ;
739753 mstatus |= u64:: from ( self . fs ) << MSTATUS_FS_SHIFT ;
754+ mstatus &= 0x8000_0003_000d_e162 ;
740755 if self . fs == 3 {
741756 mstatus |= 1 << 63 ;
742757 }
743758 mstatus
744759 }
745- Csr :: Sie => self . csr [ Csr :: Mie as usize ] & self . csr [ Csr :: Mideleg as usize ] ,
746- Csr :: Sip => self . mmu . mip & self . csr [ Csr :: Mideleg as usize ] ,
747- Csr :: Mip => self . mmu . mip ,
760+ Csr :: Stval => self . csr . stval ,
761+ Csr :: Stvec => self . csr . stvec ,
748762 Csr :: Time => self . mmu . get_clint ( ) . read_mtime ( ) ,
749- Csr :: Cycle | Csr :: Mcycle | Csr :: Minstret => self . cycle ,
750- Csr :: Satp => self . mmu . satp ,
751- _ => self . csr [ csr as usize ] ,
763+ Csr :: Ustatus => self . csr . ustatus ,
764+ _ => 0 ,
752765 }
753766 }
754767
755768 fn write_csr_raw ( & mut self , csr : Csr , value : u64 ) {
756769 match csr {
757- Csr :: Misa => { } // Not writable
770+ Csr :: Mcycle => self . cycle = value,
771+ Csr :: Fcsr => self . write_fcsr ( value) ,
758772 Csr :: Fflags => self . write_fflags ( ( value & 31 ) as u8 ) ,
759773 Csr :: Frm => self . write_frm (
760774 FromPrimitive :: from_u64 ( value & 7 ) . unwrap_or ( RoundingMode :: RoundNearestEven ) ,
761775 ) ,
762- Csr :: Fcsr => self . write_fcsr ( value) ,
776+ Csr :: Mcause => self . csr . mcause = value,
777+ Csr :: Medeleg => self . csr . medeleg = value,
778+ Csr :: Mepc => self . csr . mepc = value,
779+ Csr :: Mhartid => self . csr . mhartid = value,
780+ Csr :: Mideleg => self . csr . mideleg = value & 0x222 ,
781+ Csr :: Mie => self . csr . mie = value,
782+ Csr :: Mip => self . mmu . mip = value,
783+ Csr :: Mscratch => self . csr . mscratch = value,
784+ Csr :: Mstatus => {
785+ let mask = MSTATUS_MASK & !( MSTATUS_VS | MSTATUS_UXL_MASK | MSTATUS_SXL_MASK ) ;
786+ self . mmu . mstatus = value & mask | self . mmu . mstatus & !mask;
787+ self . fs = ( ( value >> MSTATUS_FS_SHIFT ) & 3 ) as u8 ;
788+ }
789+ Csr :: Mtval => self . csr . mtval = value,
790+ Csr :: Mtvec => self . csr . mtvec = value,
791+ Csr :: Scause => self . csr . scause = value,
792+ Csr :: Sedeleg => self . csr . sedeleg = value,
793+ Csr :: Sepc => self . csr . sepc = value,
794+ Csr :: Sideleg => self . csr . sideleg = value,
795+ Csr :: Sie => self . csr . mie = self . csr . mie & !0x222 | value & 0x222 ,
796+ Csr :: Sip => self . mmu . mip = value & 0x222 | self . mmu . mip & !0x222 ,
797+ Csr :: Sscratch => self . csr . sscratch = value,
763798 Csr :: Sstatus => {
764799 self . mmu . mstatus &= !0x8000_0003_000d_e162 ;
765800 self . mmu . mstatus |= value & 0x8000_0003_000d_e162 ;
766801 self . fs = ( ( value >> MSTATUS_FS_SHIFT ) & 3 ) as u8 ;
767802 }
768- Csr :: Sie => {
769- self . csr [ Csr :: Mie as usize ] &= !0x222 ;
770- self . csr [ Csr :: Mie as usize ] |= value & 0x222 ;
771- }
772- Csr :: Sip => {
773- let mask = 0x222 ;
774- self . mmu . mip = value & mask | self . mmu . mip & !mask;
775- }
776- Csr :: Mip => {
777- let mask = !0 ; // XXX 0x555 was too restrictive?? Stopped Ubuntu booting
778- self . mmu . mip = value & mask | self . mmu . mip & !mask;
779- }
780- Csr :: Mideleg => {
781- self . csr [ Csr :: Mideleg as usize ] = value & 0x222 ;
782- }
783- Csr :: Mstatus => {
784- self . mmu . mstatus = value;
785- self . fs = ( ( value >> MSTATUS_FS_SHIFT ) & 3 ) as u8 ;
786- }
787- Csr :: Time => {
788- // XXX This should trap actually
789- self . mmu . get_mut_clint ( ) . write_mtime ( value) ;
790- }
791- Csr :: Satp => {
792- self . mmu . satp = value;
793- self . mmu . clear_page_cache ( ) ;
794- }
795- /* Csr::Cycle | */ Csr :: Mcycle => self . cycle = value,
796- _ => {
797- self . csr [ csr as usize ] = value;
798- }
803+ Csr :: Stval => self . csr . stval = value,
804+ Csr :: Stvec => self . csr . stvec = value,
805+ Csr :: Time => self . mmu . get_mut_clint ( ) . write_mtime ( value) , // XXX SHOULD trap
806+ Csr :: Ustatus => self . csr . ustatus = value,
807+ _ => log:: warn!( "We are ignoring writes to {csr:?}" ) ,
799808 }
800809 }
801810
@@ -1974,7 +1983,7 @@ mod test_cpu {
19741983 cpu. update_pc ( MEMORY_BASE ) ;
19751984
19761985 // Machine timer interrupt but mie in mstatus is not enabled yet
1977- cpu. write_csr_raw ( Csr :: Mie , MIP_MTIP ) ;
1986+ cpu. csr . mie = MIP_MTIP ;
19781987 cpu. mmu . mip |= MIP_MTIP ;
19791988 cpu. write_csr_raw ( Csr :: Mtvec , handler_vector) ;
19801989
0 commit comments