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::scheduler::mlfq::MLFQSched;
19use kernel::utilities::registers::interfaces::ReadWriteable;
20use kernel::utilities::single_thread_value::SingleThreadValue;
21use kernel::utilities::StaticRef;
22use kernel::{create_capability, debug, static_init};
23use rv32i::csr;
24
25mod io;
26mod litex_generated_constants;
27
28use litex_generated_constants as socc;
35
36struct LiteXSimInterruptablePeripherals {
44 gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
45 uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
46 timer0: &'static litex_vexriscv::timer::LiteXTimer<
47 'static,
48 socc::SoCRegisterFmt,
49 socc::ClockFrequency,
50 >,
51 ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
52 'static,
53 { socc::ETHMAC_TX_SLOTS },
54 socc::SoCRegisterFmt,
55 >,
56}
57
58impl LiteXSimInterruptablePeripherals {
59 pub fn init(&'static self) {
61 kernel::deferred_call::DeferredCallClient::register(self.uart0);
62 }
63}
64
65impl InterruptService for LiteXSimInterruptablePeripherals {
66 unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
67 match interrupt as usize {
68 socc::UART_INTERRUPT => {
69 self.uart0.service_interrupt();
70 true
71 }
72 socc::TIMER0_INTERRUPT => {
73 self.timer0.service_interrupt();
74 true
75 }
76 socc::ETHMAC_INTERRUPT => {
77 self.ethmac0.service_interrupt();
78 true
79 }
80 socc::GPIO_INTERRUPT => {
81 self.gpio0.service_interrupt();
82 true
83 }
84 _ => false,
85 }
86 }
87}
88
89const NUM_PROCS: usize = 4;
90
91type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>;
92type AlarmHw =
93 litex_vexriscv::timer::LiteXAlarm<'static, 'static, socc::SoCRegisterFmt, socc::ClockFrequency>;
94type SchedulerTimerHw =
95 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
96type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
97
98static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
100 SingleThreadValue::new(PanicResources::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 MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>,
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 = MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>;
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 PANIC_RESOURCES
236 .bind_to_thread_unsafe::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
237
238 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
242 rv32i::pmp::kernel_protection::FlashRegion(
243 rv32i::pmp::NAPOTRegionSpec::from_start_end(
244 core::ptr::addr_of!(_sflash),
245 core::ptr::addr_of!(_eflash),
246 )
247 .unwrap(),
248 ),
249 rv32i::pmp::kernel_protection::RAMRegion(
250 rv32i::pmp::NAPOTRegionSpec::from_start_end(
251 core::ptr::addr_of!(_ssram),
252 core::ptr::addr_of!(_esram),
253 )
254 .unwrap(),
255 ),
256 rv32i::pmp::kernel_protection::MMIORegion(
257 rv32i::pmp::NAPOTRegionSpec::from_start_size(
258 0xf0000000 as *const u8, 0x10000000, )
261 .unwrap(),
262 ),
263 rv32i::pmp::kernel_protection::KernelTextRegion(
264 rv32i::pmp::TORRegionSpec::from_start_end(
265 core::ptr::addr_of!(_stext),
266 core::ptr::addr_of!(_etext),
267 )
268 .unwrap(),
269 ),
270 )
271 .unwrap();
272
273 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
275 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
276
277 let processes = components::process_array::ProcessArrayComponent::new()
279 .finalize(components::process_array_component_static!(NUM_PROCS));
280 PANIC_RESOURCES.get().map(|resources| {
281 resources.processes.put(processes.as_slice());
282 });
283
284 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
286
287 let timer0 = static_init!(
291 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
292 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
293 socc::CSR_TIMER0_BASE
294 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
295 ),)
296 );
297
298 let timer0_uptime = static_init!(
300 litex_vexriscv::timer::LiteXTimerUptime<
301 'static,
302 socc::SoCRegisterFmt,
303 socc::ClockFrequency,
304 >,
305 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
306 );
307
308 let litex_alarm = static_init!(
311 AlarmHw,
312 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
313 );
314 timer0.set_timer_client(litex_alarm);
315 litex_alarm.initialize();
316
317 let mux_alarm = static_init!(MuxAlarm<'static, AlarmHw>, MuxAlarm::new(litex_alarm));
320 litex_alarm.set_alarm_client(mux_alarm);
321
322 let virtual_alarm_user = static_init!(
324 VirtualMuxAlarm<'static, AlarmHw>,
325 VirtualMuxAlarm::new(mux_alarm)
326 );
327 virtual_alarm_user.setup();
328
329 let alarm = static_init!(
330 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
331 capsules_core::alarm::AlarmDriver::new(
332 virtual_alarm_user,
333 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
334 )
335 );
336 virtual_alarm_user.set_alarm_client(alarm);
337
338 let scheduler_timer =
339 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
340 .finalize(components::virtual_scheduler_timer_component_static!(
341 AlarmHw
342 ));
343
344 let uart0 = static_init!(
348 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
349 litex_vexriscv::uart::LiteXUart::new(
350 StaticRef::new(
351 socc::CSR_UART_BASE
352 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
353 ),
354 None, )
356 );
357 uart0.initialize();
358
359 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
364 .finalize(components::uart_mux_component_static!());
365
366 let ethmac0 = static_init!(
370 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
371 litex_vexriscv::liteeth::LiteEth::new(
372 StaticRef::new(
373 socc::CSR_ETHMAC_BASE
374 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
375 ),
376 socc::MEM_ETHMAC_BASE,
377 socc::MEM_ETHMAC_SIZE,
378 socc::ETHMAC_SLOT_SIZE,
379 socc::ETHMAC_RX_SLOTS,
380 socc::ETHMAC_TX_SLOTS,
381 )
382 );
383
384 ethmac0.initialize();
386
387 type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
389
390 let gpio0 = static_init!(
392 litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
393 litex_vexriscv::gpio::LiteXGPIOController::new(
394 StaticRef::new(
395 socc::CSR_GPIO_BASE
396 as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
397 ),
398 32, ),
400 );
401 gpio0.initialize();
402
403 let gpio_driver = components::gpio::GpioComponent::new(
406 board_kernel,
407 capsules_core::gpio::DRIVER_NUM,
408 components::gpio_component_helper_owned!(
409 GPIOPin,
410 16 => gpio0.get_gpio_pin(16).unwrap(),
411 17 => gpio0.get_gpio_pin(17).unwrap(),
412 18 => gpio0.get_gpio_pin(18).unwrap(),
413 19 => gpio0.get_gpio_pin(19).unwrap(),
414 20 => gpio0.get_gpio_pin(20).unwrap(),
415 21 => gpio0.get_gpio_pin(21).unwrap(),
416 22 => gpio0.get_gpio_pin(22).unwrap(),
417 23 => gpio0.get_gpio_pin(23).unwrap(),
418 24 => gpio0.get_gpio_pin(24).unwrap(),
419 25 => gpio0.get_gpio_pin(25).unwrap(),
420 26 => gpio0.get_gpio_pin(26).unwrap(),
421 27 => gpio0.get_gpio_pin(27).unwrap(),
422 28 => gpio0.get_gpio_pin(28).unwrap(),
423 29 => gpio0.get_gpio_pin(29).unwrap(),
424 30 => gpio0.get_gpio_pin(30).unwrap(),
425 31 => gpio0.get_gpio_pin(31).unwrap(),
426 ),
427 )
428 .finalize(components::gpio_component_static!(GPIOPin));
429
430 let led_gpios = static_init!(
433 [GPIOPin; 8],
434 [
435 gpio0.get_gpio_pin(0).unwrap(),
436 gpio0.get_gpio_pin(1).unwrap(),
437 gpio0.get_gpio_pin(2).unwrap(),
438 gpio0.get_gpio_pin(3).unwrap(),
439 gpio0.get_gpio_pin(4).unwrap(),
440 gpio0.get_gpio_pin(5).unwrap(),
441 gpio0.get_gpio_pin(6).unwrap(),
442 gpio0.get_gpio_pin(7).unwrap(),
443 ]
444 );
445
446 let led_driver =
447 components::led::LedsComponent::new().finalize(components::led_component_static!(
448 kernel::hil::led::LedHigh<GPIOPin>,
449 LedHigh::new(&led_gpios[0]),
450 LedHigh::new(&led_gpios[1]),
451 LedHigh::new(&led_gpios[2]),
452 LedHigh::new(&led_gpios[3]),
453 LedHigh::new(&led_gpios[4]),
454 LedHigh::new(&led_gpios[5]),
455 LedHigh::new(&led_gpios[6]),
456 LedHigh::new(&led_gpios[7]),
457 ));
458
459 let button_driver = components::button::ButtonComponent::new(
462 board_kernel,
463 capsules_core::button::DRIVER_NUM,
464 components::button_component_helper_owned!(
465 GPIOPin,
466 (
467 gpio0.get_gpio_pin(8).unwrap(),
468 kernel::hil::gpio::ActivationMode::ActiveHigh,
469 kernel::hil::gpio::FloatingState::PullNone
470 ),
471 (
472 gpio0.get_gpio_pin(9).unwrap(),
473 kernel::hil::gpio::ActivationMode::ActiveHigh,
474 kernel::hil::gpio::FloatingState::PullNone
475 ),
476 (
477 gpio0.get_gpio_pin(10).unwrap(),
478 kernel::hil::gpio::ActivationMode::ActiveHigh,
479 kernel::hil::gpio::FloatingState::PullNone
480 ),
481 (
482 gpio0.get_gpio_pin(11).unwrap(),
483 kernel::hil::gpio::ActivationMode::ActiveHigh,
484 kernel::hil::gpio::FloatingState::PullNone
485 ),
486 (
487 gpio0.get_gpio_pin(12).unwrap(),
488 kernel::hil::gpio::ActivationMode::ActiveHigh,
489 kernel::hil::gpio::FloatingState::PullNone
490 ),
491 (
492 gpio0.get_gpio_pin(13).unwrap(),
493 kernel::hil::gpio::ActivationMode::ActiveHigh,
494 kernel::hil::gpio::FloatingState::PullNone
495 ),
496 (
497 gpio0.get_gpio_pin(14).unwrap(),
498 kernel::hil::gpio::ActivationMode::ActiveHigh,
499 kernel::hil::gpio::FloatingState::PullNone
500 ),
501 (
502 gpio0.get_gpio_pin(15).unwrap(),
503 kernel::hil::gpio::ActivationMode::ActiveHigh,
504 kernel::hil::gpio::FloatingState::PullNone
505 ),
506 ),
507 )
508 .finalize(components::button_component_static!(GPIOPin));
509
510 let interrupt_service = static_init!(
513 LiteXSimInterruptablePeripherals,
514 LiteXSimInterruptablePeripherals {
515 gpio0,
516 uart0,
517 timer0,
518 ethmac0,
519 }
520 );
521 interrupt_service.init();
522
523 let chip = static_init!(
524 litex_vexriscv::chip::LiteXVexRiscv<
525 LiteXSimInterruptablePeripherals,
526 >,
527 litex_vexriscv::chip::LiteXVexRiscv::new(
528 "Verilated LiteX on VexRiscv",
529 interrupt_service,
530 pmp,
531 )
532 );
533 PANIC_RESOURCES.get().map(|resources| {
534 resources.chip.put(chip);
535 });
536
537 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
538 .finalize(components::process_printer_text_component_static!());
539 PANIC_RESOURCES.get().map(|resources| {
540 resources.printer.put(process_printer);
541 });
542
543 csr::CSR
545 .mie
546 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
547 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
548
549 chip.unmask_interrupts();
551
552 let console = components::console::ConsoleComponent::new(
554 board_kernel,
555 capsules_core::console::DRIVER_NUM,
556 uart_mux,
557 )
558 .finalize(components::console_component_static!());
559 components::debug_writer::DebugWriterComponent::new_unsafe(
561 uart_mux,
562 create_capability!(capabilities::SetDebugWriterCapability),
563 || unsafe {
564 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
565 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
566 >();
567 },
568 )
569 .finalize(components::debug_writer_component_static!());
570
571 let lldb = components::lldb::LowLevelDebugComponent::new(
572 board_kernel,
573 capsules_core::low_level_debug::DRIVER_NUM,
574 uart_mux,
575 )
576 .finalize(components::low_level_debug_component_static!());
577
578 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
579 components::mlfq_component_static!(
580 litex_vexriscv::timer::LiteXAlarm<
581 'static,
582 'static,
583 socc::SoCRegisterFmt,
584 socc::ClockFrequency,
585 >,
586 NUM_PROCS
587 ),
588 );
589
590 let litex_sim = LiteXSim {
591 gpio_driver,
592 button_driver,
593 led_driver,
594 console,
595 alarm,
596 lldb,
597 ipc: kernel::ipc::IPC::new(
598 board_kernel,
599 kernel::ipc::DRIVER_NUM,
600 &memory_allocation_cap,
601 ),
602 scheduler,
603 scheduler_timer,
604 };
605
606 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
607
608 kernel::process::load_processes(
609 board_kernel,
610 chip,
611 core::slice::from_raw_parts(
612 core::ptr::addr_of!(_sapps),
613 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
614 ),
615 core::slice::from_raw_parts_mut(
616 core::ptr::addr_of_mut!(_sappmem),
617 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
618 ),
619 &FAULT_RESPONSE,
620 &process_mgmt_cap,
621 )
622 .unwrap_or_else(|err| {
623 debug!("Error loading processes!");
624 debug!("{:?}", err);
625 });
626
627 (board_kernel, litex_sim, chip)
628}
629
630#[no_mangle]
632pub unsafe fn main() {
633 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
634
635 let (board_kernel, board, chip) = start();
636 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
637}