1#![no_std]
8#![no_main]
9
10use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::hil::led::LedHigh;
14use kernel::hil::time::{Alarm, Timer};
15use kernel::platform::chip::InterruptService;
16use kernel::platform::{KernelResources, SyscallDriverLookup};
17use kernel::process::ProcessArray;
18use kernel::scheduler::mlfq::MLFQSched;
19use kernel::utilities::registers::interfaces::ReadWriteable;
20use kernel::utilities::StaticRef;
21use kernel::{create_capability, debug, static_init};
22use rv32i::csr;
23
24mod io;
25mod litex_generated_constants;
26
27use litex_generated_constants as socc;
34
35struct LiteXSimInterruptablePeripherals {
43 gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
44 uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
45 timer0: &'static litex_vexriscv::timer::LiteXTimer<
46 'static,
47 socc::SoCRegisterFmt,
48 socc::ClockFrequency,
49 >,
50 ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
51 'static,
52 { socc::ETHMAC_TX_SLOTS },
53 socc::SoCRegisterFmt,
54 >,
55}
56
57impl LiteXSimInterruptablePeripherals {
58 pub fn init(&'static self) {
60 kernel::deferred_call::DeferredCallClient::register(self.uart0);
61 }
62}
63
64impl InterruptService for LiteXSimInterruptablePeripherals {
65 unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
66 match interrupt as usize {
67 socc::UART_INTERRUPT => {
68 self.uart0.service_interrupt();
69 true
70 }
71 socc::TIMER0_INTERRUPT => {
72 self.timer0.service_interrupt();
73 true
74 }
75 socc::ETHMAC_INTERRUPT => {
76 self.ethmac0.service_interrupt();
77 true
78 }
79 socc::GPIO_INTERRUPT => {
80 self.gpio0.service_interrupt();
81 true
82 }
83 _ => false,
84 }
85 }
86}
87
88const NUM_PROCS: usize = 4;
89
90type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>;
91type AlarmHw =
92 litex_vexriscv::timer::LiteXAlarm<'static, 'static, socc::SoCRegisterFmt, socc::ClockFrequency>;
93type SchedulerTimerHw =
94 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
95
96static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
98
99struct LiteXSimPanicReferences {
101 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
102 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
103 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
104}
105static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
106 chip: None,
107 uart: None,
108 process_printer: None,
109};
110
111const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
113 capsules_system::process_policies::PanicFaultPolicy {};
114
115kernel::stack_size! {0x2000}
116
117struct LiteXSim {
120 gpio_driver: &'static capsules_core::gpio::GPIO<
121 'static,
122 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
123 >,
124 button_driver: &'static capsules_core::button::Button<
125 'static,
126 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
127 >,
128 led_driver: &'static capsules_core::led::LedDriver<
129 'static,
130 LedHigh<
131 'static,
132 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
133 >,
134 8,
135 >,
136 console: &'static capsules_core::console::Console<'static>,
137 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
138 'static,
139 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
140 >,
141 alarm: &'static capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
142 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
143 scheduler: &'static MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>,
144 scheduler_timer: &'static SchedulerTimerHw,
145}
146
147impl SyscallDriverLookup for LiteXSim {
149 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
150 where
151 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
152 {
153 match driver_num {
154 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
155 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
156 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
157 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
158 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
159 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
160 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
161 _ => f(None),
162 }
163 }
164}
165
166impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
167 for LiteXSim
168{
169 type SyscallDriverLookup = Self;
170 type SyscallFilter = ();
171 type ProcessFault = ();
172 type Scheduler = MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>;
173 type SchedulerTimer = SchedulerTimerHw;
174 type WatchDog = ();
175 type ContextSwitchCallback = ();
176
177 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
178 self
179 }
180 fn syscall_filter(&self) -> &Self::SyscallFilter {
181 &()
182 }
183 fn process_fault(&self) -> &Self::ProcessFault {
184 &()
185 }
186 fn scheduler(&self) -> &Self::Scheduler {
187 self.scheduler
188 }
189 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
190 self.scheduler_timer
191 }
192 fn watchdog(&self) -> &Self::WatchDog {
193 &()
194 }
195 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
196 &()
197 }
198}
199
200#[inline(never)]
204unsafe fn start() -> (
205 &'static kernel::Kernel,
206 LiteXSim,
207 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
208) {
209 extern "C" {
211 static _sapps: u8;
213 static _eapps: u8;
215 static mut _sappmem: u8;
217 static _eappmem: u8;
219 static _stext: u8;
221 static _etext: u8;
223 static _sflash: u8;
225 static _eflash: u8;
227 static _ssram: u8;
229 static _esram: u8;
231 }
232
233 rv32i::configure_trap_handler();
237
238 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
240 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
241 >();
242
243 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
247 rv32i::pmp::kernel_protection::FlashRegion(
248 rv32i::pmp::NAPOTRegionSpec::from_start_end(
249 core::ptr::addr_of!(_sflash),
250 core::ptr::addr_of!(_eflash),
251 )
252 .unwrap(),
253 ),
254 rv32i::pmp::kernel_protection::RAMRegion(
255 rv32i::pmp::NAPOTRegionSpec::from_start_end(
256 core::ptr::addr_of!(_ssram),
257 core::ptr::addr_of!(_esram),
258 )
259 .unwrap(),
260 ),
261 rv32i::pmp::kernel_protection::MMIORegion(
262 rv32i::pmp::NAPOTRegionSpec::from_start_size(
263 0xf0000000 as *const u8, 0x10000000, )
266 .unwrap(),
267 ),
268 rv32i::pmp::kernel_protection::KernelTextRegion(
269 rv32i::pmp::TORRegionSpec::from_start_end(
270 core::ptr::addr_of!(_stext),
271 core::ptr::addr_of!(_etext),
272 )
273 .unwrap(),
274 ),
275 )
276 .unwrap();
277
278 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
280 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
281
282 let processes = components::process_array::ProcessArrayComponent::new()
284 .finalize(components::process_array_component_static!(NUM_PROCS));
285 PROCESSES = Some(processes);
286
287 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
289
290 let timer0 = static_init!(
294 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
295 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
296 socc::CSR_TIMER0_BASE
297 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
298 ),)
299 );
300
301 let timer0_uptime = static_init!(
303 litex_vexriscv::timer::LiteXTimerUptime<
304 'static,
305 socc::SoCRegisterFmt,
306 socc::ClockFrequency,
307 >,
308 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
309 );
310
311 let litex_alarm = static_init!(
314 AlarmHw,
315 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
316 );
317 timer0.set_timer_client(litex_alarm);
318 litex_alarm.initialize();
319
320 let mux_alarm = static_init!(MuxAlarm<'static, AlarmHw>, MuxAlarm::new(litex_alarm));
323 litex_alarm.set_alarm_client(mux_alarm);
324
325 let virtual_alarm_user = static_init!(
327 VirtualMuxAlarm<'static, AlarmHw>,
328 VirtualMuxAlarm::new(mux_alarm)
329 );
330 virtual_alarm_user.setup();
331
332 let alarm = static_init!(
333 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
334 capsules_core::alarm::AlarmDriver::new(
335 virtual_alarm_user,
336 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
337 )
338 );
339 virtual_alarm_user.set_alarm_client(alarm);
340
341 let scheduler_timer =
342 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
343 .finalize(components::virtual_scheduler_timer_component_static!(
344 AlarmHw
345 ));
346
347 let uart0 = static_init!(
351 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
352 litex_vexriscv::uart::LiteXUart::new(
353 StaticRef::new(
354 socc::CSR_UART_BASE
355 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
356 ),
357 None, )
359 );
360 uart0.initialize();
361
362 PANIC_REFERENCES.uart = Some(uart0);
363
364 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
369 .finalize(components::uart_mux_component_static!());
370
371 let ethmac0 = static_init!(
375 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
376 litex_vexriscv::liteeth::LiteEth::new(
377 StaticRef::new(
378 socc::CSR_ETHMAC_BASE
379 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
380 ),
381 socc::MEM_ETHMAC_BASE,
382 socc::MEM_ETHMAC_SIZE,
383 socc::ETHMAC_SLOT_SIZE,
384 socc::ETHMAC_RX_SLOTS,
385 socc::ETHMAC_TX_SLOTS,
386 )
387 );
388
389 ethmac0.initialize();
391
392 type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
394
395 let gpio0 = static_init!(
397 litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
398 litex_vexriscv::gpio::LiteXGPIOController::new(
399 StaticRef::new(
400 socc::CSR_GPIO_BASE
401 as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
402 ),
403 32, ),
405 );
406 gpio0.initialize();
407
408 let gpio_driver = components::gpio::GpioComponent::new(
411 board_kernel,
412 capsules_core::gpio::DRIVER_NUM,
413 components::gpio_component_helper_owned!(
414 GPIOPin,
415 16 => gpio0.get_gpio_pin(16).unwrap(),
416 17 => gpio0.get_gpio_pin(17).unwrap(),
417 18 => gpio0.get_gpio_pin(18).unwrap(),
418 19 => gpio0.get_gpio_pin(19).unwrap(),
419 20 => gpio0.get_gpio_pin(20).unwrap(),
420 21 => gpio0.get_gpio_pin(21).unwrap(),
421 22 => gpio0.get_gpio_pin(22).unwrap(),
422 23 => gpio0.get_gpio_pin(23).unwrap(),
423 24 => gpio0.get_gpio_pin(24).unwrap(),
424 25 => gpio0.get_gpio_pin(25).unwrap(),
425 26 => gpio0.get_gpio_pin(26).unwrap(),
426 27 => gpio0.get_gpio_pin(27).unwrap(),
427 28 => gpio0.get_gpio_pin(28).unwrap(),
428 29 => gpio0.get_gpio_pin(29).unwrap(),
429 30 => gpio0.get_gpio_pin(30).unwrap(),
430 31 => gpio0.get_gpio_pin(31).unwrap(),
431 ),
432 )
433 .finalize(components::gpio_component_static!(GPIOPin));
434
435 let led_gpios = static_init!(
438 [GPIOPin; 8],
439 [
440 gpio0.get_gpio_pin(0).unwrap(),
441 gpio0.get_gpio_pin(1).unwrap(),
442 gpio0.get_gpio_pin(2).unwrap(),
443 gpio0.get_gpio_pin(3).unwrap(),
444 gpio0.get_gpio_pin(4).unwrap(),
445 gpio0.get_gpio_pin(5).unwrap(),
446 gpio0.get_gpio_pin(6).unwrap(),
447 gpio0.get_gpio_pin(7).unwrap(),
448 ]
449 );
450
451 let led_driver =
452 components::led::LedsComponent::new().finalize(components::led_component_static!(
453 kernel::hil::led::LedHigh<GPIOPin>,
454 LedHigh::new(&led_gpios[0]),
455 LedHigh::new(&led_gpios[1]),
456 LedHigh::new(&led_gpios[2]),
457 LedHigh::new(&led_gpios[3]),
458 LedHigh::new(&led_gpios[4]),
459 LedHigh::new(&led_gpios[5]),
460 LedHigh::new(&led_gpios[6]),
461 LedHigh::new(&led_gpios[7]),
462 ));
463
464 let button_driver = components::button::ButtonComponent::new(
467 board_kernel,
468 capsules_core::button::DRIVER_NUM,
469 components::button_component_helper_owned!(
470 GPIOPin,
471 (
472 gpio0.get_gpio_pin(8).unwrap(),
473 kernel::hil::gpio::ActivationMode::ActiveHigh,
474 kernel::hil::gpio::FloatingState::PullNone
475 ),
476 (
477 gpio0.get_gpio_pin(9).unwrap(),
478 kernel::hil::gpio::ActivationMode::ActiveHigh,
479 kernel::hil::gpio::FloatingState::PullNone
480 ),
481 (
482 gpio0.get_gpio_pin(10).unwrap(),
483 kernel::hil::gpio::ActivationMode::ActiveHigh,
484 kernel::hil::gpio::FloatingState::PullNone
485 ),
486 (
487 gpio0.get_gpio_pin(11).unwrap(),
488 kernel::hil::gpio::ActivationMode::ActiveHigh,
489 kernel::hil::gpio::FloatingState::PullNone
490 ),
491 (
492 gpio0.get_gpio_pin(12).unwrap(),
493 kernel::hil::gpio::ActivationMode::ActiveHigh,
494 kernel::hil::gpio::FloatingState::PullNone
495 ),
496 (
497 gpio0.get_gpio_pin(13).unwrap(),
498 kernel::hil::gpio::ActivationMode::ActiveHigh,
499 kernel::hil::gpio::FloatingState::PullNone
500 ),
501 (
502 gpio0.get_gpio_pin(14).unwrap(),
503 kernel::hil::gpio::ActivationMode::ActiveHigh,
504 kernel::hil::gpio::FloatingState::PullNone
505 ),
506 (
507 gpio0.get_gpio_pin(15).unwrap(),
508 kernel::hil::gpio::ActivationMode::ActiveHigh,
509 kernel::hil::gpio::FloatingState::PullNone
510 ),
511 ),
512 )
513 .finalize(components::button_component_static!(GPIOPin));
514
515 let interrupt_service = static_init!(
518 LiteXSimInterruptablePeripherals,
519 LiteXSimInterruptablePeripherals {
520 gpio0,
521 uart0,
522 timer0,
523 ethmac0,
524 }
525 );
526 interrupt_service.init();
527
528 let chip = static_init!(
529 litex_vexriscv::chip::LiteXVexRiscv<
530 LiteXSimInterruptablePeripherals,
531 >,
532 litex_vexriscv::chip::LiteXVexRiscv::new(
533 "Verilated LiteX on VexRiscv",
534 interrupt_service,
535 pmp,
536 )
537 );
538
539 PANIC_REFERENCES.chip = Some(chip);
540
541 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
542 .finalize(components::process_printer_text_component_static!());
543
544 PANIC_REFERENCES.process_printer = Some(process_printer);
545
546 csr::CSR
548 .mie
549 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
550 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
551
552 chip.unmask_interrupts();
554
555 let console = components::console::ConsoleComponent::new(
557 board_kernel,
558 capsules_core::console::DRIVER_NUM,
559 uart_mux,
560 )
561 .finalize(components::console_component_static!());
562 components::debug_writer::DebugWriterComponent::new_unsafe(
564 uart_mux,
565 create_capability!(capabilities::SetDebugWriterCapability),
566 || unsafe {
567 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
568 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
569 >();
570 },
571 )
572 .finalize(components::debug_writer_component_static!());
573
574 let lldb = components::lldb::LowLevelDebugComponent::new(
575 board_kernel,
576 capsules_core::low_level_debug::DRIVER_NUM,
577 uart_mux,
578 )
579 .finalize(components::low_level_debug_component_static!());
580
581 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
582 components::mlfq_component_static!(
583 litex_vexriscv::timer::LiteXAlarm<
584 'static,
585 'static,
586 socc::SoCRegisterFmt,
587 socc::ClockFrequency,
588 >,
589 NUM_PROCS
590 ),
591 );
592
593 let litex_sim = LiteXSim {
594 gpio_driver,
595 button_driver,
596 led_driver,
597 console,
598 alarm,
599 lldb,
600 ipc: kernel::ipc::IPC::new(
601 board_kernel,
602 kernel::ipc::DRIVER_NUM,
603 &memory_allocation_cap,
604 ),
605 scheduler,
606 scheduler_timer,
607 };
608
609 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
610
611 kernel::process::load_processes(
612 board_kernel,
613 chip,
614 core::slice::from_raw_parts(
615 core::ptr::addr_of!(_sapps),
616 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
617 ),
618 core::slice::from_raw_parts_mut(
619 core::ptr::addr_of_mut!(_sappmem),
620 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
621 ),
622 &FAULT_RESPONSE,
623 &process_mgmt_cap,
624 )
625 .unwrap_or_else(|err| {
626 debug!("Error loading processes!");
627 debug!("{:?}", err);
628 });
629
630 (board_kernel, litex_sim, chip)
631}
632
633#[no_mangle]
635pub unsafe fn main() {
636 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
637
638 let (board_kernel, board, chip) = start();
639 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
640}