r3_port_riscv 0.1.1

RISC-V port for R3
Documentation
The RISC-V port for [the R3 kernel](::r3).

# Startup code

[`use_rt!`] hooks up the entry points ([`EntryPoint`]) using `#[`[`::riscv_rt::entry`]`]`. If this is not desirable for some reason, you can opt not to use it and call the entry points in other ways.

# Interrupts

This port supports the basic interrupt handling model from the RISC-V specification.

Other interrupt handling models such as [RISC-V Core-Local Interrupt Controller] are not supported.

[RISC-V Core-Local Interrupt Controller]: https://github.com/riscv/riscv-fast-interrupt

## Local Interrupts

The first few interrupt numbers are allocated for interrupts defined by the RISC-V privileged architecture (Machine software interrupts, timer interrupts, and external interrupts), which we collectively call **local interrupts**. The [second-level interrupt handlers] for these interrupt numbers are called with their respective interrupts disabled (`mie.M[STE]IE = 0`) and global interrupts enabled (`mstatus.MIE = 1`).

| Interrupt Type | Interrupt Number       | Can [Pend]? |
| -------------- | ---------------------- | ----------- |
| Software       | [`INTERRUPT_SOFTWARE`] | Yes         |
| Timer          | [`INTERRUPT_TIMER`]    | No          |
| External       | [`INTERRUPT_EXTERNAL`] | No          |

The local interrupts **follow a fixed priority scheme** in which they are handled in the following decreasing priority order: External, Software, Timer. Interrupts with a higher priority can preempt lower ones, but not the other way. This is realized by carefully controlling the enable bits in the top-level interrupt handler.

The interrupt handler of a particular interrupt number can re-enable the interrupts of the said interrupt number to allow re-entry by preemption (this is useful for external interrupts, which usually have multiple interrupt sources with varying priorities).

The local interrupts are always enabled from an API point of view. **[`InterruptLine::disable`] will always return [`NotSupported`]**.

[second-level interrupt handlers]: r3::kernel::InterruptHandler
[`InterruptLine::disable`]: r3::kernel::InterruptLine::disable
[Pend]: r3::kernel::InterruptLine::pend
[`NotSupported`]: r3::kernel::EnableInterruptLineError::NotSupported
[*managed*]: r3#interrupt-handling-framework

<div class="admonition-follows"></div>

> **Rationale:** Because their enable bits are toggled frequently in the top-level interrupt handler, removing the ability to disable these interrupts simplifies the implementation and reduces interupt latency. This should pose no problems for most cases.

The local interrupts are always [*managed*]. This is because CPU Lock is currently mapped to `mstatus.MIE` (global interrupt-enable).

## Interrupt Controller

The remaining interrupt numbers (≥ [`INTERRUPT_PLATFORM_START`]) are controlled by **an interrupt controller driver**.

<span class="center">![interrupts]</span>

