LiteXの続き。LiteXでどうにかBIOSを立ち上げることができるようになったが、次はキーボードの入力が受け付けられない。 これはおそらく割込みをまじめに接続していないことだろう。LiteXのほかのデザインはどうだろうか?
まずはRocketの実装とVexRiscVの実装を見てみる。
- Rocketの場合
self.cpu_params = dict( # Clk / Rst. i_clock = ClockSignal("sys"), i_reset = ResetSignal("sys") | self.reset, # Debug (ignored). i_debug_clock = 0, i_debug_reset = ResetSignal() | self.reset, o_debug_clockeddmi_dmi_req_ready = Open(), i_debug_clockeddmi_dmi_req_valid = 0, i_debug_clockeddmi_dmi_req_bits_addr = 0, i_debug_clockeddmi_dmi_req_bits_data = 0, i_debug_clockeddmi_dmi_req_bits_op = 0, i_debug_clockeddmi_dmi_resp_ready = 0, o_debug_clockeddmi_dmi_resp_valid = Open(), o_debug_clockeddmi_dmi_resp_bits_data = Open(), o_debug_clockeddmi_dmi_resp_bits_resp = Open(), i_debug_clockeddmi_dmiClock = 0, i_debug_clockeddmi_dmiReset = ResetSignal() | self.reset, o_debug_ndreset = Open(), o_debug_dmactive = Open(), i_debug_dmactiveAck = 0, # IRQ. i_interrupts = self.interrupt,
- VexRiscVの場合
# CPU Instance. self.cpu_params = dict( i_clk = ClockSignal("sys"), i_reset = ResetSignal("sys") | self.reset, i_externalInterruptArray = self.interrupt, i_timerInterrupt = 0, i_softwareInterrupt = 0,
Interruptという信号を接続しているようだ。これは元をたどれば、タイマーとUARTに接続されているようだ。
always @(*) begin main_interrupt <= 32'd0; main_interrupt[1] <= main_timer_irq; main_interrupt[0] <= main_uart_irq; end
さらにこれをPLICに接続することが前提のようだ。Rocket側の実装を追いかけると、PLICのラッパーに接続されているようだ。
ClockSinkDomain plicDomainWrapper ( // @[Plic.scala 359:39] .auto_plic_int_in_0(plicDomainWrapper_auto_plic_int_in_0), .auto_plic_int_in_1(plicDomainWrapper_auto_plic_int_in_1), .auto_plic_int_in_2(plicDomainWrapper_auto_plic_int_in_2), .auto_plic_int_in_3(plicDomainWrapper_auto_plic_int_in_3), .auto_plic_int_in_4(plicDomainWrapper_auto_plic_int_in_4), .auto_plic_int_in_5(plicDomainWrapper_auto_plic_int_in_5), .auto_plic_int_in_6(plicDomainWrapper_auto_plic_int_in_6), .auto_plic_int_in_7(plicDomainWrapper_auto_plic_int_in_7), .auto_plic_int_out_0(plicDomainWrapper_auto_plic_int_out_0), .auto_plic_in_a_ready(plicDomainWrapper_auto_plic_in_a_ready), .auto_plic_in_a_valid(plicDomainWrapper_auto_plic_in_a_valid), .auto_plic_in_a_bits_opcode(plicDomainWrapper_auto_plic_in_a_bits_opcode), .auto_plic_in_a_bits_param(plicDomainWrapper_auto_plic_in_a_bits_param), .auto_plic_in_a_bits_size(plicDomainWrapper_auto_plic_in_a_bits_size), .auto_plic_in_a_bits_source(plicDomainWrapper_auto_plic_in_a_bits_source), .auto_plic_in_a_bits_address(plicDomainWrapper_auto_plic_in_a_bits_address), .auto_plic_in_a_bits_mask(plicDomainWrapper_auto_plic_in_a_bits_mask), .auto_plic_in_a_bits_data(plicDomainWrapper_auto_plic_in_a_bits_data), .auto_plic_in_a_bits_corrupt(plicDomainWrapper_auto_plic_in_a_bits_corrupt), .auto_plic_in_d_ready(plicDomainWrapper_auto_plic_in_d_ready), .auto_plic_in_d_valid(plicDomainWrapper_auto_plic_in_d_valid), .auto_plic_in_d_bits_opcode(plicDomainWrapper_auto_plic_in_d_bits_opcode), .auto_plic_in_d_bits_size(plicDomainWrapper_auto_plic_in_d_bits_size), .auto_plic_in_d_bits_source(plicDomainWrapper_auto_plic_in_d_bits_source), .auto_plic_in_d_bits_data(plicDomainWrapper_auto_plic_in_d_bits_data), .auto_clock_in_clock(plicDomainWrapper_auto_clock_in_clock), .auto_clock_in_reset(plicDomainWrapper_auto_clock_in_reset) );
VexRiscVの場合は、直接MEIPに接続されるようになっている。ちょっと強引かな。
CsrPlugin_mip_MEIP <= externalInterrupt; CsrPlugin_mip_MTIP <= timerInterrupt; CsrPlugin_mip_MSIP <= softwareInterrupt;
PLICの実装は、どこからかオープンソースのものを取ってこようと思う。