1#![no_std]
8#![no_main]
9
10use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::debug::PanicResources;
14use kernel::hil::led::LedHigh;
15use kernel::hil::time::{Alarm, Timer};
16use kernel::platform::chip::InterruptService;
17use kernel::platform::{KernelResources, SyscallDriverLookup};
18use kernel::utilities::StaticRef;
19use kernel::utilities::registers::interfaces::ReadWriteable;
20use kernel::utilities::single_thread_value::SingleThreadValue;
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>;
95type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
96type SchedulerInUse = components::sched::mlfq::MLFQComponentType<AlarmHw>;
97
98static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
100 SingleThreadValue::new();
101
102const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
104 capsules_system::process_policies::PanicFaultPolicy {};
105
106kernel::stack_size! {0x2000}
107
108struct LiteXSim {
111 gpio_driver: &'static capsules_core::gpio::GPIO<
112 'static,
113 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
114 >,
115 button_driver: &'static capsules_core::button::Button<
116 'static,
117 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
118 >,
119 led_driver: &'static capsules_core::led::LedDriver<
120 'static,
121 LedHigh<
122 'static,
123 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
124 >,
125 8,
126 >,
127 console: &'static capsules_core::console::Console<'static>,
128 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
129 'static,
130 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
131 >,
132 alarm: &'static capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
133 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
134 scheduler: &'static SchedulerInUse,
135 scheduler_timer: &'static SchedulerTimerHw,
136}
137
138impl SyscallDriverLookup for LiteXSim {
140 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
141 where
142 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
143 {
144 match driver_num {
145 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
146 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
147 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
148 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
149 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
150 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
151 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
152 _ => f(None),
153 }
154 }
155}
156
157impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
158 for LiteXSim
159{
160 type SyscallDriverLookup = Self;
161 type SyscallFilter = ();
162 type ProcessFault = ();
163 type Scheduler = SchedulerInUse;
164 type SchedulerTimer = SchedulerTimerHw;
165 type WatchDog = ();
166 type ContextSwitchCallback = ();
167
168 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
169 self
170 }
171 fn syscall_filter(&self) -> &Self::SyscallFilter {
172 &()
173 }
174 fn process_fault(&self) -> &Self::ProcessFault {
175 &()
176 }
177 fn scheduler(&self) -> &Self::Scheduler {
178 self.scheduler
179 }
180 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
181 self.scheduler_timer
182 }
183 fn watchdog(&self) -> &Self::WatchDog {
184 &()
185 }
186 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
187 &()
188 }
189}
190
191#[inline(never)]
195unsafe fn start() -> (
196 &'static kernel::Kernel,
197 LiteXSim,
198 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
199) {
200 extern "C" {
202 static _sapps: u8;
204 static _eapps: u8;
206 static mut _sappmem: u8;
208 static _eappmem: u8;
210 static _stext: u8;
212 static _etext: u8;
214 static _sflash: u8;
216 static _eflash: u8;
218 static _ssram: u8;
220 static _esram: u8;
222 }
223
224 rv32i::configure_trap_handler();
228
229 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
231 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
232 >();
233
234 let _ = PANIC_RESOURCES
236 .bind_to_thread_unsafe::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>(
237 PanicResources::new(),
238 );
239
240 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
244 rv32i::pmp::kernel_protection::FlashRegion(
245 rv32i::pmp::NAPOTRegionSpec::from_start_end(
246 core::ptr::addr_of!(_sflash),
247 core::ptr::addr_of!(_eflash),
248 )
249 .unwrap(),
250 ),
251 rv32i::pmp::kernel_protection::RAMRegion(
252 rv32i::pmp::NAPOTRegionSpec::from_start_end(
253 core::ptr::addr_of!(_ssram),
254 core::ptr::addr_of!(_esram),
255 )
256 .unwrap(),
257 ),
258 rv32i::pmp::kernel_protection::MMIORegion(
259 rv32i::pmp::NAPOTRegionSpec::from_start_size(
260 0xf0000000 as *const u8, 0x10000000, )
263 .unwrap(),
264 ),
265 rv32i::pmp::kernel_protection::KernelTextRegion(
266 rv32i::pmp::TORRegionSpec::from_start_end(
267 core::ptr::addr_of!(_stext),
268 core::ptr::addr_of!(_etext),
269 )
270 .unwrap(),
271 ),
272 )
273 .unwrap();
274
275 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
277 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
278
279 let processes = components::process_array::ProcessArrayComponent::new()
281 .finalize(components::process_array_component_static!(NUM_PROCS));
282 PANIC_RESOURCES.get().map(|resources| {
283 resources.processes.put(processes.as_slice());
284 });
285
286 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
288
289 let timer0 = static_init!(
293 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
294 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
295 socc::CSR_TIMER0_BASE
296 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
297 ),)
298 );
299
300 let timer0_uptime = static_init!(
302 litex_vexriscv::timer::LiteXTimerUptime<
303 'static,
304 socc::SoCRegisterFmt,
305 socc::ClockFrequency,
306 >,
307 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
308 );
309
310 let litex_alarm = static_init!(
313 AlarmHw,
314 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
315 );
316 timer0.set_timer_client(litex_alarm);
317 litex_alarm.initialize();
318
319 let mux_alarm = static_init!(MuxAlarm<'static, AlarmHw>, MuxAlarm::new(litex_alarm));
322 litex_alarm.set_alarm_client(mux_alarm);
323
324 let virtual_alarm_user = static_init!(
326 VirtualMuxAlarm<'static, AlarmHw>,
327 VirtualMuxAlarm::new(mux_alarm)
328 );
329 virtual_alarm_user.setup();
330
331 let alarm = static_init!(
332 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
333 capsules_core::alarm::AlarmDriver::new(
334 virtual_alarm_user,
335 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
336 )
337 );
338 virtual_alarm_user.set_alarm_client(alarm);
339
340 let scheduler_timer =
341 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
342 .finalize(components::virtual_scheduler_timer_component_static!(
343 AlarmHw
344 ));
345
346 let uart0 = static_init!(
350 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
351 litex_vexriscv::uart::LiteXUart::new(
352 StaticRef::new(
353 socc::CSR_UART_BASE
354 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
355 ),
356 None, )
358 );
359 uart0.initialize();
360
361 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
366 .finalize(components::uart_mux_component_static!());
367
368 let ethmac0 = static_init!(
372 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
373 litex_vexriscv::liteeth::LiteEth::new(
374 StaticRef::new(
375 socc::CSR_ETHMAC_BASE
376 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
377 ),
378 socc::MEM_ETHMAC_BASE,
379 socc::MEM_ETHMAC_SIZE,
380 socc::ETHMAC_SLOT_SIZE,
381 socc::ETHMAC_RX_SLOTS,
382 socc::ETHMAC_TX_SLOTS,
383 )
384 );
385
386 ethmac0.initialize();
388
389 type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
391
392 let gpio0 = static_init!(
394 litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
395 litex_vexriscv::gpio::LiteXGPIOController::new(
396 StaticRef::new(
397 socc::CSR_GPIO_BASE
398 as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
399 ),
400 32, ),
402 );
403 gpio0.initialize();
404
405 let gpio_driver = components::gpio::GpioComponent::new(
408 board_kernel,
409 capsules_core::gpio::DRIVER_NUM,
410 components::gpio_component_helper_owned!(
411 GPIOPin,
412 16 => gpio0.get_gpio_pin(16).unwrap(),
413 17 => gpio0.get_gpio_pin(17).unwrap(),
414 18 => gpio0.get_gpio_pin(18).unwrap(),
415 19 => gpio0.get_gpio_pin(19).unwrap(),
416 20 => gpio0.get_gpio_pin(20).unwrap(),
417 21 => gpio0.get_gpio_pin(21).unwrap(),
418 22 => gpio0.get_gpio_pin(22).unwrap(),
419 23 => gpio0.get_gpio_pin(23).unwrap(),
420 24 => gpio0.get_gpio_pin(24).unwrap(),
421 25 => gpio0.get_gpio_pin(25).unwrap(),
422 26 => gpio0.get_gpio_pin(26).unwrap(),
423 27 => gpio0.get_gpio_pin(27).unwrap(),
424 28 => gpio0.get_gpio_pin(28).unwrap(),
425 29 => gpio0.get_gpio_pin(29).unwrap(),
426 30 => gpio0.get_gpio_pin(30).unwrap(),
427 31 => gpio0.get_gpio_pin(31).unwrap(),
428 ),
429 create_capability!(capabilities::MemoryAllocationCapability),
430 )
431 .finalize(components::gpio_component_static!(GPIOPin));
432
433 let led_gpios = static_init!(
436 [GPIOPin; 8],
437 [
438 gpio0.get_gpio_pin(0).unwrap(),
439 gpio0.get_gpio_pin(1).unwrap(),
440 gpio0.get_gpio_pin(2).unwrap(),
441 gpio0.get_gpio_pin(3).unwrap(),
442 gpio0.get_gpio_pin(4).unwrap(),
443 gpio0.get_gpio_pin(5).unwrap(),
444 gpio0.get_gpio_pin(6).unwrap(),
445 gpio0.get_gpio_pin(7).unwrap(),
446 ]
447 );
448
449 let led_driver =
450 components::led::LedsComponent::new().finalize(components::led_component_static!(
451 kernel::hil::led::LedHigh<GPIOPin>,
452 LedHigh::new(&led_gpios[0]),
453 LedHigh::new(&led_gpios[1]),
454 LedHigh::new(&led_gpios[2]),
455 LedHigh::new(&led_gpios[3]),
456 LedHigh::new(&led_gpios[4]),
457 LedHigh::new(&led_gpios[5]),
458 LedHigh::new(&led_gpios[6]),
459 LedHigh::new(&led_gpios[7]),
460 ));
461
462 let button_driver = components::button::ButtonComponent::new(
465 board_kernel,
466 capsules_core::button::DRIVER_NUM,
467 components::button_component_helper_owned!(
468 GPIOPin,
469 (
470 gpio0.get_gpio_pin(8).unwrap(),
471 kernel::hil::gpio::ActivationMode::ActiveHigh,
472 kernel::hil::gpio::FloatingState::PullNone
473 ),
474 (
475 gpio0.get_gpio_pin(9).unwrap(),
476 kernel::hil::gpio::ActivationMode::ActiveHigh,
477 kernel::hil::gpio::FloatingState::PullNone
478 ),
479 (
480 gpio0.get_gpio_pin(10).unwrap(),
481 kernel::hil::gpio::ActivationMode::ActiveHigh,
482 kernel::hil::gpio::FloatingState::PullNone
483 ),
484 (
485 gpio0.get_gpio_pin(11).unwrap(),
486 kernel::hil::gpio::ActivationMode::ActiveHigh,
487 kernel::hil::gpio::FloatingState::PullNone
488 ),
489 (
490 gpio0.get_gpio_pin(12).unwrap(),
491 kernel::hil::gpio::ActivationMode::ActiveHigh,
492 kernel::hil::gpio::FloatingState::PullNone
493 ),
494 (
495 gpio0.get_gpio_pin(13).unwrap(),
496 kernel::hil::gpio::ActivationMode::ActiveHigh,
497 kernel::hil::gpio::FloatingState::PullNone
498 ),
499 (
500 gpio0.get_gpio_pin(14).unwrap(),
501 kernel::hil::gpio::ActivationMode::ActiveHigh,
502 kernel::hil::gpio::FloatingState::PullNone
503 ),
504 (
505 gpio0.get_gpio_pin(15).unwrap(),
506 kernel::hil::gpio::ActivationMode::ActiveHigh,
507 kernel::hil::gpio::FloatingState::PullNone
508 ),
509 ),
510 create_capability!(capabilities::MemoryAllocationCapability),
511 )
512 .finalize(components::button_component_static!(GPIOPin));
513
514 let interrupt_service = static_init!(
517 LiteXSimInterruptablePeripherals,
518 LiteXSimInterruptablePeripherals {
519 gpio0,
520 uart0,
521 timer0,
522 ethmac0,
523 }
524 );
525 interrupt_service.init();
526
527 let chip = static_init!(
528 litex_vexriscv::chip::LiteXVexRiscv<
529 LiteXSimInterruptablePeripherals,
530 >,
531 litex_vexriscv::chip::LiteXVexRiscv::new(
532 "Verilated LiteX on VexRiscv",
533 interrupt_service,
534 pmp,
535 )
536 );
537 PANIC_RESOURCES.get().map(|resources| {
538 resources.chip.put(chip);
539 });
540
541 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
542 .finalize(components::process_printer_text_component_static!());
543 PANIC_RESOURCES.get().map(|resources| {
544 resources.printer.put(process_printer);
545 });
546
547 csr::CSR
549 .mie
550 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
551 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
552
553 chip.unmask_interrupts();
555
556 let console = components::console::ConsoleComponent::new(
558 board_kernel,
559 capsules_core::console::DRIVER_NUM,
560 uart_mux,
561 create_capability!(capabilities::MemoryAllocationCapability),
562 )
563 .finalize(components::console_component_static!());
564 components::debug_writer::DebugWriterComponent::new_unsafe(
566 uart_mux,
567 create_capability!(capabilities::SetDebugWriterCapability),
568 || unsafe {
569 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
570 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
571 >();
572 },
573 )
574 .finalize(components::debug_writer_component_static!());
575
576 let lldb = components::lldb::LowLevelDebugComponent::new(
577 board_kernel,
578 capsules_core::low_level_debug::DRIVER_NUM,
579 uart_mux,
580 create_capability!(capabilities::MemoryAllocationCapability),
581 )
582 .finalize(components::low_level_debug_component_static!());
583
584 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes)
585 .finalize(components::mlfq_component_static!(AlarmHw, NUM_PROCS));
586
587 let litex_sim = LiteXSim {
588 gpio_driver,
589 button_driver,
590 led_driver,
591 console,
592 alarm,
593 lldb,
594 ipc: kernel::ipc::IPC::new(
595 board_kernel,
596 kernel::ipc::DRIVER_NUM,
597 &memory_allocation_cap,
598 ),
599 scheduler,
600 scheduler_timer,
601 };
602
603 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
604
605 kernel::process::load_processes(
606 board_kernel,
607 chip,
608 core::slice::from_raw_parts(
609 core::ptr::addr_of!(_sapps),
610 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
611 ),
612 core::slice::from_raw_parts_mut(
613 core::ptr::addr_of_mut!(_sappmem),
614 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
615 ),
616 &FAULT_RESPONSE,
617 &process_mgmt_cap,
618 )
619 .unwrap_or_else(|err| {
620 debug!("Error loading processes!");
621 debug!("{:?}", err);
622 });
623
624 (board_kernel, litex_sim, chip)
625}
626
627#[no_mangle]
629pub unsafe fn main() {
630 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
631
632 let (board_kernel, board, chip) = start();
633 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
634}