Commit 07e1012
committed
PolarFire SoC: LPDDR4 init for MPFS250T Video Kit (M-Mode)
## Summary
Standalone wolfBoot M-mode bootloader for the Microchip PolarFire SoC MPFS250T Video Kit that replaces HSS as the early-boot supervisor. wolfBoot runs on E51 hart 0 in M-mode out of L2 Scratch, brings up the MSS/DDR PLLs, NWC IO, DDRC, and PHY, runs a manual LPDDR4 training sequence followed by the HSS LPDDR4 `POST_INITIALIZATION` sequence, and is positioned to load a signed image from SD card via SDHCI/PDMA into DDR. Branch: `polarfire_ddr_2`, single squashed commit on top of `origin/master` (`c3d255d8`). Pre-squash backups at `backup/polarfire_ddr_2_pre_squash_2026-05-15` (19-commit WIP), `backup/polarfire_ddr_2_pre_squash_2026-05-14`, and `backup/polarfire_ddr_2_20260512-2055`.
## Hardware target
- Board: PolarFire SoC MPFS250T Video Kit (FCG1152)
- DRAM: Micron MT53D512M32D2DS-053, LPDDR4 x32, 1600 Mbps, 2 GB (32 MB DDR-Lo + 1888 MB DDR-Hi per HSS MEMTEST)
- Boot mode: non-secure boot from eNVM (bootmode 1), via `mpfsBootmodeProgrammer.jar`
- Monitor hart: E51 (hart 0) in M-mode out of L2 Scratch at `0x0A000000`
- Debug: FlashPro6b (USB ID `1514:200b`)
## What landed
### DDR initialization (`hal/mpfs250.c`, ~4970 lines added)
- **MSS/DDR PLL bring-up** from external refclk (`RFCKMUX=0x5`), MSS PLL CTRL via DDR bank controller soft reset, lock-poll.
- **NWC + SGMII/clock mux + IO mux + DDR PHY pull-up/down configuration.**
- **DDRC SEG configuration** matching the HSS Video Kit canonical 6-SEG layout: cached at `0x80000000`, non-cached (WCB) at `0xC0000000`, with `SEG0_BLOCKER=0x01`.
- **`set_ddr_rpc_regs` LPDDR4 arm** matches HSS pre-train state: `rpc98=0x04`, `rpc220=0x0C`, `rpc226=0x14`, `UNUSED_SPACE0[0]=0xA000`, `SPARE0=0xA000`, `rpc27=0x02`, `rpc203=0x0`, all four ODT registers. The `rpc220=0x0C` and `rpc226=0x14` values were captured via HSS `DEBUG HEXDUMP 0x20007000` while HSS was running on this same board -- writing `0x01` instead (an earlier assumption) was the gate that blocked AXI reads on every cold boot.
- **`training_reset_and_rotate`** mirrors HSS `DDR_TRAINING_ROTATE_CLK`: 7-step expert PLL count rotation, BCLK_VCOPHS_OFFSET-driven 0x67/0x66 cycle, DLYCNT load via DQ/DQS sequence `shim=0x06 -> 0x04 -> 0x00`.
- **LPDDR4 manual training:** device reset, PLL frequency double for MR programming, manual ADDCMD with HSS-style MOVE_CK rotation across 3 retries, ADDCMD threshold `18` (`ADD_CMD_TRANS_A5_THRES_LPDDR4`), CA VREF training, manual ZQ cal. Reaches `train_stat=0x1F` consistently.
- **`PHY_TRAINING_SKIP=0`** so TIP runs the full training stack including ADDCMD on top of our manual ADDCMD setup. HSS uses `0x02` but that path depends on additional pre-WRLVL PHY state we don't yet match.
- **`setup_phy()` runs before `setup_controller()`** (HSS state-machine order: SET_MODE_VS_BITS before SETUP_DDRC). All four data lanes train, eye widths 10-15 taps.
- **DFI register access uses correct base** (DDRCFG + `0x10000`); a previously latent offset bug had wolfBoot reading STAT_DFI_INIT_COMPLETE at the wrong offset, masking the real DFI handshake state.
- **HSS LPDDR4 `POST_INITIALIZATION` ported verbatim** from `mss_ddr.c:5597-5646`: drop `expert_dfi_status_override_to_shim`, pulse `expert_dlycnt_pause`, release CKE, write 9 LPDDR4 mode registers (MR1, MR2, MR3, MR4, MR11, MR16, MR17, MR22, MR13) via `INIT_MR_W_REQ`, trigger `INIT_ZQ_CAL_START`, poll `INIT_ACK` with bounded timeout (255 iterations of `udelay(10)`), restore `CFG_AUTO_ZQ_CAL_EN` to the Libero value. Also includes an unmasked MR2 rewrite (`mpfs_mr_unmasked_write(2, 0x2D)`) post-training to clear LPDDR4 MR2 OP[7] (write-leveling enable) -- documented in the polar-fire-guide rule "MUST clear the write-leveling bit in MR2 after `DFI_WRLVL_RESP=1`".
- **Critical DDRC register-offset bug fixes** (the largest single fix in this branch): wolfBoot's hand-coded register-write tables were missing the `UNUSED_SPACE` gaps in the HSS struct definitions at `mss_ddr_sgmii_regs.h:3842-3928`. The 38-register-offset bug landed in four blocks:
- **MC_BASE1**: `UNUSED_SPACE0[9]` at struct offset `0xA0` and `UNUSED_SPACE1[6]` at `0xC8` were missing, shifting `CFG_NIBBLE_DEVICES`, all 32 `CFG_BIT_MAP_INDEX_CS*_*`, `CFG_NUM_LOGICAL_RANKS_PER_3DS`, `CFG_RFC_DLR1/2/4`, `CFG_RRD_DLR`, `CFG_FAW_DLR`, and `CFG_ADVANCE_ACTIVATE_READY` by 60 bytes. The `CFG_BIT_MAP_INDEX_*` registers carry the AXI-address-to-DRAM-bank/row/column mapping; leaving them at zero defaults meant every AXI access targeted unmapped DRAM cells and the controller never returned an AXI response.
- **REORDER**: `CFG_MAINTAIN_COHERENCY` and `CFG_Q_AGE_LIMIT` slipped one slot late (missing `UNUSED_SPACE0` at struct `0x14`).
- **MTA**: 5 `__I` status registers (`MTC_ACQ_CYCS_STORED..MTC_ACK`) at struct `0x1c..0x2c` shifted `CFG_TRIG_MT_ADDR_0..ERR_MASK_4` and `MTC_ACQ_WR_DATA[0..2]` by 20 bytes; `CFG_PRE_TRIG_CYCS` and `CFG_DATA_SEL_FIRST_ERROR` were also off (50-dword `UNUSED_SPACE0` + 3-dword `MTC_ACQ_RD_DATA` gap).
- **CA_PAR_ERR**: `STAT_CA_PARITY_ERROR` (`__I`) plus `UNUSED_SPACE0[2]` shifted `INIT_CA_PARITY_ERROR_GEN_REQ` and `_CMD` by 12 bytes.
After the realignment the post-init register diff vs HSS dropped from 48 deltas to 14, and all remaining 14 are `__I` read-only status registers (transient post-init state, not configuration).
### L2 cache
- Configure SiFive L2 with `WAY_ENABLE=0x0B` (12 cache ways + 4 scratchpad ways) matching the HSS Video Kit configuration.
- All 14 L2 way masks (`DMA / AXI0-3 / E51 D+I / U54_1-4 D+I`) set to `0xFF` so masters share the full cache range.
- SHA384 image-integrity reads route through the non-cached DDR alias (`0xC2xxxxxx`) to avoid L2-Scratch eviction during cached reads of the 19 MB load buffer.
### Boot path
- **Trap handler** (`src/boot_riscv.c`) dumps full 32 GPRs, L2-Scratch canaries, and `mcause`/`mepc`/`mtval` on entry. Weak `handle_trap_ex` hook for HAL-specific reporting. The halt loop pets MSS WDT so GDB can inspect trap state indefinitely on MPFS250.
- **SDHCI PDMA read path** with single-dot-per-64-block progress and a first-DDR-block 3-way byte diagnostic (staging buffer in L2 scratch / DDR cached / DDR non-cached). Confirms exactly where bytes land vs source.
- **`update_disk` loader** with post-load buffer peek.
- **M-mode -> S-mode boot path scaffolding** for Linux (single-hart MVP) in `src/boot_riscv.c` / `src/vector_riscv.S` (`riscv_mmode_to_smode`, `enter_smode`, `setup_pmp_for_smode`). Not enabled in this branch -- gated on DDR write-path being fixed.
- **`wolfBoot_panic`** pets MSS WDT in its spin loop on MPFS250 so GDB has unlimited halt time at panic.
### Build
- New `config/examples/polarfire_mpfs250_m.config` with `WOLFBOOT_LOAD_ADDRESS=0x82000000`, `SDHCI_BLOCK_VIA_PDMA=1`, `NO_ASM=1` (E51/U54 cores lack Zknh crypto extensions).
- `arch.mk` gates `MPFS_DDR_INIT` on `LIBERO_FPGA_CONFIG_DIR` so the DDR init path only compiles for boards that provide their Libero `fpga_design_config/` headers.
- `.github/workflows/test-configs.yml` adds a build of the MPFS250 M-mode config so the DDR init path is exercised in CI.
- `docs/Targets.md` adds a PolarFire SoC section, including the GDB-via-OpenOCD recipe.
### Diagnostic tooling
- `tools/scripts/ddr-diff.py`: parses HSS `DEBUG_DDR_DDRCFG` dump format (`Register, 0xADDR ,Value, 0xVAL`) and wolfBoot's `mpfs_dump_ddrc_regs()` / `mpfs_dump_phy_regs()` output. Optional third arg parses the HSS struct typedef header (`mss_ddr_sgmii_regs.h`) to annotate each delta with the canonical field name. Output: sorted list of register-address differences with per-bit XOR mask.
- `mpfs_dump_ddrc_regs()` and `mpfs_dump_phy_regs()` in `hal/mpfs250.c`: emit register contents in HSS-compatible format. Not called from the normal boot path (DDRC matches HSS exactly, PHY only has read-only-status diffs); retained for future re-use.
- `mpfs_settle_ddrc_regs()`: silent register-read walk, kept for cases where APB-bus quiescence between post-init and first AXI access is needed.
## How to build and flash
```bash
cp config/examples/polarfire_mpfs250_m.config .config
make wolfboot.elf \
LIBERO_FPGA_CONFIG_DIR=$HOME/workspace_riscv/hart-software-services/build/boards/mpfs-video-kit/fpga_design_config
# Power-cycle the board (this example uses a Pi4 controlling GPIO 20 to gate VBUS).
ssh pi@Pi4 'raspi-gpio set 20 op dl' && sleep 30 && ssh pi@Pi4 'raspi-gpio set 20 op dh' && sleep 15
# Program via the SoftConsole bootmode programmer.
java -jar $SC_INSTALL_DIR/extras/mpfs/mpfsBootmodeProgrammer.jar \
--bootmode 1 --die MPFS250T --package FCG1152 --workdir $PWD wolfboot.elf
```
UART output appears on `POLARFIRE_SOC_UART0` (115200 8N1). The `uart-monitor` skill PTY at `/tmp/uart-monitor/pty/POLARFIRE_SOC_UART0` is the recommended access path.
## How to debug via GDB
```sh
# Terminal 1 - power-cycle the board, then start OpenOCD BEFORE running any
# mpfsBootmodeProgrammer.jar (which locks FP6b until the next power cycle).
$SC_INSTALL_DIR/openocd/bin/openocd \
--command "set DEVICE MPFS" --file board/microsemi-riscv.cfg
# Terminal 2 - attach GDB.
riscv64-unknown-elf-gdb -nx wolfboot.elf
(gdb) set $target_riscv=1
(gdb) set mem inaccessible-by-default off
(gdb) set architecture riscv:rv64
(gdb) target remote :3333
(gdb) monitor halt
(gdb) hbreak src/sdhci.c:1727 # after first PDMA copy
(gdb) continue
(gdb) x/16xw sdhci_pdma_staging # SD source bytes
(gdb) x/16xw block_dst # cached DDR readback
(gdb) set $nc = ((unsigned long)block_dst) | 0x40000000
(gdb) x/16xw $nc # raw DRAM via WCB alias
```
The WDT-pet patches in `wolfBoot_panic` and `handle_trap_ex` halt mean once the GDB session is attached and the chip halts (panic or trap), the chip stays alive indefinitely while you inspect memory.
## Verification
- **Build** with the matching HSS Video Kit Libero config tree compiles cleanly.
- **Cold-boot** reaches `train_stat=0x1F` with `DFI_INIT_COMPLETE=1`, `DFI_TRAINING_COMPLETE=1`, `CTRLR_INIT_DONE=1`, `INIT_ACK=1` on the post-init handoff. All four data lanes train with eye widths 11-15 taps.
- **AXI naked read** at `0xC0000000` (non-cached DDR alias) returns valid data (e.g. `0x2020000` or `0x200`) on every cold boot. The mcycle-delta around the read confirms a single load instruction completes in ~2.6 M cycles.
- **PDMA pre-fill** of 1 MB at `0xC0000000` completes.
- **L2 flush** of the 1 MB region completes.
- **SDHCI/PDMA load** reads 19 MB / 38606 blocks from SD card to DDR.
- **SHA384 integrity check** runs end-to-end over the full 19,766,516-byte image via the non-cached read alias.
- **HSS comparison**: HSS-on-board MEMTEST passes on this exact board, confirming the hardware is fully functional. wolfBoot's DDRC registers match the HSS-captured `DDR_TRAINING_SET_FINAL_MODE` state byte-for-byte across 496 common addresses (0 diffs). PHY registers show only 12 diffs, all in `__I` read-only training-status registers (`dqdqs_window`, `delta0/1`, `dqdqs_status0/2/5/6`, `addcmd_status0/1`, `expert_addcmd_ln_readback`).
- **CI build**: the new MPFS250 M-mode job in `.github/workflows/test-configs.yml` compiles cleanly.
## Open issues
The HAL contains explicit comments documenting these:
1. **Lane 2/3 PDMA write-side byte corruption.** Reads from any DDR address complete reliably and return consistent data, including across cached and non-cached aliases. PDMA writes from the SDHCI staging buffer to DDR land byte 0 (lane 0) correctly but bytes 1, 2, 3 (lanes 1, 2, 3) come back zero, scrambled, or holding pre-existing DRAM content. The first-DDR-block diagnostic confirms the source data (`D0 0D FE ED 01 2D 9C F4 ...` -- DTB magic from a FIT image header) is correctly read from the SD card into the L2 staging buffer; only the PDMA-write-into-DRAM phase corrupts bytes 1-3. HSS MEMTEST passes on this same board through HSS's own PDMA path, so the hardware is capable -- some PHY-runtime-state difference between HSS and wolfBoot is the unidentified gate. Cached `memory_test()` fails on the same lane pattern but is now non-fatal so the boot proceeds to disk-load.
2. **Cached integrity-check reads can evict L2 Scratch.** SHA384 reads route through the non-cached DDR alias `0xC2xxxxxx` so the cached fill path is not exercised during integrity verification. Why cached fills bypass the (correctly-set) per-master way masks under specific timing is unknown; not worth chasing while the non-cached workaround is clean.
3. **Outer-retry loop relies on the WDT REFRESH pet inside the WRCALIB sweep.** Without that pet, an MTC TIMEOUT during the ~42 s sweep triggers a WDT chip reset mid-sweep instead of a clean FAIL. The pet writes REFRESH to all 5 MSS WDOGs at the start of each `cal_data` iteration.
4. **`memory_test()` cached path is non-fatal.** With lane 2/3 PDMA writes corrupt, the cached L2-flush-then-read sequence fails 4/4 patterns. Boot proceeds to disk-load on the assumption that PDMA bursts (which the disk-load uses) are equally affected, so failing here doesn't predict disk-load failure -- the disk-load path is the real test.
## Reference
HSS reference source (read-only) at `$HOME/workspace_riscv/hart-software-services/baremetal/polarfire-soc-bare-metal-library/src/platform/mpfs_hal/common/nwc/mss_ddr.c`. Key sections referenced in HAL comments:
- `setup_ddr_segments` -- `mss_ddr.c:4415-4443`
- `clear_bootup_cache_ways` -- `mss_ddr.c:4454-4470`
- `set_ddr_rpc_regs` LPDDR4 arm with rpc226=0x14 -- `mss_ddr.c:2319-2570`
- `training_reset_and_rotate` (DDR_TRAINING_ROTATE_CLK) -- `mss_ddr.c:776-859`
- `load_dq` (post-train DQ delay load with shim=0x07) -- `mss_ddr.c:2916-2958`
- `mode_register_masked_write` / `_x5` -- `mss_ddr.c:4922-4949`
- LPDDR4 `POST_INITIALIZATION` -- `mss_ddr.c:5597-5646`
HSS struct definitions used as the canonical register-offset source:
- `DDR_CSR_APB_MC_BASE1_TypeDef` -- `mss_ddr_sgmii_regs.h:3842-3928`
- `DDR_CSR_APB_MC_BASE2_TypeDef` -- `mss_ddr_sgmii_regs.h:3931+`
- `DDR_CSR_APB_REORDER_TypeDef` -- `mss_ddr_sgmii_regs.h:4172-4183`
- `DDR_CSR_APB_MTA_TypeDef` -- `mss_ddr_sgmii_regs.h:4219-4255`
- `DDR_CSR_APB_CA_PAR_ERR_TypeDef` -- `mss_ddr_sgmii_regs.h:4265-4273`
- `DDR_CSR_APB_DFI_TypeDef` -- `mss_ddr_sgmii_regs.h:4276-4299`
- `DDR_CSR_APB_AXI_IF_TypeDef` -- `mss_ddr_sgmii_regs.h:4302-4324`
- `CFG_DDR_SGMII_PHY_TypeDef` -- `mss_ddr_sgmii_phy_defs.h:4270-4674`
## Test plan
- [ ] 5 cold-boot regression: `train_stat=0x1F` reached, post-init `INIT_ACK=1`, all DFI handshake signals asserted on each boot.
- [ ] Build with `DEBUG_DDR` undefined succeeds and still reaches `train_stat=0x1F`.
- [ ] CI MPFS250 M-mode job compiles cleanly.
- [ ] Verify the open-issue notes are accurate against a fresh log (lane 2/3 corruption + non-cached SHA384 workaround both still apply on this branch).
- [ ] No regression on the other RISC-V targets that share `src/boot_riscv.c` / `src/vector_riscv.S` (the new `handle_trap_ex` hook is weak, and the old `handle_trap` weak ABI is preserved -- spot-check on `microchip_mpfs_icicle`).
- [ ] GDB-via-OpenOCD recipe works on a fresh power-cycle: `openocd --command "set DEVICE MPFS" --file board/microsemi-riscv.cfg` claims FlashPro6b, `riscv64-unknown-elf-gdb` attaches on `:3333`, `monitor halt` succeeds, `x/16xw 0x82000000` returns DDR data.1 parent c3d255d commit 07e1012
14 files changed
Lines changed: 6166 additions & 95 deletions
File tree
- .github/workflows
- config/examples
- docs
- hal
- include
- src
- tools/scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
307 | 307 | | |
308 | 308 | | |
309 | 309 | | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
310 | 319 | | |
311 | 320 | | |
312 | 321 | | |
313 | 322 | | |
314 | 323 | | |
| 324 | + | |
315 | 325 | | |
316 | 326 | | |
317 | 327 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
702 | 702 | | |
703 | 703 | | |
704 | 704 | | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
705 | 711 | | |
706 | 712 | | |
707 | 713 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
803 | 803 | | |
804 | 804 | | |
805 | 805 | | |
806 | | - | |
| 806 | + | |
807 | 807 | | |
808 | 808 | | |
809 | 809 | | |
| |||
812 | 812 | | |
813 | 813 | | |
814 | 814 | | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
| 832 | + | |
| 833 | + | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
815 | 838 | | |
816 | 839 | | |
817 | 840 | | |
818 | | - | |
819 | | - | |
820 | | - | |
821 | | - | |
822 | | - | |
823 | | - | |
824 | | - | |
825 | | - | |
826 | | - | |
827 | | - | |
828 | | - | |
829 | | - | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
830 | 856 | | |
831 | 857 | | |
832 | 858 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
30 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
| |||
0 commit comments