Usually, there are more than one interrupt source connected to the external interrupt pin of a hart through an interrupt controller. An interrupt controller driver is responsible for determining the source of an external interrupt and dispatching the appropriate handler. At configuration time, it attaches an interrupt handler to [`INTERRUPT_EXTERNAL`]. The interrupt handler, when called, queries the currently pending interrupt (let's assume the interrupt number is `n`). It can set `mie.MEIE` to allow nested interrupts (assuming the underlying hardware supports that). Then it fetches the corresponding interrupt handler by indexing [`INTERRUPT_HANDLERS`] by `n + INTERRUPT_PLATFORM_START` and calls that.

The [`PortInterrupts`] implementation generated by `use_port!` delegates method calls to an interrupt controller driver through [`InterruptController`] for these interrupt numbers.

Your system type should be combined with an interrupt controller driver by implementing [`InterruptController`]. Most systems are equipped with [Platform-Level Interrupt Controller (PLIC)], whose driver is provided by [`use_plic!`]. PLIC does not support pending or clearing interrupt lines.

[Platform-Level Interrupt Controller (PLIC)]: https://github.com/riscv/riscv-plic-spec/blob/master/riscv-plic.adoc
[`PortInterrupts`]: r3::kernel::PortInterrupts
[`INTERRUPT_HANDLERS`]: r3::kernel::KernelCfg2::INTERRUPT_HANDLERS

# Emulation

## `LR`/`SC` Emulation

The **`emulate-lr-sc`** Cargo feature enables the software emulation of the `lr` (load-reserved) and `sc` (store-conditional) instructions. This is useful for a target that supports atomic memory operations but doesn't support these particular instructions, such as FE310. The following limitations should be kept in mind when using this feature:

 - The software emulation is slow and non-preemptive (increases the worst-case interrupt latency).
 - The addition of the software emulation code introduces a non-negligible code size overhead.
 - It doesn't do actual bus snooping and therefore it will behave incorrectly if there's another bus master<!-- TODO: find a better, non-offensive word --> controlling the same memory address.
 - Instructions with `rd = sp` are not supported and will behave incorrectly. This shouldn't be a problem in practice.
 - It doesn't do actual bus snooping and can't detect a conflicting memory write that doesn't modify the memory contents. This shouldn't be a problem for the atomic operations currently provided by the standard library.

`lr` and `sc` instructions are generated when the program uses atomic operations that aren't covered by AMO instructions (e.g., `Atomic*::compare_and_swap`).

## `mstatus.MPIE` Maintenance

The **`maintain-pie`** Cargo feature enables the work-around for the hardware quirk where the `mret` instruction clears `mstatus.MPIE` in violation of the specification. This quirk is found in QEMU 4.2 and K210. The common symptom is methods returning `Err(BadContext)`.

# Implementation

The CPU Lock state is mapped to `mstatus.MIE` (global interrupt-enable). Unmanaged interrupts aren't supported.

## Context State

The state of an interrupted thread is stored to the interrupted thread's stack in the following form:

```rust,ignore
#[repr(C)]
struct ContextState {
    // Second-level state (SLS)
    // ------------------------
    //
    // Includes everything that is not included in the first-level state. These
    // are moved between memory and registers only when switching tasks.

    // SLS.HDR: Second-level state, header
    //
    // The `mstatus` field preserves the state of `mstatus.FS[1]`.
    // `mstatus.FS[0]` is assumed to `1`. This means `mstatus.FS` can only take
    // one of the following states: Initial and Dirty.
    // Irrelevant bits are don't-care (hence `_part`).
    #[cfg(target_feature = "f")]
    mstatus_part: usize,

    // SLS.F: Second-level state, FP registers
    //
    // This portion exists only if `mstatus.FS[1] != 0`.
    #[cfg(target_feature = "f")]
    f8: [FReg; 2],  // fs0-fs1
    #[cfg(target_feature = "f")]
    f18: [FReg; 10], // fs2-fs11

    // SLS.X: Second-level state, X registers
    x8: usize,  // s0/fp
    x9: usize,  // s1
    #[cfg(not(target_feature = "e"))]
    x18: usize, // s2
    #[cfg(not(target_feature = "e"))]
    x19: usize, // s3
    #[cfg(not(target_feature = "e"))]
    x20: usize, // s4
    #[cfg(not(target_feature = "e"))]
    x21: usize, // s5
    #[cfg(not(target_feature = "e"))]
    x22: usize, // s6
    #[cfg(not(target_feature = "e"))]
    x23: usize, // s7
    #[cfg(not(target_feature = "e"))]
    x24: usize, // s8
    #[cfg(not(target_feature = "e"))]
    x25: usize, // s9
    #[cfg(not(target_feature = "e"))]
    x26: usize, // s10
    #[cfg(not(target_feature = "e"))]
    x27: usize, // s11

    // First-level state (FLS)
    // -----------------------
    //
    // This section is comprised of caller-saved registers. In an exception
    // handler, saving/restoring this set of registers at entry and exit allows
    // it to call Rust functions.
    //
    // The registers are ordered in the encoding order (rather than grouping
    // them by their purposes, as done by Linux and FreeBSD) to improve the
    // compression ratio very slightly when transmitting the code over a
    // network.

    // FLS.F: First-level state, FP registers
    //
    // This portion exists only if `mstatus.FS[1] != 0`.
    #[cfg(target_feature = "f")]
    f0: [FReg; 8],  // ft0-ft7
    #[cfg(target_feature = "f")]
    f10: [FReg; 8], // fa0-fa7
    #[cfg(target_feature = "f")]
    f28: [FReg; 4], // ft8-ft11
    fcsr: usize,
    _pad: [u8; (max(FLEN, XLEN) - XLEN) / 8],

    // FLS.X: First-level state, X registers
    x1: usize,  // ra
    x5: usize,  // t0
    x6: usize,  // t1
    x7: usize,  // t2
    x10: usize, // a0
    x11: usize, // a1
    x12: usize, // a2
    x13: usize, // a3
    x14: usize, // a4
    x15: usize, // a5
    #[cfg(not(e))]
    x16: usize, // a6
    #[cfg(not(e))]
    x17: usize, // a7
    #[cfg(not(e))]
    x28: usize, // t3
    #[cfg(not(e))]
    x29: usize, // t4
    #[cfg(not(e))]
    x30: usize, // t5
    #[cfg(not(e))]
    x31: usize, // t6
    pc: usize, // original program counter
}
```

`x2` (`sp`) is stored in [`TaskCb::port_task_state`]. The stored stack pointer is only aligned to word boundaries.

[`TaskCb::port_task_state`]: r3::kernel::TaskCb::port_task_state

The idle task (the implicit task that runs when `*`[`running_task_ptr`]`().is_none()`) always execute with `sp == 0`. For the idle task, saving and restoring the context store is essentially replaced with no-op or loads of hard-coded values. In particular, `pc` is always “restored” with the entry point of the idle task.

[`running_task_ptr`]: r3::kernel::State::running_task_ptr

When a task is activated, a new context state is created inside the task's stack. By default, only essential registers are preloaded with known values. The **`preload-registers`** Cargo feature enables preloading for all `x` registers, which might help in debugging at the cost of performance and code size.

The trap handler stores a first-level state directly below the current stack pointer. This means **the stack pointer must be aligned to a `max(XLEN, FLEN)`-bit boundary all the time**. This requirement is weaker than the standard ABI's requirement, so it shouldn't pose a problem for most cases.

## Processor Modes

All code executes in Machine mode. The value of `mstatus.MPP` is always `M` (`0b11`).

<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

<!--
FIXME: Work-around for `svgbobdoc` not supporting `#[doc(include = ...)]`
       or `rustdoc` not integrating `svgbob` yet ;)
       Related: <https://github.com/ivanceras/svgbob/issues/26>

