From 1e284767cd9cdbc7b92b5d22c56f039ad9fc72db Mon Sep 17 00:00:00 2001 From: Jason <83615043+JJassonn69@users.noreply.github.com> Date: Tue, 7 Apr 2026 02:51:48 +0300 Subject: [PATCH] fix(test,docs): remove dead xfft_32 files, update test infra for dual-16 FFT, add regression guide - Remove xfft_32.v, tb_xfft_32.v, and fft_twiddle_32.mem (dead code since PR #33 moved Doppler to dual 16-pt FFT architecture) - Update run_regression.sh: xfft_16 in PROD_RTL, remove xfft_32 from EXTRA_RTL and all compile commands - Update tb_fft_engine.v to test with N=16 / fft_twiddle_16.mem - Update validate_mem_files.py: validate fft_twiddle_16.mem instead of 32 - Update testbenches and golden data from main_cleanup branch to match dual-16 architecture (tb_doppler_cosim, tb_doppler_realdata, tb_fullchain_realdata, tb_fullchain_mti_cfar_realdata, tb_system_e2e, radar_receiver_final, golden_doppler.mem) - Update CONTRIBUTING.md with full regression test instructions covering FPGA, MCU, GUI, co-simulation, and formal verification Regression: 23/23 FPGA, 20/20 MCU, 57/58 GUI, 56/56 mem validation, all co-sim scenarios PASS. --- 9_Firmware/9_2_FPGA/fft_twiddle_32.mem | 11 - 9_Firmware/9_2_FPGA/radar_receiver_final.v | 13 +- 9_Firmware/9_2_FPGA/run_regression.sh | 18 +- .../9_2_FPGA/tb/cosim/validate_mem_files.py | 26 +- .../9_2_FPGA/tb/golden/golden_doppler.mem | 4222 ++++++++--------- 9_Firmware/9_2_FPGA/tb/tb_doppler_cosim.v | 12 +- 9_Firmware/9_2_FPGA/tb/tb_doppler_realdata.v | 4 +- 9_Firmware/9_2_FPGA/tb/tb_fft_engine.v | 10 +- .../tb/tb_fullchain_mti_cfar_realdata.v | 6 +- .../9_2_FPGA/tb/tb_fullchain_realdata.v | 6 +- 9_Firmware/9_2_FPGA/tb/tb_system_e2e.v | 2 +- 9_Firmware/9_2_FPGA/tb/tb_xfft_32.v | 355 -- 9_Firmware/9_2_FPGA/xfft_16.v | 2 +- 9_Firmware/9_2_FPGA/xfft_32.v | 278 -- CONTRIBUTING.md | 106 + 15 files changed, 2265 insertions(+), 2806 deletions(-) delete mode 100644 9_Firmware/9_2_FPGA/fft_twiddle_32.mem delete mode 100644 9_Firmware/9_2_FPGA/tb/tb_xfft_32.v delete mode 100644 9_Firmware/9_2_FPGA/xfft_32.v diff --git a/9_Firmware/9_2_FPGA/fft_twiddle_32.mem b/9_Firmware/9_2_FPGA/fft_twiddle_32.mem deleted file mode 100644 index 5e49ff4..0000000 --- a/9_Firmware/9_2_FPGA/fft_twiddle_32.mem +++ /dev/null @@ -1,11 +0,0 @@ -// Quarter-wave cosine ROM for 32-point FFT -// 8 entries, 16-bit signed Q15 ($readmemh format) -// cos(2*pi*k/32) for k = 0..7 -7FFF -7D89 -7641 -6A6D -5A82 -471C -30FB -18F9 diff --git a/9_Firmware/9_2_FPGA/radar_receiver_final.v b/9_Firmware/9_2_FPGA/radar_receiver_final.v index d3fa9ed..c417092 100644 --- a/9_Firmware/9_2_FPGA/radar_receiver_final.v +++ b/9_Firmware/9_2_FPGA/radar_receiver_final.v @@ -403,11 +403,12 @@ assign range_data_32bit = {mti_range_q, mti_range_i}; assign range_data_valid = mti_range_valid; // ========== DOPPLER PROCESSOR ========== -doppler_processor_optimized #( - .DOPPLER_FFT_SIZE(32), - .RANGE_BINS(64), - .CHIRPS_PER_FRAME(32) // MUST MATCH YOUR ACTUAL FRAME SIZE! -) doppler_proc ( +doppler_processor_optimized #( + .DOPPLER_FFT_SIZE(16), + .RANGE_BINS(64), + .CHIRPS_PER_FRAME(32), + .CHIRPS_PER_SUBFRAME(16) +) doppler_proc ( .clk(clk), .reset_n(reset_n), .range_data(range_data_32bit), @@ -473,4 +474,4 @@ assign dbg_adc_i = adc_i_scaled; assign dbg_adc_q = adc_q_scaled; assign dbg_adc_valid = adc_valid_sync; -endmodule \ No newline at end of file +endmodule diff --git a/9_Firmware/9_2_FPGA/run_regression.sh b/9_Firmware/9_2_FPGA/run_regression.sh index 7d8e949..43602f4 100755 --- a/9_Firmware/9_2_FPGA/run_regression.sh +++ b/9_Firmware/9_2_FPGA/run_regression.sh @@ -67,7 +67,7 @@ PROD_RTL=( matched_filter_processing_chain.v range_bin_decimator.v doppler_processor.v - xfft_32.v + xfft_16.v fft_engine.v usb_data_interface.v edge_detector.v @@ -369,7 +369,7 @@ run_test "Chirp Contract" \ run_test "Doppler Processor (DSP48)" \ tb/tb_doppler_reg.vvp \ - tb/tb_doppler_cosim.v doppler_processor.v xfft_32.v fft_engine.v + tb/tb_doppler_cosim.v doppler_processor.v xfft_16.v fft_engine.v run_test "Threshold Detector (detection bugs)" \ tb/tb_threshold_detector.vvp \ @@ -414,7 +414,7 @@ if [[ "$QUICK" -eq 0 ]]; then cdc_modules.v fir_lowpass.v ddc_input_interface.v \ chirp_memory_loader_param.v latency_buffer.v \ matched_filter_multi_segment.v matched_filter_processing_chain.v \ - range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v \ + range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v \ rx_gain_control.v mti_canceller.v # Golden compare @@ -426,7 +426,7 @@ if [[ "$QUICK" -eq 0 ]]; then cdc_modules.v fir_lowpass.v ddc_input_interface.v \ chirp_memory_loader_param.v latency_buffer.v \ matched_filter_multi_segment.v matched_filter_processing_chain.v \ - range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v \ + range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v \ rx_gain_control.v mti_canceller.v # Full system top (monitoring-only, legacy) @@ -439,7 +439,7 @@ if [[ "$QUICK" -eq 0 ]]; then cdc_modules.v fir_lowpass.v ddc_input_interface.v \ chirp_memory_loader_param.v latency_buffer.v \ matched_filter_multi_segment.v matched_filter_processing_chain.v \ - range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v \ + range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v \ usb_data_interface.v edge_detector.v radar_mode_controller.v \ rx_gain_control.v cfar_ca.v mti_canceller.v fpga_self_test.v @@ -453,7 +453,7 @@ if [[ "$QUICK" -eq 0 ]]; then cdc_modules.v fir_lowpass.v ddc_input_interface.v \ chirp_memory_loader_param.v latency_buffer.v \ matched_filter_multi_segment.v matched_filter_processing_chain.v \ - range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v \ + range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v \ usb_data_interface.v edge_detector.v radar_mode_controller.v \ rx_gain_control.v cfar_ca.v mti_canceller.v fpga_self_test.v else @@ -472,10 +472,6 @@ run_test "FFT Engine" \ tb/tb_fft_reg.vvp \ tb/tb_fft_engine.v fft_engine.v -run_test "XFFT-32 Wrapper" \ - tb/tb_xfft_reg.vvp \ - tb/tb_xfft_32.v xfft_32.v fft_engine.v - run_test "NCO 400MHz" \ tb/tb_nco_reg.vvp \ tb/tb_nco_400m.v nco_400m_enhanced.v @@ -487,7 +483,7 @@ run_test "FIR Lowpass" \ run_test "Matched Filter Chain" \ tb/tb_mf_reg.vvp \ tb/tb_matched_filter_processing_chain.v matched_filter_processing_chain.v \ - xfft_32.v fft_engine.v chirp_memory_loader_param.v + fft_engine.v chirp_memory_loader_param.v echo "" diff --git a/9_Firmware/9_2_FPGA/tb/cosim/validate_mem_files.py b/9_Firmware/9_2_FPGA/tb/cosim/validate_mem_files.py index 910b2d7..160c712 100644 --- a/9_Firmware/9_2_FPGA/tb/cosim/validate_mem_files.py +++ b/9_Firmware/9_2_FPGA/tb/cosim/validate_mem_files.py @@ -30,7 +30,7 @@ T_LONG_CHIRP = 30e-6 # 30 us long chirp T_SHORT_CHIRP = 0.5e-6 # 0.5 us short chirp CIC_DECIMATION = 4 FFT_SIZE = 1024 -DOPPLER_FFT_SIZE = 32 +DOPPLER_FFT_SIZE = 16 LONG_CHIRP_SAMPLES = int(T_LONG_CHIRP * FS_SYS) # 3000 at 100 MHz # Overlap-save parameters @@ -84,7 +84,7 @@ def test_structural(): expected = { # FFT twiddle files (quarter-wave cosine ROMs) 'fft_twiddle_1024.mem': {'lines': 256, 'desc': '1024-pt FFT quarter-wave cos ROM'}, - 'fft_twiddle_32.mem': {'lines': 8, 'desc': '32-pt FFT quarter-wave cos ROM'}, + 'fft_twiddle_16.mem': {'lines': 4, 'desc': '16-pt FFT quarter-wave cos ROM'}, # Long chirp segments (4 segments x 1024 samples each) 'long_chirp_seg0_i.mem': {'lines': 1024, 'desc': 'Long chirp seg 0 I'}, 'long_chirp_seg0_q.mem': {'lines': 1024, 'desc': 'Long chirp seg 0 Q'}, @@ -145,13 +145,13 @@ def test_twiddle_1024(): print(f" Max twiddle error: {max_err} LSB across {len(vals)} entries") -def test_twiddle_32(): - print("\n=== TEST 2b: FFT Twiddle 32 Validation ===") - vals = read_mem_hex('fft_twiddle_32.mem') +def test_twiddle_16(): + print("\n=== TEST 2b: FFT Twiddle 16 Validation ===") + vals = read_mem_hex('fft_twiddle_16.mem') max_err = 0 - for k in range(min(8, len(vals))): - angle = 2.0 * math.pi * k / 32.0 + for k in range(min(4, len(vals))): + angle = 2.0 * math.pi * k / 16.0 expected = int(round(math.cos(angle) * 32767.0)) expected = max(-32768, min(32767, expected)) actual = vals[k] @@ -160,13 +160,13 @@ def test_twiddle_32(): max_err = err check(max_err <= 1, - f"fft_twiddle_32.mem: max twiddle error = {max_err} LSB (tolerance: 1)") + f"fft_twiddle_16.mem: max twiddle error = {max_err} LSB (tolerance: 1)") print(f" Max twiddle error: {max_err} LSB across {len(vals)} entries") - # Print all 8 entries for reference - print(" Twiddle 32 entries:") - for k in range(min(8, len(vals))): - angle = 2.0 * math.pi * k / 32.0 + # Print all 4 entries for reference + print(" Twiddle 16 entries:") + for k in range(min(4, len(vals))): + angle = 2.0 * math.pi * k / 16.0 expected = int(round(math.cos(angle) * 32767.0)) print(f" k={k}: file=0x{vals[k] & 0xFFFF:04x} ({vals[k]:6d}), " f"expected=0x{expected & 0xFFFF:04x} ({expected:6d}), " @@ -605,7 +605,7 @@ def main(): test_structural() test_twiddle_1024() - test_twiddle_32() + test_twiddle_16() test_long_chirp() test_short_chirp() test_chirp_vs_model() diff --git a/9_Firmware/9_2_FPGA/tb/golden/golden_doppler.mem b/9_Firmware/9_2_FPGA/tb/golden/golden_doppler.mem index 1432e58..9b2497a 100644 --- a/9_Firmware/9_2_FPGA/tb/golden/golden_doppler.mem +++ b/9_Firmware/9_2_FPGA/tb/golden/golden_doppler.mem @@ -1,2176 +1,2176 @@ // 0x00000000 -ffbc003a -00840005 -ff29ffad -00d00059 -fe7d016f -02a8fc3d -ff7103e1 -fe2efd50 -ff9401fa -0366ff1e -fac1fd9e -05d606c2 -fcd7faae -00a20014 -0010ffb3 -003f020e +ffedffb5 +0056002f +fef8fdf4 +00bb03e9 +ff67fd79 +02890060 +fb84ff8a +0391003b +ff0d0073 +00ae0099 +fc9cfefa +0433fe37 +fe0303e7 +0027fe60 +000cff08 +00450115 // 0x00000010 -ffacfda4 -ff1e02fd -01abfddd -fee401df -0065ffa5 -ff8efd57 -00910087 -ff74ff24 -fff004e0 -0054fd38 -003bfffc -ff62003e -0023ffd6 -0084ff90 -fff600c1 -ffdbff66 +ffda004b +ff09ff80 +01e40140 +fed4fde4 +019102c6 +fac60187 +046efae2 +fe600256 +fee0ff41 +0131002c +0220ffcc +fd1cfdfa +019104b2 +ff4cfd11 +003a00be +001cffd8 // 0x00000020 -ffc80043 -fff7ffd4 -fffeffad -00870047 -ff580088 -0060fe86 -ff0b00a0 -00d7011a -fdddffc5 -02f200d5 -ff46fc45 -014a0506 -fd06fcaa -002aff01 -0391035e -fea3fbf3 +ffe3ffff +00e1ff79 +fef10061 +01650080 +fd9dfeef +04330116 +fa4cfd95 +04660217 +ff33ffb5 +fe990157 +0051fca7 +004bffd8 +ff6d04e5 +0067fd3e +0072ffcb +ffb6007d // 0x00000030 -fcdc01f9 -0305018c -fdf8fe8f -011f0155 -fcf4fe72 -04fc00c2 -fcfd00ea -0191fb84 -00630833 -fec6f9db -00bc01d7 -fefcff8a -00d20070 -0066ff97 -ff870048 -0049ff83 +ffc10027 +ffe40007 +00f5ff8a +fe04001c +00f202a7 +ff5bfd55 +feb5fef5 +0588007d +f9e10265 +01f6fdf7 +ff51020e +0086fcd4 +01b00389 +fd7bfe31 +012900ef +ffb6ff77 // 0x00000040 -ffcf002b -0003002f -000dff5a -001a0091 -fe9300fe -039bfebf -fd0bffae -02c30020 -fc5201a4 -0316ff87 -ff35fcfd -fe6d0225 -00ca0079 -ff2afccc -0295019e -ff9202e1 +ffc4ffdb +0092fffd +ff0fff3e +01d8002f +fd6a0180 +018cff18 +fcf7fdb8 +0745034a +fa62ff4f +fe6afe99 +035d0062 +ffdc00f1 +feb4ffea +0108ff8e +ff01002c +00cf0042 // 0x00000050 -fd0dff45 -03e9fd9d -fa730340 -0524fc5b -fe25005a -fefb00c1 -01dd0126 -fe71feb6 -00b202cc -0092fca1 -fecb024d -01f1fe07 -fd6601cf -019cfea8 -ffbb012a -002eff49 +ffa3000e +ff84ff01 +018c02cb +fe98fd35 +003103aa +fe93faee +0224020a +fe3d00ab +01e3ff84 +ff2a029f +fd70fc23 +01b60147 +0155014c +ff27ffa6 +fea40058 +00ddffdd // 0x00000060 -ffe3003d -ffd4fff8 -000affbf -00e0000c -fd480132 -0433fe7f -fd64ffcc -00fd015c -ff11ffc9 -012bff05 -fdd60084 -02250089 -ff64fedc -fe98fe2a -00c60216 -00980204 +fffeffe6 +00e5ffd5 +fe89fefd +01c5016b +fe9affd6 +0024ffe3 +fe8bfebe +03d80037 +fdc802fe +ff8ffe6d +ffb5fd0f +01cb014d +fe000306 +0088fe47 +00ffff66 +ff5000b5 // 0x00000070 -026ffefd -fc08ff4c -013c0067 -0112ffe4 -fd4cfeae -02fdfe15 -fc4e043e -03a3fcaa -fe3505a1 -0039fbb3 -00fc0186 -fe7dff0f -01680050 -ffc8ff96 -ff9800c0 -0044ff5e +ffd1ffc7 +003bff75 +00970297 +fde0fd96 +01fa004e +fe6d01df +0139fb91 +fd19057f +038bfb63 +ff890353 +ff93fcef +fe5002b6 +018e00ec +ff4bfe39 +00890075 +ff8b0065 // 0x00000080 -ffae003f -0028ffde -ff7fff3e -00a60183 -ff91ffd4 -00f5fd71 -ff60023d -ff870080 -00c8fe4c -ff670167 -feb9fe23 -026e03f3 -fe39fb1a -fedd018a -020200e4 -015d0034 -// 0x00000090 -fe6eff53 -00e80316 -fe71fb14 -009402eb -feb9fe74 -0121ff4d -ff420299 -00ebfc1c -ffd40856 -005df875 -006302fb -ff50ff33 -fffdff5a -00a90130 -ff58ffa6 -0089ff94 -// 0x000000a0 -ff83ffe1 -006a002f -ff42000f -011dff69 -ff780101 -00bdfe8c -fddd006b -02bf005a -fcd600ac -0208ffe9 -fec0ffe1 -04150097 -fae8fdc2 -0214009f -0294ff48 -fb0a00b1 -// 0x000000b0 -053500e9 -fca60091 -fdacfe8b -0325fed5 -fe8402f3 -0165fd62 -ff0f00af -feb3014c -03fa0132 -fd24fdeb -00520045 -00a9005b -ff94002a -008effb7 -ff40ffd6 -00c40021 -// 0x000000c0 -002d005f -ffdeff46 -001700f8 -ff84ff23 -008700fa -0137fef5 -ff9101d0 -fd61fcc0 -02fd02cb -ffe3fdd3 -fe2c00d4 -fe520083 -0396ffc3 -fea7020c -003ffc01 -00ce0227 -// 0x000000d0 -ffe5ff7f -01c0ff0a -fafd036a -00f2fc3b -01f101da -fd6dff15 -033bfe92 -fec90454 -006dfcab -fe3702fd -0288fe0e -fde00047 -010600dd -001dfe3a -003d0141 -ffa0ff7d -// 0x000000e0 -ffb5007e -0054ff99 -ff01002d -018f0045 -fea3ffe9 -015dfe20 -ffff01b8 -0002fff4 -fec900c2 -00350070 -ff5efcde -048c00df -f9030042 -04b3ff61 -fe6b0239 -00dffd33 -// 0x000000f0 -fe4302a0 -0208fdc1 -fe710223 -fe19ffcd -03fffdb7 -fd490274 -017ffee8 -ff3effa4 -011f0058 -fd0700e6 -02b0fffe -ff20fed7 -ffe301ce -00c7fee3 -ff7f00d3 -0085ff25 -// 0x00000100 -fff1002f -ffd1ffe1 -fffcffc6 -000500a1 -ffc0006c -0205fd3c -fe0803a0 -006dfe1b -fff2fe1b -ff9202cd -fe5bfda9 -040f05f2 -fd8ef9ce -fee70245 -01d6ffcb -005bfcab -// 0x00000110 -ff0d0429 -02ebff7b -fa7eff36 -03410019 -fe8801e2 -ffc9fd36 -01b600ec -feddfd3d -01c40695 -fd5afc87 -01b3ff6f -009b00f4 -fee6ff94 -00630029 -0004000d -001bff9d -// 0x00000120 -ffda004a -ffeaffd8 -0051ffe1 -ff740018 -feea0062 -030aff25 -fe5e0211 -00fbfde8 -fd540164 -04dafe11 -fb12ff8c -ff690358 -049bfcfc -fc0401b7 -017cfd7b -015b03cb -// 0x00000130 -fdf6ff44 -03fcfe52 -f9c50141 -02dcfe9c -010a0170 -fe22fe57 -01fa013d -ff4bfe98 -ff0802ce -0100fec1 -ff000022 -017bff04 -ff3500da -0078ffc9 -ffb4003f -0023ff6d -// 0x00000140 -ffd6003c -0039ff94 -ffa90079 -ffabffd4 -ff9c0087 -0376ff9e -fce7004a -0186fec8 -fec4025a -017afdeb -fddcfef2 -000004ab -03c7fa98 -fabb012e -053a001f -fe4901bd -// 0x00000150 -fd50fec8 -0301ff76 -fa3f0297 -04e7fc80 -00240391 -ffa6fd5c -ffd10294 -0012fca4 -ff3e02ea -00e8feb3 -ff68ffe6 -00c2ff81 -ff4901b0 -ffedfef8 -004a0043 -000bffbf -// 0x00000160 -ff7a0058 -0094ffba -ff57007d -0023ff19 -ff31023f -0362fd12 -fd770120 -ffbf004a -00b6ffbc -ffee01c5 -fe7afc1d -00fc04e2 -014efa52 -ff04035f -008fff3e -ffa1ff09 -// 0x00000170 -ff7802fc -fd78ffa6 -02b9fd63 -028d0163 -fcf101ad -00fcfc8c -fec502be -00f1fcca -fef00380 -024afeaf -fda2001b -0160005e -ffe8ffba -ff6affe7 -00590064 -0053ff4f -// 0x00000180 -ffbe0016 -0008fffb -ffc70011 -009bffa7 -ff710232 -0152fc2f -ff2a01f3 -0082005c -fe35ffba -00eb013a -fe55fb10 -04450846 -fc08f7b0 -03870161 -fd4e05c9 -017efadf -// 0x00000190 -ff7e02a8 -ff1aff29 -ff1bfed7 -016dffc9 -02570162 -fc7afe19 -00a80341 -ff68fd04 -0257026c -fef7fece -ff810034 -ffa7ffa6 -00f000c0 -ffa9ff83 -fff0002f -0054ffcd -// 0x000001a0 -ffe70050 -0035ff8a -ff0a00cb -0104fed0 -00e20282 -feabfb6a -012a02e2 -fdeefee2 -0311025c -fd60fd44 -0064002c -ff5f045e -0094fae5 -01d900d0 -fe60024e -000ffb73 -// 0x000001b0 -01750308 -ffa100ea -fd40fe49 -015a012c -ff48fe3a -ff7700e2 -030e00e2 -fc42fffe -02630118 -ff1efdb4 -021201b4 -fde3ff8e -00c2fff3 -0049ffa0 -ff8800ca -0059ff6d -// 0x000001c0 -fff20056 -ffdcff98 -0079ffd7 -ff5e00f4 -007d000a -00d2fe89 -feccffd2 -ffbf03bc -ffc2fd65 -02edffc5 -fd65fe94 -017c03d3 -01e2fca2 -fa37004e -0436fdba -00f202f8 -// 0x000001d0 -fab4ff44 -05a20252 -fa9bfd4b -02fa010e -fe93fff8 -009efefd -00f40266 -014ffd26 -fe2802ed -005dfd11 -fecf02ba -00a0fe0f -ffde0140 -00b1ff3c -ffb2009e -001cffa2 -// 0x000001e0 -0001005d -fffdffba -ffecffff -feefff84 -01050122 -0199feeb -fdcc00b6 -00c7004c -ffcdfeff -025d01a3 -fa36fdba -034002e9 -01ddfb72 -fde903d8 -00affe98 -0164ff0b -// 0x000001f0 -fccd01b7 -040bfe0e -fa80038f -0179fc34 -01cb02ce -feabfe25 -01540066 -ffcd0098 -fe95024d -0257fce9 -fee20184 -00c0febf -ff53011e -002ffe7c -fffd0180 -0008ff19 -// 0x00000200 -ff960046 -003effb1 -ffc4ffba -003700d4 -fedc010b -036ffcfb -fd55020c -fefffffd -012cfeb8 -ffa701bb -0022fd14 -0252070f -fde3f7e6 -00120368 -fe9cff7c -048bfd55 -// 0x00000210 -fafc04ee -03cefe39 -fd6afe36 -fdbb021a -037efec9 -ff790027 -fecf019c -0149fc8d -007a0684 -ff65fa6b -00440208 -0020ff3f -ff6bfffe -0046ffde -ffbc0098 -0081ff7d -// 0x00000220 -ffde006d -0005ff70 -ff7100fa -0168fe4e -fded0253 -0267fd45 -ff9103c0 -fe7ffd0d -0056feea -0156039b -fe2dfd5e -014d0360 -0013faf2 -ffc0022f -ff3800a3 -0133fd39 -// 0x00000230 -002e029f -fea3fe4c -fe91037a -01420070 -0067fb8f -ff9b015d -00fb02aa -ffdffb71 -0036057a -ff86fba9 -005d02ca -ffe1fe3e -ff5900a4 -00caffaf -ffb8009f -0027ff3d -// 0x00000240 -fff90044 -ffe8000d -000cff68 -ffe300f5 -ffc600e8 -0228fd28 -fd9c0244 -0175fdc8 -fdab01e1 -030e00b9 -fc6efdcd -03bf01ff -fc87ff80 -011ffd5f -0371022c -fcfb0056 -// 0x00000250 -0019ffde -01e20129 -fb7cfcaa -028902b1 -0036fd18 -00ce01c6 -fd7c028c -0115fbb0 -01e3048d -fe18fd01 -00a20141 -0069fecb -ff650090 -ffab0053 -00e70014 -ffa7ff62 -// 0x00000260 -ffd90015 -0008ffff -ff8bffd2 -0163ffec -fdb40108 -0342fe7a -fdf500c6 -0078feea -00190332 -fe2afd59 -022d00c7 -01aeffe3 -fac6fee5 -02deff17 -017efec5 -ff1205de -// 0x00000270 -fe7ffbfb -ff640385 -0295fe0a -fde7fef8 -fff60012 -031effe4 -fd7f01b8 -003afba6 -ffe70656 -fffafbc7 -00e301e9 -fee0fe8d -00500181 -0032ff97 -0026ffa9 -0004fffe -// 0x00000280 -ffab0047 -0043ffba -ff48001c -0110ffd9 -fefb01b0 -028afc6e -fd230240 -011bffa6 -ff6c0048 -001b0026 -feecfde9 -01070439 -015afc9d -fd59ff31 -01980233 -0246ff60 -// 0x00000290 -fc2b0007 -036d0314 -fc1efb3e -00e8010b -018d0072 -fe92ff50 -00610228 -002dfba8 -014a077a -fe29fbd4 -00c2ffa1 -001dfff3 -002200e1 -ff97ff99 -00600041 -0036ff82 -// 0x000002a0 -fffe0006 -fff0ffb7 -ffa2009a -0074fe78 -00d50306 -ff0dfd62 -00bf0076 -ffa6003c -ff18ff4a -00c4017b -0036fce8 -ff5f04f7 -001dfb21 -ff680274 -0166fe35 -fde00330 -// 0x000002b0 -03eafd00 -ff2800d9 -fb6201f8 -0396feb6 -ff35fdb8 -ff2d007c -019100a4 -fd0401e4 -02ecff20 -ff080095 -0066005a -006ffec3 -fe7d00c1 -01caff86 -ff3affed -002e0030 -// 0x000002c0 -001e0043 -ff95ff75 -009000c4 -000bff84 -ff2b0061 -0148ffda -0056fedc -ffeb005c -fcff00a4 -02eeffa8 -fee50028 -0189006d -fbe8ff81 -046e0124 -fbd8fb1b -04200643 -// 0x000002d0 -ffd4fcd9 -fe33fef3 -007a053c -fe35f9d6 -030b0529 -fc12fa7c -023202bc -ffe9003c -009f0210 -ffaafe24 -ffddff8c -003700dd -ffaa002d -00a8ff3a -ffcc00a1 -ffecff89 -// 0x000002e0 -ffc8fffe -ffc9ffd4 -00380090 -ffaaffea -ffab000f -023fff3b -fe04fff1 -01770149 -fce5ff7c -03e700a2 -fb3bfd31 -045a04db -ff80fcff -ff220003 -030ffcab -fbe304c7 -// 0x000002f0 -ffd0fe76 -0345fe0e -fb8403fc -011cfd5e -02bfff85 -fc4d022b -0248ff1d -00850033 -002fff84 -ff970134 -fe39ff97 -02c8fe7d -fdb20119 -01ceffc7 -fead0023 -00b1ffe5 -// 0x00000300 -ffb0007a -000cff4b -005800bc -ff1dff85 -00eb0226 -00d9fc88 -fe7c01b7 -01170106 -fe23fdab -024a02a9 -fcdafb5c -05f70758 -fadcf95d -004b0248 -01bcff52 -fec000b0 -// 0x00000310 -ffe4010c -0484ffab -f9b60012 -02e7fe23 -ff8f0128 -0031fda2 -ff7c02d9 -ff2ffcde -007d04e7 -011aff29 -fe1cfdc6 -02bd0164 -fe4eff65 -0027ff76 -fff00106 -0052ff58 -// 0x00000320 -0001005e -fffaffc2 -ffdcffd9 -ff6d007b -01c1ffb5 -ff07ffbf -ff48009d -0122fee8 -ff22010a -ff20005c -0167fefe -fe680361 -0334fb5d -fce40061 -02260127 -0281fdf7 -// 0x00000330 -f8e7040a -05c2fcca -fa240347 -02fbfd4f -00c7007f -ffcb0153 -ffe8fe39 -ffe800c4 -017a01d6 -fec4ff2c -fffdfec6 -0100ff89 -ff5801af -ff2afeb9 -013e00e7 -ff95ff19 -// 0x00000340 -ff93003b -008afff8 -ff76ffff -0042ffbc -ff8f00d3 -0206ff71 -fe680053 -fe96ffb5 -01b1fec2 -01030334 -fec6fbd6 -001c0622 -fee6f7ee -026b0559 -fc81fcaa -039c02ea -// 0x00000350 -fe29fe79 -02e4027e -fad8fda1 -013e01f0 -02dbfc0f -fcce0253 -02b4020b -0050fb57 -fce704e6 -0293fc52 -feac028e -0080ff52 -feb4ff5c -01e500c7 -ff4bffdc -003aff9a -// 0x00000360 -ff87004d -0025ffba -ffce002c -012d0046 -fea3008e -022cfd74 -fdb40385 -000bfd8f -001ffe82 -0234035c -fcf1fce6 -022b0103 -fe1e00a6 -0333ff38 -fb94025c -0283fd19 -// 0x00000370 -fdfd02b3 -03b1fd52 -fe28ffa2 -fd5d02ae -03f5fbfa -fc6403c4 -02ba0069 -fe39fee1 -0069ff72 -00320078 -00d5012c -ff7ffeb5 -ff9e0076 -0051ffa0 -ffe200de -00b5ff3b -// 0x00000380 -ffe1001a -ffc30041 -0032ffee -009bff51 -fea30210 -01dcfc10 -00030337 -fe3b0091 -0021fea4 -01410049 -fc04fd02 -07ea080f -fa2ff873 -02b500d8 -fe4b012e -0031ffd0 -// 0x00000390 -0091011a -0137fee3 -fc12ff28 -029f01b1 -ff13fd50 -ff6e038c -004fffad -00effd0b -0111046c -fe0dfc9f -01300108 -ff4cffb7 -00ff0071 -fea9ff78 -00830096 -0025ff84 -// 0x000003a0 -ffca000a -0044fffe -ff3c0022 -00f5ffcb -001e017a -ffb8fd15 -00990122 -fe3e0150 -026dfe9b -fca50059 -0218fed2 -ff840493 -ffbefafb -011c004b -ffb002fd -0146fbff -// 0x000003b0 -fdf204ca -0268fd98 -fa10ffa6 -05f1005f -fcf8fdf0 -011001c3 -ff25012e -0028feca -026701f9 -fe43fe71 -ff38ffba -00860073 -014c0013 -fe78ff95 -00b6006f -0004ffaf -// 0x000003c0 -000fffe5 -ffc9002c -0048ffee -fff7ffe4 -00a100dd -0002fe7d -0014ffe7 -fe2c01af -01e6fe63 -010000c9 -fc56fdac -034d046f -fbe3fd25 -05b5ffc5 -faa500c1 -03f5fe58 -// 0x000003d0 -00df0209 -fddfff34 -fef8ffa6 -ff850130 -ffcffe6b -fe7efe5f -055c053b -fd80fc2b -fe7c01e3 -0204fe6b -fefe01c8 -ffd70009 -ffadff57 -0117004b -ffe7ffad -ffe70032 -// 0x000003e0 -00270081 -ffc6ff02 -000401dc -fffffe2a -0075002a -ff9d0070 -0188005e -fec8ff8f -fed900b9 -020ffd6d -fd7f0406 -00bfff29 -0228fc72 -fef1024c -0063feff -fe0400bb -// 0x000003f0 -03f9ffa5 -fb56005c -00f8029e -0119fc8a -ff73ff80 -ffb3013a -027a0128 -fd7afe89 -ffcbff91 -ffbd0145 -01a5009c -fed5ff73 -015c001c -ff0fff7a -005b0087 -ffc6ff8d -// 0x00000400 -ffe60028 -ffb6fff1 -ffe0ff60 -007500c8 -fee5ffad -02b1ffca -fd430074 -01b50021 -fd7b0055 -0285feba -fd2dfdd7 -02d70657 -fea1fc5d -ff93fd8b -028a05a9 -fe2cfa84 -// 0x00000410 -004e032a -fbc80095 -067cfe6a -fe850158 -fe05fe2b -ffd10024 -028300ac -fd41fe7b -013d05fd -ffa9fa78 -016f0213 -ff43fef1 -0049007f -006fffbf -ff18000b -007affa8 -// 0x00000420 -ffb80041 -005bffc8 -ff71ffc6 -009e001d -ffb3014f -011bfd91 -fd7600ff -0248006b -fd8afffb -0221ffd0 -fe74fcb4 -02ee0548 -fdacfe9a -fd5bfd4b -03a20316 -0087fee8 -// 0x00000430 -fd94ffcb -0177000a -ff290050 -ffaa00ed -febffe23 -040d006d -fce60155 -01dcfd2d -ff060551 -ff59fb8e -00e201ce -feeeffb2 -01b60004 -ff81ffdf -00220046 -0021ff74 -// 0x00000440 -ffa80038 -005cfffe -ff44ffa0 -012f009e -fdff0017 -030eff14 -fe7700a1 -ffd4ffcd -011e005c -fe3fff0f -00d1fed1 -fe9b0298 -00c8ffb0 -00b7fb16 -fe1c0649 -02f4fdd6 -// 0x00000450 -fcac0136 -03f6ff18 -fbd20012 -017300a0 -00bbfd5d -ffa60218 -ff35005b -01a6fd15 -fe4205e2 -013ffd2f -ffa9fea1 -00c300fa -ff6a0000 -ffd5ffca -003800c7 -0052ff18 -// 0x00000460 -ffa00002 -00020038 -ffe1ff9f -00f60014 -fe15000d -0286ffe2 -fe4cffaa -00f5fffc -fe7b018f -0265fe64 -fb48006a -06920099 -fb27fe48 -01a1fe4b -ff7b02c4 -00450014 -// 0x00000470 -017800b4 -fbd2ff9a -00dd0099 -02eafeb6 -fe6dfec5 -01320256 -fe8afff6 -00b3fd5c -00c503e7 -fce7fe72 -037efef2 -feba0109 -000f006a -fff7ff1d -fffb00a8 -0097ff90 -// 0x00000480 -ffac004d -0031ff9e -ff75001f -0186004a -fe6000cf -01effcf2 -fe210248 -0086ffb5 -ffa6ff5b -ff950040 -0115ffbb -ffb2029b -ff68fce2 -ffe3002e -00f5001c +0025001e +00e1ffd5 +fea0febf +0168024f +ff8dff20 +0079004f +fd6afe0b +03e40009 +fef50360 +fe3ffdaf +ffdcfec1 +01fcffcd +fd61035e +01affebd +006aff41 ff180083 +// 0x00000090 +ffedfff3 +fe94003c +029eff3a +fd74013c +015dfe53 +febd02fb +ff39fac8 +02790477 +fe83ffa7 +ffc2fd6c +00520068 +ff72ffdc +02ef038f +fda5fdbd +ff8b004a +00d9ffe1 +// 0x000000a0 +00420058 +ffaeff4f +fffb00d1 +00f6ff23 +fe26012a +01ddffa5 +fcccfe0b +03570175 +00ca0380 +fbfafa9d +01db0215 +00e4ffbf +ff7e01da +001bfdf3 +ffd600db +0007ff7d +// 0x000000b0 +fffafff5 +000d0058 +012dff89 +fe590051 +ff36005e +02c60171 +fc8ffe01 +00b9fde1 +02a401bf +fd7b0048 +01c900cd +fbb5ff11 +059c002a +fcf60097 +00ebfffd +ff85ffd5 +// 0x000000c0 +ff8bff8e +ff9b004f +018aff23 +fd0501b3 +034dfebf +fd1900e3 +0206005b +ff6bfd29 +02fd022a +f9890147 +023afdd3 +042b0027 +fce30169 +002bff47 +ff8eff27 +00ed00e5 +// 0x000000d0 +0053ffd4 +ff90000b +00f40139 +ff43fd97 +02a2022c +fb00fe91 +036c0250 +ff0dfde6 +021dff70 +fccc01bd +017eff43 +ff3d00a5 +ff7eff2c +01c8ff53 +00720178 +ff2fffa2 +// 0x000000e0 +00390021 +ffebffe1 +ff0dfe43 +02fa0231 +fc1001aa +02eafb6d +fde3015d +011a0181 +0033ff1b +fd91021b +033dfdd3 +fea2ffcb +006c01fa +fffafe33 +000b00b5 +ffcaffdf +// 0x000000f0 +0001ffb9 +ff7900fb +00fdff0a +ff30ffee +ff8d017e +028bfe6a +fb8f00ba +02fdff37 +ff4700f9 +fde30025 +018dfe9e +00e600ba +fdc3ff54 +027d009e +ff0f0122 +0029ff81 +// 0x00000100 +fff8001d +00500017 +0020fe41 +feb8030d +0181fde1 +016400dd +fbe7fff9 +01a1fcba +033e044f +fc22fe97 +fe94009b +03a0fc75 +fe31066b +0162fb7d +ff050173 +0047ffbc +// 0x00000110 +ffc7ffd8 +ff09000e +02450011 +fefb0140 +feb8fd04 +ff280566 +004df9d4 +02fe0138 +fef702f2 +fd03fe0a +021f00dd +ffaffd78 +00a203d6 +ffb8feba +ff4fffaa +00a40038 +// 0x00000120 +001affd9 +00200089 +0053fdce +ffbf0336 +ffeffd64 +fec601ef +0109ff38 +0256fec0 +fe5401bb +fd14ff05 +02230030 +0191ff94 +fe4b01fc +ffd2fdc7 +01010126 +ff66ffe2 +// 0x00000130 +ffbb0032 +ffe9ff00 +ffdd01f6 +00c9fec2 +015801ad +f949fe9f +05cbfe57 +fd2f020a +03f9ffde +fadf0014 +02a3ff22 +0049ffa0 +fef80257 +00a3fee5 +ff59000d +0063ffdc +// 0x00000140 +0017ffff +ff6f00a6 +015cfe5b +ff24013c +ff7a009f +002fffe2 +ff20fda4 +04ad0291 +fc53ffbf +fd63fd58 +04380279 +fe08ffb0 +002c0063 +00cbfea8 +ff3401d0 +0063fef3 +// 0x00000150 +0016fff6 +ff19ff89 +01810262 +feb5fd68 +01ee01a5 +faf90129 +03d6fab4 +00f40372 +fed0feac +fe150305 +0245fe54 +fff9ffa4 +feec01cd +002dfe59 +ffc4010a +003affba +// 0x00000160 +006e001a +ff8e0062 +001dfe83 +006301ea +001500ac +fe8afe41 +0235fecd +003c0102 +fc400396 +04def99c +fc57048f +0081fdd8 +017d0110 +fef2ffdd +001f0065 +fff0ff70 +// 0x00000170 +ff7fffd4 +ff58ff40 +028902a0 +fca0fd55 +01e50184 +fd76005b +01d9fd1c +00d30044 +fd710210 +02c0ffd8 +ffb5fee8 +ff3affff +00330264 +fecefebd +00b1ff30 +007700c8 +// 0x00000180 +00060041 +007dff8b +fe8dff98 +02c6015b +fc2e0098 +0378fe4f +fef8fc43 +ff1405e1 +ffce0059 +ff3ffad1 +02b5044e +fd1afe7b +02aa0106 +fe34ff51 +00ea003f +ffd4ffad +// 0x00000190 +ffc3ffd0 +ff7e000c +026700c8 +fdc5ff4c +005a00b6 +fe2001fb +0145f987 +01460570 +fee5fe36 +fee400c4 +01fffd1c +fe7d034a +01d2ffa4 +fe02ff39 +012100c5 +ffb4ffe6 +// 0x000001a0 +00510002 +ff93ff34 +ff1f0091 +01f6ffc4 +fef40137 +008a0107 +ffd2fb8b +fe1101a1 +04f1029e +fb11feb6 +011ffdbb +01ac0330 +fdfefd99 +01b20203 +ff5cfe71 +ffcd00bf +// 0x000001b0 +003fff78 +ff120109 +02f1fec6 +fc88007b +03e7ffb8 +fb0a0229 +03a1fd95 +00010040 +ff6d0144 +fed2ff89 +ff5dff2c +0112fff3 +01490194 +ff82ff21 +00150069 +ffd5004e +// 0x000001c0 +ff8affb9 +00fc0054 +ff14fefe +017e028a +fde3fc9b +028b0178 +fbda0173 +061efc63 +fcf8032d +fde8fea6 +00a8ff08 +0236006e +fe6701d7 +ff41ff4e +0116ff5f +000600b5 +// 0x000001d0 +0020001c +ff0dffde +02c60027 +fb420001 +04ef00a2 +fb8e00b1 +02e0fb2b +00690239 +fdea02c2 +ff81fd2e +001a002d +02a2013b +fe67fea8 +ff3c013f +00800011 +ffcbff97 +// 0x000001e0 +0019ffe1 +ff22ffdd +01ceff14 +fe9f0168 +023d0036 +fb31fe88 +04900010 +feabffb6 +012500c3 +fb3c00a9 +02f8fee8 +02350044 +fcad007e +0195ffe2 +ff82ffec +005d005e +// 0x000001f0 +001dffd9 +ff03feed +020101e0 +fdabff44 +0277ffff +fb7601a9 +0245fc38 +01f9016b +fef10077 +fd7d0073 +025ffffe +fe91ff04 +019302a5 +ff36fe4b +ffe3ffde +ffef00b1 +// 0x00000200 +ffccffd9 +01070063 +ff32fe4f +ff7c0349 +001afd11 +030001e0 +fc0dfebf +0238fd1e +ff86050d +fdadfed7 +02e2fe19 +fee6ff8f +ff600389 +0100fe2a +ffa3ffe1 +0022003e +// 0x00000210 +0003ffb4 +feaaff8a +032901ce +fc5bfe22 +013a007e +ff120327 +0060f98f +020e02d2 +fe930312 +fcb8fb46 +03ed01b2 +fe57ffd4 +02580204 +fe40fee1 +ff92ff99 +006c00b0 +// 0x00000220 +001bfff0 +0008ff7a +0043ff39 +fe5c0336 +0327fd05 +fd730201 +0101fddb +feeeff5a +02c50250 +fc5a01e2 +017dfaef +005201d0 +ffb901bb +0013ff8b +0007ff1d +fff40098 +// 0x00000230 +ffa5ffb1 +007f003d +ff5100f3 +0164ff40 +fd73008f +00760136 +0091fc2a +0101025d +ff13fdad +fec905f9 +0069fa0d +01f8021c +ff71011b +ffc2ffb0 +ff290016 +00a3fff3 +// 0x00000240 +ffee0007 +00ad0012 +ff2aff21 +002400b9 +00a300df +ffdaff18 +fc78fddb +06270337 +fd6800ab +fcfbfd42 +051cffd5 +fb8200cb +025b01e7 +ff7efdfc +002600e7 +fffbffad +// 0x00000250 +ff510020 +fed4ff91 +02fb011c +fe3dfe99 +ff56027e +ff80febe +000fff5f +00f7ff66 +00c70228 +fc8afedb +01ddfe18 +ff9f0231 +0156fffa +ff96fffa +fe5dffd5 +01b10014 +// 0x00000260 +ffd50063 +007aff81 +ff4bff80 +013e006e +fd94020a +0334fed7 +fa73fcd5 +08e40354 +f9f30087 +ff64ff13 +02edfd88 +fe2601b2 +0014017c +00b2fefd +ffb50053 +0024ff84 +// 0x00000270 +ffba0034 +0010fff7 +00910182 +fe95fd97 +00510179 +02a900b1 +fca2ff17 +ffc2ffaa +fed00066 +0414fe81 +fe4b027a +000dfccf +001503fd +ffdffda3 +ffa201c5 +0060feec +// 0x00000280 +ffec003b +005bff9f +ff65ff6c +00bd015d +ff010043 +0100fef8 +fe1aff3e +03a2ffe9 +fecc0381 +fc29fc01 +038f0154 +ff71fdd7 +ff6f05e5 +003cfb00 +004201f6 +fff8ff73 +// 0x00000290 +ffacffbd +ff1b003e +02fa0080 +fc71ff9a +01a5fffe +fd0e0185 +0317fb5e +008f0467 +fde000c9 +ff53fc18 +015c00f0 +ffe5ffee +01330324 +fea8fd81 +ffff00ca +00970015 +// 0x000002a0 +ffc9002e +ffe6feb8 +ffd70220 +00d5ff2d +feebffa0 +01c4013c +fdc2fdd0 +012800f7 +03410028 +f9ba013a +0295fc90 +01450307 +ffb3fefe +ff1c007e +ffdaff2c +008e0089 +// 0x000002b0 +004f0003 +ff8a000b +018700c8 +ff36ff00 +ff5c010a +ff46ff56 +00effe8b +fe5d0180 +045dfd0d +fcce0535 +0089fad0 +fe2401c6 +026c00c6 +00b2ff96 +fec500d5 +0001ff06 +// 0x000002c0 +ffc5ff8e +0088005b +ff08ff4c +01fa009f +fdc1ff0d +021301a2 +fc94ff4d +0369fd1e +ffd902cc +fcfa010d +ffe0ff5e +03e8fdfb +fd91030d +00ebfe4e +ff6c001d +005d0068 +// 0x000002d0 +ffd1ffc9 +00610065 +ffb4014e +0102fce5 +fddb02e3 +01bdfe7a +ff6901ff +fc5fff63 +03c7fba5 +ffc503df +012cfe44 +fcb2020f +03110073 +fdf1feb2 +010300d3 +ffb9ffb1 +// 0x000002e0 +0037ffd5 +ffb900c4 +0019fe0b +0158021a +fdcdffa9 +0174fe79 +fd7d008d +04d401c4 +fd3dfd35 +fd250252 +03e5ffa3 +fefcfe36 +012302dd +fd8efd91 +018900e5 +ff90001c +// 0x000002f0 +000bff9a +ffc10058 +015700d3 +fe57fe9f +01270152 +fbd500e2 +0505fe23 +fcc2fcb5 +031102e6 +fcf90194 +fffdfcd5 +020902c1 +ff09fe2e +00d50112 +fec3ffed +0012ffb3 +// 0x00000300 +ffbbff9e +009e0076 +ff4fff62 +00f90182 +fe76feaf +03d2ff7d +fa800031 +0359ffcb +017f00a0 +facc0040 +02e1fea2 +ffeb0052 +007c02ff +ff6cfc9d +ffac0177 +0093fff9 +// 0x00000310 +ffeaff9b +feeeff97 +0330011a +fcfd0012 +0097ff92 +fedb0283 +ff94fa5b +00aa0175 +02660361 +fce8fd91 +01b4ff34 +fe81ff34 +00b904be +ff7bfd71 +fff0febb +00140169 +// 0x00000320 +ffe70000 +ffb1ffcf +01240069 +ff2cff29 +fff1015e +fff2006f +fee8fd04 +04ae007e +fc2d0298 +fd23fe8d +0448ffe3 +ff42fecd +ffa703aa +fff2fc35 +ffa00278 +008cff24 +// 0x00000330 +ff8bffda +fee9001e +01d7ff4b +ff8600bc +fea4ffb6 +ff720205 +0248fb85 +01f7021c +fc970190 +ff030084 +015bff13 +fedefee6 +020a01e4 +ff7afe71 +ff260079 +011d004a +// 0x00000340 +0030ffb4 +ffcffff1 +0127ffbd +fd600172 +0379fdfa +fe59032a +ffddfbaa +0059003f +02560302 +f995ff2f +04d1fdc7 +ff7e0150 +fe950068 +00bb013e +ffeffdea +fff90147 +// 0x00000350 +ff8a007f +ffadff5d +01090196 +fe6dfdbc +00e90243 +feb3ff2a +00d5fdb4 +feb2019b +023afffd +fc970025 +00fdfc7e +04510222 +fc7f017d +0011ff40 +ff79004c +00d8ff1b +// 0x00000360 +ffd0fffe +00f7fff0 +ffabff59 +fd5a0287 +03c5fd48 +fdb8ffe8 +024700eb +fca50123 +0118fdc4 +ffd9027a +0297fdeb +fd54025d +0103fd46 +0014020a +ffafff09 +00290015 +// 0x00000370 +ff8bff4b +ffdc00bf +016dff46 +fedc00dc +ff850045 +ff9efdfd +00fe013c +fe95ffd9 +023f0239 +fbf8fce5 +00b7fefa +02e40272 +fd99ff67 +01f60053 +fe9effc4 +00cb00c5 +// 0x00000380 +00230066 +0064ff92 +fed9fe56 +02590478 +fca7fd38 +04bbff49 +fb3cff3f +022f019c +0043009e +fe10feb0 +022300ee +fe23fdc0 +00b70398 +007dfde5 +ffcc0111 +ffe1ff54 +// 0x00000390 +ff5aff9e +0086ffca +00fe00bf +fdcaffb4 +0269ff52 +fbfc0544 +0301f80a +fd9902db +03b600ae +fc4affe6 +fedefe47 +0326014a +00270016 +fea0fff8 +008bff5c +000300fb +// 0x000003a0 +001a0025 +002bff7f +fefb0041 +01c500d4 +fe47ffad +01ec00f1 +fe0efbe2 +0208020e +ff6a03a7 +fd17fb7d +03230095 +fe99009a +010d0213 +fea2fd7b +01040154 +ffc2ff84 +// 0x000003b0 +ffc5ffa7 +ff4e008c +024dff99 +fd1a005d +01eefe22 +fe2a0354 +0184fc82 +01140159 +ffe10175 +fdcc00e6 +ff3dfc3f +004e02ad +02f0ff36 +fcc0006a +01ceff1a +ffc000d5 +// 0x000003c0 +ffcb0013 +0031ff89 +ffca002a +000c00e8 +00b9fe9f +0023015f +fe08fdb8 +0024fedb +031504c7 +fc97ff7d +febcfb0c +049a04fc +fd6bfd6b +0089027f +ff86fdce +00aa00bd +// 0x000003d0 +ffb10043 +ffeb002b +01cb0041 +fcecff28 +040b007e +fb46001d +032d001b +fdb10059 +0293fe15 +fd4700ff +fee7fe53 +054e0258 +fc69fffe +ffb4fff5 +0099005d +0019ff3b +// 0x000003e0 +001cffcf +fedd0048 +017bfecf +0071023d +fef5fda9 +fdf4030f +0353fc4a +fe890164 +02300229 +fb7ffe7c +0363fddf +ff9503a5 +ff77fd5b +00440149 +001fff9c +ffd5000e +// 0x000003f0 +001dffa4 +00a30115 +febaff77 +01baff65 +ffcdffd2 +fe3103d5 +01e7fba1 +fe670108 +00d7fdca +022f04c1 +fc1cfd2d +04260013 +fbe70068 +029100e1 +0033ff1b +ff6d007c +// 0x00000400 +001b0033 +0046ff75 +007eff31 +ffd20210 +fd56fea6 +0471003f +fbb5fe33 +02b202ac +fd7300e3 +0402fe25 +fbd0ff71 +03e80062 +fc5801b0 +025bfe7b +0011005f +ff30ffee +// 0x00000410 +0034fff3 +ff76ffe3 +00f500c9 +fecbff52 +01d70081 +fae70113 +03d4fc53 +0288024d +f97e002f +06cc0089 +fbcbfe99 +00dbfe86 +020304cd +fefffdb9 +00100063 +ff9affcb +// 0x00000420 +fffbffe8 +008cff87 +ff6500b5 +0096ffed +fd82ffae +05cafeba +f8aa023d +0588feab +fdd90004 +ff84023b +00cdfb8d +007801e7 +fe2602a2 +00e2fe00 +00d0ffdd +ff86006d +// 0x00000430 +ffcd001b +ff21ffcf +02810023 +fd0a004e +018c00a7 +fd76ff7f +00fffcd0 +02590484 +fd99fdf1 +ffd70039 +00bd00fd +ff92fe64 +00c601b5 +fe6effa9 +016bfff8 +ffcfffea +// 0x00000440 +0037ffeb +00560015 +ff68fec1 +009b019a +fef70042 +0161ffd9 +fdebfce7 +02f0036c +fec7ff67 +fd7c0063 +0338fe6f +ff51ff38 +fe9f0420 +016dfc53 +ff910195 +ffd4ffbe +// 0x00000450 +ff8eff89 +ff8fffef +00b2012d +fee1fecb +01c4ffbb +fcb00004 +0468fe6b +fceb0442 +012cff0b +fdc3ffc9 +00ccfe11 +00d1002d +ffb2042d +ff9efc94 +ffb20043 +00db00de +// 0x00000460 +fff3004f +0040ffa9 +ff94ff7a +00c70072 +ff0c012d +0011fe45 +fe71ff07 +03a1017b +fd8f039d +fe9cfac7 +03c001a4 +fd87ff58 +ff92033b +026ffcb7 +fe430167 +008dff6f +// 0x00000470 +ff8eff88 +00980001 +ffa400ff +ff6dfe1d +01480138 +febc02b0 +ffd9fa8a +feba03c0 +00cefcd4 +018c047f +fd76fd13 +0199ffdb +feec0160 +0104ff08 +ffd50098 +00040068 +// 0x00000480 +ffe20026 +0103ffc9 +fe7cff78 +00e60195 +ff31fe5f +01fe0214 +fcd3fd60 +02ad00a2 +010800f6 +fbd5007d +0258fe4e +ffb8fe27 +ffc105ed +0086fc4e +fff5008a +ffe1ffe2 // 0x00000490 -002200f7 -02f7ffde -fb2fff51 -017c00ca -00f0fed7 -ffd1ff0c -fec7024a -0084fb41 -01a408cd -fdc3fa20 -00ff01a1 -00700011 -ffc0ff1c -ffed00f0 -004bffa6 -003aff9f +ff89ffc7 +ff8300c3 +01f9ff5b +fd970093 +0036ff02 +001301c6 +0084fda9 +fefb0045 +028d0275 +fbfbfec5 +033dfe99 +fe0bffbb +024c0352 +fe5fff6e +ff9efefb +01130059 // 0x000004a0 -ffba0009 -0016fffd -fff2ff6e -ffae004e -010901e4 -ffcffd29 -fe6e00d2 -0194006b -ff29fffe -ff6b009d -00a7fcfb -01d2060d -fe73fa6b -fee00109 -03290015 -fe8e005b +0004005b +00b0ff48 +ff2a017d +00c8fe9a +fe440150 +03dfff45 +fb32fea8 +04300190 +feac0031 +feb0ff3c +0086fe91 +0014011e +0000012c +ffa9ffe3 +008aff4a +ffac0004 // 0x000004b0 -fe24fe83 -01a40293 -fc14fe4c -04b402be -fcc3fd08 -033700cd -fe120084 -ffcafe2d -008d044a -0063fd13 -fffb012b -ff94ffd3 -009dff15 -ffe200c1 -ffafff85 -008c0011 +00210001 +feb2ff49 +034800a7 +fcdd003b +00b6ff80 +ff030212 +0083fbc5 +027a017c +fcf7ff8b +ff8602db +016cfd91 +fed1fe67 +018e0394 +ff15fea6 +0035ff73 +00000056 // 0x000004c0 -ffd30026 -ff84ffa6 -0079009d -00ebffaa -fe1a002b -0153ff40 -000701ca -fee6fdb7 -01560192 -01eafe86 -fb760066 -019b01c6 -ffc4fe00 -00110005 -ff24ff0b -017c0281 +ffcb0010 +00fe0019 +fee6ff68 +ff3500d9 +02e6ff0f +fd3f022b +ff23fdd2 +0370fdc4 +fe9b068c +fe10fb4d +017201f0 +00bdfd67 +ff1c03b5 +012bfe37 +ff45ffb6 +fffefff4 // 0x000004d0 -034b0192 -fb42fd1c -015b014d -ff39fd88 -01f801d5 -fc79fea4 -01bf01f0 -00ecfe71 -00f401ba -fc68ffd8 -042efea0 -fcd50164 -018aff6c -ffd30007 -ffb6fffb -0076ffcb +ffb1ff77 +011800f6 +fe94ff8e +00bcffbb +028e00c3 +fadb003f +0377fe42 +fbd8023d +05c1fda5 +fddc0166 +ff48fe26 +00f2038b +ff10fe39 +00e5ff5d +007d013a +ff96ffdd // 0x000004e0 -ff9fff82 -000000bd -000dff32 -00090091 -ffc900d8 -0165fdbe -fdee01fc -02d8ff7e -fdbffecf -002f01e4 -ff8efb11 -02b40715 -fe2bfbbf -fe23fea2 -02200294 -ff0d007d +00710032 +0033ffc6 +ff71ffaa +00af0091 +fdf900c1 +04acfe00 +fa5000b7 +03f0009a +fefd00ec +fe81fe9a +01e7fe2c +0081032f +fd79ff9d +0110fe9c +0148008f +fea00012 // 0x000004f0 -0161feb2 -fe480183 -0063fe5a -00310091 -ff6ffe96 -01170054 -fee20242 -01a2ff8a -fe61fff9 -0009ff74 -0036ffe3 -00860071 -ffedfec7 -00610194 -feecff5e -01050053 +ffeaff9e +ff9bff9c +01c80051 +ff1e0197 +ff42fdfb +fe6d01a6 +024ffaec +fed304eb +0092fde4 +00630066 +ff06feb5 +007e02cf +ffa6fe13 +004500f4 +ffafff0e +001100b3 // 0x00000500 -ffd6002b -ffde0010 -0047ffa6 -ffd4ffb8 -005a02d6 -000afaf4 -005303a2 -fe94fecd -00e10023 -ff29022b -0157fa11 -00f80960 -ff49f8d6 -fd35ffdb -0335015a -ff5afff0 +fff8003e +00cbff5b +fe480011 +018a0155 +fe5cff8e +04faffd8 +f87cff10 +0545ffc7 +0028002e +fc8502fb +0078fce3 +038afed5 +fc900416 +01c6fdbe +ffa8ffc4 +ffa7004b // 0x00000510 -ff64001f -0190ffb2 -fe4d01d4 -fe86fef0 -0296fefa -fd0e0022 -032dff56 -fe48ff75 -ffe104a7 -ffb1fdf7 -01edfe79 -fe7e01d4 -0073fe3e -fffb015b -ffebffa2 -004affd2 +ffa7000e +ff74ff54 +02e200ad +fd91ffb7 +002c016b +fe6c0080 +029afa2a +00000445 +ffd5ff6a +fee40062 +00f2fecb +0029fe69 +ffac0535 +0074fc82 +ff7e007e +00ae005b // 0x00000520 -ffe30044 -ffe2fff8 -fff90009 -ff68ff77 -00bf0150 -01e4fe4d -fee802b1 -fe52fd4f -0113ff4c -00bb042b -fe06f9a5 -ffe106ae -026efb0b -ff2a0223 -fdaaffcc -03180000 +003e0047 +ff22ffaa +0254feb9 +fcde0350 +0312fe78 +fdf8ff2c +01bcfffd +fe56ff40 +01a401bb +fe1aff88 +00dcfee7 +ff2400e6 +009cffca +0118009e +fe54ffaf +008cfffe // 0x00000530 -fe850078 -02da0072 -fbe9fd29 -01780375 -0035fd16 -ff6c007b -ffde01c3 -ffc4fdfd -006101ec -ffe1ffb3 -01d0ffd5 -ff1bffa2 -fec2009b -0106ff75 -ffb80084 -003eff60 +ffb8ffde +ff50ff64 +01ab01cb +ffd8fe34 +ff130200 +fce9fe29 +04a9fe2a +fd8302dd +02860042 +fbdefe6c +0281fe5d +ffba0182 +ff17017c +0235fde3 +fe23013a +00bfffb9 // 0x00000540 -ffc9002c -004b0004 -ffe70011 -fff6ff97 -ff7100c7 -01edfee3 -fdcf010e -017efd79 -fdae0385 -0354ff8c -fd41feae -015601b7 -004bfc68 -fefaffd9 -02e103bd -fcfdff5b +fffaffbb +ffba0052 +0056ff6f +ff78ff9e +00fc01b4 +fddfffe5 +0162fb89 +00c90701 +0148fbfd +fab0ff70 +04520099 +febc0186 +0046febc +003700a9 +ff12ff5f +00e30073 // 0x00000550 -fffffca2 -030902fa -f91dff8f -04a0fecf -fff500d7 -fe49ff0f -020d03aa -ff1cfc97 -ffa20179 -00acffda -002f0066 -0038fef7 -fe970106 -0114ff09 -001f00df -fffdff69 +ff8a0024 +0012ff83 +00bd0124 +ff93fdc4 +ff3d041b +ff94fe92 +0011fc2d +01af03c3 +ff50fe14 +fda40213 +0091fd22 +0299027c +fd5d0019 +01d2ff18 +fe9500d1 +00c1ffbd // 0x00000560 -ff980040 -0085ffe8 -ff8b0066 -ffd1ff3a -000f0172 -01a3fdb4 -fed20048 -fd8d0229 -0449fe5c -fd1c01d7 -0127fdcf -fece0297 -ff35fad1 -0544031d -faab0167 -03fcfee0 +005affef +ff62007b +002ffea3 +004701bc +01240008 +fd1200ce +041bf9dd +fde805b1 +ff14006f +0096fd29 +ffdbff07 +0065036c +001efde6 +fe7e0156 +0143ff35 +ffcc0057 // 0x00000570 -fcb6ffa0 -017301f0 -fdd5fbe4 -031b03c2 -fc5dfc8c -027f027e -00a20050 -fe93ff91 -004dffec -00ecff79 -fee50153 -ff66fe89 -01230159 -ffeaff09 -000d00b5 -0034ff5a +ff87000a +ffacff81 +02770161 +fafefe50 +03da0087 +ff17000a +ffd8ff83 +00510172 +feebff10 +002aff9f +fe01ffa9 +02bcffc8 +ffb8005f +fef7ff82 +00f400e3 +ffe9ff9a // 0x00000580 -00150056 -ffe9001a -0011ffc6 -ffb40012 -ffe50129 -0178fc9e -00620307 -fc80fed6 -025b01c4 -ffd9ff9c -0005fcd3 -0343058e -faaffb53 -051dffba -fa350203 -0387fd53 +009b0003 +ffe40035 +ff89fda3 +011c03d0 +fe3efe42 +0433fffc +fbe9fec4 +ff1dffb4 +03d502a3 +fca4fd7f +02a701fb +fd26fe72 +005e0120 +0211ffc4 +ff7b005e +ff35ffce // 0x00000590 -ffc90214 -00770046 -fcb7feda -02900116 -006dff21 -fe9e0008 -febe033d -02f0fadc -fdf7042e -fffbfda8 -02770099 -fd9dffde -013f0097 -ff91ffdc -fff7004d -ffedff57 +ffad0039 +ff78ff9b +02390107 +fd2efdb9 +021503aa +feeeff84 +0133fd24 +fdb701e2 +01afff8f +fd8c00f5 +012bfcc1 +01c4039f +fd5fffc2 +012efe38 +ffe10160 +000fffba // 0x000005a0 -ffbf004f -0046ff78 -ff7e00b8 -00ddff29 -fed201ff -00edfc60 -02190410 -fca2fca4 -019e01dc -0013feb6 -fdb0ff8b -02ef0324 -fd21fcff -018d0127 -001bfe80 -000b02d9 +0022ffdc +00610028 +fea6fe85 +013f0327 +ffc0fe4f +00e7008a +fd1dfebc +02d1ff02 +019e0462 +fa6bfd14 +03f8ffc9 +ffb5fea9 +ff1c041f +0059fd26 +00690062 +ff6f002a // 0x000005b0 -0461fd43 -fa22010c -ffae00b2 -ffcbff55 -0386ffb5 -fd6dff24 -ffd10212 -0222fdd0 -ff9a02ba -fd99ff3a -0290ff0f -fded0096 -018f0085 -002dff71 -ff4f002a -0065ffbb +004c0007 +ffcd0026 +002e009f +0108feba +004e00e2 +fd4f015f +00dbfe2c +ff0b0239 +0364f9eb +fc4705d0 +032efc73 +ff160322 +ff26fef8 +005dff27 +014d0196 +feffff4f // 0x000005c0 -00270035 -ffe7ffce -0017fff2 -ffeaffd2 -0016010c -012dfef3 -ffa50139 -fdd7fea3 -01ab0018 -0161ff62 -fdd7fff8 -ffad01e3 -0077ff0b -0055feb2 -006702c3 -fed4fcee +ffe00008 +003fff88 +00cfffee +fdb90212 +0248fc91 +ff690333 +ff2ffd57 +ff6900d7 +04680102 +fa39fff0 +024dfd6c +0043028c +ff94fec5 +ffef0269 +0089fddf +ffd30087 // 0x000005d0 -027d0295 -0245fd82 -f6f7012c -06c200fc -fc3efd3e -024700ef -fef301cb -0039fe99 -001101de -ffbbfdc2 -01ef0316 -fd6ffdfb -0195001b -ff970070 -007dffad -ff9cffe2 +ffe6006a +ff97ff82 +00ed0171 +ff30fe35 +020e015d +fc14ff2c +02690001 +ff450088 +04c8ffbc +f8a702ac +019dfc35 +008201ad +ffec0021 +00f2000a +ff35005d +0065ff7a // 0x000005e0 -ffde005b -0019ff2d -fffe00a1 -ffe3ff6f -ffd000b6 -ff8bff5d -00e7015e -005eff15 -ff22fee6 -ffbe01c8 -0224fd98 -fca1038d -029cfd35 -fcb4ff8e -04360082 -feac0218 +ff97ffa5 +0073003c +ff870012 +004e0073 +ffaeff1e +01680226 +fc91fd0e +04d3017f +fecfffd1 +fd8b0114 +ff03fdca +0678009b +fa9800d4 +0122ff3a +ffb9ffe6 +005f008b // 0x000005f0 -ffeafce3 -005f010f -fc1a000b -010b0305 -032afd36 -fba5ff83 -0411ff4a -fff2048b -fe26fd74 -016a0058 -feb0fff8 -0229ffef -fe42ff77 -00c4ffd6 -ffde009a -0024ff88 +0046ffd1 +ffdbffb5 +ff2dffe0 +020e014b +fdbbff10 +0007ff18 +011bfee4 +00b20310 +00e0fc0f +fa63046b +0567fb8e +fe140369 +00ebfe98 +004b0110 +ff45fe8e +006c009c // 0x00000600 -fffa0024 -0019ffc0 -ff9c0029 -005eff8b -fe6b0233 -03c5fbb6 -fdab0344 -ff4aff65 -0181010a -fc7bfeb5 -02d6fe71 -024705a3 -fe08fa76 -fe59fff1 -036401fa -febdfe78 +ffeafff7 +00220040 +ff38fd98 +01b60397 +fc21ffc1 +060dfe1b +fa20ff80 +04d6017d +fcb60049 +0132ffe0 +ff42fe2e +00e0005d +ff73034b +003bfd29 +004a0056 +ffe00043 // 0x00000610 -fde20142 -00b10052 -009efe31 -fe0a02ad -0219ff47 -ffcbfdea -007d0264 -fddefd01 -03d705cc -fc83fb21 -013801a9 -0001ffe5 -0058ff84 -ffcf004f -0024ffea -ffdbffea +00230029 +ff4aff58 +02900208 +fc68fe98 +01acff39 +ff700494 +001bf940 +029202bc +fcd5014d +ff26fe54 +03c200d2 +fd22fec8 +037801dd +fd840084 +008fff1a +00080020 // 0x00000620 -ff9e0067 -008eff53 -ff18011e -013bfe83 -ff09028c -00e2fba1 -ffbd0461 -ffc4fc69 -febf01a8 -fffb017a -0322fbee -fdab04ce -ffe2fc07 -ffe000e7 -01300248 -ff40fcef +005dffe2 +0005fffd +ff31ff8f +00ac0184 +fea8ff39 +0355008d +fd47fdba +00980213 +018fffda +fb9fffb3 +03f5ff93 +0058ff10 +fd2c03f3 +013ffc07 +00eb019c +ff14ffb5 // 0x00000630 -ff6a01f7 -01b2ff3d -fca00160 -00ffff01 -0337fee8 -fc700079 -01830149 -00d8fdcf -feb5040e -feb1fdfe -0226fff8 -ff73ff1e -006200d1 -ffe20057 -0010ffda -004cff79 +ffb0ffdb +ffc1007e +0138ffae +002fffe9 +fcbb024e +0238fd25 +fee1ff7a +02820142 +fea2004b +fe2b01a0 +01cafc20 +00b5026b +fe0f0114 +0200fee9 +fec100b0 +00e6ffbe // 0x00000640 -ff760033 -008d0000 -ffa9ff8a -ffbe0082 -fff6ffb1 -010fff1f -fd6901b1 -03e9fed8 -fcceffdf -024602a3 -fc71fd64 -031601d3 -ff84fce2 -fef8ffdd -03730404 -fd85fc83 +0025ffdf +ffc50072 +0037ff0c +fff7ffa1 +015402b2 +fc98fe22 +01f6fd37 +00920530 +011bfcd1 +fc6102b4 +03bffc08 +fc9900f3 +02940256 +fea6fee0 +0024ffb5 +0042005c // 0x00000650 -fe36fedd -026d03f6 -fdabfda0 -ffb602a4 -ffcafbfb -0363040d -fd93ff6f -00e7fbd6 -ffda0541 -0034fd8b -ff3f01ce -019afe4f -fe7800b2 -013aff33 -ff3d00d0 -00afff67 +00030023 +ff6bff52 +0101ff97 +ffd40214 +fe42fee3 +001d013e +ff77fc10 +04b70261 +fa450053 +00c7ff18 +fff30187 +024efd04 +fe4a02e3 +00ed0008 +ff31ff1e +001b004f // 0x00000660 -ffdb0044 -ffdaff9c -ffef00b9 -0157fed3 -fe0001e5 -0281fd08 -ff120180 -fece0023 -00f00113 -fe52fdce -010c01be -0126fdd0 -fed90341 -ff8efcf7 -0257fe29 -fd590490 +fffdffda +008cffa6 +fed0ff37 +01fe0225 +fd54ffdb +0238fdf6 +fcc501a9 +0539febf +fe650312 +fd48fdc2 +00e8fd85 +030201ed +fc0e0245 +01ccfe0e +0067ff97 +ff4700bb // 0x00000670 -0191fce8 -fde605a2 -0277faf3 -fd8f006b -001600a3 -0175fe9e -01320222 -ff08fc3f -fe2c067d -00b6fc18 -0116008a -feb00062 -00f1ffc3 -0094001f -ff550029 -0055ff8e +ffb3ffc8 +00bc0086 +00b900cc +fd9cfe44 +01790040 +005f0115 +006a00be +fd94fd5c +ff6502c4 +0386fc28 +fe0b03ba +0230fc74 +fdff0504 +000bfd35 +00e20114 +ffb4ff9c // 0x00000680 -ff95003a -008bffec -ff17fffb -00efffd4 -ff5d01a4 -0226fc4c -fddd020f -008101af -fe7bfcd3 -0214028b -fe67fece -02020120 -0008fd51 -fcd901e8 -0255fe91 -0004fff0 +00320039 +0004ffb1 +ff78feef +013b0348 +ff1afcec +fffd00c2 +ff630102 +01aafc7e +00f00631 +fc6afa29 +004a0139 +028f011e +fe1c0212 +00d5fc90 +ffeb01fe +ffe4ff60 // 0x00000690 -ff3d026e -02f301bc -f9e3fadb -05210186 -fcef0192 -0110fc7e -016103b3 -fd73fce3 -01eb04f9 -feb2fcf1 -fffb004c -01eaffca -fe7c0055 -005d0042 -0019ffed -004cffa2 +ffa80009 +ff08fff5 +03430062 +fc340019 +003fff76 +013a01c4 +fea0fbd5 +01230121 +00d00433 +fd5afbcd +014500dc +ff94fed9 +011502fa +ff74ff5e +feecff71 +01150029 // 0x000006a0 -ffbeffbe -ffdb0062 -ffb6ff89 -00e1fff2 -00890151 -ff16fe27 -ffa30056 -00c80080 -fdd5ff6a -029000cb -fd72ff38 -03ed04c0 -fcf7f839 -00c703dc -00f2ffa7 -ffedfef4 +ffda006b +0053fe6b +ff98021b +007dff1c +ff67ff0c +0128027c +fe01fc44 +0172017f +015a0165 +fb8d007b +032afc67 +ffc30312 +fff9ff24 +ffc80142 +ffd1fe1a +005600cf // 0x000006b0 -ff84ffda -fe7101ee -019a022b -ff95fb6e -ff470029 -00e2ffcb -ff250232 -0034ffd4 -00e9ff86 -fea80011 -01560108 -ff2dffa0 -ffc9ff95 -017dffbe -feaefffd -00b70050 +003bffdf +ffa60087 +01cdff59 +fe920009 +ff920039 +ffc80396 +feedf9a7 +03780261 +faf1fed5 +0660024d +fbddfd65 +ffe402bd +00a2fdeb +00860146 +0039000b +fefeff91 // 0x000006c0 -00410077 -ffccff9a -fffaffc1 -ffbe0091 -00d60006 -ffb7ff78 -ff6affe7 -00330060 -0121000e -feb7fefc -0018020b -fe1cffb1 -01fefdc7 -005701b3 -ffc8ffc4 -033ffea0 +ffbfffac +0045ffb2 +ffff0064 +ffe0ff3d +011e0086 +fd1f020d +020dfbc1 +01d901ac +fd81008e +fde70086 +028bfe5a +00e00241 +fe0efe1c +0151018b +ff65fee5 +006300c6 // 0x000006d0 -f9170255 -056efd6a -fb1c048d -035efc37 -ff3800a4 -002100dc -029efe4d -fb850144 -023f012e -ff7ffd50 -00aa02c7 -ffc0feab -ffdc008f -0061ff31 -007800c0 -ff51ff30 +ffe40064 +ff02ffef +01b4fff0 +fe27006f +01befe8a +fe4301de +0082ff7c +02feff88 +fbfa006c +01100251 +ff32feee +0025fc75 +01940316 +ff4f0066 +ffd8ffa6 +0062ff80 // 0x000006e0 -ff60ffd2 -00a40026 -ff07ffed -01a70043 -fe8bffcc -01c2feb5 -fec300e6 -00b5015f -fe83fe2b -fffb00bf -ff97fea3 -0511022b -f861fe1f -07c50026 -f9dcfe9a -02e6039e +0048003b +0006ffdd +ff9afece +01ae027d +fc7cfef1 +041ffea8 +fcd1ff47 +027a0274 +fd70fe9d +fec601d9 +041cfd64 +fdc20111 +ff8402c7 +017dfc7a +ff9101d7 +ffdeff46 // 0x000006f0 -fe5eff34 -00cafcc6 -ff5f04fb -ff53fc75 -0247ffea -ff74ff27 -fd770366 -0255fd3f -004f02e3 -fcc3fe0d -01cf0145 -01f9ffa9 -fe7dffa7 -00990056 -ff2effaa -00fc0038 +001affc7 +ffd400be +00eeff2b +fe8e00b3 +ffa0fe5d +01cb026f +ff45ff77 +fbd8feb3 +03fafec9 +fede032c +00eefc43 +fe3803cf +0018fd1f +012b039f +ff1bfd9f +ffe200a3 // 0x00000700 -ffd5007c -0030ff5a -ff9b0092 -0013ff42 -ff2d027a -036dfb56 -fcc303da -0110ff93 -fed9fe91 -0011021c -ffe1fd16 -0354073a -fd15f76b -00a6025c -0196ffd2 -ff50feb0 +ffeefff9 +00110047 +ffd1fddd +00ad03bd +fe72fe00 +033f014c +fb42fc6f +04c00134 +fe260329 +fd81fe57 +02e9fe8d +ff2dfed7 +ffde058e +0017fb2e +000801f7 +0016ffa0 // 0x00000710 -fe53037a -0134fefc -fe0dff60 -001b015c -01c9fd72 -ff6701a6 -0011006a -0024fc25 -00a706c5 -fec7fcd2 -005fff44 -00caffdc -ff3d00dd -000aff9c -003e004e -fff0ff7c +ffe40008 +feeeff75 +03410185 +fc92fff7 +ffb5fe9a +00050495 +0090f960 +019d008d +fe8c033a +fe7aff33 +0185febd +00a2ff01 +ffeb03e4 +ffbffd7f +ff520096 +009bfff7 // 0x00000720 -0004003a -0019ffe4 -fecb004b -017bff1f -fea40120 -02acfed8 -fcc302d2 -0300fbd7 -fcd602bd -0479ffed -fa93fd24 -0144052f -0113fb1f -002901bb -0077011c -0072fe90 +004a001f +ff09ff1b +01e00008 +fd87006a +0267008a +fd6400bf +0166fc59 +00dd0262 +ffd20163 +fcfbff19 +03a6fe18 +fe3100e2 +ffc9029c +01b0fd45 +fe9800c7 +00830032 // 0x00000730 -ff4c0146 -0017ff5c -fe4b0135 -01dbfee5 -ff62fd92 -002c01c8 -ff2f01f8 -006afca1 -010604a3 -fe37fd97 -021bffa0 -ffe2fffd -feab00af -0117ff19 -ffb30096 -ffe0ff70 +fff2ffef +ffa40060 +001b0043 +00f70002 +ffd401ba +fab5fe4a +03f8feb2 +00dd0174 +feb2ff25 +00c4027c +fe3ffc07 +0101020a +0020017e +00c7fe4e +fef600f0 +0037ff74 // 0x00000740 -ffcd0048 -0069ffbd -ff3600ba -009cfe83 -fee20260 -01ddfd82 -ff8501df -ff7dff24 -0110001e -ff2501d5 -fe43fa44 -011d0940 -00d7f8ef -01feffa3 -fef00279 -ffdcfff3 +001effa1 +ff6d000a +fff1ff24 +00ce0103 +ffc0019a +0026fe9a +ff32fb41 +028e06e9 +fcf2fc57 +ffb501c2 +022bfd70 +fe6a0231 +00d8ffd2 +ffb80072 +ff9afe97 +00aa013b // 0x00000750 -fd6dff86 -02e5fe69 -fc9e01ce -017a0063 -ff70fdd0 -00b302bc -025900e5 -fd89fb9a -00da03d8 -ff71fdb1 -0071020c -000dfe5e -feeb00c5 -0136fefb -ffb20133 -fff6ff53 +ffed000a +ffedff7e +004a01ab +ff7fff0e +016d002a +f9d4010c +07aafd0f +fd12014a +00bbffa0 +fdcf0132 +feb6ffbb +054ffe10 +fcdf01fc +0104fffc +ff22ffeb +002cfff0 // 0x00000760 -ffa20062 -0025ffb4 -ff4cffd3 -019e0052 -fda6018f -02e8fd07 -fe19021e -ffeafed2 -ff4e0010 -02f201cd -fe1dfd46 -01860302 -fdd3fe1c -00b2fedf -fe4e01b8 -03b0fe1a +001b001a +0134ff84 +fe4cffd2 +0002016b +0172fdf7 +00b801e2 +fcb5ff7b +0234fe19 +fef90194 +016400c6 +ffb20000 +fe96fe3d +009a0043 +00d40180 +ff8dff63 +ffb0fffb // 0x00000770 -fd320270 -0139fce2 -fe2001f9 -01a002a4 -003cfbaf -fe160341 -003d0060 -02eefcf6 -fcce02be -02e0fd95 -ff4301f6 -ffecfe28 -feb3013e -0138ffc9 -ff58006a -0090ff36 +ffbcffac +ff460028 +018f010c +fe4cfe4b +fffa02e9 +ffd5fdde +0065fe63 +000b02f2 +0062fdc2 +fd2603a8 +0035faf4 +036a0399 +fdb00011 +00fbfe42 +fe4f0165 +0103ffaa // 0x00000780 -ffb7002c -006ffffc -ff370067 -0089fedf -005802ad -ffb3fb0c -ff8b038c -0127ff36 -fefe00b8 -008200d7 -fd65fd94 -070c0507 -f9d4f7e1 -02c703d1 -fe110197 -0214fc5f +008a004b +ff7cffba +fedbffbf +02b80008 +fe430207 +0139fdfd +ff06fe77 +ff02013a +013002d7 +00a2fa9e +ffa1050f +fd00fcf6 +0313014f +0029ffa7 +fee600bb +004eff54 // 0x00000790 -ff010168 -fef50222 -fee7fb7f -02ab03a7 -ff3c0013 -ff3dfee0 -feab0280 -0101fc38 -01d60344 -feb2fdd3 -006900c6 -ffe80013 -000400d7 -fff1fef3 -ffd50085 -005cffab +fff0fff7 +ff6c0013 +02a7ff51 +fd460188 +004bff26 +00b604a1 +fd26f7b9 +03e10465 +fd2afee5 +fefe001b +0209fea3 +ff0e0234 +0167ff6a +fe58ffdd +00f6004f +ff8b000b // 0x000007a0 -ffc80047 -0048ff40 -ffca00f1 -ffd8ff7d -00690135 -00d3fd5f -ff0e0096 -006e0014 -ff570267 -fff5fd7a -fef600a9 -00e80241 -0109fb0a -fee501a8 -009001cf -00d8ff87 +ffd0ffca +000800b8 +ff0aff01 +028bffde +fd8c0228 +ffb9ff48 +0164fca1 +00cc037a +ffb0ffc4 +fc28fdea +0316037f +00a1fc9c +00100286 +fe9bfe66 +00a000eb +0044ff74 // 0x000007b0 -fe50000f -0284feb0 -fa9a0265 -02cefd17 -036f020d -f9a1ff85 -0544feb6 -fbbc010c -03f90253 -ff07fdba -fe7e00a9 -0106ff6b -005700ec -ff3fff50 -00b60055 -fffaffb9 +fff6ffc1 +ff230058 +02b5007b +fd06fe72 +01f6011c +fdc1026c +0120fa7a +007b045a +00eafdd7 +fcb102ae +021bfced +fe8cfff0 +03fa02c0 +fcafff26 +0100ffe2 +003f0044 // 0x000007c0 -ff710080 -00d2ff05 -fe670104 -0213ff44 -fe2e01be -02c5fda7 -fda7003d -ff2f00cf -0139fdce -010002f8 -fd7fff1f -011500ee -fdfafd2d -04fa02aa -fcedff82 -00ecfe81 +fff4ffe0 +0067ffca +ff74003a +feef00cc +03b9fe4a +fba302e4 +0304fb52 +fd930292 +038c01c0 +fc2dfe36 +0064fe24 +02290332 +fee3fe56 +ffc10180 +0030fea0 +0035007c // 0x000007d0 -004bff7e -ff22034d -fe51fda2 -017f004a -fe6a00e8 -01e3fd5f -0001030b -ff7ffefd -ff370078 -0124002a -0071007b -feddff6c -00e20019 -ffe6ff34 -ffd300e6 -0092ff53 +005eff5f +fee800b1 +023900f0 +fcd0fdd9 +013000a5 +ffa10032 +ff650149 +01b1fe0c +fdceffc5 +00800039 +00a10076 +ffaaffef +ff0400ff +011fff04 +00310001 +ff9d0094 // 0x000007e0 -0027002d -ff93ffd2 -fff3ffce -00d1006e -ffe4ff9d -ff7e0140 -0081fe46 -fe66006f -0261ffff -ff2affc1 -ff3affa4 -ff560297 -ffaafe2d -01e5fe96 -00a700ea -ff53ffa8 +ff5cffff +00adff00 +003001c7 +fe85fe80 +02340003 +ff280263 +fda6fb46 +03c003ae +ffe6fd29 +fb4103fa +02b6fc75 +0111012c +ff020055 +004a0087 +fef4ff5e +01520062 // 0x000007f0 -fbab005b -06010092 -fbf70488 -01fff960 -fdac034b -0408feda -fde1fece -009a00f7 -fe5900ad -01e2003b -ffc0ff7e -fef6ffff -00ea0177 -ffb5fd68 -0093019a -ffa1ff46 +ffe3ff95 +ffe300c2 +ffc9ffce +ffb0fed6 +022a0084 +fc3f0040 +030500f0 +0071fd0a +fbc7037d +0489ff40 +fdf10228 +ff40fbd6 +ffe0035e +0001fd86 +018d0156 +ff13ffe2 diff --git a/9_Firmware/9_2_FPGA/tb/tb_doppler_cosim.v b/9_Firmware/9_2_FPGA/tb/tb_doppler_cosim.v index 0f1c6ee..b90dbda 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_doppler_cosim.v +++ b/9_Firmware/9_2_FPGA/tb/tb_doppler_cosim.v @@ -6,8 +6,8 @@ * * Tests the complete Doppler processing pipeline: * - Accumulates 32 chirps x 64 range bins into BRAM - * - Processes each range bin: Hamming window -> 32-pt FFT - * - Outputs 2048 samples (64 range bins x 32 Doppler bins) + * - Processes each range bin: Hamming window -> dual 16-pt FFT (staggered PRF) + * - Outputs 2048 samples (64 range bins x 32 packed Doppler bins) * * Validates: * 1. FSM state transitions (IDLE -> ACCUMULATE -> LOAD_FFT -> ... -> OUTPUT) @@ -20,10 +20,10 @@ * RTL output written to: tb/cosim/rtl_doppler_.csv * RTL FFT inputs written: tb/cosim/rtl_doppler_fft_in_.csv * - * Compile (SIMULATION branch — uses behavioral xfft_32/fft_engine): + * Compile (SIMULATION branch — uses behavioral xfft_16/fft_engine): * iverilog -g2001 -DSIMULATION \ * -o tb/tb_doppler_cosim.vvp \ - * tb/tb_doppler_cosim.v doppler_processor.v xfft_32.v fft_engine.v + * tb/tb_doppler_cosim.v doppler_processor.v xfft_16.v fft_engine.v * * Scenarios (use -D flags): * default: stationary target @@ -37,7 +37,7 @@ module tb_doppler_cosim; // Parameters // ============================================================================ localparam CLK_PERIOD = 10.0; // 100 MHz -localparam DOPPLER_FFT = 32; +localparam DOPPLER_FFT = 32; // Total packed Doppler bins (2 sub-frames x 16-pt FFT) localparam RANGE_BINS = 64; localparam CHIRPS = 32; localparam TOTAL_INPUTS = CHIRPS * RANGE_BINS; // 2048 @@ -193,7 +193,7 @@ initial begin $display("Doppler Processor Co-Sim Testbench"); $display("Scenario: %0s", SCENARIO); $display("Input samples: %0d (32 chirps x 64 range bins)", TOTAL_INPUTS); - $display("Expected outputs: %0d (64 range bins x 32 doppler bins)", + $display("Expected outputs: %0d (64 range bins x 32 packed Doppler bins, dual 16-pt FFT)", TOTAL_OUTPUTS); $display("============================================================"); diff --git a/9_Firmware/9_2_FPGA/tb/tb_doppler_realdata.v b/9_Firmware/9_2_FPGA/tb/tb_doppler_realdata.v index d2c77ec..e19e904 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_doppler_realdata.v +++ b/9_Firmware/9_2_FPGA/tb/tb_doppler_realdata.v @@ -17,7 +17,7 @@ * Compile: * iverilog -Wall -DSIMULATION -g2012 \ * -o tb/tb_doppler_realdata.vvp \ - * tb/tb_doppler_realdata.v doppler_processor.v xfft_32.v fft_engine.v + * tb/tb_doppler_realdata.v doppler_processor.v xfft_16.v fft_engine.v * * Run from: 9_Firmware/9_2_FPGA/ * vvp tb/tb_doppler_realdata.vvp @@ -29,7 +29,7 @@ module tb_doppler_realdata; // PARAMETERS // ============================================================================ localparam CLK_PERIOD = 10.0; // 100 MHz -localparam DOPPLER_FFT = 32; +localparam DOPPLER_FFT = 32; // Total packed Doppler bins (2 sub-frames x 16-pt FFT) localparam RANGE_BINS = 64; localparam CHIRPS = 32; localparam TOTAL_INPUTS = CHIRPS * RANGE_BINS; // 2048 diff --git a/9_Firmware/9_2_FPGA/tb/tb_fft_engine.v b/9_Firmware/9_2_FPGA/tb/tb_fft_engine.v index 6c45921..de2c712 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_fft_engine.v +++ b/9_Firmware/9_2_FPGA/tb/tb_fft_engine.v @@ -4,7 +4,7 @@ * tb_fft_engine.v * * Testbench for the synthesizable FFT engine. - * Tests with N=32 first (fast), then validates key properties. + * Tests with N=16 (matching the dual-16 Doppler architecture). * * Test Groups: * 1. Impulse response: FFT of delta[0] should be all 1s @@ -19,10 +19,10 @@ module tb_fft_engine; // ============================================================================ -// PARAMETERS — test with 32-pt for speed +// PARAMETERS — test with 16-pt to match dual-FFT Doppler architecture // ============================================================================ -localparam N = 32; -localparam LOG2N = 5; +localparam N = 16; +localparam LOG2N = 4; localparam DATA_W = 16; localparam INT_W = 32; localparam TW_W = 16; @@ -47,7 +47,7 @@ fft_engine #( .DATA_W(DATA_W), .INTERNAL_W(INT_W), .TWIDDLE_W(TW_W), - .TWIDDLE_FILE("fft_twiddle_32.mem") + .TWIDDLE_FILE("fft_twiddle_16.mem") ) dut ( .clk(clk), .reset_n(reset_n), diff --git a/9_Firmware/9_2_FPGA/tb/tb_fullchain_mti_cfar_realdata.v b/9_Firmware/9_2_FPGA/tb/tb_fullchain_mti_cfar_realdata.v index 1b56f24..51e1d19 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_fullchain_mti_cfar_realdata.v +++ b/9_Firmware/9_2_FPGA/tb/tb_fullchain_mti_cfar_realdata.v @@ -9,7 +9,7 @@ * * range_bin_decimator (peak detection, 1024->64) * -> mti_canceller (2-pulse, mti_enable=1) - * -> doppler_processor_optimized (Hamming + 32-pt FFT) + * -> doppler_processor_optimized (Hamming + dual 16-pt FFT) * -> DC notch filter (width=2, inline logic) * -> cfar_ca (CA mode, guard=2, train=8, alpha=0x30) * @@ -41,7 +41,7 @@ * -o tb/tb_fullchain_mti_cfar_realdata.vvp \ * tb/tb_fullchain_mti_cfar_realdata.v \ * range_bin_decimator.v mti_canceller.v doppler_processor.v \ - * xfft_32.v fft_engine.v cfar_ca.v + * xfft_16.v fft_engine.v cfar_ca.v * * Run from: 9_Firmware/9_2_FPGA/ * vvp tb/tb_fullchain_mti_cfar_realdata.vvp @@ -375,7 +375,7 @@ initial begin $display(" Full-Chain Real-Data Co-Simulation (MTI + CFAR)"); $display(" range_bin_decimator (peak, 1024->64)"); $display(" -> mti_canceller (2-pulse, enable=1)"); - $display(" -> doppler_processor_optimized (Hamming + 32-pt FFT)"); + $display(" -> doppler_processor_optimized (Hamming + dual 16-pt FFT)"); $display(" -> DC notch filter (width=%0d)", DC_NOTCH_WIDTH); $display(" -> cfar_ca (CA, guard=2, train=8, alpha=0x30)"); $display(" ADI CN0566 Phaser 10.525 GHz X-band FMCW"); diff --git a/9_Firmware/9_2_FPGA/tb/tb_fullchain_realdata.v b/9_Firmware/9_2_FPGA/tb/tb_fullchain_realdata.v index 3c279b7..af6003f 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_fullchain_realdata.v +++ b/9_Firmware/9_2_FPGA/tb/tb_fullchain_realdata.v @@ -7,7 +7,7 @@ * (post-range-FFT, 32 chirps x 1024 bins) through: * * range_bin_decimator (peak detection, 1024→64) - * → doppler_processor_optimized (Hamming + 32-pt FFT) + * → doppler_processor_optimized (Hamming + dual 16-pt FFT) * * and compares the Doppler output bit-for-bit against the Python golden * reference that models the same chain (golden_reference.py). @@ -27,7 +27,7 @@ * iverilog -Wall -DSIMULATION -g2012 \ * -o tb/tb_fullchain_realdata.vvp \ * tb/tb_fullchain_realdata.v \ - * range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v + * range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v * * Run from: 9_Firmware/9_2_FPGA/ * vvp tb/tb_fullchain_realdata.vvp @@ -243,7 +243,7 @@ initial begin $display("============================================================"); $display(" Full-Chain Real-Data Co-Simulation"); $display(" range_bin_decimator (peak, 1024->64)"); - $display(" -> doppler_processor_optimized (Hamming + 32-pt FFT)"); + $display(" -> doppler_processor_optimized (Hamming + dual 16-pt FFT)"); $display(" ADI CN0566 Phaser 10.525 GHz X-band FMCW"); $display(" Input: %0d chirps x %0d range FFT bins = %0d samples", CHIRPS, INPUT_BINS, TOTAL_INPUT_SAMPLES); diff --git a/9_Firmware/9_2_FPGA/tb/tb_system_e2e.v b/9_Firmware/9_2_FPGA/tb/tb_system_e2e.v index 77166c4..7a075c7 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_system_e2e.v +++ b/9_Firmware/9_2_FPGA/tb/tb_system_e2e.v @@ -34,7 +34,7 @@ * cdc_modules.v fir_lowpass.v ddc_input_interface.v \ * chirp_memory_loader_param.v latency_buffer.v \ * matched_filter_multi_segment.v matched_filter_processing_chain.v \ - * range_bin_decimator.v doppler_processor.v xfft_32.v fft_engine.v \ + * range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v \ * usb_data_interface.v edge_detector.v radar_mode_controller.v * * Run: diff --git a/9_Firmware/9_2_FPGA/tb/tb_xfft_32.v b/9_Firmware/9_2_FPGA/tb/tb_xfft_32.v deleted file mode 100644 index ed176cf..0000000 --- a/9_Firmware/9_2_FPGA/tb/tb_xfft_32.v +++ /dev/null @@ -1,355 +0,0 @@ -`timescale 1ns / 1ps - -/** - * tb_xfft_32.v - * - * Testbench for xfft_32 AXI-Stream FFT wrapper. - * Verifies the wrapper correctly interfaces with fft_engine via AXI-Stream. - * - * Test Groups: - * 1. Impulse response (all output bins = input amplitude) - * 2. DC input (bin 0 = A*N, rest ~= 0) - * 3. Single tone detection - * 4. AXI-Stream handshake correctness (tvalid, tlast, tready) - * 5. Back-to-back transforms (no state leakage) - */ - -module tb_xfft_32; - -// ============================================================================ -// PARAMETERS -// ============================================================================ -localparam N = 32; -localparam CLK_PERIOD = 10; - -// ============================================================================ -// SIGNALS -// ============================================================================ -reg aclk, aresetn; -reg [7:0] cfg_tdata; -reg cfg_tvalid; -wire cfg_tready; -reg [31:0] din_tdata; -reg din_tvalid; -reg din_tlast; -wire [31:0] dout_tdata; -wire dout_tvalid; -wire dout_tlast; -reg dout_tready; - -// ============================================================================ -// DUT -// ============================================================================ -xfft_32 dut ( - .aclk(aclk), - .aresetn(aresetn), - .s_axis_config_tdata(cfg_tdata), - .s_axis_config_tvalid(cfg_tvalid), - .s_axis_config_tready(cfg_tready), - .s_axis_data_tdata(din_tdata), - .s_axis_data_tvalid(din_tvalid), - .s_axis_data_tlast(din_tlast), - .m_axis_data_tdata(dout_tdata), - .m_axis_data_tvalid(dout_tvalid), - .m_axis_data_tlast(dout_tlast), - .m_axis_data_tready(dout_tready) -); - -// ============================================================================ -// CLOCK -// ============================================================================ -initial aclk = 0; -always #(CLK_PERIOD/2) aclk = ~aclk; - -// ============================================================================ -// PASS/FAIL TRACKING -// ============================================================================ -integer pass_count, fail_count; - -task check; - input cond; - input [512*8-1:0] label; - begin - if (cond) begin - $display(" [PASS] %0s", label); - pass_count = pass_count + 1; - end else begin - $display(" [FAIL] %0s", label); - fail_count = fail_count + 1; - end - end -endtask - -// ============================================================================ -// OUTPUT CAPTURE -// ============================================================================ -reg signed [15:0] out_re [0:N-1]; -reg signed [15:0] out_im [0:N-1]; -integer out_idx; -reg got_tlast; -integer tlast_count; - -// ============================================================================ -// HELPER TASKS -// ============================================================================ - -task do_reset; - begin - aresetn = 0; - cfg_tdata = 0; - cfg_tvalid = 0; - din_tdata = 0; - din_tvalid = 0; - din_tlast = 0; - dout_tready = 1; - repeat(5) @(posedge aclk); - aresetn = 1; - repeat(2) @(posedge aclk); - end -endtask - -// Send config (forward FFT: tdata[0]=1) -// Waits for cfg_tready (wrapper in S_IDLE) before sending -task send_config; - input [7:0] cfg; - integer wait_cnt; - begin - // Wait for wrapper to be ready (S_IDLE) - wait_cnt = 0; - while (!cfg_tready && wait_cnt < 5000) begin - @(posedge aclk); - wait_cnt = wait_cnt + 1; - end - cfg_tdata = cfg; - cfg_tvalid = 1; - @(posedge aclk); - cfg_tvalid = 0; - cfg_tdata = 0; - end -endtask - -// Feed N samples: each sample is {im[15:0], re[15:0]} -// in_re_arr and in_im_arr must be pre-loaded -reg signed [15:0] feed_re [0:N-1]; -reg signed [15:0] feed_im [0:N-1]; - -task feed_data; - integer i; - begin - for (i = 0; i < N; i = i + 1) begin - din_tdata = {feed_im[i], feed_re[i]}; - din_tvalid = 1; - din_tlast = (i == N - 1) ? 1 : 0; - @(posedge aclk); - end - din_tvalid = 0; - din_tlast = 0; - din_tdata = 0; - end -endtask - -// Capture N output samples -task capture_output; - integer timeout; - begin - out_idx = 0; - got_tlast = 0; - tlast_count = 0; - timeout = 0; - while (out_idx < N && timeout < 5000) begin - @(posedge aclk); - if (dout_tvalid && dout_tready) begin - out_re[out_idx] = dout_tdata[15:0]; - out_im[out_idx] = dout_tdata[31:16]; - if (dout_tlast) begin - got_tlast = 1; - tlast_count = tlast_count + 1; - end - out_idx = out_idx + 1; - end - timeout = timeout + 1; - end - end -endtask - -// ============================================================================ -// VCD -// ============================================================================ -initial begin - $dumpfile("tb_xfft_32.vcd"); - $dumpvars(0, tb_xfft_32); -end - -// ============================================================================ -// MAIN TEST -// ============================================================================ -integer i; -reg signed [31:0] err; -integer max_err; -integer max_mag_bin; -reg signed [31:0] max_mag, mag; -real angle; - -initial begin - pass_count = 0; - fail_count = 0; - - $display("============================================================"); - $display(" xfft_32 AXI-Stream Wrapper Testbench"); - $display("============================================================"); - - do_reset; - - // ================================================================ - // TEST 1: Impulse Response - // ================================================================ - $display(""); - $display("--- Test 1: Impulse Response ---"); - - for (i = 0; i < N; i = i + 1) begin - feed_re[i] = (i == 0) ? 16'sd1000 : 16'sd0; - feed_im[i] = 16'sd0; - end - - send_config(8'h01); // Forward FFT - feed_data; - capture_output; - - check(out_idx == N, "Received N output samples"); - check(got_tlast == 1, "Got tlast on output"); - - max_err = 0; - for (i = 0; i < N; i = i + 1) begin - err = out_re[i] - 1000; - if (err < 0) err = -err; - if (err > max_err) max_err = err; - err = out_im[i]; - if (err < 0) err = -err; - if (err > max_err) max_err = err; - end - $display(" Impulse max error: %0d", max_err); - check(max_err < 10, "Impulse: all bins ~= 1000"); - - // ================================================================ - // TEST 2: DC Input - // ================================================================ - $display(""); - $display("--- Test 2: DC Input ---"); - - for (i = 0; i < N; i = i + 1) begin - feed_re[i] = 16'sd100; - feed_im[i] = 16'sd0; - end - - send_config(8'h01); - feed_data; - capture_output; - - $display(" DC bin[0] = %0d + j%0d (expect ~3200)", out_re[0], out_im[0]); - check(out_re[0] >= 3100 && out_re[0] <= 3300, "DC: bin 0 ~= 3200 (5% tol)"); - - max_err = 0; - for (i = 1; i < N; i = i + 1) begin - err = out_re[i]; if (err < 0) err = -err; - if (err > max_err) max_err = err; - err = out_im[i]; if (err < 0) err = -err; - if (err > max_err) max_err = err; - end - $display(" DC max non-DC: %0d", max_err); - check(max_err < 25, "DC: non-DC bins ~= 0"); - - // ================================================================ - // TEST 3: Single Tone (bin 4) - // ================================================================ - $display(""); - $display("--- Test 3: Single Tone (bin 4) ---"); - - for (i = 0; i < N; i = i + 1) begin - angle = 6.28318530718 * 4.0 * i / 32.0; - feed_re[i] = $rtoi($cos(angle) * 1000.0); - feed_im[i] = 16'sd0; - end - - send_config(8'h01); - feed_data; - capture_output; - - max_mag = 0; - max_mag_bin = 0; - for (i = 0; i < N; i = i + 1) begin - mag = out_re[i] * out_re[i] + out_im[i] * out_im[i]; - if (mag > max_mag) begin - max_mag = mag; - max_mag_bin = i; - end - end - $display(" Tone peak bin: %0d (expect 4 or 28)", max_mag_bin); - check(max_mag_bin == 4 || max_mag_bin == 28, "Tone: peak at bin 4 or 28"); - - // ================================================================ - // TEST 4: Back-to-back transforms - // ================================================================ - $display(""); - $display("--- Test 4: Back-to-Back Transforms ---"); - - // First: impulse - for (i = 0; i < N; i = i + 1) begin - feed_re[i] = (i == 0) ? 16'sd500 : 16'sd0; - feed_im[i] = 16'sd0; - end - send_config(8'h01); - feed_data; - capture_output; - check(out_idx == N, "Back-to-back 1st: got N outputs"); - - // Second: DC immediately after - for (i = 0; i < N; i = i + 1) begin - feed_re[i] = 16'sd50; - feed_im[i] = 16'sd0; - end - send_config(8'h01); - feed_data; - capture_output; - check(out_idx == N, "Back-to-back 2nd: got N outputs"); - $display(" 2nd transform bin[0] = %0d (expect ~1600)", out_re[0]); - check(out_re[0] >= 1500 && out_re[0] <= 1700, "Back-to-back 2nd: bin 0 ~= 1600"); - - // ================================================================ - // TEST 5: Zero input - // ================================================================ - $display(""); - $display("--- Test 5: Zero Input ---"); - - for (i = 0; i < N; i = i + 1) begin - feed_re[i] = 16'sd0; - feed_im[i] = 16'sd0; - end - send_config(8'h01); - feed_data; - capture_output; - - max_err = 0; - for (i = 0; i < N; i = i + 1) begin - err = out_re[i]; if (err < 0) err = -err; - if (err > max_err) max_err = err; - err = out_im[i]; if (err < 0) err = -err; - if (err > max_err) max_err = err; - end - check(max_err == 0, "Zero input: all outputs = 0"); - - // ================================================================ - // SUMMARY - // ================================================================ - $display(""); - $display("============================================================"); - $display(" RESULTS: %0d/%0d passed", pass_count, pass_count + fail_count); - if (fail_count == 0) - $display(" ALL TESTS PASSED"); - else - $display(" SOME TESTS FAILED"); - $display("============================================================"); - - $finish; -end - -endmodule diff --git a/9_Firmware/9_2_FPGA/xfft_16.v b/9_Firmware/9_2_FPGA/xfft_16.v index 7776e0a..382167e 100644 --- a/9_Firmware/9_2_FPGA/xfft_16.v +++ b/9_Firmware/9_2_FPGA/xfft_16.v @@ -5,7 +5,7 @@ // Wraps the synthesizable fft_engine (radix-2 DIT) with the AXI-Stream port // interface expected by the doppler_processor dual-FFT architecture. // -// Identical interface to xfft_32.v but with N=16. +// Used by the doppler_processor dual-FFT architecture (2 x 16-pt sub-frames). // // Data format: {Q[15:0], I[15:0]} packed 32-bit. // Config tdata[0]: 1 = forward FFT, 0 = inverse FFT. diff --git a/9_Firmware/9_2_FPGA/xfft_32.v b/9_Firmware/9_2_FPGA/xfft_32.v deleted file mode 100644 index cd1932b..0000000 --- a/9_Firmware/9_2_FPGA/xfft_32.v +++ /dev/null @@ -1,278 +0,0 @@ -`timescale 1ns / 1ps -// ============================================================================ -// xfft_32.v — 32-point FFT with AXI-Stream interface -// ============================================================================ -// Wraps the synthesizable fft_engine (radix-2 DIT) with the AXI-Stream port -// interface expected by doppler_processor.v. -// -// Port interface matches the Xilinx LogiCORE IP Fast Fourier Transform -// (AXI-Stream variant) as instantiated in doppler_processor.v. -// -// Data format: {Q[15:0], I[15:0]} packed 32-bit. -// Config tdata[0]: 1 = forward FFT, 0 = inverse FFT. -// ============================================================================ - -module xfft_32 ( - input wire aclk, - input wire aresetn, - - // Configuration channel (AXI-Stream slave) - input wire [7:0] s_axis_config_tdata, - input wire s_axis_config_tvalid, - output wire s_axis_config_tready, - - // Data input channel (AXI-Stream slave) - input wire [31:0] s_axis_data_tdata, - input wire s_axis_data_tvalid, - input wire s_axis_data_tlast, - - // Data output channel (AXI-Stream master) - output wire [31:0] m_axis_data_tdata, - output wire m_axis_data_tvalid, - output wire m_axis_data_tlast, - input wire m_axis_data_tready -); - -// ============================================================================ -// PARAMETERS -// ============================================================================ -localparam N = 32; -localparam LOG2N = 5; - -// ============================================================================ -// INTERNAL SIGNALS -// ============================================================================ - -// FSM states -localparam [2:0] S_IDLE = 3'd0, - S_CONFIG = 3'd1, // Latch config (fwd/inv) - S_FEED = 3'd2, // Feed input to FFT engine - S_WAIT = 3'd3, // Wait for FFT to complete - S_OUTPUT = 3'd4; // Stream output - -reg [2:0] state; - -// Configuration -reg inverse_reg; - -// Input buffering -reg signed [15:0] in_buf_re [0:N-1]; -reg signed [15:0] in_buf_im [0:N-1]; -reg [5:0] in_count; // 0..31 for loading, extra bit for overflow check - -// Output buffering -reg signed [15:0] out_buf_re [0:N-1]; -reg signed [15:0] out_buf_im [0:N-1]; -reg [5:0] out_count; -reg [5:0] out_total; // counts how many outputs captured from engine - -// FFT engine interface -reg fft_start; -reg fft_inverse; -reg signed [15:0] fft_din_re, fft_din_im; -reg fft_din_valid; -wire signed [15:0] fft_dout_re, fft_dout_im; -wire fft_dout_valid; -wire fft_busy; -wire fft_done; - -// Feed counter for streaming into engine -reg [5:0] feed_count; - -// ============================================================================ -// FFT ENGINE INSTANCE -// ============================================================================ -fft_engine #( - .N(N), - .LOG2N(LOG2N), - .DATA_W(16), - .INTERNAL_W(32), - .TWIDDLE_W(16), - .TWIDDLE_FILE("fft_twiddle_32.mem") -) fft_core ( - .clk(aclk), - .reset_n(aresetn), - .start(fft_start), - .inverse(fft_inverse), - .din_re(fft_din_re), - .din_im(fft_din_im), - .din_valid(fft_din_valid), - .dout_re(fft_dout_re), - .dout_im(fft_dout_im), - .dout_valid(fft_dout_valid), - .busy(fft_busy), - .done(fft_done) -); - -// ============================================================================ -// AXI-STREAM OUTPUTS -// ============================================================================ - -// Config is accepted when idle -assign s_axis_config_tready = (state == S_IDLE); - -// Output data: {Q, I} packed -assign m_axis_data_tdata = {out_buf_im[out_count[4:0]], out_buf_re[out_count[4:0]]}; -assign m_axis_data_tvalid = (state == S_OUTPUT) && (out_count < N); -assign m_axis_data_tlast = (state == S_OUTPUT) && (out_count == N - 1); - -// ============================================================================ -// BUFFER WRITE LOGIC — separate always block, NO async reset -// Allows Vivado to infer distributed RAM instead of dissolving into registers. -// ============================================================================ -// Input buffer write enable -reg in_buf_we; -reg [4:0] in_buf_waddr; -reg signed [15:0] in_buf_wdata_re, in_buf_wdata_im; - -// Output buffer write enable -reg out_buf_we; -reg [4:0] out_buf_waddr; -reg signed [15:0] out_buf_wdata_re, out_buf_wdata_im; - -always @(posedge aclk) begin - if (in_buf_we) begin - in_buf_re[in_buf_waddr] <= in_buf_wdata_re; - in_buf_im[in_buf_waddr] <= in_buf_wdata_im; - end - if (out_buf_we) begin - out_buf_re[out_buf_waddr] <= out_buf_wdata_re; - out_buf_im[out_buf_waddr] <= out_buf_wdata_im; - end -end - -// ============================================================================ -// MAIN FSM -// ============================================================================ -always @(posedge aclk or negedge aresetn) begin - if (!aresetn) begin - state <= S_IDLE; - inverse_reg <= 1'b0; - in_count <= 0; - out_count <= 0; - out_total <= 0; - feed_count <= 0; - fft_start <= 1'b0; - fft_inverse <= 1'b0; - fft_din_re <= 0; - fft_din_im <= 0; - fft_din_valid <= 1'b0; - in_buf_we <= 1'b0; - in_buf_waddr <= 0; - in_buf_wdata_re <= 0; - in_buf_wdata_im <= 0; - out_buf_we <= 1'b0; - out_buf_waddr <= 0; - out_buf_wdata_re <= 0; - out_buf_wdata_im <= 0; - end else begin - // Defaults - fft_start <= 1'b0; - fft_din_valid <= 1'b0; - in_buf_we <= 1'b0; - out_buf_we <= 1'b0; - - case (state) - - // ================================================================ - S_IDLE: begin - in_count <= 0; - if (s_axis_config_tvalid) begin - // Config tdata[0]: 1=forward, 0=inverse - // fft_engine: inverse=0 means forward, inverse=1 means inverse - inverse_reg <= ~s_axis_config_tdata[0]; - state <= S_FEED; - in_count <= 0; - feed_count <= 0; - end - end - - // ================================================================ - // S_FEED: Buffer all N inputs first, then start engine. - // ================================================================ - S_FEED: begin - if (in_count < N) begin - // Still accepting input data - if (s_axis_data_tvalid) begin - in_buf_we <= 1'b1; - in_buf_waddr <= in_count[4:0]; - in_buf_wdata_re <= s_axis_data_tdata[15:0]; - in_buf_wdata_im <= s_axis_data_tdata[31:16]; - in_count <= in_count + 1; - end - end else if (feed_count == 0) begin - // All N inputs buffered, start the FFT engine - fft_start <= 1'b1; - fft_inverse <= inverse_reg; - feed_count <= 0; - state <= S_WAIT; - out_total <= 0; - end - end - - // ================================================================ - // S_WAIT: Feed buffered data to engine, then wait for output - // ================================================================ - S_WAIT: begin - if (feed_count < N) begin - fft_din_re <= in_buf_re[feed_count[4:0]]; - fft_din_im <= in_buf_im[feed_count[4:0]]; - fft_din_valid <= 1'b1; - feed_count <= feed_count + 1; - end - - // Capture engine outputs - if (fft_dout_valid && out_total < N) begin - out_buf_we <= 1'b1; - out_buf_waddr <= out_total[4:0]; - out_buf_wdata_re <= fft_dout_re; - out_buf_wdata_im <= fft_dout_im; - out_total <= out_total + 1; - end - - // Engine done - if (fft_done) begin - state <= S_OUTPUT; - out_count <= 0; - end - end - - // ================================================================ - // S_OUTPUT: Stream buffered results via AXI-Stream master - // ================================================================ - S_OUTPUT: begin - if (m_axis_data_tready || !m_axis_data_tvalid) begin - if (out_count < N) begin - // m_axis_data_tdata driven combinationally from out_buf - if (m_axis_data_tready) begin - out_count <= out_count + 1; - end - end - if (out_count >= N - 1 && m_axis_data_tready) begin - state <= S_IDLE; - end - end - end - - default: state <= S_IDLE; - - endcase - end -end - -// ============================================================================ -// MEMORY INIT (simulation only) -// ============================================================================ -`ifdef SIMULATION -integer init_k; -initial begin - for (init_k = 0; init_k < N; init_k = init_k + 1) begin - in_buf_re[init_k] = 0; - in_buf_im[init_k] = 0; - out_buf_re[init_k] = 0; - out_buf_im[init_k] = 0; - end -end -`endif - -endmodule diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1761723..4f97c55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,6 +28,112 @@ for getting a change reviewed and merged. if not, note which scripts your change affects - **Whitespace** — `git diff --check` should be clean - Keep PRs focused: one logical change per PR is easier to review +- **Run the regression tests** (see below) + +## Running regression tests + +After any change, run the relevant test suites to verify nothing is +broken. All commands assume you are at the repository root. + +### Prerequisites + +| Tool | Used by | Install | +|------|---------|---------| +| [Icarus Verilog](http://iverilog.icarus.com/) (`iverilog`) | FPGA regression | `brew install icarus-verilog` / `apt install iverilog` | +| Python 3.8+ | GUI tests, co-sim | Usually pre-installed | +| GNU Make | MCU tests | Usually pre-installed | +| [SymbiYosys](https://symbiyosys.readthedocs.io/) (`sby`) | Formal verification | Optional — see SymbiYosys docs | + +### FPGA regression (RTL lint + unit/integration/signal-processing tests) + +```bash +cd 9_Firmware/9_2_FPGA +bash run_regression.sh +``` + +This runs four phases: + +| Phase | What it checks | +|-------|----------------| +| 0 — Lint | `iverilog -Wall` on all production RTL + static regex checks | +| 1 — Changed Modules | Unit tests for individual blocks (CIC, Doppler, CFAR, etc.) | +| 2 — Integration | DDC chain, receiver golden-compare, system-top, end-to-end | +| 3 — Signal Processing | FFT engine, NCO, FIR, matched filter chain | +| 4 — Infrastructure | CDC modules, edge detector, USB interface, range-bin decimator, mode controller | + +All tests must pass (exit code 0). Advisory lint warnings (e.g., `case +without default`) are non-blocking. + +### MCU unit tests + +```bash +cd 9_Firmware/9_1_Microcontroller/tests +make clean && make all +``` + +Runs 20 C-based unit tests covering safety, bug-fix, and gap-3 tests. +Every test binary must exit 0. + +### GUI / dashboard tests + +```bash +cd 9_Firmware/9_3_GUI +python3 -m pytest test_radar_dashboard.py -v +# or without pytest: +python3 -m unittest test_radar_dashboard -v +``` + +57+ protocol and rendering tests. The `test_record_and_stop` test +requires `h5py` and will be skipped if it is not installed. + +### Co-simulation (Python vs RTL golden comparison) + +Run from the co-sim directory after a successful FPGA regression (the +regression generates the RTL CSV outputs that the co-sim scripts compare +against): + +```bash +cd 9_Firmware/9_2_FPGA/tb/cosim + +# Validate all .mem files (twiddles, chirp ROMs, addressing) +python3 validate_mem_files.py + +# DDC chain: RTL vs Python model (5 scenarios) +python3 compare.py dc +python3 compare.py single_target +python3 compare.py multi_target +python3 compare.py noise_only +python3 compare.py sine_1mhz + +# Doppler processor: RTL vs golden reference +python3 compare_doppler.py stationary + +# Matched filter: RTL vs Python model (4 scenarios) +python3 compare_mf.py all +``` + +Each script prints PASS/FAIL per scenario and exits non-zero on failure. + +### Formal verification (optional) + +Requires SymbiYosys (`sby`), Yosys, and a solver (z3 or boolector): + +```bash +cd 9_Firmware/9_2_FPGA/formal +sby -f fv_doppler_processor.sby +sby -f fv_radar_mode_controller.sby +``` + +### Quick checklist + +Before pushing, confirm: + +1. `bash run_regression.sh` — all phases pass +2. `make all` (MCU tests) — 20/20 pass +3. `python3 -m unittest test_radar_dashboard -v` — all pass +4. `python3 validate_mem_files.py` — all checks pass +5. `python3 compare.py dc && python3 compare_doppler.py stationary && python3 compare_mf.py all` +6. `git diff --check` — no whitespace issues ## Areas where help is especially welcome