```svgbob

                     ,--------------------------------------------------------------,
                     |                                                              |
                     |     "INTERRUPT_HANDLERS"                                     |
                     |    ,---+----------------,                                    |
                  ,--)-\> | 0 | Software       |                                    |
  ,-----------,   |  |    +---+----------------+                                    |
  | Top-Level | --+--)-\> | 1 | Timer          |      Interrupt Controller Driver   |
  '-----------'   |  |    +---+----------------+        ,----------------------,    |
                  '--)-\> | 2 | External       | ----\> | Interrupt Dispatcher | ---'
                     |    +---+----------------+        '----------------------'
                     '-\> | 3 | IC Interrupt 0 | ---,
                          +---+----------------+    |     ,--------------------,
                          | 4 | IC Interrupt 1 |    '--\> | Interrupt Handler  |
                          '---+----------------'          | for IC Interrupt 0 |
                                                          '--------------------'

```

The following data URI was generated by processing the above text through `svgbobdoc`. Make sure to replace `\>` with `->`.
-->

[interrupts]: data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iYm9iIiBmb250LWZhbWlseT0iJ1NvdXJjZSBDb2RlIFBybycsJ0FuZGFsZSBNb25vJywnU2Vnb2UgVUkgTW9ubycsJ0RlamF2dSBTYW5zIE1vbm8nLG1vbm9zcGFjZSIgZm9udC1zaXplPSIxNCIgaGVpZ2h0PSIyNTYiIHdpZHRoPSI2ODAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxkZWZzPgo8bWFya2VyIGlkPSJ0cmlhbmdsZSIgbWFya2VySGVpZ2h0PSI4IiBtYXJrZXJXaWR0aD0iOCIgb3JpZW50PSJhdXRvIiByZWZYPSI0IiByZWZZPSIyIiB2aWV3Qm94PSIwIDAgOCA0Ij4KPHBvbHlnb24gY2xhc3M9ImZnX2ZpbGwiIHBvaW50cz0iMCwwIDAsNCA4LDIgMCwwIi8+CjwvbWFya2VyPgo8bWFya2VyIGlkPSJjbGVhcl90cmlhbmdsZSIgbWFya2VySGVpZ2h0PSIxMCIgbWFya2VyV2lkdGg9IjEwIiBvcmllbnQ9ImF1dG8iIHJlZlg9IjEiIHJlZlk9IjciIHZpZXdCb3g9IjAgMCAyMCAxNCI+Cjxwb2x5Z29uIGNsYXNzPSJiZ19maWxsIiBwb2ludHM9IjIsMiAyLDEyIDE4LDcgMiwyIi8+CjwvbWFya2VyPgo8bWFya2VyIGlkPSJjaXJjbGUiIG1hcmtlckhlaWdodD0iNSIgbWFya2VyV2lkdGg9IjUiIG9yaWVudD0iYXV0byIgcmVmWD0iMTAiIHJlZlk9IjEwIiB2aWV3Qm94PSIwIDAgMjAgMjAiPgo8Y2lyY2xlIGNsYXNzPSJmZ19maWxsIiBjeD0iMTAiIGN5PSIxMCIgcj0iOCIvPgo8L21hcmtlcj4KPG1hcmtlciBpZD0ic3F1YXJlIiBtYXJrZXJIZWlnaHQ9IjUiIG1hcmtlcldpZHRoPSI1IiBvcmllbnQ9ImF1dG8iIHJlZlg9IjEwIiByZWZZPSIxMCIgdmlld0JveD0iMCAwIDIwIDIwIj4KPHJlY3QgY2xhc3M9ImZnX2ZpbGwiIGhlaWdodD0iMjAiIHdpZHRoPSIyMCIgeD0iMCIgeT0iMCIvPgo8L21hcmtlcj4KPG1hcmtlciBpZD0ib3Blbl9jaXJjbGUiIG1hcmtlckhlaWdodD0iMTAiIG1hcmtlcldpZHRoPSIxMCIgb3JpZW50PSJhdXRvIiByZWZYPSIxMCIgcmVmWT0iMTAiIHZpZXdCb3g9IjAgMCAyMCAyMCI+CjxjaXJjbGUgY2xhc3M9ImJnX2ZpbGwiIGN4PSIxMCIgY3k9IjEwIiByPSI0Ii8+CjwvbWFya2VyPgo8bWFya2VyIGlkPSJiaWdfb3Blbl9jaXJjbGUiIG1hcmtlckhlaWdodD0iMjAiIG1hcmtlcldpZHRoPSIyMCIgb3JpZW50PSJhdXRvIiByZWZYPSIyMCIgcmVmWT0iMjAiIHZpZXdCb3g9IjAgMCA0MCA0MCI+CjxjaXJjbGUgY2xhc3M9ImJnX2ZpbGwiIGN4PSIyMCIgY3k9IjIwIiByPSI2Ii8+CjwvbWFya2VyPgo8L2RlZnM+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CgpyZWN0LmJhY2tkcm9wIHsKICAgIGZpbGw6IHdoaXRlOwp9CnRleHR7CiAgICBmaWxsOiBibGFjazsKfQoKY2lyY2xlIHsKICAgIGZpbGw6IG5vbmU7CiAgICBzdHJva2U6IGJsYWNrOwogICAgc3Ryb2tlLXdpZHRoOiAxOwp9CgpsaW5lIHsKICAgIHN0cm9rZTogYmxhY2s7CiAgICBzdHJva2Utd2lkdGg6IDE7CiAgICBzdHJva2Utb3BhY2l0eTogMTsKICAgIGZpbGwtb3BhY2l0eTogMTsKICAgIHN0cm9rZS1saW5lY2FwOiByb3VuZDsKICAgIHN0cm9rZS1saW5lam9pbjogbWl0ZXI7Cn0KCnBhdGggewogICAgZmlsbDogbm9uZTsKICAgIHN0cm9rZTogYmxhY2s7CiAgICBzdHJva2Utd2lkdGg6IDE7CiAgICBzdHJva2Utb3BhY2l0eTogMTsKICAgIGZpbGwtb3BhY2l0eTogMTsKICAgIHN0cm9rZS1saW5lY2FwOiByb3VuZDsKICAgIHN0cm9rZS1saW5lam9pbjogbWl0ZXI7Cn0KCmxpbmUuZGFzaGVkIHsKICAgIHN0cm9rZS1kYXNoYXJyYXk6IDU7Cn0KCi5mZ19maWxsIHsKICAgIGZpbGw6IGJsYWNrOwp9CgoKLmJnX2ZpbGwgewogICAgZmlsbDogd2hpdGU7CiAgICBzdHJva2U6IGJsYWNrOwogICAgc3Ryb2tlLXdpZHRoOiAxOwp9Cgp0c3Bhbi5oZWFkewogICAgZmlsbDogbm9uZTsKICAgIHN0cm9rZTogbm9uZTsKfQogICAgCjwvc3R5bGU+CjxyZWN0IGNsYXNzPSJiYWNrZHJvcCIgaGVpZ2h0PSIyNTYiIHdpZHRoPSI2ODAiIHg9IjAiIHk9IjAiLz4KPGc+CjxsaW5lIHgxPSIyMCIgeDI9IjIwIiB5MT0iMTA4IiB5Mj0iMTMyIi8+CjxwYXRoIGQ9Ik0gMjAgMTMyIEEgNCA0IDAgMCAwIDI0IDEzNiIvPgo8cGF0aCBkPSJNIDI0IDEwNCBBIDQgNCAwIDAgMCAyMCAxMDgiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjI0IiB4Mj0iMTEyIiB5MT0iMTA0IiB5Mj0iMTA0Ii8+CjxwYXRoIGQ9Ik0gMTE2IDEwOCBBIDQgNCAwIDAgMCAxMTIgMTA0Ii8+CjwvZz4KPGc+CjxsaW5lIHgxPSIyNCIgeDI9IjExMiIgeTE9IjEzNiIgeTI9IjEzNiIvPgo8cGF0aCBkPSJNIDExMiAxMzYgQSA0IDQgMCAwIDAgMTE2IDEzMiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMTE2IiB4Mj0iMTE2IiB5MT0iMTA4IiB5Mj0iMTMyIi8+CjwvZz4KPGc+CjxsaW5lIHgxPSIxMjgiIHgyPSIxNDgiIHkxPSIxMjAiIHkyPSIxMjAiLz4KPGxpbmUgeDE9IjE0OCIgeDI9IjE0OCIgeTE9IjkyIiB5Mj0iMTIwIi8+CjxsaW5lIHgxPSIxNDgiIHgyPSIxNDgiIHkxPSIxMjAiIHkyPSIxNDgiLz4KPGxpbmUgeDE9IjE0OCIgeDI9IjE2OCIgeTE9IjEyMCIgeTI9IjEyMCIvPgo8bGluZSB4MT0iMTY4IiB4Mj0iMTc2IiB5MT0iMTIwIiB5Mj0iMTIwIi8+CjxsaW5lIG1hcmtlci1lbmQ9InVybCgjdHJpYW5nbGUpIiB4MT0iMTc2IiB4Mj0iMTk2IiB5MT0iMTIwIiB5Mj0iMTIwIi8+CjxwYXRoIGQ9Ik0gMTQ4IDE0OCBBIDQgNCAwIDAgMCAxNTIgMTUyIi8+CjxwYXRoIGQ9Ik0gMTUyIDg4IEEgNCA0IDAgMCAwIDE0OCA5MiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMTUyIiB4Mj0iMTY4IiB5MT0iODgiIHkyPSI4OCIvPgo8bGluZSB4MT0iMTY4IiB4Mj0iMTc2IiB5MT0iODgiIHkyPSI4OCIvPgo8bGluZSBtYXJrZXItZW5kPSJ1cmwoI3RyaWFuZ2xlKSIgeDE9IjE3NiIgeDI9IjE5NiIgeTE9Ijg4IiB5Mj0iODgiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjE1MiIgeDI9IjE2OCIgeTE9IjE1MiIgeTI9IjE1MiIvPgo8bGluZSB4MT0iMTY4IiB4Mj0iMTc2IiB5MT0iMTUyIiB5Mj0iMTUyIi8+CjxsaW5lIG1hcmtlci1lbmQ9InVybCgjdHJpYW5nbGUpIiB4MT0iMTc2IiB4Mj0iMTk2IiB5MT0iMTUyIiB5Mj0iMTUyIi8+CjwvZz4KPGc+CjxsaW5lIHgxPSIxNzIiIHgyPSIxNzIiIHkxPSIyOCIgeTI9IjgwIi8+CjxwYXRoIGQ9Ik0gMTcyIDk2IEEgMTAgMTAgMCAwIDAgMTcyIDgwIi8+CjxwYXRoIGQ9Ik0gMTc2IDI0IEEgNCA0IDAgMCAwIDE3MiAyOCIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMTcyIiB4Mj0iMTcyIiB5MT0iOTYiIHkyPSIxMTIiLz4KPHBhdGggZD0iTSAxNzIgMTI4IEEgMTAgMTAgMCAwIDAgMTcyIDExMiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMTcyIiB4Mj0iMTcyIiB5MT0iMTI4IiB5Mj0iMTQ0Ii8+CjxwYXRoIGQ9Ik0gMTcyIDE2MCBBIDEwIDEwIDAgMCAwIDE3MiAxNDQiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjE3MiIgeDI9IjE3MiIgeTE9IjE2MCIgeTI9IjE4MCIvPgo8cGF0aCBkPSJNIDE3MiAxODAgQSA0IDQgMCAwIDAgMTc2IDE4NCIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMTc2IiB4Mj0iNjcyIiB5MT0iMjQiIHkyPSIyNCIvPgo8cGF0aCBkPSJNIDY3NiAyOCBBIDQgNCAwIDAgMCA2NzIgMjQiLz4KPC9nPgo8Zz4KPGxpbmUgbWFya2VyLWVuZD0idXJsKCN0cmlhbmdsZSkiIHgxPSIxNzYiIHgyPSIxOTYiIHkxPSIxODQiIHkyPSIxODQiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjIxMiIgeDI9IjIxMiIgeTE9Ijc2IiB5Mj0iMTA0Ii8+CjxsaW5lIHgxPSIyMTIiIHgyPSIyMTIiIHkxPSIxMDQiIHkyPSIxMzYiLz4KPGxpbmUgeDE9IjIxMiIgeDI9IjI0NCIgeTE9IjEwNCIgeTI9IjEwNCIvPgo8bGluZSB4MT0iMjEyIiB4Mj0iMjEyIiB5MT0iMTM2IiB5Mj0iMTY4Ii8+CjxsaW5lIHgxPSIyMTIiIHgyPSIyNDQiIHkxPSIxMzYiIHkyPSIxMzYiLz4KPGxpbmUgeDE9IjIxMiIgeDI9IjIxMiIgeTE9IjE2OCIgeTI9IjIwMCIvPgo8bGluZSB4MT0iMjEyIiB4Mj0iMjQ0IiB5MT0iMTY4IiB5Mj0iMTY4Ii8+CjxsaW5lIHgxPSIyMTIiIHgyPSIyMTIiIHkxPSIyMDAiIHkyPSIyMjgiLz4KPGxpbmUgeDE9IjIxMiIgeDI9IjI0NCIgeTE9IjIwMCIgeTI9IjIwMCIvPgo8bGluZSB4MT0iMjQ0IiB4Mj0iMjQ0IiB5MT0iNzIiIHkyPSIxMDQiLz4KPGxpbmUgeDE9IjI0NCIgeDI9IjM3NiIgeTE9IjcyIiB5Mj0iNzIiLz4KPGxpbmUgeDE9IjI0NCIgeDI9IjI0NCIgeTE9IjEwNCIgeTI9IjEzNiIvPgo8bGluZSB4MT0iMjQ0IiB4Mj0iMzgwIiB5MT0iMTA0IiB5Mj0iMTA0Ii8+CjxsaW5lIHgxPSIyNDQiIHgyPSIyNDQiIHkxPSIxMzYiIHkyPSIxNjgiLz4KPGxpbmUgeDE9IjI0NCIgeDI9IjM4MCIgeTE9IjEzNiIgeTI9IjEzNiIvPgo8bGluZSB4MT0iMjQ0IiB4Mj0iMjQ0IiB5MT0iMTY4IiB5Mj0iMjAwIi8+CjxsaW5lIHgxPSIyNDQiIHgyPSIzODAiIHkxPSIxNjgiIHkyPSIxNjgiLz4KPGxpbmUgeDE9IjI0NCIgeDI9IjI0NCIgeTE9IjIwMCIgeTI9IjIzMiIvPgo8bGluZSB4MT0iMjQ0IiB4Mj0iMzgwIiB5MT0iMjAwIiB5Mj0iMjAwIi8+CjxsaW5lIHgxPSIyNDQiIHgyPSIzNzYiIHkxPSIyMzIiIHkyPSIyMzIiLz4KPGxpbmUgeDE9IjM4MCIgeDI9IjM4MCIgeTE9Ijc2IiB5Mj0iMTA0Ii8+CjxsaW5lIHgxPSIzODAiIHgyPSIzODAiIHkxPSIxMDQiIHkyPSIxMzYiLz4KPGxpbmUgeDE9IjM4MCIgeDI9IjM4MCIgeTE9IjEzNiIgeTI9IjE2OCIvPgo8bGluZSB4MT0iMzgwIiB4Mj0iMzgwIiB5MT0iMTY4IiB5Mj0iMjAwIi8+CjxsaW5lIHgxPSIzODAiIHgyPSIzODAiIHkxPSIyMDAiIHkyPSIyMjgiLz4KPHBhdGggZD0iTSAyMTIgMjI4IEEgNCA0IDAgMCAwIDIxNiAyMzIiLz4KPHBhdGggZD0iTSAyMTYgNzIgQSA0IDQgMCAwIDAgMjEyIDc2Ii8+CjxwYXRoIGQ9Ik0gMzc2IDIzMiBBIDQgNCAwIDAgMCAzODAgMjI4Ii8+CjxwYXRoIGQ9Ik0gMzgwIDc2IEEgNCA0IDAgMCAwIDM3NiA3MiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMjE2IiB4Mj0iMjQ0IiB5MT0iNzIiIHkyPSI3MiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iMjE2IiB4Mj0iMjQ0IiB5MT0iMjMyIiB5Mj0iMjMyIi8+CjwvZz4KPGc+CjxsaW5lIG1hcmtlci1lbmQ9InVybCgjdHJpYW5nbGUpIiB4MT0iMzkyIiB4Mj0iNDM2IiB5MT0iMTUyIiB5Mj0iMTUyIi8+CjwvZz4KPGc+CjxsaW5lIHgxPSIzOTIiIHgyPSI0MTYiIHkxPSIxODQiIHkyPSIxODQiLz4KPHBhdGggZD0iTSA0MjAgMTg4IEEgNCA0IDAgMCAwIDQxNiAxODQiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjQyMCIgeDI9IjQyMCIgeTE9IjE4OCIgeTI9IjIxMiIvPgo8cGF0aCBkPSJNIDQyMCAyMTIgQSA0IDQgMCAwIDAgNDI0IDIxNiIvPgo8L2c+CjxnPgo8bGluZSBtYXJrZXItZW5kPSJ1cmwoI3RyaWFuZ2xlKSIgeDE9IjQyNCIgeDI9IjQ1MiIgeTE9IjIxNiIgeTI9IjIxNiIvPgo8L2c+CjxnPgo8bGluZSB4MT0iNDUyIiB4Mj0iNDUyIiB5MT0iMTQwIiB5Mj0iMTY0Ii8+CjxwYXRoIGQ9Ik0gNDUyIDE2NCBBIDQgNCAwIDAgMCA0NTYgMTY4Ii8+CjxwYXRoIGQ9Ik0gNDU2IDEzNiBBIDQgNCAwIDAgMCA0NTIgMTQwIi8+CjwvZz4KPGc+CjxsaW5lIHgxPSI0NTYiIHgyPSI2MzIiIHkxPSIxMzYiIHkyPSIxMzYiLz4KPHBhdGggZD0iTSA2MzYgMTQwIEEgNCA0IDAgMCAwIDYzMiAxMzYiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjQ1NiIgeDI9IjYzMiIgeTE9IjE2OCIgeTI9IjE2OCIvPgo8cGF0aCBkPSJNIDYzMiAxNjggQSA0IDQgMCAwIDAgNjM2IDE2NCIvPgo8L2c+CjxnPgo8bGluZSB4MT0iNDY4IiB4Mj0iNDY4IiB5MT0iMjA0IiB5Mj0iMjQ0Ii8+CjxwYXRoIGQ9Ik0gNDY4IDI0NCBBIDQgNCAwIDAgMCA0NzIgMjQ4Ii8+CjxwYXRoIGQ9Ik0gNDcyIDIwMCBBIDQgNCAwIDAgMCA0NjggMjA0Ii8+CjwvZz4KPGc+CjxsaW5lIHgxPSI0NzIiIHgyPSI2MzIiIHkxPSIyMDAiIHkyPSIyMDAiLz4KPHBhdGggZD0iTSA2MzYgMjA0IEEgNCA0IDAgMCAwIDYzMiAyMDAiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjQ3MiIgeDI9IjYzMiIgeTE9IjI0OCIgeTI9IjI0OCIvPgo8cGF0aCBkPSJNIDYzMiAyNDggQSA0IDQgMCAwIDAgNjM2IDI0NCIvPgo8L2c+CjxnPgo8bGluZSB4MT0iNjM2IiB4Mj0iNjM2IiB5MT0iMTQwIiB5Mj0iMTY0Ii8+CjwvZz4KPGc+CjxsaW5lIHgxPSI2MzYiIHgyPSI2MzYiIHkxPSIyMDQiIHkyPSIyNDQiLz4KPC9nPgo8Zz4KPGxpbmUgeDE9IjY0OCIgeDI9IjY3MiIgeTE9IjE1MiIgeTI9IjE1MiIvPgo8cGF0aCBkPSJNIDY3MiAxNTIgQSA0IDQgMCAwIDAgNjc2IDE0OCIvPgo8L2c+CjxnPgo8bGluZSB4MT0iNjc2IiB4Mj0iNjc2IiB5MT0iMjgiIHkyPSIxNDgiLz4KPC9nPgo8Zz4KPHRleHQgeD0iMzMiIHk9IjEyNCIgdGV4dExlbmd0aD0iNzIiPgpUb3AtTGV2ZWwKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSIyMTciIHk9IjYwIiB0ZXh0TGVuZ3RoPSIxNDQiPgpJTlRFUlJVUFRfSEFORExFUlMKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSIyMjUiIHk9IjkyIiB0ZXh0TGVuZ3RoPSI4Ij4KMAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjIyNSIgeT0iMTI0IiB0ZXh0TGVuZ3RoPSI4Ij4KMQo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjIyNSIgeT0iMTU2IiB0ZXh0TGVuZ3RoPSI4Ij4KMgo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjIyNSIgeT0iMTg4IiB0ZXh0TGVuZ3RoPSI4Ij4KMwo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjIyNSIgeT0iMjIwIiB0ZXh0TGVuZ3RoPSI4Ij4KNAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjI1NyIgeT0iOTIiIHRleHRMZW5ndGg9IjY0Ij4KU29mdHdhcmUKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSIyNTciIHk9IjEyNCIgdGV4dExlbmd0aD0iNDAiPgpUaW1lcgo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjI1NyIgeT0iMTU2IiB0ZXh0TGVuZ3RoPSI2NCI+CkV4dGVybmFsCjwvdGV4dD4KPC9nPgo8Zz4KPHRleHQgeD0iMjU3IiB5PSIxODgiIHRleHRMZW5ndGg9IjE2Ij4KSUMKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSIyNTciIHk9IjIyMCIgdGV4dExlbmd0aD0iMTYiPgpJQwo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjI4MSIgeT0iMTg4IiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjI4MSIgeT0iMjIwIiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjM2MSIgeT0iMTg4IiB0ZXh0TGVuZ3RoPSI4Ij4KMAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjM2MSIgeT0iMjIwIiB0ZXh0TGVuZ3RoPSI4Ij4KMQo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjQzMyIgeT0iMTI0IiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjQ2NSIgeT0iMTU2IiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjQ4MSIgeT0iMjIwIiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjQ4MSIgeT0iMjM2IiB0ZXh0TGVuZ3RoPSIyNCI+CmZvcgo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjUxMyIgeT0iMTI0IiB0ZXh0TGVuZ3RoPSI4MCI+CkNvbnRyb2xsZXIKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSI1MTMiIHk9IjIzNiIgdGV4dExlbmd0aD0iMTYiPgpJQwo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjUzNyIgeT0iMjM2IiB0ZXh0TGVuZ3RoPSI3MiI+CkludGVycnVwdAo8L3RleHQ+CjwvZz4KPGc+Cjx0ZXh0IHg9IjU0NSIgeT0iMTU2IiB0ZXh0TGVuZ3RoPSI4MCI+CkRpc3BhdGNoZXIKPC90ZXh0Pgo8L2c+CjxnPgo8dGV4dCB4PSI1NjEiIHk9IjIyMCIgdGV4dExlbmd0aD0iNTYiPgpIYW5kbGVyCjwvdGV4dD4KPC9nPgo8Zz4KPHRleHQgeD0iNjAxIiB5PSIxMjQiIHRleHRMZW5ndGg9IjQ4Ij4KRHJpdmVyCjwvdGV4dD4KPC9nPgo8Zz4KPHRleHQgeD0iNjE3IiB5PSIyMzYiIHRleHRMZW5ndGg9IjgiPgowCjwvdGV4dD4KPC9nPgo8L3N2Zz4=